Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Client.Wasm/Components/StudentCard.razor
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
</CardHeader>
<CardBody>
<UnorderedList Unstyled>
<UnorderedListItem>Номер <Strong>№X "Название лабораторной"</Strong></UnorderedListItem>
<UnorderedListItem>Вариант <Strong>№Х "Название варианта"</Strong></UnorderedListItem>
<UnorderedListItem>Выполнена <Strong>Фамилией Именем 65ХХ</Strong> </UnorderedListItem>
<UnorderedListItem><Link To="https://puginarug.com/">Ссылка на форк</Link></UnorderedListItem>
<UnorderedListItem>Номер <Strong>№1 "Кэширование"</Strong></UnorderedListItem>
<UnorderedListItem>Вариант <Strong>№2 "Кредитная заявка"</Strong></UnorderedListItem>
<UnorderedListItem>Выполнил <Strong>Сукач Данил 6511</Strong> </UnorderedListItem>
<UnorderedListItem><Link To="https://github.com/DanilSukach/cloud-development.git">Ссылка на форк</Link></UnorderedListItem>
</UnorderedList>
</CardBody>
</Card>
2 changes: 1 addition & 1 deletion Client.Wasm/wwwroot/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
}
},
"AllowedHosts": "*",
"BaseAddress": "https://localhost:7170/land-plot"
"BaseAddress": "https://localhost:7084/api/Credit"
}
40 changes: 38 additions & 2 deletions CloudDevelopment.sln
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.14.36811.4
# Visual Studio Version 18
VisualStudioVersion = 18.3.11505.172 d18.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client.Wasm", "Client.Wasm\Client.Wasm.csproj", "{AE7EEA74-2FE0-136F-D797-854FD87E022A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreditApp.AppHost", "CreditApp\CreditApp.AppHost\CreditApp.AppHost.csproj", "{595C6305-ACA3-4E87-8CBF-27A4C92BAE97}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreditApp.ServiceDefaults", "CreditApp\CreditApp.ServiceDefaults\CreditApp.ServiceDefaults.csproj", "{A7B14B5D-B738-B77E-404F-CF5182E30A41}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreditApp.Api", "CreditApp.Api\CreditApp.Api.csproj", "{E7D4CA8B-53EA-9676-D96D-BE2F0CB11054}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreditApp.Domain", "CreditApp.Domain\CreditApp.Domain.csproj", "{2B736CD0-1260-4F6F-854F-5F35E0CBC260}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreditApp.Application", "CreditApp.Application\CreditApp.Application.csproj", "{69FCFAEE-907C-4365-897A-EF120A644131}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CreditApp.Infrastructure", "CreditApp.Infrastructure\CreditApp.Infrastructure.csproj", "{C5A26B57-58ED-45E9-9371-AAF64F30C3A8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -15,6 +27,30 @@ Global
{AE7EEA74-2FE0-136F-D797-854FD87E022A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE7EEA74-2FE0-136F-D797-854FD87E022A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE7EEA74-2FE0-136F-D797-854FD87E022A}.Release|Any CPU.Build.0 = Release|Any CPU
{595C6305-ACA3-4E87-8CBF-27A4C92BAE97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{595C6305-ACA3-4E87-8CBF-27A4C92BAE97}.Debug|Any CPU.Build.0 = Debug|Any CPU
{595C6305-ACA3-4E87-8CBF-27A4C92BAE97}.Release|Any CPU.ActiveCfg = Release|Any CPU
{595C6305-ACA3-4E87-8CBF-27A4C92BAE97}.Release|Any CPU.Build.0 = Release|Any CPU
{A7B14B5D-B738-B77E-404F-CF5182E30A41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7B14B5D-B738-B77E-404F-CF5182E30A41}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7B14B5D-B738-B77E-404F-CF5182E30A41}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7B14B5D-B738-B77E-404F-CF5182E30A41}.Release|Any CPU.Build.0 = Release|Any CPU
{E7D4CA8B-53EA-9676-D96D-BE2F0CB11054}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E7D4CA8B-53EA-9676-D96D-BE2F0CB11054}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E7D4CA8B-53EA-9676-D96D-BE2F0CB11054}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E7D4CA8B-53EA-9676-D96D-BE2F0CB11054}.Release|Any CPU.Build.0 = Release|Any CPU
{2B736CD0-1260-4F6F-854F-5F35E0CBC260}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2B736CD0-1260-4F6F-854F-5F35E0CBC260}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B736CD0-1260-4F6F-854F-5F35E0CBC260}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B736CD0-1260-4F6F-854F-5F35E0CBC260}.Release|Any CPU.Build.0 = Release|Any CPU
{69FCFAEE-907C-4365-897A-EF120A644131}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{69FCFAEE-907C-4365-897A-EF120A644131}.Debug|Any CPU.Build.0 = Debug|Any CPU
{69FCFAEE-907C-4365-897A-EF120A644131}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69FCFAEE-907C-4365-897A-EF120A644131}.Release|Any CPU.Build.0 = Release|Any CPU
{C5A26B57-58ED-45E9-9371-AAF64F30C3A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C5A26B57-58ED-45E9-9371-AAF64F30C3A8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5A26B57-58ED-45E9-9371-AAF64F30C3A8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C5A26B57-58ED-45E9-9371-AAF64F30C3A8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
36 changes: 36 additions & 0 deletions CreditApp.Api/Controllers/CreditController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using CreditApp.Application.Interfaces;
using Microsoft.AspNetCore.Mvc;

namespace CreditApp.Api.Controllers;

/// <summary>
/// Контроллер для работы с кредитными заявками через HTTP API.
/// Реализует конечную точку получения заявки по идентификатору.
/// <param name="creditService">Сервис для получения данных кредитных заявок.</param>
/// <param name="logger">Логгер для записи событий и ошибок.</param>
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class CreditController(
ICreditService creditService,
ILogger<CreditController> logger
) : ControllerBase
{
/// <summary>
/// Получает кредитную заявку по идентификатору.
/// </summary>
/// <param name="id">Идентификатор запрашиваемой заявки (передаётся в строке запроса).</param>
/// <param name="ct">Токен отмены для асинхронной операции.</param>
/// <returns>HTTP 200 с объектом заявки при успешном получении.</returns>
[HttpGet]
public async Task<IActionResult> Get([FromQuery] int id, CancellationToken ct)
{
logger.LogInformation("Request for credit {CreditId} started", id);

var result = await creditService.GetAsync(id, ct);

logger.LogInformation("Request for credit {CreditId} completed", id);

return Ok(result);
}
}
24 changes: 24 additions & 0 deletions CreditApp.Api/CreditApp.Api.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Aspire.StackExchange.Redis" Version="13.1.1" />
<PackageReference Include="Aspire.StackExchange.Redis.DistributedCaching" Version="13.1.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.1.3" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CreditApp.Application\CreditApp.Application.csproj" />
<ProjectReference Include="..\CreditApp.Domain\CreditApp.Domain.csproj" />
<ProjectReference Include="..\CreditApp.Infrastructure\CreditApp.Infrastructure.csproj" />
<ProjectReference Include="..\CreditApp\CreditApp.ServiceDefaults\CreditApp.ServiceDefaults.csproj" />
</ItemGroup>

</Project>
51 changes: 51 additions & 0 deletions CreditApp.Api/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using CreditApp.Application.Interfaces;
using CreditApp.Application.Services;
using CreditApp.Infrastructure.Generators;
using Microsoft.OpenApi;
using System.Reflection;

var builder = WebApplication.CreateBuilder(args);

builder.AddRedisDistributedCache("credit-cache");

var centralBankRate = builder.Configuration.GetValue<double>("CreditGenerator:CentralBankRate", 16.0);

builder.Services.AddSingleton<ICreditApplicationGenerator>(
new CreditApplicationGenerator(centralBankRate));

builder.Services.AddScoped<ICreditService, CreditService>();

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
options.IncludeXmlComments(xmlPath);
});

builder.Services.AddCors(options =>
{
options.AddPolicy("DefaultCors",
policy => policy.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod());
});

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "V1");
c.RoutePrefix = string.Empty;
});
}

app.UseCors("DefaultCors");

app.MapControllers();

app.Run();
38 changes: 38 additions & 0 deletions CreditApp.Api/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:53917",
"sslPort": 44347
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5022",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7084;http://localhost:5022",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
8 changes: 8 additions & 0 deletions CreditApp.Api/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
16 changes: 16 additions & 0 deletions CreditApp.Api/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"redis": "localhost:6379"
}
,
"CreditGenerator": {
"CentralBankRate": 16.0
}
}
18 changes: 18 additions & 0 deletions CreditApp.Application/CreditApp.Application.csproj
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="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CreditApp.Domain\CreditApp.Domain.csproj" />
</ItemGroup>

</Project>
18 changes: 18 additions & 0 deletions CreditApp.Application/Interfaces/ICreditApplicationGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using CreditApp.Domain.Entities;

namespace CreditApp.Application.Interfaces;

/// <summary>
/// Генерирует объекты заявок на кредит для тестирования, заполнения демонстрационных данных или инициализации.
/// Реализации должны создавать и возвращать готовый к использованию экземпляр <see cref="CreditApplication"/>.
/// </summary>
public interface ICreditApplicationGenerator
{
/// <summary>
/// Асинхронно генерирует заявку на кредит с указанным идентификатором.
/// </summary>
/// <param name="id">Идентификатор создаваемой заявки.</param>
/// <param name="ct">Токен отмены для асинхронной операции.</param>
/// <returns>Сгенерированный экземпляр <see cref="CreditApplication"/>.</returns>
public Task<CreditApplication> GenerateAsync(int id, CancellationToken ct);
}
19 changes: 19 additions & 0 deletions CreditApp.Application/Interfaces/ICreditService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using CreditApp.Domain.Entities;

namespace CreditApp.Application.Interfaces;

/// <summary>
/// Сервис для работы с объектами кредитных заявок.
/// Предоставляет операции получения и управления заявками в приложении.
/// </summary>
public interface ICreditService
{
/// <summary>
/// Асинхронно получает заявку на кредит по её идентификатору.
/// </summary>
/// <param name="id">Идентификатор заявки.</param>
/// <param name="ct">Токен отмены для асинхронной операции.</param>
/// <returns>Экземпляр <see cref="CreditApplication"/>, соответствующий запрошенному идентификатору.</returns>
public Task<CreditApplication> GetAsync(int id, CancellationToken ct);

}
43 changes: 43 additions & 0 deletions CreditApp.Application/Services/CreditService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.Text.Json;
using CreditApp.Application.Interfaces;
using CreditApp.Domain.Entities;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;

namespace CreditApp.Application.Services;

public class CreditService(IDistributedCache distributedCache,
ICreditApplicationGenerator generator,
ILogger<CreditService> logger)
: ICreditService
{
public async Task<CreditApplication> GetAsync(int id, CancellationToken ct)
{
var cacheKey = $"Credit_{id}";

var cached = await distributedCache.GetStringAsync(cacheKey, ct);

if (!string.IsNullOrEmpty(cached))
{
logger.LogInformation("Cache HIT {CacheKey}", cacheKey);
return JsonSerializer.Deserialize<CreditApplication>(cached)!;
}

logger.LogInformation("Cache MISS {CacheKey}", cacheKey);

var credit = await generator.GenerateAsync(id, ct);

var options = new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(10)
};

await distributedCache.SetStringAsync(
cacheKey,
JsonSerializer.Serialize(credit),
options,
ct);

return credit;
}
}
9 changes: 9 additions & 0 deletions CreditApp.Domain/CreditApp.Domain.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
Loading