-
Notifications
You must be signed in to change notification settings - Fork 76
Лаб. 4 6413 Верховая Анна #269
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
7732045
add domain models and enums
AnnaVerh04 d6d103d
Adding test data about a counterparty
AnnaVerh04 ee1641c
Adding test data about real estate and requests
AnnaVerh04 cdceb19
Writing tests
AnnaVerh04 b4726fa
adding comments
AnnaVerh04 9c21073
Adding results and descriptions
AnnaVerh04 b47b7a0
Making changes
AnnaVerh04 d7880b5
Correction of comments
AnnaVerh04 d16c29a
fix
AnnaVerh04 35beeff
Setting up an action
AnnaVerh04 878d4c6
new yml
AnnaVerh04 a906e7f
error search
AnnaVerh04 e183893
fix
AnnaVerh04 7482a48
new yml
AnnaVerh04 3282a22
start for next lab
AnnaVerh04 49f799c
DTO development
AnnaVerh04 b5659bc
Implementing repositories
AnnaVerh04 4d67fd5
Add AutoMapper configuration
AnnaVerh04 9116445
Creating controllers and a separate service for analytical queries
AnnaVerh04 dfc0930
developing tests and verifying the correctness of the results
AnnaVerh04 3aebced
Configuring projects and enabling MongoDB
AnnaVerh04 86510cf
Implementing MongoDB repositories
AnnaVerh04 0675297
Creating a service to fill the database with initial data
AnnaVerh04 5ec4c07
Support for two operating modes
AnnaVerh04 961ca89
Integration tests for MongoDB and verification of results
AnnaVerh04 cde8a6c
Error Correction
AnnaVerh04 c923bb8
Update Readme
AnnaVerh04 9b57a91
Correction of comments
AnnaVerh04 a4a2927
Making edits to the RealEstateDbContext constructor
AnnaVerh04 eaab0d9
lab4 done
AnnaVerh04 4726d10
fix
AnnaVerh04 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| name: .NET Tests Simple | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ "main" ] | ||
| pull_request: | ||
| branches: [ "main" ] | ||
|
|
||
| jobs: | ||
| test: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup .NET | ||
| uses: actions/setup-dotnet@v4 | ||
| with: | ||
| dotnet-version: 8.0.x | ||
|
|
||
| - name: Run tests directly | ||
| run: | | ||
| cd RealEstateAgency.tests | ||
| dotnet restore | ||
| dotnet build | ||
| dotnet test --verbosity normal |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| var builder = DistributedApplication.CreateBuilder(args); | ||
|
|
||
| // MongoDB | ||
| var mongodb = builder.AddMongoDB("mongodb") | ||
| .WithDataVolume("mongodb-data"); | ||
|
|
||
| var mongoDatabase = mongodb.AddDatabase("realestatedb"); | ||
|
|
||
| // NATS | ||
| var nats = builder.AddNats("nats") | ||
| .WithJetStream() | ||
| .WithDataVolume("nats-data"); | ||
|
|
||
| // WebApi | ||
| builder.AddProject<Projects.RealEstateAgency_WebApi>("webapi") | ||
| .WithReference(mongoDatabase) | ||
| .WithReference(nats) | ||
| .WaitFor(mongoDatabase) | ||
| .WaitFor(nats) | ||
| .WithExternalHttpEndpoints(); | ||
|
|
||
| // Generator | ||
| builder.AddProject<Projects.RealEstateAgency_Generator>("generator") | ||
| .WithReference(nats) | ||
| .WaitFor(nats) | ||
| .WaitFor(mongoDatabase); | ||
|
|
||
| builder.Build().Run(); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| { | ||
| "$schema": "https://json.schemastore.org/launchsettings.json", | ||
| "profiles": { | ||
| "https": { | ||
| "commandName": "Project", | ||
| "dotnetRunMessages": true, | ||
| "launchBrowser": true, | ||
| "applicationUrl": "https://localhost:17197;http://localhost:15247", | ||
| "environmentVariables": { | ||
| "ASPNETCORE_ENVIRONMENT": "Development", | ||
| "DOTNET_ENVIRONMENT": "Development", | ||
| "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21093", | ||
| "ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22056" | ||
| } | ||
| }, | ||
| "http": { | ||
| "commandName": "Project", | ||
| "dotnetRunMessages": true, | ||
| "launchBrowser": true, | ||
| "applicationUrl": "http://localhost:15247", | ||
| "environmentVariables": { | ||
| "ASPNETCORE_ENVIRONMENT": "Development", | ||
| "DOTNET_ENVIRONMENT": "Development", | ||
| "ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19133", | ||
| "ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20054" | ||
| } | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <Sdk Name="Aspire.AppHost.Sdk" Version="9.5.2" /> | ||
|
|
||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFramework>net8.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| <UserSecretsId>e80bf9ea-04bf-4190-adb9-7d9a244a2049</UserSecretsId> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="Aspire.Hosting.AppHost" Version="9.5.2" /> | ||
| <PackageReference Include="Aspire.Hosting.MongoDB" Version="9.5.2" /> | ||
| <PackageReference Include="Aspire.Hosting.Nats" Version="9.5.2" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\RealEstateAgency.Generator\RealEstateAgency.Generator.csproj" /> | ||
| <ProjectReference Include="..\RealEstateAgency.ServiceDefaults\RealEstateAgency.ServiceDefaults.csproj" IsAspireProjectResource="false" /> | ||
| <ProjectReference Include="..\RealEstateAgency.WebApi\RealEstateAgency.WebApi.csproj" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| { | ||
| "Logging": { | ||
| "LogLevel": { | ||
| "Default": "Information", | ||
| "Microsoft.AspNetCore": "Warning" | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| { | ||
| "Logging": { | ||
| "LogLevel": { | ||
| "Default": "Information", | ||
| "Microsoft.AspNetCore": "Warning", | ||
| "Aspire.Hosting.Dcp": "Warning" | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| using AutoMapper; | ||
| using RealEstateAgency.Contracts.Dto; | ||
| using RealEstateAgency.Domain.Models; | ||
|
|
||
| namespace RealEstateAgency.Application.Mapping; | ||
|
|
||
| /// <summary> | ||
| /// Профиль AutoMapper для маппинга сущностей и DTO | ||
| /// </summary> | ||
| public class MappingProfile : Profile | ||
| { | ||
| public MappingProfile() | ||
| { | ||
| CreateMap<Counterparty, CounterpartyDto>(); | ||
| CreateMap<CreateCounterpartyDto, Counterparty>() | ||
| .ForMember(dest => dest.Id, opt => opt.Ignore()); | ||
| CreateMap<UpdateCounterpartyDto, Counterparty>() | ||
| .ForMember(dest => dest.Id, opt => opt.Ignore()); | ||
|
|
||
| CreateMap<RealEstateProperty, RealEstatePropertyDto>(); | ||
| CreateMap<CreateRealEstatePropertyDto, RealEstateProperty>() | ||
| .ForMember(dest => dest.Id, opt => opt.Ignore()); | ||
| CreateMap<UpdateRealEstatePropertyDto, RealEstateProperty>() | ||
| .ForMember(dest => dest.Id, opt => opt.Ignore()); | ||
|
|
||
| CreateMap<Request, RequestDto>() | ||
| .ForMember(dest => dest.CounterpartyId, opt => opt.MapFrom(src => src.Counterparty.Id)) | ||
| .ForMember(dest => dest.PropertyId, opt => opt.MapFrom(src => src.Property.Id)); | ||
| } | ||
| } |
18 changes: 18 additions & 0 deletions
18
RealEstateAgency.Application/RealEstateAgency.Application.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFramework>net8.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="AutoMapper" Version="13.0.1" /> | ||
| <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.2" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\RealEstateAgency.Contracts\RealEstateAgency.Contracts.csproj" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
148 changes: 148 additions & 0 deletions
148
RealEstateAgency.Application/Services/AnalyticsService.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,148 @@ | ||
| using RealEstateAgency.Contracts.Dto; | ||
| using RealEstateAgency.Contracts.Interfaces; | ||
| using RealEstateAgency.Domain.Enums; | ||
| using RealEstateAgency.Domain.Interfaces; | ||
|
|
||
| namespace RealEstateAgency.Application.Services; | ||
|
|
||
| /// <summary> | ||
| /// Реализация сервиса аналитики | ||
| /// </summary> | ||
| public class AnalyticsService( | ||
| IRequestRepository requestRepository, | ||
| ICounterpartyRepository counterpartyRepository, | ||
| IRealEstatePropertyRepository propertyRepository) : IAnalyticsService | ||
| { | ||
|
|
||
| /// <summary> | ||
| /// Получить продавцов за указанный период | ||
| /// </summary> | ||
| public async Task<IEnumerable<string>> GetSellersInPeriodAsync(DateTime startDate, DateTime endDate) | ||
| { | ||
| var requests = (await requestRepository.GetAllAsync()).ToList(); | ||
| var counterparties = (await counterpartyRepository.GetAllAsync()).ToDictionary(c => c.Id); | ||
|
|
||
| return | ||
| [ | ||
| .. requests | ||
| .Where(r => r.Type == RequestType.Sale && | ||
| r.Date >= startDate && | ||
| r.Date <= endDate) | ||
| .Select(r => counterparties.TryGetValue(r.CounterpartyId, out var c) ? c.FullName : r.Counterparty?.FullName) | ||
| .Where(name => !string.IsNullOrEmpty(name)) | ||
| .Distinct() | ||
| .Order() | ||
| ]; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Получить топ-5 клиентов по количеству заявок | ||
| /// </summary> | ||
| public async Task<Top5ClientsResultDto> GetTop5ClientsByRequestCountAsync() | ||
| { | ||
| var requests = (await requestRepository.GetAllAsync()).ToList(); | ||
| var counterparties = (await counterpartyRepository.GetAllAsync()).ToDictionary(c => c.Id); | ||
|
|
||
| var topPurchaseClients = requests | ||
| .Where(r => r.Type == RequestType.Purchase) | ||
| .GroupBy(r => r.CounterpartyId) | ||
| .Select(g => new TopClientDto | ||
| { | ||
| FullName = counterparties.TryGetValue(g.Key, out var c) ? c.FullName : g.First().Counterparty?.FullName ?? "", | ||
| RequestCount = g.Count() | ||
| }) | ||
| .Where(x => !string.IsNullOrEmpty(x.FullName)) | ||
| .OrderByDescending(x => x.RequestCount) | ||
| .ThenBy(x => x.FullName) | ||
| .Take(5); | ||
|
|
||
| var topSaleClients = requests | ||
| .Where(r => r.Type == RequestType.Sale) | ||
| .GroupBy(r => r.CounterpartyId) | ||
| .Select(g => new TopClientDto | ||
| { | ||
| FullName = counterparties.TryGetValue(g.Key, out var c) ? c.FullName : g.First().Counterparty?.FullName ?? "", | ||
| RequestCount = g.Count() | ||
| }) | ||
| .Where(x => !string.IsNullOrEmpty(x.FullName)) | ||
| .OrderByDescending(x => x.RequestCount) | ||
| .ThenBy(x => x.FullName) | ||
| .Take(5); | ||
|
|
||
| return new Top5ClientsResultDto | ||
| { | ||
| TopPurchaseClients = [.. topPurchaseClients], | ||
| TopSaleClients = [.. topSaleClients] | ||
| }; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Получить статистику заявок по типам недвижимости | ||
| /// </summary> | ||
| public async Task<IEnumerable<PropertyTypeStatisticsDto>> GetRequestCountByPropertyTypeAsync() | ||
| { | ||
| var requests = (await requestRepository.GetAllAsync()).ToList(); | ||
| var properties = (await propertyRepository.GetAllAsync()).ToDictionary(p => p.Id); | ||
|
|
||
| return | ||
| [ | ||
| .. requests | ||
| .Select(r => new | ||
| { | ||
| PropertyType = properties.TryGetValue(r.PropertyId, out var p) ? p.Type : r.Property?.Type ?? default | ||
| }) | ||
| .GroupBy(x => x.PropertyType) | ||
| .Select(g => new PropertyTypeStatisticsDto | ||
| { | ||
| PropertyType = g.Key, | ||
| RequestCount = g.Count() | ||
| }) | ||
| .OrderBy(x => x.PropertyType) | ||
| ]; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Получить клиентов с минимальной суммой заявки | ||
| /// </summary> | ||
| public async Task<ClientWithMinAmountDto> GetClientsWithMinAmountAsync() | ||
| { | ||
| var requests = (await requestRepository.GetAllAsync()).ToList(); | ||
| var counterparties = (await counterpartyRepository.GetAllAsync()).ToDictionary(c => c.Id); | ||
|
|
||
| var minAmount = requests.Min(r => r.Amount); | ||
|
|
||
| var clients = requests | ||
| .Where(r => r.Amount == minAmount) | ||
| .Select(r => counterparties.TryGetValue(r.CounterpartyId, out var c) ? c.FullName : r.Counterparty?.FullName) | ||
| .Where(name => !string.IsNullOrEmpty(name)) | ||
| .Distinct() | ||
| .Order(); | ||
|
|
||
| return new ClientWithMinAmountDto | ||
| { | ||
| FullName = string.Join(", ", clients), | ||
| MinAmount = minAmount | ||
| }; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Получить клиентов, ищущих определённый тип недвижимости | ||
| /// </summary> | ||
| public async Task<IEnumerable<string>> GetClientsSeekingPropertyTypeAsync(PropertyType propertyType) | ||
| { | ||
| var requests = (await requestRepository.GetAllAsync()).ToList(); | ||
| var counterparties = (await counterpartyRepository.GetAllAsync()).ToDictionary(c => c.Id); | ||
| var properties = (await propertyRepository.GetAllAsync()).ToDictionary(p => p.Id); | ||
|
|
||
| return | ||
| [ | ||
| .. requests | ||
| .Where(r => r.Type == RequestType.Purchase && | ||
| (properties.TryGetValue(r.PropertyId, out var p) ? p.Type : r.Property?.Type ?? default) == propertyType) | ||
| .Select(r => counterparties.TryGetValue(r.CounterpartyId, out var c) ? c.FullName : r.Counterparty?.FullName) | ||
| .Where(name => !string.IsNullOrEmpty(name)) | ||
| .Distinct() | ||
| .Order() | ||
| ]; | ||
| } | ||
| } |
57 changes: 57 additions & 0 deletions
57
RealEstateAgency.Application/Services/CounterpartyService.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| using AutoMapper; | ||
| using RealEstateAgency.Contracts.Dto; | ||
| using RealEstateAgency.Contracts.Interfaces; | ||
| using RealEstateAgency.Domain.Interfaces; | ||
| using RealEstateAgency.Domain.Models; | ||
|
|
||
| namespace RealEstateAgency.Application.Services; | ||
|
|
||
| /// <summary> | ||
| /// Сервис контрагентов | ||
| /// </summary> | ||
| public class CounterpartyService(ICounterpartyRepository repository, IMapper mapper) : ICounterpartyService | ||
| { | ||
| /// <inheritdoc /> | ||
| public async Task<IEnumerable<CounterpartyDto>> GetAllAsync() | ||
| { | ||
| var counterparties = await repository.GetAllAsync(); | ||
| return mapper.Map<IEnumerable<CounterpartyDto>>(counterparties); | ||
| } | ||
|
|
||
| /// <inheritdoc /> | ||
| public async Task<CounterpartyDto?> GetByIdAsync(Guid id) | ||
| { | ||
| var counterparty = await repository.GetByIdAsync(id); | ||
| return counterparty == null ? null : mapper.Map<CounterpartyDto>(counterparty); | ||
| } | ||
|
|
||
| /// <inheritdoc /> | ||
| public async Task<CounterpartyDto> CreateAsync(CreateCounterpartyDto dto) | ||
| { | ||
| var counterparty = mapper.Map<Counterparty>(dto); | ||
| var created = await repository.AddAsync(counterparty); | ||
| return mapper.Map<CounterpartyDto>(created); | ||
| } | ||
|
|
||
| /// <inheritdoc /> | ||
| public async Task<CounterpartyDto?> UpdateAsync(Guid id, CreateCounterpartyDto dto) | ||
| { | ||
| var counterparty = mapper.Map<Counterparty>(dto); | ||
| var updated = await repository.UpdateAsync(id, counterparty); | ||
| return updated == null ? null : mapper.Map<CounterpartyDto>(updated); | ||
| } | ||
|
|
||
| /// <inheritdoc /> | ||
| public async Task<CounterpartyDto?> UpdateAsync(Guid id, UpdateCounterpartyDto dto) | ||
| { | ||
| var counterparty = mapper.Map<Counterparty>(dto); | ||
| var updated = await repository.UpdateAsync(id, counterparty); | ||
| return updated == null ? null : mapper.Map<CounterpartyDto>(updated); | ||
| } | ||
|
|
||
| /// <inheritdoc /> | ||
| public async Task<bool> DeleteAsync(Guid id) | ||
| { | ||
| return await repository.DeleteAsync(id); | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
В целом если вам нужны какие то адреса - можно просто через переменные окружения их пробрасывать:
Тут же вам было бы достаточно обратиться к ConnectionString с именем "nats"