diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index eb1e3b0..9fa6f86 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -15,10 +15,10 @@
]
},
"dotnet-ef": {
- "version": "6.0.26",
+ "version": "8.0.7",
"commands": [
"dotnet-ef"
]
}
}
-}
+}
\ No newline at end of file
diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
new file mode 100644
index 0000000..4831c18
--- /dev/null
+++ b/.github/workflows/dotnet.yml
@@ -0,0 +1,34 @@
+# This workflow will build a .NET project
+# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
+
+name: .NET
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+jobs:
+ build:
+ services:
+ mysql:
+ image: mysql:9.0.1
+ env:
+ MYSQL_ROOT_PASSWORD: b@nk1
+ MYSQL_DATABASE: bank_db
+ ports:
+ - "3307:3306"
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 8.0.x
+ - name: Restore dependencies
+ run: dotnet restore
+ - name: Build
+ run: dotnet build --no-restore
+ - name: Test
+ run: dotnet test --no-build --verbosity normal
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..39bb010
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,33 @@
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "name": ".NET Core Launch (web)",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": "build",
+ "program": "${workspaceFolder}/Bank.Api/bin/Debug/net6.0/Bank.Api.dll",
+ "args": [],
+ "cwd": "${workspaceFolder}/Bank.Api",
+ "stopAtEntry": false,
+ "serverReadyAction": {
+ "action": "openExternally",
+ "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
+ },
+ "env": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "sourceFileMap": {
+ "/Views": "${workspaceFolder}/Views"
+ }
+ },
+ {
+ "name": ".NET Core Attach",
+ "type": "coreclr",
+ "request": "attach"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..f42f114
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,41 @@
+{
+ "version": "2.0.0",
+ "tasks": [
+ {
+ "label": "build",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "build",
+ "${workspaceFolder}/Bank.sln",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "publish",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "publish",
+ "${workspaceFolder}/Bank.sln",
+ "/property:GenerateFullPaths=true",
+ "/consoleloggerparameters:NoSummary;ForceNoAlign"
+ ],
+ "problemMatcher": "$msCompile"
+ },
+ {
+ "label": "watch",
+ "command": "dotnet",
+ "type": "process",
+ "args": [
+ "watch",
+ "run",
+ "--project",
+ "${workspaceFolder}/Bank.sln"
+ ],
+ "problemMatcher": "$msCompile"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/Bank.Api/Bank.Api.csproj b/Bank.Api/Bank.Api.csproj
index ffc75bc..fa8e780 100644
--- a/Bank.Api/Bank.Api.csproj
+++ b/Bank.Api/Bank.Api.csproj
@@ -1,6 +1,6 @@
- net6.0
+ net8.0
Linux
..\Bank
win-x64;osx-x64;linux-x64
@@ -9,10 +9,10 @@
-
+
-
+
\ No newline at end of file
diff --git a/Bank.Api/Dockerfile b/Bank.Api/Dockerfile
index 556035b..f2c57f6 100644
--- a/Bank.Api/Dockerfile
+++ b/Bank.Api/Dockerfile
@@ -1,10 +1,10 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
-FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
+FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
-FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
+FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet restore
diff --git a/Bank.Api/Handlers/IncomeRequestHandler.cs b/Bank.Api/Handlers/IncomeRequestHandler.cs
index 778c25c..04d9c3c 100644
--- a/Bank.Api/Handlers/IncomeRequestHandler.cs
+++ b/Bank.Api/Handlers/IncomeRequestHandler.cs
@@ -22,12 +22,18 @@ public IncomeRequestHandler(BankDbContext context, IYieldService yieldService)
_yieldService = yieldService;
}
- public async Task Handle(CalculateIncomeCommand request, CancellationToken cancellationToken)
+ public Task Handle(CalculateIncomeCommand request, CancellationToken cancellationToken)
{
var accounts = this._context.Accounts.ToArray();
- _yieldService.CalculateInterestFor(request.ForDate, accounts, request.InterestRate, cancellationToken, days: 1);
- await _context.SaveChangesAsync(cancellationToken);
- return Unit.Value;
+
+ foreach (var account in accounts)
+ {
+ var yield = _yieldService.CalculateInterestFor(request.ForDate, account, request.InterestRate, days: 1);
+ account.SetYield(yield, request.ForDate);
+ }
+
+ _context.SaveChanges();
+ return Unit.Task;
}
}
}
diff --git a/Bank.Api/Startup.cs b/Bank.Api/Startup.cs
index 91b3a18..ce299a8 100644
--- a/Bank.Api/Startup.cs
+++ b/Bank.Api/Startup.cs
@@ -1,27 +1,15 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Threading.Tasks;
-
-using Bank.Api.Handlers;
using Bank.Domain;
using Bank.Domain.Contracts;
-using Bank.Domain.Events;
-using Bank.Domain.SeedWork;
using Bank.Infra;
using MediatR;
-using MediatR.Pipeline;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
-using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
namespace Bank.Api
diff --git a/Bank.Api/appsettings.Development.json b/Bank.Api/appsettings.Development.json
index 721ec62..aba6cbc 100644
--- a/Bank.Api/appsettings.Development.json
+++ b/Bank.Api/appsettings.Development.json
@@ -3,7 +3,8 @@
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
- "Microsoft.Hosting.Lifetime": "Information"
+ "Microsoft.Hosting.Lifetime": "Information",
+ "Microsoft.EntityFrameworkCore.Database.Command": "Information"
}
},
"ConnectionStrings": {
diff --git a/Bank.Domain/Account.cs b/Bank.Domain/Account.cs
index b2b92c2..cf97706 100644
--- a/Bank.Domain/Account.cs
+++ b/Bank.Domain/Account.cs
@@ -90,15 +90,16 @@ public void ChargePayment(Invoice invoice)
public void AddOperation(AccountOperation accountOperation) =>
_operations.Add(accountOperation);
- public IReadOnlyCollection Operations => _operations;
+ public IReadOnlyCollection Operations => _operations.AsReadOnly();
public DateTime? LastYieldedDate { get; private set; }
public void SetYield(decimal yield, DateTime currentDate)
{
+ this.AddOperation(new AccountOperation(currentDate, $"Rendimento em {currentDate}", yield, EventType.Income));
this.Balance += yield;
this.LastYieldedDate = currentDate;
this.AddDomainEvent(new CalculatedIncomeEvent(this, yield));
}
}
-}
\ No newline at end of file
+}
diff --git a/Bank.Domain/AccountOperation.cs b/Bank.Domain/AccountOperation.cs
index d5f4b5e..7d1e5d2 100644
--- a/Bank.Domain/AccountOperation.cs
+++ b/Bank.Domain/AccountOperation.cs
@@ -23,6 +23,7 @@ public AccountOperation(DateTime date, string description, decimal amount, Event
public string Description { get; private set; }
public decimal Amount { get; private set; }
public EventType Operation { get; private set; }
- public int AccountNo { get; private set; }
+ public int AccountNo { get; set; }
+ public Account Account { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/Bank.Domain/Bank.Domain.csproj b/Bank.Domain/Bank.Domain.csproj
index e3c6f2f..64e63b2 100644
--- a/Bank.Domain/Bank.Domain.csproj
+++ b/Bank.Domain/Bank.Domain.csproj
@@ -1,9 +1,9 @@
- net6.0
+ net8.0
win-x64;osx-x64;linux-x64
-
+
\ No newline at end of file
diff --git a/Bank.Domain/Contracts/IYieldService.cs b/Bank.Domain/Contracts/IYieldService.cs
index 28b66bb..cb0a055 100644
--- a/Bank.Domain/Contracts/IYieldService.cs
+++ b/Bank.Domain/Contracts/IYieldService.cs
@@ -1,15 +1,9 @@
using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
namespace Bank.Domain.Contracts
{
public interface IYieldService
{
- void CalculateInterestFor(DateTime currentDate, IYieldAccount account, double interestRate, uint days = 1);
- void CalculateInterestFor(DateTime currentDate, IEnumerable accounts, double interestRate, CancellationToken cancellationToken, uint days = 1);
+ decimal CalculateInterestFor(DateTime currentDate, IYieldAccount account, double interestRate, uint days = 1);
}
-}
\ No newline at end of file
+}
diff --git a/Bank.Domain/YieldService.cs b/Bank.Domain/YieldService.cs
index 7a7c66a..18d0e62 100644
--- a/Bank.Domain/YieldService.cs
+++ b/Bank.Domain/YieldService.cs
@@ -10,28 +10,21 @@ namespace Bank.Domain
{
public class YieldService : IYieldService
{
- public void CalculateInterestFor(DateTime forDate, IYieldAccount account, double interestRate, uint days = 1)
+ public decimal CalculateInterestFor(DateTime forDate, IYieldAccount account, double interestRate, uint days = 1)
{
if (HasPositiveBalance(account)
&& ItHasAlreadyBeenCalculated(forDate, account.LastYieldedDate.GetValueOrDefault(), days))
{
decimal calc = Convert.ToDecimal(Math.Pow(1 + interestRate / 100d, days / 252d) - 1);
- var balance = Math.Round(calc * account.Balance, 2);
- account.SetYield(balance, forDate);
+ var yield = Math.Round(calc * account.Balance, 2);
+ return yield;
}
+ return 0;
}
-
- public void CalculateInterestFor(DateTime forDate, IEnumerable accounts, double interestRate, CancellationToken cancellationToken, uint days = 1)
- {
- var paralleOptions = new ParallelOptions { CancellationToken = cancellationToken };
-
- Parallel.ForEach(accounts, paralleOptions, account =>
- this.CalculateInterestFor(forDate, account, interestRate, days));
- }
-
+
private static bool ItHasAlreadyBeenCalculated(DateTime forDate, DateTime lastYieldedDate, uint days) =>
forDate > lastYieldedDate.AddDays(days);
private static bool HasPositiveBalance(IYieldAccount account) => account.Balance > 0;
}
-}
\ No newline at end of file
+}
diff --git a/Bank.Infra/Bank.Infra.csproj b/Bank.Infra/Bank.Infra.csproj
index 2972b7d..02d93e1 100644
--- a/Bank.Infra/Bank.Infra.csproj
+++ b/Bank.Infra/Bank.Infra.csproj
@@ -1,19 +1,16 @@
- net6.0
+ net8.0
win-x64;osx-x64;linux-x64
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
-
-
+
+
+
+
-
+
\ No newline at end of file
diff --git a/Bank.Infra/BankContext.cs b/Bank.Infra/BankContext.cs
index e58bca1..23dfca9 100644
--- a/Bank.Infra/BankContext.cs
+++ b/Bank.Infra/BankContext.cs
@@ -88,7 +88,7 @@ private void ConfigureAccount(ModelBuilder builder)
account.Property(a => a.OwnerId);
account.HasMany(a => a.Operations)
- .WithOne()
+ .WithOne(o => o.Account)
.HasForeignKey(h => h.AccountNo)
.OnDelete(DeleteBehavior.Cascade);
@@ -106,4 +106,4 @@ private static void CleanEvents(IEnumerable entities)
entity.ClearEvents();
}
}
-}
\ No newline at end of file
+}
diff --git a/Bank.Tests/Bank.Tests.csproj b/Bank.Tests/Bank.Tests.csproj
index c123ea5..1814169 100644
--- a/Bank.Tests/Bank.Tests.csproj
+++ b/Bank.Tests/Bank.Tests.csproj
@@ -1,6 +1,6 @@
- net6.0
+ net8.0
false
win-x64;osx-x64;linux-x64
@@ -22,12 +22,12 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
-
+
+
-
+
\ No newline at end of file
diff --git a/Bank.Tests/Unit/YieldServiceTest.cs b/Bank.Tests/Unit/YieldServiceTest.cs
index ae581c6..331106c 100644
--- a/Bank.Tests/Unit/YieldServiceTest.cs
+++ b/Bank.Tests/Unit/YieldServiceTest.cs
@@ -3,6 +3,8 @@
using Bank.Domain;
using Bank.Domain.Contracts;
+using FluentAssertions;
+
using NSubstitute;
using NSubstitute.ReceivedExtensions;
@@ -19,9 +21,9 @@ public void Should_apply_savings_to_balance_every_day_with_by_given_rate()
account.Balance.Returns(67.95m);
var currentDate = new DateTime(2020, 07, 29);
var yieldService = new YieldService();
- yieldService.CalculateInterestFor(currentDate, account, interestRate: 3.52, days: 1);
+ var yield = yieldService.CalculateInterestFor(currentDate, account, interestRate: 3.52, days: 1);
- account.Received().SetYield(.01m, currentDate);
+ yield.Should().Be(0.01m);
}
[Theory]
@@ -48,9 +50,9 @@ public void Should_not_calculate_interest_rate_twice_for_the_same_day()
var currentDate = new DateTime(2020, 07, 29);
var yieldService = new YieldService();
- yieldService.CalculateInterestFor(currentDate, account, interestRate: 3.52, days: 1);
+ var yield = yieldService.CalculateInterestFor(currentDate, account, interestRate: 3.52, days: 1);
- account.Received(Quantity.None()).SetYield(Arg.Any(), Arg.Any());
+ yield.Should().Be(0);
}
[Fact]
@@ -62,9 +64,9 @@ public void Should_respect_given_days_to_calculate_the_interest_rate()
var currentDate = new DateTime(2020, 07, 29);
var yieldService = new YieldService();
- yieldService.CalculateInterestFor(currentDate, account, interestRate: 3.52, days: 2);
+ var yield = yieldService.CalculateInterestFor(currentDate, account, interestRate: 3.52, days: 2);
- account.Received(Quantity.None()).SetYield(Arg.Any(), Arg.Any());
+ yield.Should().Be(0);
}
}
diff --git a/README.md b/README.md
index eb9515c..c579fd3 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
## Banco Simples
-Esse projeto tem como intenção simular algumas operações bancárias, de maneira simplificada como Depositar, Sacar e Pagar.
+Esse projeto tem como intenção simular algumas operações bancárias, de maneira simplificada com ações como: Depositar, Sacar e Pagar.
-Foi construído usando .NET 5 e MySQL.
+Foi construído usando .NET 8 e MySQL.
Para testar a aplicação basta executar o seguinte comando na pasta raiz:
@@ -24,7 +24,7 @@ Também é possível interagir com a aplicação vida API:
#### Depositar
> POST /api/account/deposit
->
+>
Request body:
```json
{
@@ -43,7 +43,7 @@ $ curl -X POST "http://localhost:8080/api/account/deposit" \
#### Saque
> POST /api/account/withdraw
-
+
Request body:
```json
{
@@ -59,7 +59,7 @@ $ curl -X POST "http://localhost:8080/api/account/withdraw" \
-#### Pagamento:
+#### Pagamento:
> POST api/account/payment
Request body:
@@ -107,7 +107,7 @@ $ curl -X GET "http://localhost:8080/api/account/{id}/statement" -H "accept: te
```
#### Conta com Rendimento
-É possível ainda fazer com que a conta tenha rendimentos diários, essa é a api para fazer render a conta
+É possível ainda fazer com que a conta tenha rendimentos diários, essa é a api para fazer render a conta
> PUT /api/account/calculateIncome
Request body