diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..3729ff0c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..a49cfb28 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +################################################################################ +# Este arquivo .gitignore foi criado automaticamente pelo Microsoft(R) Visual Studio. +################################################################################ + +/.vs +/src/building blocks/Wappa.Core/bin/Debug/netcoreapp3.1 +/src/building blocks/Wappa.Core/obj +/src/services/Wappa.Motorista.API/bin/Debug/netcoreapp3.1 +/src/services/Wappa.Motorista.API/obj +/obj +/bin/Debug +/src/services/Wappa.Motoristas.API/obj/Docker +/src/building blocks/Wappa.MessageBus/obj +/src/building blocks/Wappa.MessageBus/bin/Debug/netcoreapp3.1 +/src/services/Wappa.Geolocalizacao.API/bin/Debug/netcoreapp3.1 +/src/services/Wappa.Geolocalizacao.API/obj +/src/services/Wappa.CoordenadasGeograficas.API/bin/Debug/netcoreapp3.1 +/src/services/Wappa.CoordenadasGeograficas.API/obj +/src/building blocks/Wappa.WebAPI.Core/bin/Debug/netcoreapp3.1 +/src/building blocks/Wappa.WebAPI.Core/obj +/src/services/Wappa.Motorista.API/bin/Debug diff --git a/Wappa.sln b/Wappa.sln new file mode 100644 index 00000000..fd81d85a --- /dev/null +++ b/Wappa.sln @@ -0,0 +1,81 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30804.86 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Building Blocks", "Building Blocks", "{DC4A0A94-B314-410C-803D-95E4A3F5C0FA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Services", "Services", "{D7CC5A53-341D-41FD-9A24-0BD3C5569258}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{C5A6B0DC-3A32-46A4-858D-73410D1A81E9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wappa.Core", "src\building blocks\Wappa.Core\Wappa.Core.csproj", "{F1EF41B4-CA77-4B64-8C64-8AA0E16626A1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Motorista", "Motorista", "{545ADEF2-79F6-4825-97A7-AD34D64A94EC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wappa.Motoristas.API", "src\services\Wappa.Motorista.API\Wappa.Motoristas.API.csproj", "{9AB883F8-6E98-41BF-87A0-F7AA0B0F3C60}" +EndProject +Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{496BCAED-C350-4AD3-AEDE-5810E67E724C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MessageBus", "MessageBus", "{C94A4B68-ABAF-4566-8E42-3D603870A4F2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Wappa.MessageBus", "src\building blocks\Wappa.MessageBus\Wappa.MessageBus.csproj", "{D4975541-0CC6-493B-90B2-AB3757D2A1B2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Coordenadas Geograficas", "Coordenadas Geograficas", "{951C0702-1109-463A-8FB3-276221ADB711}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wappa.CoordenadasGeograficas.API", "src\services\Wappa.CoordenadasGeograficas.API\Wappa.CoordenadasGeograficas.API.csproj", "{B6B9227F-7CBE-426E-90C6-53D015B86357}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Services", "Services", "{DC09A6A3-F2B1-48A3-B3ED-268E650A7EB0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wappa.WebAPI.Core", "src\building blocks\Wappa.WebAPI.Core\Wappa.WebAPI.Core.csproj", "{8155999B-3EB8-44D2-BA43-86C97F42AE38}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F1EF41B4-CA77-4B64-8C64-8AA0E16626A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1EF41B4-CA77-4B64-8C64-8AA0E16626A1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1EF41B4-CA77-4B64-8C64-8AA0E16626A1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1EF41B4-CA77-4B64-8C64-8AA0E16626A1}.Release|Any CPU.Build.0 = Release|Any CPU + {9AB883F8-6E98-41BF-87A0-F7AA0B0F3C60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9AB883F8-6E98-41BF-87A0-F7AA0B0F3C60}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9AB883F8-6E98-41BF-87A0-F7AA0B0F3C60}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9AB883F8-6E98-41BF-87A0-F7AA0B0F3C60}.Release|Any CPU.Build.0 = Release|Any CPU + {496BCAED-C350-4AD3-AEDE-5810E67E724C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {496BCAED-C350-4AD3-AEDE-5810E67E724C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {496BCAED-C350-4AD3-AEDE-5810E67E724C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {496BCAED-C350-4AD3-AEDE-5810E67E724C}.Release|Any CPU.Build.0 = Release|Any CPU + {D4975541-0CC6-493B-90B2-AB3757D2A1B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D4975541-0CC6-493B-90B2-AB3757D2A1B2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D4975541-0CC6-493B-90B2-AB3757D2A1B2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D4975541-0CC6-493B-90B2-AB3757D2A1B2}.Release|Any CPU.Build.0 = Release|Any CPU + {B6B9227F-7CBE-426E-90C6-53D015B86357}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6B9227F-7CBE-426E-90C6-53D015B86357}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6B9227F-7CBE-426E-90C6-53D015B86357}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6B9227F-7CBE-426E-90C6-53D015B86357}.Release|Any CPU.Build.0 = Release|Any CPU + {8155999B-3EB8-44D2-BA43-86C97F42AE38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8155999B-3EB8-44D2-BA43-86C97F42AE38}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8155999B-3EB8-44D2-BA43-86C97F42AE38}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8155999B-3EB8-44D2-BA43-86C97F42AE38}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {C5A6B0DC-3A32-46A4-858D-73410D1A81E9} = {DC4A0A94-B314-410C-803D-95E4A3F5C0FA} + {F1EF41B4-CA77-4B64-8C64-8AA0E16626A1} = {C5A6B0DC-3A32-46A4-858D-73410D1A81E9} + {545ADEF2-79F6-4825-97A7-AD34D64A94EC} = {D7CC5A53-341D-41FD-9A24-0BD3C5569258} + {9AB883F8-6E98-41BF-87A0-F7AA0B0F3C60} = {545ADEF2-79F6-4825-97A7-AD34D64A94EC} + {C94A4B68-ABAF-4566-8E42-3D603870A4F2} = {DC4A0A94-B314-410C-803D-95E4A3F5C0FA} + {D4975541-0CC6-493B-90B2-AB3757D2A1B2} = {C94A4B68-ABAF-4566-8E42-3D603870A4F2} + {951C0702-1109-463A-8FB3-276221ADB711} = {D7CC5A53-341D-41FD-9A24-0BD3C5569258} + {B6B9227F-7CBE-426E-90C6-53D015B86357} = {951C0702-1109-463A-8FB3-276221ADB711} + {DC09A6A3-F2B1-48A3-B3ED-268E650A7EB0} = {DC4A0A94-B314-410C-803D-95E4A3F5C0FA} + {8155999B-3EB8-44D2-BA43-86C97F42AE38} = {DC09A6A3-F2B1-48A3-B3ED-268E650A7EB0} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1ABF1BAA-6091-41E7-93DE-3428D39E26BC} + EndGlobalSection +EndGlobal diff --git a/docker-compose.dcproj b/docker-compose.dcproj new file mode 100644 index 00000000..6f758b48 --- /dev/null +++ b/docker-compose.dcproj @@ -0,0 +1,18 @@ + + + + 2.1 + Linux + 496bcaed-c350-4ad3-aede-5810e67e724c + LaunchBrowser + {Scheme}://localhost:{ServicePort}/swagger + wappa.motoristas.api + + + + docker-compose.yml + + + + + \ No newline at end of file diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 00000000..2e101b74 --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,74 @@ +version: '3.4' + +services: + banco: + container_name: banco_sql + environment: + - ASPNETCORE_ENVIRONMENT=Development + - SA_PASSWORD=yourStrong(!)Password + - ACCEPT_EULA=Y + healthcheck: + test: ["CMD", "/opt/mssql-tools/bin/sqlcmd", "-Usa", "-PyourStrong(!)Password", "-Q", "select 1"] + interval: 1s + retries: 20 + ports: + - "1435:1433" + networks: + - local + + rabbitmq: + image: rabbitmq:management + hostname: rabbit-host + container_name: rabbit + ports: + - 5672:5672 + - 15672:15672 + networks: + - local + + portainer: + image: portainer/portainer + hostname: portainer-host + container_name: portainer-local + command: -H unix:///var/run/docker.sock + restart: always + ports: + - 9000:9000 + - 8000:8000 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - portainer_data:/data + + wappa.motoristas.api: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=https://+:5001;http://+:4001 + - CONTAINER=true + ports: + - "4001:4001" + - "5001:5001" + volumes: + - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro + - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro + networks: + - local + + wappa.coordenadasgeograficas.api: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=https://+:5002;http://+:4002 + ports: + - "4002:4002" + - "5002:5002" + volumes: + - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro + - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro + networks: + - local + +networks: + local: + driver: bridge + +volumes: + portainer_data: \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..bb66042f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,23 @@ +version: '3.4' + +services: + banco: + image: mcr.microsoft.com/mssql/server:2017-latest + + rabbitmq: + image: rabbitmq:management + + portainer: + image: portainer/portainer + + wappa.motoristas.api: + image: ${DOCKER_REGISTRY-}wappamotoristasapi + build: + context: . + dockerfile: src/services/Wappa.Motorista.API/Dockerfile + + wappa.coordenadasgeograficas.api: + image: ${DOCKER_REGISTRY-}coordenadasgeograficasapi + build: + context: . + dockerfile: src/services/Wappa.CoordenadasGeograficas.API/Dockerfile \ No newline at end of file diff --git a/src/building blocks/Wappa.Core/Communication/ResponseResult.cs b/src/building blocks/Wappa.Core/Communication/ResponseResult.cs new file mode 100644 index 00000000..26e3cc09 --- /dev/null +++ b/src/building blocks/Wappa.Core/Communication/ResponseResult.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; + +namespace Wappa.Core.Communication +{ + public class ResponseResult + { + public ResponseResult() + { + Errors = new ResponseErrorMessages(); + } + + public string Title { get; set; } + public int Status { get; set; } + public ResponseErrorMessages Errors { get; set; } + } + + public class ResponseErrorMessages + { + public ResponseErrorMessages() + { + Mensagens = new List(); + } + + public List Mensagens { get; set; } + } +} diff --git a/src/building blocks/Wappa.Core/Data/IRepository.cs b/src/building blocks/Wappa.Core/Data/IRepository.cs new file mode 100644 index 00000000..7ce95f12 --- /dev/null +++ b/src/building blocks/Wappa.Core/Data/IRepository.cs @@ -0,0 +1,10 @@ +using System; +using Wappa.Core.DomainObjects; + +namespace Wappa.Core.Data +{ + public interface IRepository : IDisposable where T : IAggregateRoot + { + IUnitOfWork UnitOfWork { get; } + } +} \ No newline at end of file diff --git a/src/building blocks/Wappa.Core/Data/IUnitOfWork.cs b/src/building blocks/Wappa.Core/Data/IUnitOfWork.cs new file mode 100644 index 00000000..f182272e --- /dev/null +++ b/src/building blocks/Wappa.Core/Data/IUnitOfWork.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace Wappa.Core.Data +{ + public interface IUnitOfWork + { + Task Commit(); + } +} \ No newline at end of file diff --git a/src/building blocks/Wappa.Core/DomainObjects/Entity.cs b/src/building blocks/Wappa.Core/DomainObjects/Entity.cs new file mode 100644 index 00000000..bcb31d24 --- /dev/null +++ b/src/building blocks/Wappa.Core/DomainObjects/Entity.cs @@ -0,0 +1,54 @@ +using System; + +namespace Wappa.Core.DomainObjects +{ + public abstract class Entity + { + public Guid Id { get; set; } + + protected Entity() + { + Id = Guid.NewGuid(); + } + + #region Comparações + + public override bool Equals(object obj) + { + var compareTo = obj as Entity; + + if (ReferenceEquals(this, compareTo)) return true; + if (ReferenceEquals(null, compareTo)) return false; + + return Id.Equals(compareTo.Id); + } + + public static bool operator ==(Entity a, Entity b) + { + if (ReferenceEquals(a, null) && ReferenceEquals(b, null)) + return true; + + if (ReferenceEquals(a, null) || ReferenceEquals(b, null)) + return false; + + return a.Equals(b); + } + + public static bool operator !=(Entity a, Entity b) + { + return !(a == b); + } + + public override int GetHashCode() + { + return (GetType().GetHashCode() * 907) + Id.GetHashCode(); + } + + public override string ToString() + { + return $"{GetType().Name} [Id={Id}]"; + } + + #endregion + } +} \ No newline at end of file diff --git a/src/building blocks/Wappa.Core/DomainObjects/IAggregateRoot.cs b/src/building blocks/Wappa.Core/DomainObjects/IAggregateRoot.cs new file mode 100644 index 00000000..8c3dc9bb --- /dev/null +++ b/src/building blocks/Wappa.Core/DomainObjects/IAggregateRoot.cs @@ -0,0 +1,4 @@ +namespace Wappa.Core.DomainObjects +{ + public interface IAggregateRoot { } +} \ No newline at end of file diff --git a/src/building blocks/Wappa.Core/DomainObjects/Localizacao.cs b/src/building blocks/Wappa.Core/DomainObjects/Localizacao.cs new file mode 100644 index 00000000..21749a95 --- /dev/null +++ b/src/building blocks/Wappa.Core/DomainObjects/Localizacao.cs @@ -0,0 +1,7 @@ +namespace Wappa.Core.DomainObjects +{ + public class Localizacao + { + + } +} \ No newline at end of file diff --git a/src/building blocks/Wappa.Core/Extensions/AppSettings.cs b/src/building blocks/Wappa.Core/Extensions/AppSettings.cs new file mode 100644 index 00000000..e0fb101a --- /dev/null +++ b/src/building blocks/Wappa.Core/Extensions/AppSettings.cs @@ -0,0 +1,8 @@ +namespace Wappa.Core.Extensions +{ + public class AppSettings + { + public string GoogleGeocodingUrl { get; set; } + public string GoogleAPiKey { get; set; } + } +} diff --git a/src/building blocks/Wappa.Core/Mediator/IMediatorHandler.cs b/src/building blocks/Wappa.Core/Mediator/IMediatorHandler.cs new file mode 100644 index 00000000..c8e125d5 --- /dev/null +++ b/src/building blocks/Wappa.Core/Mediator/IMediatorHandler.cs @@ -0,0 +1,12 @@ +using FluentValidation.Results; +using Wappa.Core.Messages; +using System.Threading.Tasks; + +namespace Wappa.Core.Mediator +{ + public interface IMediatorHandler + { + Task PublicarEvento(T evento) where T : Event; + Task EnviarComando(T comando) where T : Command; + } +} diff --git a/src/building blocks/Wappa.Core/Mediator/MediatorHandler.cs b/src/building blocks/Wappa.Core/Mediator/MediatorHandler.cs new file mode 100644 index 00000000..95623e36 --- /dev/null +++ b/src/building blocks/Wappa.Core/Mediator/MediatorHandler.cs @@ -0,0 +1,27 @@ +using FluentValidation.Results; +using MediatR; +using Wappa.Core.Messages; +using System.Threading.Tasks; + +namespace Wappa.Core.Mediator +{ + public class MediatorHandler : IMediatorHandler + { + private readonly IMediator _mediator; + + public MediatorHandler(IMediator mediator) + { + _mediator = mediator; + } + + public async Task EnviarComando(T comando) where T : Command + { + return await _mediator.Send(comando); + } + + public async Task PublicarEvento(T evento) where T : Event + { + await _mediator.Publish(evento); + } + } +} diff --git a/src/building blocks/Wappa.Core/Messages/Command.cs b/src/building blocks/Wappa.Core/Messages/Command.cs new file mode 100644 index 00000000..679778e3 --- /dev/null +++ b/src/building blocks/Wappa.Core/Messages/Command.cs @@ -0,0 +1,24 @@ +using FluentValidation.Results; +using MediatR; +using System; +using System.Text.Json.Serialization; + +namespace Wappa.Core.Messages +{ + public abstract class Command : Message, IRequest + { + public DateTime TimeStamp { get; private set; } + [JsonIgnore] + public ValidationResult ValidationResult { get; set; } + + protected Command() + { + TimeStamp = DateTime.Now; + } + + public virtual bool EhValido() + { + throw new NotImplementedException(); + } + } +} diff --git a/src/building blocks/Wappa.Core/Messages/CommandHandler.cs b/src/building blocks/Wappa.Core/Messages/CommandHandler.cs new file mode 100644 index 00000000..54a4e93a --- /dev/null +++ b/src/building blocks/Wappa.Core/Messages/CommandHandler.cs @@ -0,0 +1,28 @@ +using FluentValidation.Results; +using System.Threading.Tasks; +using Wappa.Core.Data; + +namespace Wappa.Core.Messages +{ + public abstract class CommandHandler + { + protected ValidationResult ValidationResult; + + protected CommandHandler() + { + ValidationResult = new ValidationResult(); + } + + protected void AdicionarErro(string message) + { + ValidationResult.Errors.Add(new ValidationFailure(string.Empty, message)); + } + + protected async Task PersistirDados(IUnitOfWork unitOfWork) + { + if (!await unitOfWork.Commit()) AdicionarErro("Houve um erro ao persistir os dados"); + + return ValidationResult; + } + } +} diff --git a/src/building blocks/Wappa.Core/Messages/Event.cs b/src/building blocks/Wappa.Core/Messages/Event.cs new file mode 100644 index 00000000..fd3d3dc4 --- /dev/null +++ b/src/building blocks/Wappa.Core/Messages/Event.cs @@ -0,0 +1,15 @@ +using MediatR; +using System; + +namespace Wappa.Core.Messages +{ + public class Event : Message, INotification + { + public DateTime Timestamp { get; private set; } + + protected Event() + { + Timestamp = DateTime.Now; + } + } +} diff --git a/src/building blocks/Wappa.Core/Messages/Integration/IntegrationEvent.cs b/src/building blocks/Wappa.Core/Messages/Integration/IntegrationEvent.cs new file mode 100644 index 00000000..2d34d32c --- /dev/null +++ b/src/building blocks/Wappa.Core/Messages/Integration/IntegrationEvent.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Wappa.Core.Messages.Integration +{ + public abstract class IntegrationEvent : Event + { + } +} diff --git a/src/building blocks/Wappa.Core/Messages/Integration/ResponseMessage.cs b/src/building blocks/Wappa.Core/Messages/Integration/ResponseMessage.cs new file mode 100644 index 00000000..034d0a1a --- /dev/null +++ b/src/building blocks/Wappa.Core/Messages/Integration/ResponseMessage.cs @@ -0,0 +1,18 @@ +using FluentValidation.Results; + +namespace Wappa.Core.Messages.Integration +{ + public class ResponseMessage : Message + { + public ValidationResult ValidationResult { get; set; } + public decimal Longitude { get; set; } + public decimal Latitude { get; set; } + + public ResponseMessage(ValidationResult validationResult, decimal longitude, decimal latitude) + { + ValidationResult = validationResult; + Longitude = longitude; + Latitude = latitude; + } + } +} diff --git a/src/building blocks/Wappa.Core/Messages/Integration/SolicitouCadastroMotoristaIntegrationEvent.cs b/src/building blocks/Wappa.Core/Messages/Integration/SolicitouCadastroMotoristaIntegrationEvent.cs new file mode 100644 index 00000000..0f012306 --- /dev/null +++ b/src/building blocks/Wappa.Core/Messages/Integration/SolicitouCadastroMotoristaIntegrationEvent.cs @@ -0,0 +1,56 @@ +using FluentValidation; +using FluentValidation.Results; + +namespace Wappa.Core.Messages.Integration +{ + public class SolicitouCadastroMotoristaIntegrationEvent : IntegrationEvent + { + public SolicitouCadastroMotoristaIntegrationEvent(string logradouro, string numero, string complemento, string bairro, string cep, string cidade, string estado) + { + Logradouro = logradouro; + Numero = numero; + Complemento = complemento; + Bairro = bairro; + Cep = cep; + Cidade = cidade; + Estado = estado; + } + + public string Logradouro { get; set; } + public string Numero { get; set; } + public string Complemento { get; set; } + public string Bairro { get; set; } + public string Cep { get; set; } + public string Cidade { get; set; } + public string Estado { get; set; } + + public ValidationResult ValidationResult { get; protected set; } + + public bool EhValido() + { + var erros = new SolicitouCadastroMotoristaIntegrationEventValidation().Validate(this).Errors; + + ValidationResult = new ValidationResult(erros); + + return ValidationResult.IsValid; + } + + public class SolicitouCadastroMotoristaIntegrationEventValidation : AbstractValidator + { + public SolicitouCadastroMotoristaIntegrationEventValidation() + { + RuleFor(c => c.Logradouro) + .NotNull() + .WithMessage("Informe o logradouro"); + + RuleFor(c => c.Cidade) + .NotNull() + .WithMessage("Informe a cidade"); + + RuleFor(c => c.Estado) + .NotNull() + .WithMessage("Informe o estado"); + } + } + } +} diff --git a/src/building blocks/Wappa.Core/Messages/Message.cs b/src/building blocks/Wappa.Core/Messages/Message.cs new file mode 100644 index 00000000..859d3555 --- /dev/null +++ b/src/building blocks/Wappa.Core/Messages/Message.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Wappa.Core.Messages +{ + public abstract class Message + { + public string MessageType { get; protected set; } + public Guid AggregateId { get; protected set; } + + protected Message() + { + MessageType = GetType().Name; + } + } +} diff --git a/src/building blocks/Wappa.Core/Utils/ConfigurationExtensions.cs b/src/building blocks/Wappa.Core/Utils/ConfigurationExtensions.cs new file mode 100644 index 00000000..45d122e0 --- /dev/null +++ b/src/building blocks/Wappa.Core/Utils/ConfigurationExtensions.cs @@ -0,0 +1,12 @@ +using Microsoft.Extensions.Configuration; + +namespace Wappa.Core.Utils +{ + public static class ConfigurationExtensions + { + public static string GetMessageQueueConnection(this IConfiguration configuration, string name) + { + return configuration?.GetSection("MessageQueueConnection")?[name]; + } + } +} diff --git a/src/building blocks/Wappa.Core/Wappa.Core.csproj b/src/building blocks/Wappa.Core/Wappa.Core.csproj new file mode 100644 index 00000000..c41a7514 --- /dev/null +++ b/src/building blocks/Wappa.Core/Wappa.Core.csproj @@ -0,0 +1,13 @@ + + + + netcoreapp3.1 + + + + + + + + + diff --git a/src/building blocks/Wappa.MessageBus/DependencyInjectionExtensions.cs b/src/building blocks/Wappa.MessageBus/DependencyInjectionExtensions.cs new file mode 100644 index 00000000..4cc82597 --- /dev/null +++ b/src/building blocks/Wappa.MessageBus/DependencyInjectionExtensions.cs @@ -0,0 +1,17 @@ +using Microsoft.Extensions.DependencyInjection; +using System; + +namespace Wappa.MessageBus +{ + public static class DependencyInjectionExtensions + { + public static IServiceCollection AddMessageBus(this IServiceCollection services, string connection) + { + if (string.IsNullOrEmpty(connection)) throw new ArgumentNullException(); + + services.AddSingleton(new MessageBus(connection)); + + return services; + } + } +} diff --git a/src/building blocks/Wappa.MessageBus/IMessageBus.cs b/src/building blocks/Wappa.MessageBus/IMessageBus.cs new file mode 100644 index 00000000..dd0d36c0 --- /dev/null +++ b/src/building blocks/Wappa.MessageBus/IMessageBus.cs @@ -0,0 +1,37 @@ +using EasyNetQ; +using System; +using System.Threading.Tasks; +using Wappa.Core.Messages.Integration; + +namespace Wappa.MessageBus +{ + public interface IMessageBus : IDisposable + { + bool IsConnected { get; } + IAdvancedBus AdvancedBus { get; } + + void Publish(T message) where T : IntegrationEvent; + + Task PublishAsync(T message) where T : IntegrationEvent; + + void Subscribe(string subscriptionId, Action onMessage) where T : class; + + void SubscribeAsync(string subscriptionId, Func onMessage) where T : class; + + TResponse Request(TRequest request) + where TRequest : IntegrationEvent + where TResponse : ResponseMessage; + + Task RequestAsync(TRequest request) + where TRequest : IntegrationEvent + where TResponse : ResponseMessage; + + IDisposable Respond(Func responder) + where TRequest : IntegrationEvent + where TResponse : ResponseMessage; + + IDisposable RespondAsync(Func> responder) + where TRequest : IntegrationEvent + where TResponse : ResponseMessage; + } +} \ No newline at end of file diff --git a/src/building blocks/Wappa.MessageBus/MessageBus.cs b/src/building blocks/Wappa.MessageBus/MessageBus.cs new file mode 100644 index 00000000..86a5555d --- /dev/null +++ b/src/building blocks/Wappa.MessageBus/MessageBus.cs @@ -0,0 +1,109 @@ +using System; +using System.Threading.Tasks; +using EasyNetQ; +using Wappa.Core.Messages.Integration; +using Polly; +using RabbitMQ.Client.Exceptions; + +namespace Wappa.MessageBus +{ + public class MessageBus : IMessageBus + { + private IBus _bus; + private IAdvancedBus _advancedBus; + + private readonly string _connectionString; + + public MessageBus(string connectionString) + { + _connectionString = connectionString; + TryConnect(); + } + + public bool IsConnected => _bus?.IsConnected ?? false; + public IAdvancedBus AdvancedBus => _bus?.Advanced; + + public void Publish(T message) where T : IntegrationEvent + { + TryConnect(); + _bus.Publish(message); + } + + public async Task PublishAsync(T message) where T : IntegrationEvent + { + TryConnect(); + await _bus.PublishAsync(message); + } + + public void Subscribe(string subscriptionId, Action onMessage) where T : class + { + TryConnect(); + _bus.Subscribe(subscriptionId, onMessage); + } + + public void SubscribeAsync(string subscriptionId, Func onMessage) where T : class + { + TryConnect(); + _bus.SubscribeAsync(subscriptionId, onMessage); + } + + public TResponse Request(TRequest request) where TRequest : IntegrationEvent + where TResponse : ResponseMessage + { + TryConnect(); + return _bus.Request(request); + } + + public async Task RequestAsync(TRequest request) + where TRequest : IntegrationEvent where TResponse : ResponseMessage + { + TryConnect(); + return await _bus.RequestAsync(request); + } + + public IDisposable Respond(Func responder) + where TRequest : IntegrationEvent where TResponse : ResponseMessage + { + TryConnect(); + return _bus.Respond(responder); + } + + public IDisposable RespondAsync(Func> responder) + where TRequest : IntegrationEvent where TResponse : ResponseMessage + { + TryConnect(); + return _bus.RespondAsync(responder); + } + + private void TryConnect() + { + if (IsConnected) return; + + var policy = Policy.Handle() + .Or() + .WaitAndRetry(3, retryAttempt => + TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); + + policy.Execute(() => + { + _bus = RabbitHutch.CreateBus(_connectionString); + _advancedBus = _bus.Advanced; + _advancedBus.Disconnected += OnDisconnect; + }); + } + + private void OnDisconnect(object s, EventArgs e) + { + var policy = Policy.Handle() + .Or() + .RetryForever(); + + policy.Execute(TryConnect); + } + + public void Dispose() + { + _bus.Dispose(); + } + } +} \ No newline at end of file diff --git a/src/building blocks/Wappa.MessageBus/Wappa.MessageBus.csproj b/src/building blocks/Wappa.MessageBus/Wappa.MessageBus.csproj new file mode 100644 index 00000000..e04efcb9 --- /dev/null +++ b/src/building blocks/Wappa.MessageBus/Wappa.MessageBus.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + + diff --git a/src/building blocks/Wappa.WebAPI.Core/Controllers/MainController.cs b/src/building blocks/Wappa.WebAPI.Core/Controllers/MainController.cs new file mode 100644 index 00000000..c82a502c --- /dev/null +++ b/src/building blocks/Wappa.WebAPI.Core/Controllers/MainController.cs @@ -0,0 +1,83 @@ +using FluentValidation.Results; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using System.Collections.Generic; +using System.Linq; +using Wappa.Core.Communication; + +namespace Wappa.WebAPI.Core.Controllers +{ + [ApiController] + public abstract class MainController : ControllerBase + { + protected ICollection Erros = new List(); + + protected ActionResult CustomResponse(object result = null) + { + if (OperacaoValida()) + { + return Ok(result ?? new { sucesso = true}); + } + + return BadRequest(new ValidationProblemDetails(new Dictionary + { + { "Mensagens", Erros.ToArray() } + })); + } + + protected ActionResult CustomResponse(ModelStateDictionary modelState) + { + var erros = modelState.Values.SelectMany(e => e.Errors); + foreach (var erro in erros) + { + AdicionarErroProcessamento(erro.ErrorMessage); + } + + return CustomResponse(); + } + + protected ActionResult CustomResponse(ValidationResult validationResult) + { + foreach (var erro in validationResult.Errors) + { + AdicionarErroProcessamento(erro.ErrorMessage); + } + + return CustomResponse(); + } + + protected ActionResult CustomResponse(ResponseResult resposta) + { + ResponsePossuiErros(resposta); + + return CustomResponse(); + } + + protected bool ResponsePossuiErros(ResponseResult resposta) + { + if (resposta == null || !resposta.Errors.Mensagens.Any()) return false; + + foreach (var mensagem in resposta.Errors.Mensagens) + { + AdicionarErroProcessamento(mensagem); + } + + return true; + } + + protected bool OperacaoValida() + { + return !Erros.Any(); + } + + protected void AdicionarErroProcessamento(string erro) + { + Erros.Add(erro); + } + + protected void LimparErrosProcessamento() + { + Erros.Clear(); + } + } +} diff --git a/src/building blocks/Wappa.WebAPI.Core/Wappa.WebAPI.Core.csproj b/src/building blocks/Wappa.WebAPI.Core/Wappa.WebAPI.Core.csproj new file mode 100644 index 00000000..94c25438 --- /dev/null +++ b/src/building blocks/Wappa.WebAPI.Core/Wappa.WebAPI.Core.csproj @@ -0,0 +1,15 @@ + + + + netcoreapp3.1 + + + + + + + + + + + diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Application/Events/CoordenadaEventHandler.cs b/src/services/Wappa.CoordenadasGeograficas.API/Application/Events/CoordenadaEventHandler.cs new file mode 100644 index 00000000..0633012f --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Application/Events/CoordenadaEventHandler.cs @@ -0,0 +1,14 @@ +using MediatR; +using System.Threading; +using System.Threading.Tasks; + +namespace Wappa.CoordenadasGeograficas.API.Application.Events +{ + public class CoordenadaEventHandler : INotificationHandler + { + public Task Handle(SolicitouCadastroMotoristaEvent notification, CancellationToken cancellationToken) + { + return Task.CompletedTask; + } + } +} diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Application/Events/SolicitouCadastroMotoristaEvent.cs b/src/services/Wappa.CoordenadasGeograficas.API/Application/Events/SolicitouCadastroMotoristaEvent.cs new file mode 100644 index 00000000..2ccf0e81 --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Application/Events/SolicitouCadastroMotoristaEvent.cs @@ -0,0 +1,10 @@ +using Wappa.CoordenadasGeograficas.API.Models; +using Wappa.Core.Messages; + +namespace Wappa.CoordenadasGeograficas.API.Application.Events +{ + public class SolicitouCadastroMotoristaEvent : Event + { + public Endereco Endereco { get; set; } + } +} diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Configuration/ApiConfig.cs b/src/services/Wappa.CoordenadasGeograficas.API/Configuration/ApiConfig.cs new file mode 100644 index 00000000..34cd73d4 --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Configuration/ApiConfig.cs @@ -0,0 +1,44 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + + +namespace Wappa.CoordenadasGeograficas.API.Configuration +{ + public static class ApiConfig + { + public static void AddApiConfiguration(this IServiceCollection services, IConfiguration configuration) + { + services.AddControllers(); + + services.AddCors(options => + { + options.AddPolicy("Total", + builder => + builder + .AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader()); + }); + } + + public static void UseApiConfiguration(this IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseRouting(); + + app.UseCors("Total"); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Configuration/DependencyInjectionConfig.cs b/src/services/Wappa.CoordenadasGeograficas.API/Configuration/DependencyInjectionConfig.cs new file mode 100644 index 00000000..03127f71 --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Configuration/DependencyInjectionConfig.cs @@ -0,0 +1,43 @@ +using Microsoft.Extensions.DependencyInjection; +using Polly; +using Polly.Extensions.Http; +using Polly.Retry; +using System; +using System.Net.Http; +using Wappa.CoordenadasGeograficas.API.Services; + +namespace Wappa.CoordenadasGeograficas.API.Configuration +{ + public static class DependencyInjectionConfig + { + public static void RegisterServices(this IServiceCollection services) + { + services.AddHttpClient() + .AddPolicyHandler(PollyExtensions.EsperarTentar()) + .AddTransientHttpErrorPolicy( + p => p.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30))); + } + } + + public class PollyExtensions + { + public static AsyncRetryPolicy EsperarTentar() + { + var retry = HttpPolicyExtensions + .HandleTransientHttpError() + .WaitAndRetryAsync(new[] + { + TimeSpan.FromSeconds(1), + TimeSpan.FromSeconds(5), + TimeSpan.FromSeconds(10), + }, (outcome, timespan, retryCount, context) => + { + Console.ForegroundColor = ConsoleColor.Blue; + Console.WriteLine($"Tentando pela {retryCount} vez!"); + Console.ForegroundColor = ConsoleColor.White; + }); + + return retry; + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Configuration/MessageBusConfig.cs b/src/services/Wappa.CoordenadasGeograficas.API/Configuration/MessageBusConfig.cs new file mode 100644 index 00000000..176e7991 --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Configuration/MessageBusConfig.cs @@ -0,0 +1,18 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Wappa.CoordenadasGeograficas.API.Services; +using Wappa.Core.Utils; +using Wappa.MessageBus; + +namespace Wappa.CoordenadasGeograficas.API.Configuration +{ + public static class MessageBusConfig + { + public static void AddMessageBusConfiguration(this IServiceCollection services, + IConfiguration configuration) + { + services.AddMessageBus(configuration.GetMessageQueueConnection("MessageBus")) + .AddHostedService(); + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Configuration/SwaggerConfig.cs b/src/services/Wappa.CoordenadasGeograficas.API/Configuration/SwaggerConfig.cs new file mode 100644 index 00000000..1fd95a0a --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Configuration/SwaggerConfig.cs @@ -0,0 +1,67 @@ +using System; +using System.IO; +using System.Reflection; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi.Models; + +namespace Wappa.CoordenadasGeograficas.API.Configuration +{ + public static class SwaggerConfig + { + public static void AddSwaggerConfiguration(this IServiceCollection services) + { + services.AddSwaggerGen(c => + { + var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); + + c.IncludeXmlComments(xmlPath); + c.SwaggerDoc("v1", new OpenApiInfo() + { + Title = "Wappa Coordenadas Geográficas API", + Description = "Esta API faz a consulta de do endereõ do motorista e retorna sua coordenada geográfica.", + Contact = new OpenApiContact() { Name = "Phillipe R Souza", Email = "phillrog@hotmail.com" }, + + }); + + c.EnableAnnotations(); + + c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + Description = "Insira o token JWT desta maneira: Bearer {seu token}", + Name = "Authorization", + Scheme = "Bearer", + BearerFormat = "JWT", + In = ParameterLocation.Header, + Type = SecuritySchemeType.ApiKey + }); + + c.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "Bearer" + } + }, + new string[] {} + } + }); + + }); + } + + public static void UseSwaggerConfiguration(this IApplicationBuilder app) + { + app.UseSwagger(); + app.UseSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "v1"); + }); + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Controllers/CoordenadaGeograficaController.cs b/src/services/Wappa.CoordenadasGeograficas.API/Controllers/CoordenadaGeograficaController.cs new file mode 100644 index 00000000..23eca6af --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Controllers/CoordenadaGeograficaController.cs @@ -0,0 +1,38 @@ +using Microsoft.AspNetCore.Mvc; +using Swashbuckle.AspNetCore.Annotations; +using System.Net; +using System.Threading.Tasks; +using Wappa.CoordenadasGeograficas.API.Models; +using Wappa.CoordenadasGeograficas.API.Services; +using Wappa.WebAPI.Core.Controllers; + +namespace Wappa.CoordenadasGeograficas.API.Controllers +{ + /// + /// API para consultar coordenadas geográficas + /// + [Route("api/geocoordenada")] + public class CoordenadaGeograficaController : MainController + { + private readonly IGoogleGeocondingService _googleGeocondingService; + + public CoordenadaGeograficaController(IGoogleGeocondingService googleGeocondingService) + { + _googleGeocondingService = googleGeocondingService; + } + + /// + /// Busca coordenada geográfica de um endereço + /// + /// Dados do endereço + /// 200 ou 400 ou 404 + [HttpPost] + [SwaggerResponse((int)HttpStatusCode.OK, Description = "Retorna quando sucesso.")] + [SwaggerResponse((int)HttpStatusCode.BadRequest, Description = "Retorna quando ocorre alguma falha.")] + [SwaggerResponse((int)HttpStatusCode.NotFound, Description = "Retorna quando ocorre alguma falha.")] + public async Task BuscarCoordenadaPorEndereco(Endereco endereco) + { + return CustomResponse(await _googleGeocondingService.BuscarCoordenadas(endereco)); + } + } +} diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Dockerfile b/src/services/Wappa.CoordenadasGeograficas.API/Dockerfile new file mode 100644 index 00000000..c7a32fab --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Dockerfile @@ -0,0 +1,22 @@ +#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/core/aspnet:3.1-buster-slim AS base +WORKDIR /app +EXPOSE 4002 +EXPOSE 5002 + +FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build +WORKDIR /src +COPY ["src/services/Wappa.CoordenadasGeograficas.API/Wappa.CoordenadasGeograficas.API.csproj", "src/services/Wappa.CoordenadasGeograficas.API/"] +RUN dotnet restore "src/services/Wappa.CoordenadasGeograficas.API/Wappa.CoordenadasGeograficas.API.csproj" +COPY . . +WORKDIR "/src/src/services/Wappa.CoordenadasGeograficas.API" +RUN dotnet build "Wappa.CoordenadasGeograficas.API.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Wappa.CoordenadasGeograficas.API.csproj" -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Wappa.CoordenadasGeograficas.API.dll"] \ No newline at end of file diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Models/Coordenadas.cs b/src/services/Wappa.CoordenadasGeograficas.API/Models/Coordenadas.cs new file mode 100644 index 00000000..abc0d287 --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Models/Coordenadas.cs @@ -0,0 +1,13 @@ +namespace Wappa.CoordenadasGeograficas.API.Models +{ + public class Coordenadas + { + public decimal Longitude { get; set; } + public decimal Latitude { get; set; } + + public bool EhValido() + { + return Longitude != 0 && Latitude != 0; + } + } +} diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Models/Endereco.cs b/src/services/Wappa.CoordenadasGeograficas.API/Models/Endereco.cs new file mode 100644 index 00000000..fd3b2f9a --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Models/Endereco.cs @@ -0,0 +1,21 @@ +using System; + +namespace Wappa.CoordenadasGeograficas.API.Models +{ + public class Endereco + { + public string Logradouro { get; set; } + public string Numero { get; set; } + public string Complemento { get; set; } + public string Bairro { get; set; } + public string Cep { get; set; } + public string Cidade { get; set; } + public string Estado { get; set; } + + + public string Consultar() + { + return string.Join(Logradouro, "+", Numero, "+", Complemento, "+", Bairro, "+", Cep, "+", Cidade, "+", Estado); + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Program.cs b/src/services/Wappa.CoordenadasGeograficas.API/Program.cs new file mode 100644 index 00000000..cba3f716 --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Program.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Wappa.CoordenadasGeograficas.API +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Properties/launchSettings.json b/src/services/Wappa.CoordenadasGeograficas.API/Properties/launchSettings.json new file mode 100644 index 00000000..a52f1d55 --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Properties/launchSettings.json @@ -0,0 +1,56 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:52127", + "sslPort": 44381 + } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "profiles": { + "IIS Development": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Staging": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Staging" + } + }, + "IIS Production": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Production" + } + }, + "SelfHosting - Development": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5002;http://localhost:4002" + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "publishAllPorts": true, + "useSSL": true + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Services/CoordenadasIntegrationHandler.cs b/src/services/Wappa.CoordenadasGeograficas.API/Services/CoordenadasIntegrationHandler.cs new file mode 100644 index 00000000..47b30bdd --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Services/CoordenadasIntegrationHandler.cs @@ -0,0 +1,54 @@ +using FluentValidation.Results; +using Microsoft.Extensions.Hosting; +using System; +using System.Threading; +using System.Threading.Tasks; +using Wappa.CoordenadasGeograficas.API.Models; +using Wappa.Core.Messages.Integration; +using Wappa.MessageBus; + +namespace Wappa.CoordenadasGeograficas.API.Services +{ + public class CoordenadasIntegrationHandler : BackgroundService + { + private readonly IMessageBus _bus; + private readonly IGoogleGeocondingService _googleGeocondingService; + + public CoordenadasIntegrationHandler(IMessageBus bus, IGoogleGeocondingService googleGeocondingService) + { + _bus = bus; + _googleGeocondingService = googleGeocondingService; + } + + private void SetResponder() + { + _bus.RespondAsync(async request => + await ConsultarCoordenada(request)); + } + + private async Task ConsultarCoordenada(SolicitouCadastroMotoristaIntegrationEvent request) + { + var enderecoConsultar = new Endereco(); + + enderecoConsultar.Logradouro = request.Logradouro; + enderecoConsultar.Numero = request.Numero; + enderecoConsultar.Complemento = request.Complemento; + enderecoConsultar.Bairro = request.Bairro; + enderecoConsultar.Cep = request.Cep; + enderecoConsultar.Cidade = request.Cidade; + enderecoConsultar.Estado = request.Estado; + + var result = await _googleGeocondingService.BuscarCoordenadas(enderecoConsultar); + + var coordenadaResponse = new ResponseMessage(new ValidationResult(), result.Longitude, result.Latitude); + + return coordenadaResponse; + } + + protected override Task ExecuteAsync(CancellationToken stoppingToken) + { + SetResponder(); + return Task.CompletedTask; + } + } +} diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Services/GoogleGeocondingService.cs b/src/services/Wappa.CoordenadasGeograficas.API/Services/GoogleGeocondingService.cs new file mode 100644 index 00000000..9f9d2e7c --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Services/GoogleGeocondingService.cs @@ -0,0 +1,55 @@ +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using System; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using Wappa.CoordenadasGeograficas.API.Models; +using Wappa.Core.Extensions; + +namespace Wappa.CoordenadasGeograficas.API.Services +{ + public interface IGoogleGeocondingService + { + public Task BuscarCoordenadas(Endereco endereco); + } + + public class GoogleGeocondingService : IGoogleGeocondingService + { + private readonly HttpClient _httpClient; + private readonly string _key; + + public GoogleGeocondingService(HttpClient httpClient, + IOptions settings) + { + _httpClient = httpClient; + _httpClient.BaseAddress = new Uri(settings.Value.GoogleGeocodingUrl); + _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + _key = settings.Value.GoogleAPiKey; + } + + public async Task BuscarCoordenadas(Endereco endereco) + { + var response = await _httpClient.GetAsync($"?address={endereco.Consultar()}&key={_key}"); + var coordeandas = new Coordenadas(); + + if (response.IsSuccessStatusCode) + { + string result = response.Content.ReadAsStringAsync().Result; + + var data = JsonConvert.DeserializeObject(result); + + foreach (var item in data.results) + { + coordeandas.Latitude = (decimal)(item.geometry.location.lat); + coordeandas.Longitude = (decimal)(item.geometry.location.lng); + + if (coordeandas.EhValido()) + break; + } + } + + return coordeandas; + } + } +} diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Startup.cs b/src/services/Wappa.CoordenadasGeograficas.API/Startup.cs new file mode 100644 index 00000000..78215000 --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Startup.cs @@ -0,0 +1,51 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Wappa.CoordenadasGeograficas.API.Configuration; +using Wappa.Core.Extensions; + +namespace Wappa.CoordenadasGeograficas.API +{ + public class Startup + { + public IConfiguration Configuration { get; } + + public Startup(IHostEnvironment hostEnvironment) + { + var builder = new ConfigurationBuilder() + .SetBasePath(hostEnvironment.ContentRootPath) + .AddJsonFile("appsettings.json", true, true) + .AddJsonFile($"appsettings.{hostEnvironment.EnvironmentName}.json", true, true) + .AddEnvironmentVariables(); + + if (hostEnvironment.IsDevelopment()) + { + builder.AddUserSecrets(); + } + + Configuration = builder.Build(); + } + + public void ConfigureServices(IServiceCollection services) + { + services.AddApiConfiguration(Configuration); + + services.AddSwaggerConfiguration(); + + services.RegisterServices(); + + services.AddMessageBusConfiguration(Configuration); + + services.Configure(Configuration); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + app.UseSwaggerConfiguration(); + + app.UseApiConfiguration(env); + } + } +} diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Wappa.CoordenadasGeograficas.API.csproj b/src/services/Wappa.CoordenadasGeograficas.API/Wappa.CoordenadasGeograficas.API.csproj new file mode 100644 index 00000000..e4f3aa69 --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Wappa.CoordenadasGeograficas.API.csproj @@ -0,0 +1,31 @@ + + + + netcoreapp3.1 + 0a6d6e79-de6b-4994-9749-aeaa7f18fc1b + Linux + ..\..\.. + + + + bin\Debug\netcoreapp3.1\Wappa.CoordenadasGeograficas.API.xml + bin\Debug\netcoreapp3.1\ + 1701;1702;1591 + + + + + + + + + + + + + + + + + + diff --git a/src/services/Wappa.CoordenadasGeograficas.API/Wappa.CoordenadasGeograficas.API.csproj.user b/src/services/Wappa.CoordenadasGeograficas.API/Wappa.CoordenadasGeograficas.API.csproj.user new file mode 100644 index 00000000..e681dafe --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/Wappa.CoordenadasGeograficas.API.csproj.user @@ -0,0 +1,6 @@ + + + + Docker + + \ No newline at end of file diff --git a/src/services/Wappa.CoordenadasGeograficas.API/appsettings.Development.json b/src/services/Wappa.CoordenadasGeograficas.API/appsettings.Development.json new file mode 100644 index 00000000..a8c18945 --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/appsettings.Development.json @@ -0,0 +1,14 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "GoogleGeocodingUrl": "https://maps.googleapis.com/maps/api/geocode/json?", + "GoogleAPiKey": "AIzaSyDMoSwDGKl0QsrzjD3U3IVD8sLdRGtmOxQ", + "MessageQueueConnection": { + "MessageBus": "host=rabbit:5672;publisherConfirms=true;timeout=10" + } +} diff --git a/src/services/Wappa.CoordenadasGeograficas.API/appsettings.json b/src/services/Wappa.CoordenadasGeograficas.API/appsettings.json new file mode 100644 index 00000000..d9d9a9bf --- /dev/null +++ b/src/services/Wappa.CoordenadasGeograficas.API/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +} diff --git a/src/services/Wappa.Motorista.API/Application/Commands/AdicionarMotoristaCommand.cs b/src/services/Wappa.Motorista.API/Application/Commands/AdicionarMotoristaCommand.cs new file mode 100644 index 00000000..30f0700f --- /dev/null +++ b/src/services/Wappa.Motorista.API/Application/Commands/AdicionarMotoristaCommand.cs @@ -0,0 +1,50 @@ +using FluentValidation; +using Wappa.Core.Messages; +using System; +using Wappa.Motoristas.API.Application.DTO; +using Wappa.Motoristas.API.Models; +using System.Text.Json.Serialization; + +namespace Wappa.Motoristas.API.Application.Commands +{ + public class AdicionarMotoristaCommand : Command + { + // Motorista + public string Nome { get; set; } + public string SobreNome { get; set; } + + // Carro + public CarroDTO Carro { get; set; } + + // Endereco + public EnderecoDTO Endereco { get; set; } + + public override bool EhValido() + { + ValidationResult = new AdicionarMotoristaValidation().Validate(this); + return ValidationResult.IsValid; + } + + public class AdicionarMotoristaValidation : AbstractValidator + { + public AdicionarMotoristaValidation() + { + RuleFor(c => c.Nome) + .NotNull() + .WithMessage("Inform o nome do motorista"); + + RuleFor(c => c.SobreNome) + .NotNull() + .WithMessage("Inform o sobrenome do motorista"); + + RuleFor(c => c.Carro) + .NotNull() + .WithMessage("Informe o carro do motorista"); + + RuleFor(c => c.Endereco) + .NotNull() + .WithMessage("Informe o endereço do motorista"); + } + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Application/Commands/AtualizarMotoristaCommand.cs b/src/services/Wappa.Motorista.API/Application/Commands/AtualizarMotoristaCommand.cs new file mode 100644 index 00000000..00f3cc87 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Application/Commands/AtualizarMotoristaCommand.cs @@ -0,0 +1,54 @@ +using FluentValidation; +using Wappa.Core.Messages; +using System; +using Wappa.Motoristas.API.Application.DTO; +using System.Text.Json.Serialization; + +namespace Wappa.Motoristas.API.Application.Commands +{ + public class AtualizarMotoristaCommand : Command + { + public Guid Id { get; set; } + // Motorista + public string Nome { get; set; } + public string SobreNome { get; set; } + + // Carro + public CarroDTO Carro { get; set; } + + // Endereco + public EnderecoDTO Endereco { get; set; } + + public override bool EhValido() + { + ValidationResult = new AtualizarMotoristaValidation().Validate(this); + return ValidationResult.IsValid; + } + + public class AtualizarMotoristaValidation : AbstractValidator + { + public AtualizarMotoristaValidation() + { + RuleFor(c => c.Id) + .NotEqual(Guid.Empty) + .WithMessage("Id do motorista inválido"); + + RuleFor(c => c.Nome) + .NotNull() + .WithMessage("Inform o nome do motorista"); + + RuleFor(c => c.SobreNome) + .NotNull() + .WithMessage("Inform o sobrenome do motorista"); + + RuleFor(c => c.Carro) + .NotNull() + .WithMessage("Informe o carro do motorista"); + + RuleFor(c => c.Endereco) + .NotNull() + .WithMessage("Informe o endereço do motorista"); + } + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Application/Commands/DeletarMotoristaCommand.cs b/src/services/Wappa.Motorista.API/Application/Commands/DeletarMotoristaCommand.cs new file mode 100644 index 00000000..56633e3a --- /dev/null +++ b/src/services/Wappa.Motorista.API/Application/Commands/DeletarMotoristaCommand.cs @@ -0,0 +1,27 @@ +using FluentValidation; +using Wappa.Core.Messages; +using System; + +namespace Wappa.Motoristas.API.Application.Commands +{ + public class DeletarMotoristaCommand : Command + { + // Motorista + public Guid Id { get; set; } + public override bool EhValido() + { + ValidationResult = new DeletarMotoristaValidation().Validate(this); + return ValidationResult.IsValid; + } + + public class DeletarMotoristaValidation : AbstractValidator + { + public DeletarMotoristaValidation() + { + RuleFor(c => c.Id) + .NotEqual(Guid.Empty) + .WithMessage("Id do motorista inválido"); + } + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Application/Commands/MotoristaCommandHandler.cs b/src/services/Wappa.Motorista.API/Application/Commands/MotoristaCommandHandler.cs new file mode 100644 index 00000000..59cdecd9 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Application/Commands/MotoristaCommandHandler.cs @@ -0,0 +1,70 @@ +using FluentValidation.Results; +using MediatR; +using System.Threading; +using System.Threading.Tasks; +using Wappa.Core.Messages; +using Wappa.Motoristas.API.Application.Extensions; +using Wappa.Motoristas.API.Models; + +namespace Wappa.Motoristas.API.Application.Commands +{ + public class MotoristaCommandHandler : CommandHandler, + IRequestHandler, + IRequestHandler, + IRequestHandler + { + private readonly IMotoristaRepository _motoristaRepository; + + public MotoristaCommandHandler(IMotoristaRepository motoristaRepository) + { + _motoristaRepository = motoristaRepository; + } + + public async Task Handle(AdicionarMotoristaCommand message, CancellationToken cancellationToken) + { + if (!message.EhValido()) return message.ValidationResult; + + var motorista = message.MapearMotorista(); + + _motoristaRepository.Adicionar(motorista); + + return await PersistirDados(_motoristaRepository.UnitOfWork); + } + + public async Task Handle(AtualizarMotoristaCommand message, CancellationToken cancellationToken) + { + if (!message.EhValido()) return message.ValidationResult; + + var motorista = await _motoristaRepository.ObterPorId(message.Id); + + if (motorista == null) + { + AdicionarErro("Motorista não foi encontrado"); + return ValidationResult; + } + + message.MapearMotorista(motorista); + + _motoristaRepository.Atualizar(motorista); + + return await PersistirDados(_motoristaRepository.UnitOfWork); + } + + public async Task Handle(DeletarMotoristaCommand message, CancellationToken cancellationToken) + { + if (!message.EhValido()) return message.ValidationResult; + + var motorista = await _motoristaRepository.ObterPorId(message.Id); + + if (motorista == null) + { + AdicionarErro("Motorista não foi encontrado"); + return ValidationResult; + } + + _motoristaRepository.Deletar(motorista); + + return await PersistirDados(_motoristaRepository.UnitOfWork); + } + } +} diff --git a/src/services/Wappa.Motorista.API/Application/DTO/CarroDTO.cs b/src/services/Wappa.Motorista.API/Application/DTO/CarroDTO.cs new file mode 100644 index 00000000..7c9dd8ec --- /dev/null +++ b/src/services/Wappa.Motorista.API/Application/DTO/CarroDTO.cs @@ -0,0 +1,11 @@ +using System; + +namespace Wappa.Motoristas.API.Application.DTO +{ + public class CarroDTO + { + public string Marca { get; set; } + public string Modelo { get; set; } + public string Placa { get; set; } + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Application/DTO/CoordenadasDTO.cs b/src/services/Wappa.Motorista.API/Application/DTO/CoordenadasDTO.cs new file mode 100644 index 00000000..9babd92c --- /dev/null +++ b/src/services/Wappa.Motorista.API/Application/DTO/CoordenadasDTO.cs @@ -0,0 +1,14 @@ +namespace Wappa.Motoristas.API.Application.DTO +{ + public class CoordenadasDTO + { + public CoordenadasDTO(decimal longitude, decimal latitude) + { + Longitude = longitude; + Latitude = latitude; + } + + public decimal Longitude { get; set; } + public decimal Latitude { get; set; } + } +} diff --git a/src/services/Wappa.Motorista.API/Application/DTO/EnderecoDTO.cs b/src/services/Wappa.Motorista.API/Application/DTO/EnderecoDTO.cs new file mode 100644 index 00000000..b2abcbf6 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Application/DTO/EnderecoDTO.cs @@ -0,0 +1,17 @@ +using System; +using System.Text.Json.Serialization; + +namespace Wappa.Motoristas.API.Application.DTO +{ + public class EnderecoDTO + { + public string Logradouro { get; set; } + public string Numero { get; set; } + public string Complemento { get; set; } + public string Bairro { get; set; } + public string Cep { get; set; } + public string Cidade { get; set; } + public string Estado { get; set; } + public CoordenadasDTO Coordenadas { get; set; } + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Application/DTO/MotoristaDTO.cs b/src/services/Wappa.Motorista.API/Application/DTO/MotoristaDTO.cs new file mode 100644 index 00000000..0a5f1964 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Application/DTO/MotoristaDTO.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Wappa.Motoristas.API.Models; + +namespace Wappa.Motoristas.API.Application.DTO +{ + public class MotoristaDTO + { + public Guid Id { get; set; } + public string Nome { get; set; } + public string SobreNome { get; set; } + + public EnderecoDTO Endereco { get; set; } + public CarroDTO Carro { get; set; } + + public static List ParaMotoristaDTO(dynamic motoristas) + { + var listaDeMotoristas = new List(); + + foreach (var motorista in motoristas) + { + var motoristaDTO = new MotoristaDTO + { + Id = Guid.Parse(Convert.ToString(motorista.ID)), + Nome = motorista.NOME, + SobreNome = motorista.SOBRENOME, + Carro = new CarroDTO(), + Endereco = new EnderecoDTO() + }; + + motoristaDTO.Endereco = new EnderecoDTO + { + Logradouro = motorista.LOGRADOURO, + Numero = motorista.NUMERO, + Complemento = motorista.COMPLEMENTO, + Bairro = motorista.BAIRRO, + Cep = motorista.CEP, + Cidade = motorista.CIDADE, + Estado = motorista.ESTADO, + Coordenadas = new CoordenadasDTO(motorista.LONGITUDE, motorista.LATITUDE) + }; + + motoristaDTO.Carro = new CarroDTO + { + Marca = motorista.MARCA, + Modelo = motorista.MODELO, + Placa = motorista.PLACA + }; + + listaDeMotoristas.Add(motoristaDTO); + + } + return listaDeMotoristas; + } + } +} diff --git a/src/services/Wappa.Motorista.API/Application/Extensions/AdicionarMotoristaCommandExtension.cs b/src/services/Wappa.Motorista.API/Application/Extensions/AdicionarMotoristaCommandExtension.cs new file mode 100644 index 00000000..3a5fb572 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Application/Extensions/AdicionarMotoristaCommandExtension.cs @@ -0,0 +1,33 @@ +using Wappa.Motoristas.API.Application.Commands; +using Wappa.Motoristas.API.Models; + +namespace Wappa.Motoristas.API.Application.Extensions +{ + public static class AdicionarMotoristaCommandExtension + { + public static Motorista MapearMotorista(this AdicionarMotoristaCommand message) + { + var endereco = new Endereco + { + Logradouro = message.Endereco.Logradouro, + Numero = message.Endereco.Numero, + Complemento = message.Endereco.Complemento, + Bairro = message.Endereco.Bairro, + Cep = message.Endereco.Cep, + Cidade = message.Endereco.Cidade, + Estado = message.Endereco.Estado, + Latitude = message.Endereco.Coordenadas.Latitude, + Longitude = message.Endereco.Coordenadas.Longitude, + }; + + var carro = new Carro(message.Carro.Marca, message.Carro.Modelo, message.Carro.Placa); + + var motorista = new Motorista(message.Nome, message.SobreNome); + + motorista.Carro = carro; + motorista.Endereco = endereco; + + return motorista; + } + } +} diff --git a/src/services/Wappa.Motorista.API/Application/Extensions/AtualizarMotoristaCommandExtension.cs b/src/services/Wappa.Motorista.API/Application/Extensions/AtualizarMotoristaCommandExtension.cs new file mode 100644 index 00000000..9dce2d32 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Application/Extensions/AtualizarMotoristaCommandExtension.cs @@ -0,0 +1,31 @@ +using Wappa.Motoristas.API.Application.Commands; +using Wappa.Motoristas.API.Models; + +namespace Wappa.Motoristas.API.Application.Extensions +{ + public static class AtualizarMotoristaCommandExtension + { + public static Motorista MapearMotorista(this AtualizarMotoristaCommand message, Motorista motorista) + { + motorista.Carro.Marca = message.Carro.Marca; + motorista.Carro.Modelo = message.Carro.Modelo; + motorista.Carro.Placa = message.Carro.Placa; + + motorista.Endereco.Logradouro = message.Endereco.Logradouro; + motorista.Endereco.Numero = message.Endereco.Numero; + motorista.Endereco.Complemento = message.Endereco.Complemento; + motorista.Endereco.Bairro = message.Endereco.Bairro; + motorista.Endereco.Cep = message.Endereco.Cep; + motorista.Endereco.Cidade = message.Endereco.Cidade; + motorista.Endereco.Estado = message.Endereco.Estado; + + motorista.Endereco.Longitude = message.Endereco.Coordenadas.Longitude; + motorista.Endereco.Latitude = message.Endereco.Coordenadas.Latitude; + + motorista.Nome = message.Nome; + motorista.SobreNome = message.SobreNome; + + return motorista; + } + } +} diff --git a/src/services/Wappa.Motorista.API/Application/Queries/MotoristaQueries.cs b/src/services/Wappa.Motorista.API/Application/Queries/MotoristaQueries.cs new file mode 100644 index 00000000..cf292fd8 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Application/Queries/MotoristaQueries.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Dapper; +using Wappa.Motoristas.API.Application.DTO; +using Wappa.Motoristas.API.Models; + +namespace Wappa.Motoristas.API.Application.Queries +{ + public interface IMotoristaQueries + { + Task> ObterListaMotoristas(); + } + + public class MotoristaQueries : IMotoristaQueries + { + #region Sql + const string _sql_Motoristas = @"SELECT + M.ID, + M.NOME, + M.SOBRENOME, + E.LOGRADOURO, + E.NUMERO, + E.BAIRRO, + E.CEP, + E.COMPLEMENTO, + E.CIDADE, + E.ESTADO, + E.LATITUDE, + E.LONGITUDE, + C.MARCA, + C.MODELO, + C.PLACA + FROM + MOTORISTAS M + INNER JOIN + ENDERECOS E + ON E.MOTORISTAID = M.ID + INNER JOIN + CARROS C + ON C.MOTORISTAID = M.ID + ORDER BY M.NOME"; + #endregion + private readonly IMotoristaRepository _motoristaRepository; + + public MotoristaQueries(IMotoristaRepository motoristaRepository) + { + _motoristaRepository = motoristaRepository; + } + + public async Task> ObterListaMotoristas() + { + var motorista = await _motoristaRepository.ObterConexao() + .QueryAsync(_sql_Motoristas); + + return MotoristaDTO.ParaMotoristaDTO(motorista); + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Configuration/ApiConfig.cs b/src/services/Wappa.Motorista.API/Configuration/ApiConfig.cs new file mode 100644 index 00000000..4b98a22a --- /dev/null +++ b/src/services/Wappa.Motorista.API/Configuration/ApiConfig.cs @@ -0,0 +1,58 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using System; +using Wappa.Motoristas.API.Data; + +namespace Wappa.Motoristas.API.Configuration +{ + public static class ApiConfig + { + public static void AddApiConfiguration(this IServiceCollection services, IConfiguration configuration) + { + var conn = ""; + + if (Environment.GetEnvironmentVariable("CONTAINER") == "true") + conn = configuration.GetConnectionString("Container"); + else + conn = configuration.GetConnectionString("Localhost"); + + services.AddDbContext(options => + options.UseSqlServer(conn, m => m.MigrationsAssembly("Wappa.Motoristas.API"))); + + services.AddControllers(); + + services.AddCors(options => + { + options.AddPolicy("Total", + builder => + builder + .AllowAnyOrigin() + .AllowAnyMethod() + .AllowAnyHeader()); + }); + } + + public static void UseApiConfiguration(this IApplicationBuilder app, IWebHostEnvironment env, MotoristaContext motoristaContext) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + //motoristaContext.Database.Migrate(); + + app.UseRouting(); + + app.UseCors("Total"); + + app.UseEndpoints(endpoints => + { + endpoints.MapControllers(); + }); + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Configuration/DependencyInjectionConfig.cs b/src/services/Wappa.Motorista.API/Configuration/DependencyInjectionConfig.cs new file mode 100644 index 00000000..ea8e0d34 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Configuration/DependencyInjectionConfig.cs @@ -0,0 +1,33 @@ +using FluentValidation.Results; +using MediatR; +using Microsoft.Extensions.DependencyInjection; +using Wappa.Core.Mediator; +using Wappa.Motoristas.API.Application.Commands; +using Wappa.Motoristas.API.Application.Queries; +using Wappa.Motoristas.API.Data; +using Wappa.Motoristas.API.Data.Repository; +using Wappa.Motoristas.API.Models; + +namespace Wappa.Motoristas.API.Configuration +{ + public static class DependencyInjectionConfig + { + public static void RegisterServices(this IServiceCollection services) + { + // Commands + services.AddScoped, MotoristaCommandHandler>(); + services.AddScoped, MotoristaCommandHandler>(); + services.AddScoped, MotoristaCommandHandler>(); + + services.AddScoped(); + + // Application + services.AddScoped(); + services.AddScoped(); + + // Data + services.AddScoped(); + services.AddScoped(); + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Configuration/MessageBusConfig.cs b/src/services/Wappa.Motorista.API/Configuration/MessageBusConfig.cs new file mode 100644 index 00000000..889ec5db --- /dev/null +++ b/src/services/Wappa.Motorista.API/Configuration/MessageBusConfig.cs @@ -0,0 +1,15 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Wappa.Core.Utils; +using Wappa.MessageBus; + +namespace Wappa.Motoristas.API.Configuration +{ + public static class MessageBusConfig + { + public static void AddMessageBusConfiguration(this IServiceCollection services, IConfiguration configuration) + { + services.AddMessageBus(configuration.GetMessageQueueConnection("MessageBus")); + } + } +} diff --git a/src/services/Wappa.Motorista.API/Configuration/SwaggerConfig.cs b/src/services/Wappa.Motorista.API/Configuration/SwaggerConfig.cs new file mode 100644 index 00000000..e1b59db2 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Configuration/SwaggerConfig.cs @@ -0,0 +1,67 @@ +using System; +using System.IO; +using System.Reflection; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi.Models; + +namespace Wappa.Motoristas.API.Configuration +{ + public static class SwaggerConfig + { + public static void AddSwaggerConfiguration(this IServiceCollection services) + { + services.AddSwaggerGen(c => + { + var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); + + c.IncludeXmlComments(xmlPath); + c.SwaggerDoc("v1", new OpenApiInfo() + { + Title = "Wappa Challenge Dev Motorista API", + Description = "Esta API faz controle o cadastro de motoristas.", + Contact = new OpenApiContact() { Name = "Phillipe R Souza", Email = "phillrog@hotmail.com" }, + + }); + + c.EnableAnnotations(); + + c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme + { + Description = "Insira o token JWT desta maneira: Bearer {seu token}", + Name = "Authorization", + Scheme = "Bearer", + BearerFormat = "JWT", + In = ParameterLocation.Header, + Type = SecuritySchemeType.ApiKey + }); + + c.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "Bearer" + } + }, + new string[] {} + } + }); + + }); + } + + public static void UseSwaggerConfiguration(this IApplicationBuilder app) + { + app.UseSwagger(); + app.UseSwaggerUI(c => + { + c.SwaggerEndpoint("/swagger/v1/swagger.json", "v1"); + }); + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Controllers/MotoristaController.cs b/src/services/Wappa.Motorista.API/Controllers/MotoristaController.cs new file mode 100644 index 00000000..b46deb66 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Controllers/MotoristaController.cs @@ -0,0 +1,119 @@ +using Microsoft.AspNetCore.Mvc; +using System.Threading.Tasks; +using Wappa.Core.Mediator; +using Wappa.Motoristas.API.Application.Commands; +using System.Net; +using FluentValidation.Results; +using Swashbuckle.AspNetCore.Annotations; +using Wappa.Motoristas.API.Application.Queries; +using Wappa.WebAPI.Core.Controllers; +using Wappa.MessageBus; +using Wappa.Core.Messages.Integration; +using Wappa.Motoristas.API.Application.DTO; + +namespace Wappa.Motoristas.API.Controllers +{ + /// + /// cadastro de motoristas + /// + [Route("api/motorista")] + public class MotoristaController : MainController + { + private readonly IMediatorHandler _mediator; + private readonly IMotoristaQueries _motoristaQueries; + private readonly IMessageBus _bus; + + public MotoristaController(IMediatorHandler mediator, + IMotoristaQueries motoristaQueries, + IMessageBus bus) + { + _mediator = mediator; + _motoristaQueries = motoristaQueries; + _bus = bus; + } + + /// + /// Adiciona um novo motorista ao sistema + /// + /// Dados do motoristas + /// Retorna um 200 ou 400 + [HttpPost] + [SwaggerResponse((int)HttpStatusCode.OK, Description = "Retorna quando sucesso.")] + [SwaggerResponse((int)HttpStatusCode.BadRequest, Description = "Retorna quando ocorre alguma falha.")] + public async Task AdicionarMotorista(AdicionarMotoristaCommand motorista) + { + var solicitacaoCoordenadaEvent = new SolicitouCadastroMotoristaIntegrationEvent(motorista.Endereco.Logradouro, + motorista.Endereco.Numero, + motorista.Endereco.Complemento, + motorista.Endereco.Bairro, + motorista.Endereco.Cep, + motorista.Endereco.Cidade, + motorista.Endereco.Estado); + + if (!solicitacaoCoordenadaEvent.EhValido()) + return CustomResponse(solicitacaoCoordenadaEvent.ValidationResult); + + var coordenadas = await _bus.RequestAsync(solicitacaoCoordenadaEvent); + + motorista.Endereco.Coordenadas = new CoordenadasDTO(coordenadas.Longitude, coordenadas.Latitude); + + return CustomResponse(await _mediator.EnviarComando(motorista)); + } + + /// + /// Atualiza os dados de um motorista cadastrado no sistema + /// + /// Dados do motoristas + /// Retorna um 200 ou 400 + [HttpPut] + [SwaggerResponse((int)HttpStatusCode.OK, Description = "Retorna quando sucesso.")] + [SwaggerResponse((int)HttpStatusCode.BadRequest, Description = "Retorna quando ocorre alguma falha.")] + public async Task AtualizarMotorista(AtualizarMotoristaCommand motorista) + { + var solicitacaoCoordenadaEvent = new SolicitouCadastroMotoristaIntegrationEvent(motorista.Endereco.Logradouro, + motorista.Endereco.Numero, + motorista.Endereco.Complemento, + motorista.Endereco.Bairro, + motorista.Endereco.Cep, + motorista.Endereco.Cidade, + motorista.Endereco.Estado); + + if (!solicitacaoCoordenadaEvent.EhValido()) + return CustomResponse(solicitacaoCoordenadaEvent.ValidationResult); + + var coordenadas = await _bus.RequestAsync(solicitacaoCoordenadaEvent); + + motorista.Endereco.Coordenadas = new CoordenadasDTO(coordenadas.Longitude, coordenadas.Latitude); + + return CustomResponse(await _mediator.EnviarComando(motorista)); + } + + /// + /// Deleta o cadastro do motorista do sistema + /// + /// Dados do motoristas + /// Retorna um 200 ou 400 + [HttpDelete] + [SwaggerResponse((int)HttpStatusCode.OK, Description = "Retorna quando sucesso.", Type = typeof(ValidationResult))] + [SwaggerResponse((int)HttpStatusCode.BadRequest, Description = "Retorna quando ocorre alguma falha.", Type = typeof(ValidationResult))] + public async Task DeletarMotorista(DeletarMotoristaCommand motorista) + { + return CustomResponse(await _mediator.EnviarComando(motorista)); + } + + /// + /// Busca todos os motoristas cadastrados no sistema + /// + /// Retorna um 200 ou 400 ou 404 + [HttpGet] + [SwaggerResponse((int)HttpStatusCode.OK, Description = "Retorna quando sucesso.")] + [SwaggerResponse((int)HttpStatusCode.BadRequest, Description = "Retorna quando ocorre alguma falha.")] + [SwaggerResponse((int)HttpStatusCode.NotFound, Description = "Retorna quando ocorre alguma falha.")] + public async Task ListarMotorista() + { + var motoristas = await _motoristaQueries.ObterListaMotoristas(); + + return motoristas == null ? NotFound() : CustomResponse(motoristas); + } + } +} diff --git a/src/services/Wappa.Motorista.API/Data/Mappings/CarroMapping.cs b/src/services/Wappa.Motorista.API/Data/Mappings/CarroMapping.cs new file mode 100644 index 00000000..6054695c --- /dev/null +++ b/src/services/Wappa.Motorista.API/Data/Mappings/CarroMapping.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Wappa.Motoristas.API.Models; + +namespace Wappa.Motoristas.API.Data.Mappings +{ + public class CarroMapping : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(c => c.Id); + + builder.Property(c => c.Marca) + .IsRequired() + .HasColumnType("varchar(200)"); + + builder.Property(c => c.Modelo) + .IsRequired() + .HasColumnType("varchar(100)"); + + builder.Property(c => c.Placa) + .IsRequired() + .HasColumnType("varchar(20)"); + + + builder.ToTable("Carros"); + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Data/Mappings/EnderecoMapping.cs b/src/services/Wappa.Motorista.API/Data/Mappings/EnderecoMapping.cs new file mode 100644 index 00000000..a5cd1fbf --- /dev/null +++ b/src/services/Wappa.Motorista.API/Data/Mappings/EnderecoMapping.cs @@ -0,0 +1,49 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Wappa.Motoristas.API.Models; + +namespace Wappa.Motoristas.API.Data.Mappings +{ + public class EnderecoMapping : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(c => c.Id); + + builder.Property(c => c.Logradouro) + .IsRequired() + .HasColumnType("varchar(200)"); + + builder.Property(c => c.Numero) + .IsRequired() + .HasColumnType("varchar(50)"); + + builder.Property(c => c.Cep) + .IsRequired() + .HasColumnType("varchar(20)"); + + builder.Property(c => c.Complemento) + .HasColumnType("varchar(250)"); + + builder.Property(c => c.Bairro) + .IsRequired() + .HasColumnType("varchar(100)"); + + builder.Property(c => c.Cidade) + .IsRequired() + .HasColumnType("varchar(100)"); + + builder.Property(c => c.Estado) + .IsRequired() + .HasColumnType("varchar(50)"); + + builder.Property(c => c.Longitude) + .HasColumnType("decimal(18)"); + + builder.Property(c => c.Latitude) + .HasColumnType("decimal(18)"); + + builder.ToTable("Enderecos"); + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Data/Mappings/MotoristaMapping.cs b/src/services/Wappa.Motorista.API/Data/Mappings/MotoristaMapping.cs new file mode 100644 index 00000000..d85e31ad --- /dev/null +++ b/src/services/Wappa.Motorista.API/Data/Mappings/MotoristaMapping.cs @@ -0,0 +1,32 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Wappa.Motoristas.API.Models; + +namespace Wappa.Motoristas.API.Data.Mappings +{ + public class MotoristaMapping : IEntityTypeConfiguration + { + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(c => c.Id); + + builder.Property(c => c.Nome) + .IsRequired() + .HasColumnType("varchar(200)"); + + builder.Property(c => c.SobreNome) + .IsRequired() + .HasColumnType("varchar(200)"); + + // 1 : 1 => Motorista : Endereco + builder.HasOne(c => c.Endereco) + .WithOne(c => c.Motorista); + + // 1 : 1 => Motorista : Carro + builder.HasOne(c => c.Carro) + .WithOne(c => c.Motorista); + + builder.ToTable("Motoristas"); + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Data/MotoristaContext.cs b/src/services/Wappa.Motorista.API/Data/MotoristaContext.cs new file mode 100644 index 00000000..01d8b56d --- /dev/null +++ b/src/services/Wappa.Motorista.API/Data/MotoristaContext.cs @@ -0,0 +1,48 @@ +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Wappa.Motoristas.API.Models; +using Wappa.Core.Data; +using Wappa.Core.DomainObjects; +using FluentValidation.Results; + +namespace Wappa.Motoristas.API.Data +{ + public sealed class MotoristaContext : DbContext, IUnitOfWork + { + + public MotoristaContext(DbContextOptions options) + : base(options) + { + ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; + ChangeTracker.AutoDetectChangesEnabled = false; + } + + public DbSet Motorista { get; set; } + public DbSet Enderecos { get; set; } + public DbSet Carros { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Ignore(); + + foreach (var property in modelBuilder.Model.GetEntityTypes().SelectMany( + e => e.GetProperties().Where(p => p.ClrType == typeof(string)))) + property.SetColumnType("varchar(100)"); + + foreach (var relationship in modelBuilder.Model.GetEntityTypes() + .SelectMany(e => e.GetForeignKeys())) relationship.DeleteBehavior = DeleteBehavior.Cascade; + + modelBuilder.ApplyConfigurationsFromAssembly(typeof(MotoristaContext).Assembly); + + base.OnModelCreating(modelBuilder); + } + + public async Task Commit() + { + var sucesso = await base.SaveChangesAsync() > 0; + + return sucesso; + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Data/Repository/MotoristaRepository.cs b/src/services/Wappa.Motorista.API/Data/Repository/MotoristaRepository.cs new file mode 100644 index 00000000..d4d817e2 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Data/Repository/MotoristaRepository.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using Wappa.Core.Data; +using Wappa.Motoristas.API.Models; + +namespace Wappa.Motoristas.API.Data.Repository +{ + public class MotoristaRepository : IMotoristaRepository + { + private readonly MotoristaContext _context; + + public MotoristaRepository(MotoristaContext context) + { + _context = context; + } + + public IUnitOfWork UnitOfWork => _context; + public DbConnection ObterConexao() => _context.Database.GetDbConnection(); + + public async Task> ObterTodos() + { + return await _context.Motorista.AsNoTracking().ToListAsync(); + } + + public void Adicionar(Motorista motorista) + { + _context.Motorista.Add(motorista); + } + + + public void Atualizar(Motorista motorista) + { + _context.Motorista.Update(motorista); + } + + public void Deletar(Motorista motorista) + { + _context.Motorista.Remove(motorista); + } + + public Task ObterPorId(Guid id) + { + return _context.Motorista + .Include(d => d.Carro) + .Include(f=>f.Endereco) + .FirstOrDefaultAsync(f => f.Id == id); + } + + public void Dispose() + { + _context.Dispose(); + } + + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Dockerfile b/src/services/Wappa.Motorista.API/Dockerfile new file mode 100644 index 00000000..01792a49 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Dockerfile @@ -0,0 +1,23 @@ +#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/core/aspnet:3.1-buster-slim AS base +WORKDIR /app +EXPOSE 4001 +EXPOSE 5001 + +FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS build +WORKDIR /src +COPY ["src/services/Wappa.Motorista.API/Wappa.Motoristas.API.csproj", "src/services/Wappa.Motorista.API/"] +COPY ["src/building blocks/Wappa.Core/Wappa.Core.csproj", "src/building blocks/Wappa.Core/"] +RUN dotnet restore "src/services/Wappa.Motorista.API/Wappa.Motoristas.API.csproj" +COPY . . +WORKDIR "/src/src/services/Wappa.Motorista.API" +RUN dotnet build "Wappa.Motoristas.API.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Wappa.Motoristas.API.csproj" -c Release -o /app/publish + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Wappa.Motoristas.API.dll"] \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Migrations/20210309031025_Motorista.Designer.cs b/src/services/Wappa.Motorista.API/Migrations/20210309031025_Motorista.Designer.cs new file mode 100644 index 00000000..36459b05 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Migrations/20210309031025_Motorista.Designer.cs @@ -0,0 +1,136 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Wappa.Motoristas.API.Data; + +namespace Wappa.Motoristas.API.Migrations +{ + [DbContext(typeof(MotoristaContext))] + [Migration("20210309031025_Motorista")] + partial class Motorista + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Wappa.Motoristas.API.Models.Carro", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Marca") + .IsRequired() + .HasColumnType("varchar(200)"); + + b.Property("Modelo") + .IsRequired() + .HasColumnType("varchar(100)"); + + b.Property("MotoristaId") + .HasColumnType("uniqueidentifier"); + + b.Property("Placa") + .IsRequired() + .HasColumnType("varchar(20)"); + + b.HasKey("Id"); + + b.HasIndex("MotoristaId") + .IsUnique(); + + b.ToTable("Carros"); + }); + + modelBuilder.Entity("Wappa.Motoristas.API.Models.Endereco", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Bairro") + .IsRequired() + .HasColumnType("varchar(100)"); + + b.Property("Cep") + .IsRequired() + .HasColumnType("varchar(20)"); + + b.Property("Cidade") + .IsRequired() + .HasColumnType("varchar(100)"); + + b.Property("Complemento") + .HasColumnType("varchar(250)"); + + b.Property("Estado") + .IsRequired() + .HasColumnType("varchar(50)"); + + b.Property("Logradouro") + .IsRequired() + .HasColumnType("varchar(200)"); + + b.Property("MotoristaId") + .HasColumnType("uniqueidentifier"); + + b.Property("Numero") + .IsRequired() + .HasColumnType("varchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("MotoristaId") + .IsUnique(); + + b.ToTable("Enderecos"); + }); + + modelBuilder.Entity("Wappa.Motoristas.API.Models.Motorista", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("varchar(200)"); + + b.Property("SobreNome") + .IsRequired() + .HasColumnType("varchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Motoristas"); + }); + + modelBuilder.Entity("Wappa.Motoristas.API.Models.Carro", b => + { + b.HasOne("Wappa.Motoristas.API.Models.Motorista", "Motorista") + .WithOne("Carro") + .HasForeignKey("Wappa.Motoristas.API.Models.Carro", "MotoristaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Wappa.Motoristas.API.Models.Endereco", b => + { + b.HasOne("Wappa.Motoristas.API.Models.Motorista", "Motorista") + .WithOne("Endereco") + .HasForeignKey("Wappa.Motoristas.API.Models.Endereco", "MotoristaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/services/Wappa.Motorista.API/Migrations/20210309031025_Motorista.cs b/src/services/Wappa.Motorista.API/Migrations/20210309031025_Motorista.cs new file mode 100644 index 00000000..440db8b2 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Migrations/20210309031025_Motorista.cs @@ -0,0 +1,94 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Wappa.Motoristas.API.Migrations +{ + public partial class Motorista : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Motoristas", + columns: table => new + { + Id = table.Column(nullable: false), + Nome = table.Column(type: "varchar(200)", nullable: false), + SobreNome = table.Column(type: "varchar(200)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Motoristas", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Carros", + columns: table => new + { + Id = table.Column(nullable: false), + Marca = table.Column(type: "varchar(200)", nullable: false), + Modelo = table.Column(type: "varchar(100)", nullable: false), + Placa = table.Column(type: "varchar(20)", nullable: false), + MotoristaId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Carros", x => x.Id); + table.ForeignKey( + name: "FK_Carros_Motoristas_MotoristaId", + column: x => x.MotoristaId, + principalTable: "Motoristas", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Enderecos", + columns: table => new + { + Id = table.Column(nullable: false), + Logradouro = table.Column(type: "varchar(200)", nullable: false), + Numero = table.Column(type: "varchar(50)", nullable: false), + Complemento = table.Column(type: "varchar(250)", nullable: true), + Bairro = table.Column(type: "varchar(100)", nullable: false), + Cep = table.Column(type: "varchar(20)", nullable: false), + Cidade = table.Column(type: "varchar(100)", nullable: false), + Estado = table.Column(type: "varchar(50)", nullable: false), + MotoristaId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Enderecos", x => x.Id); + table.ForeignKey( + name: "FK_Enderecos_Motoristas_MotoristaId", + column: x => x.MotoristaId, + principalTable: "Motoristas", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Carros_MotoristaId", + table: "Carros", + column: "MotoristaId", + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Enderecos_MotoristaId", + table: "Enderecos", + column: "MotoristaId", + unique: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Carros"); + + migrationBuilder.DropTable( + name: "Enderecos"); + + migrationBuilder.DropTable( + name: "Motoristas"); + } + } +} diff --git a/src/services/Wappa.Motorista.API/Migrations/20210310071419_Coordenadas.Designer.cs b/src/services/Wappa.Motorista.API/Migrations/20210310071419_Coordenadas.Designer.cs new file mode 100644 index 00000000..8357b0ad --- /dev/null +++ b/src/services/Wappa.Motorista.API/Migrations/20210310071419_Coordenadas.Designer.cs @@ -0,0 +1,142 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Wappa.Motoristas.API.Data; + +namespace Wappa.Motoristas.API.Migrations +{ + [DbContext(typeof(MotoristaContext))] + [Migration("20210310071419_Coordenadas")] + partial class Coordenadas + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Wappa.Motoristas.API.Models.Carro", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Marca") + .IsRequired() + .HasColumnType("varchar(200)"); + + b.Property("Modelo") + .IsRequired() + .HasColumnType("varchar(100)"); + + b.Property("MotoristaId") + .HasColumnType("uniqueidentifier"); + + b.Property("Placa") + .IsRequired() + .HasColumnType("varchar(20)"); + + b.HasKey("Id"); + + b.HasIndex("MotoristaId") + .IsUnique(); + + b.ToTable("Carros"); + }); + + modelBuilder.Entity("Wappa.Motoristas.API.Models.Endereco", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Bairro") + .IsRequired() + .HasColumnType("varchar(100)"); + + b.Property("Cep") + .IsRequired() + .HasColumnType("varchar(20)"); + + b.Property("Cidade") + .IsRequired() + .HasColumnType("varchar(100)"); + + b.Property("Complemento") + .HasColumnType("varchar(250)"); + + b.Property("Estado") + .IsRequired() + .HasColumnType("varchar(50)"); + + b.Property("Latitude") + .HasColumnType("decimal(18)"); + + b.Property("Logradouro") + .IsRequired() + .HasColumnType("varchar(200)"); + + b.Property("Longitute") + .HasColumnType("decimal(18)"); + + b.Property("MotoristaId") + .HasColumnType("uniqueidentifier"); + + b.Property("Numero") + .IsRequired() + .HasColumnType("varchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("MotoristaId") + .IsUnique(); + + b.ToTable("Enderecos"); + }); + + modelBuilder.Entity("Wappa.Motoristas.API.Models.Motorista", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("varchar(200)"); + + b.Property("SobreNome") + .IsRequired() + .HasColumnType("varchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Motoristas"); + }); + + modelBuilder.Entity("Wappa.Motoristas.API.Models.Carro", b => + { + b.HasOne("Wappa.Motoristas.API.Models.Motorista", "Motorista") + .WithOne("Carro") + .HasForeignKey("Wappa.Motoristas.API.Models.Carro", "MotoristaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Wappa.Motoristas.API.Models.Endereco", b => + { + b.HasOne("Wappa.Motoristas.API.Models.Motorista", "Motorista") + .WithOne("Endereco") + .HasForeignKey("Wappa.Motoristas.API.Models.Endereco", "MotoristaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/services/Wappa.Motorista.API/Migrations/20210310071419_Coordenadas.cs b/src/services/Wappa.Motorista.API/Migrations/20210310071419_Coordenadas.cs new file mode 100644 index 00000000..52770ae0 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Migrations/20210310071419_Coordenadas.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Wappa.Motoristas.API.Migrations +{ + public partial class Coordenadas : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "Latitude", + table: "Enderecos", + type: "decimal(18,10)", + nullable: false, + defaultValue: 0m); + + migrationBuilder.AddColumn( + name: "Longitude", + table: "Enderecos", + type: "decimal(18,10)", + nullable: false, + defaultValue: 0m); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "Latitude", + table: "Enderecos"); + + migrationBuilder.DropColumn( + name: "Longitude", + table: "Enderecos"); + } + } +} diff --git a/src/services/Wappa.Motorista.API/Migrations/MotoristaContextModelSnapshot.cs b/src/services/Wappa.Motorista.API/Migrations/MotoristaContextModelSnapshot.cs new file mode 100644 index 00000000..7644ec5d --- /dev/null +++ b/src/services/Wappa.Motorista.API/Migrations/MotoristaContextModelSnapshot.cs @@ -0,0 +1,140 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Wappa.Motoristas.API.Data; + +namespace Wappa.Motoristas.API.Migrations +{ + [DbContext(typeof(MotoristaContext))] + partial class MotoristaContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.3") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Wappa.Motoristas.API.Models.Carro", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Marca") + .IsRequired() + .HasColumnType("varchar(200)"); + + b.Property("Modelo") + .IsRequired() + .HasColumnType("varchar(100)"); + + b.Property("MotoristaId") + .HasColumnType("uniqueidentifier"); + + b.Property("Placa") + .IsRequired() + .HasColumnType("varchar(20)"); + + b.HasKey("Id"); + + b.HasIndex("MotoristaId") + .IsUnique(); + + b.ToTable("Carros"); + }); + + modelBuilder.Entity("Wappa.Motoristas.API.Models.Endereco", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Bairro") + .IsRequired() + .HasColumnType("varchar(100)"); + + b.Property("Cep") + .IsRequired() + .HasColumnType("varchar(20)"); + + b.Property("Cidade") + .IsRequired() + .HasColumnType("varchar(100)"); + + b.Property("Complemento") + .HasColumnType("varchar(250)"); + + b.Property("Estado") + .IsRequired() + .HasColumnType("varchar(50)"); + + b.Property("Latitude") + .HasColumnType("decimal(18,10)"); + + b.Property("Logradouro") + .IsRequired() + .HasColumnType("varchar(200)"); + + b.Property("Longitude") + .HasColumnType("decimal(18,10)"); + + b.Property("MotoristaId") + .HasColumnType("uniqueidentifier"); + + b.Property("Numero") + .IsRequired() + .HasColumnType("varchar(50)"); + + b.HasKey("Id"); + + b.HasIndex("MotoristaId") + .IsUnique(); + + b.ToTable("Enderecos"); + }); + + modelBuilder.Entity("Wappa.Motoristas.API.Models.Motorista", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Nome") + .IsRequired() + .HasColumnType("varchar(200)"); + + b.Property("SobreNome") + .IsRequired() + .HasColumnType("varchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Motoristas"); + }); + + modelBuilder.Entity("Wappa.Motoristas.API.Models.Carro", b => + { + b.HasOne("Wappa.Motoristas.API.Models.Motorista", "Motorista") + .WithOne("Carro") + .HasForeignKey("Wappa.Motoristas.API.Models.Carro", "MotoristaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Wappa.Motoristas.API.Models.Endereco", b => + { + b.HasOne("Wappa.Motoristas.API.Models.Motorista", "Motorista") + .WithOne("Endereco") + .HasForeignKey("Wappa.Motoristas.API.Models.Endereco", "MotoristaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/services/Wappa.Motorista.API/Models/Carro.cs b/src/services/Wappa.Motorista.API/Models/Carro.cs new file mode 100644 index 00000000..5df38728 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Models/Carro.cs @@ -0,0 +1,24 @@ +using Wappa.Core.DomainObjects; +using System; + +namespace Wappa.Motoristas.API.Models +{ + public class Carro: Entity + { + public string Marca { get; set; } + public string Modelo { get; set; } + public string Placa { get; set; } + + public Guid MotoristaId { get; set; } + + // EF Relation + public Motorista Motorista { get; protected set; } + + public Carro(string marca, string modelo, string placa) + { + Marca = marca; + Modelo = modelo; + Placa = placa; + } + } +} diff --git a/src/services/Wappa.Motorista.API/Models/Endereco.cs b/src/services/Wappa.Motorista.API/Models/Endereco.cs new file mode 100644 index 00000000..22798946 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Models/Endereco.cs @@ -0,0 +1,35 @@ +using Wappa.Core.DomainObjects; +using System; + +namespace Wappa.Motoristas.API.Models +{ + public class Endereco: Entity + { + public string Logradouro { get; set; } + public string Numero { get; set; } + public string Complemento { get; set; } + public string Bairro { get; set; } + public string Cep { get; set; } + public string Cidade { get; set; } + public string Estado { get; set; } + public Guid MotoristaId { get; set; } + public decimal Longitude { get; set; } + public decimal Latitude{ get; set; } + + + public Motorista Motorista { get; protected set; } + + public Endereco(){} + + public Endereco(string logradouro, string numero, string complemento, string bairro, string cep, string cidade, string estado) + { + Logradouro = logradouro; + Numero = numero; + Complemento = complemento; + Bairro = bairro; + Cep = cep; + Cidade = cidade; + Estado = estado; + } + } +} diff --git a/src/services/Wappa.Motorista.API/Models/IMotoristaRepository.cs b/src/services/Wappa.Motorista.API/Models/IMotoristaRepository.cs new file mode 100644 index 00000000..812fec77 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Models/IMotoristaRepository.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Data.Common; +using System.Threading.Tasks; +using Wappa.Core.Data; + +namespace Wappa.Motoristas.API.Models +{ + public interface IMotoristaRepository : IRepository + { + void Adicionar(Motorista motorista); + void Atualizar(Motorista motorista); + void Deletar(Motorista motorista); + + Task ObterPorId(Guid id); + Task> ObterTodos(); + + DbConnection ObterConexao(); + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Models/Motorista.cs b/src/services/Wappa.Motorista.API/Models/Motorista.cs new file mode 100644 index 00000000..502894ab --- /dev/null +++ b/src/services/Wappa.Motorista.API/Models/Motorista.cs @@ -0,0 +1,22 @@ +using Wappa.Core.DomainObjects; +using System; +using FluentValidation; + +namespace Wappa.Motoristas.API.Models +{ + public class Motorista : Entity, IAggregateRoot + { + public string Nome { get; set; } + public string SobreNome { get; set; } + public Carro Carro { get; set; } + public Endereco Endereco { get; set; } + + protected Motorista() { } + + public Motorista(string nome, string sobreNome) + { + Nome = nome; + SobreNome = sobreNome; + } + } +} diff --git a/src/services/Wappa.Motorista.API/Program.cs b/src/services/Wappa.Motorista.API/Program.cs new file mode 100644 index 00000000..e31df427 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Program.cs @@ -0,0 +1,26 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Wappa.Motoristas.API +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} diff --git a/src/services/Wappa.Motorista.API/Properties/launchSettings.json b/src/services/Wappa.Motorista.API/Properties/launchSettings.json new file mode 100644 index 00000000..391048f5 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Properties/launchSettings.json @@ -0,0 +1,56 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:52004", + "sslPort": 44317 + } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "profiles": { + "IIS Development": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Staging": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Staging" + } + }, + "IIS Production": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Production" + } + }, + "SelfHosting - Development": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:4001" + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "publishAllPorts": true, + "useSSL": true + } + } +} \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/Startup.cs b/src/services/Wappa.Motorista.API/Startup.cs new file mode 100644 index 00000000..4a802e90 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Startup.cs @@ -0,0 +1,52 @@ +using MediatR; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Wappa.Motoristas.API.Configuration; +using Wappa.Motoristas.API.Data; + +namespace Wappa.Motoristas.API +{ + public class Startup + { + public IConfiguration Configuration { get; } + + public Startup(IHostEnvironment hostEnvironment) + { + var builder = new ConfigurationBuilder() + .SetBasePath(hostEnvironment.ContentRootPath) + .AddJsonFile("appsettings.json", true, true) + .AddJsonFile($"appsettings.{hostEnvironment.EnvironmentName}.json", true, true) + .AddEnvironmentVariables(); + + if (hostEnvironment.IsDevelopment()) + { + builder.AddUserSecrets(); + } + + Configuration = builder.Build(); + } + + public void ConfigureServices(IServiceCollection services) + { + services.AddApiConfiguration(Configuration); + + services.AddSwaggerConfiguration(); + + services.AddMediatR(typeof(Startup)); + + services.RegisterServices(); + + services.AddMessageBusConfiguration(Configuration); + } + + public void Configure(IApplicationBuilder app, IWebHostEnvironment env, MotoristaContext motoristaContext) + { + app.UseSwaggerConfiguration(); + + app.UseApiConfiguration(env, motoristaContext); + } + } +} diff --git a/src/services/Wappa.Motorista.API/Wappa.Motoristas.API.csproj b/src/services/Wappa.Motorista.API/Wappa.Motoristas.API.csproj new file mode 100644 index 00000000..069a7c8d --- /dev/null +++ b/src/services/Wappa.Motorista.API/Wappa.Motoristas.API.csproj @@ -0,0 +1,50 @@ + + + + netcoreapp3.1 + Linux + ..\..\.. + 0caf6535-96f2-4d67-a416-3089d65205c3 + ..\..\..\docker-compose.dcproj + + + + bin\Debug\netcoreapp3.1\Wappa.Motoristas.API.xml + bin\Debug\netcoreapp3.1\ + 1701;1702;1591 + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + + + + + + + diff --git a/src/services/Wappa.Motorista.API/Wappa.Motoristas.API.csproj.user b/src/services/Wappa.Motorista.API/Wappa.Motoristas.API.csproj.user new file mode 100644 index 00000000..195b56e1 --- /dev/null +++ b/src/services/Wappa.Motorista.API/Wappa.Motoristas.API.csproj.user @@ -0,0 +1,9 @@ + + + + IIS Development + + + ProjectDebugger + + \ No newline at end of file diff --git a/src/services/Wappa.Motorista.API/appsettings.Development.json b/src/services/Wappa.Motorista.API/appsettings.Development.json new file mode 100644 index 00000000..a27611d5 --- /dev/null +++ b/src/services/Wappa.Motorista.API/appsettings.Development.json @@ -0,0 +1,22 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AppSettings": { + "Secret": "MEUSEGREDOSUPERSECRETO", + "ExpiracaoHoras": 2, + "Emissor": "MeuSistema", + "ValidoEm": "https://localhost" + }, + "ConnectionStrings": { + "Container": "Server=banco_sql,1433;Database=WappaDev; User=sa; Password=yourStrong(!)Password;Trusted_Connection=False;MultipleActiveResultSets=true", + "Localhost": "Server=localhost,1435;Database=WappaDev; User=sa; Password=yourStrong(!)Password;Trusted_Connection=False;MultipleActiveResultSets=true" + }, + "MessageQueueConnection": { + "MessageBus": "host=rabbit:5672;publisherConfirms=true;timeout=10" + } +} diff --git a/src/services/Wappa.Motorista.API/appsettings.json b/src/services/Wappa.Motorista.API/appsettings.json new file mode 100644 index 00000000..d9d9a9bf --- /dev/null +++ b/src/services/Wappa.Motorista.API/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" +}