Compare commits
33
Commits
399e366add
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e06e48657 | ||
|
|
5c9c6ab975 | ||
|
|
92f073e827 | ||
|
|
28bb69f4bc | ||
|
|
ae20033cfc | ||
|
|
f5e20c1fb2 | ||
|
|
420a86b92f | ||
|
|
15c29fc296 | ||
|
|
e41692a6e2 | ||
|
|
36e7c07a0d | ||
|
|
c824e26cc0 | ||
|
|
628fce5b50 | ||
|
|
3524e0d0af | ||
|
|
abe0ccb390 | ||
|
|
cc73945ae2 | ||
|
|
1e72d006c4 | ||
|
|
b24b9d697f | ||
|
|
a474313cec | ||
|
|
46f008aefa | ||
|
|
d6c1f63842 | ||
|
|
b7ba835689 | ||
|
|
3b2c0029a1 | ||
|
|
12c86f9937 | ||
|
|
9d3999f690 | ||
|
|
4c9e44e992 | ||
|
|
65b86e718d | ||
|
|
ae69d85fe2 | ||
|
|
ee40b38968 | ||
|
|
c98c96e408 | ||
|
|
3dd6577313 | ||
|
|
e3bebb120e | ||
|
|
fcf7714a4d | ||
|
|
c59c28c274 |
+38
@@ -0,0 +1,38 @@
|
||||
# Сборочные артефакты .NET
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Oo]ut/
|
||||
[Tt]est[Rr]esults/
|
||||
|
||||
# Пользовательские настройки Visual Studio
|
||||
*.user
|
||||
*.suo
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# Отладочные символы и бинарники
|
||||
*.pdb
|
||||
*.dll
|
||||
*.exe
|
||||
|
||||
# Логи
|
||||
*.log
|
||||
|
||||
# Скрипты (локальные)
|
||||
*.ps1
|
||||
|
||||
# Docker и окружение
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
docker-compose.override.yml
|
||||
|
||||
# Загруженные файлы (хранятся вне репозитория)
|
||||
uploads/
|
||||
|
||||
# IDE и ОС
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
.idea/
|
||||
.vscode/
|
||||
*.txt
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
# Build stage
|
||||
FROM mcr.microsoft.com/dotnet/sdk:10.0-preview AS build
|
||||
WORKDIR /src
|
||||
|
||||
# Copy solution and project files
|
||||
COPY ["Nashel.sln", "./"]
|
||||
COPY ["src/", "src/"]
|
||||
COPY ["tests/", "tests/"]
|
||||
|
||||
# Restore dependencies
|
||||
RUN dotnet restore "Nashel.sln"
|
||||
|
||||
# Publish the application
|
||||
WORKDIR "/src/src/Host"
|
||||
RUN dotnet publish "Nashel.Host.csproj" -c Release -o /app/publish /p:UseAppHost=false
|
||||
|
||||
# Final stage
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:10.0-preview AS final
|
||||
WORKDIR /app
|
||||
|
||||
# Устанавливаем зависимости Npgsql / Kerberos (нужны для PostgreSQL через Npgsql в .NET 10 preview)
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libgssapi-krb5-2 \
|
||||
krb5-user \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY --from=build /app/publish .
|
||||
# Copy wwwroot folder for static files (uploads)
|
||||
COPY src/Host/wwwroot /app/wwwroot
|
||||
ENV ASPNETCORE_URLS=http://+:8080
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["dotnet", "Nashel.Host.dll"]
|
||||
@@ -0,0 +1,27 @@
|
||||
FROM mcr.microsoft.com/dotnet/sdk:10.0-preview AS build
|
||||
WORKDIR /src
|
||||
|
||||
# Устанавливаем инструмент для миграций EF Core
|
||||
RUN dotnet tool install --global dotnet-ef --version 9.0.0
|
||||
ENV PATH="${PATH}:/root/.dotnet/tools"
|
||||
|
||||
# Копируем решение и проекты
|
||||
COPY ["Nashel.sln", "./"]
|
||||
COPY ["src/", "src/"]
|
||||
COPY ["tests/", "tests/"]
|
||||
|
||||
# Восстанавливаем зависимости
|
||||
RUN dotnet restore "Nashel.sln"
|
||||
|
||||
WORKDIR "/src/src/Host"
|
||||
ENTRYPOINT ["sh", "-c", "\
|
||||
echo 'Running migrations...' && \
|
||||
export PATH=\"$PATH:/root/.dotnet/tools\" && \
|
||||
dotnet ef database update --project ../Modules/Identity/Infrastructure --startup-project . --context IdentityDbContext && \
|
||||
dotnet ef database update --project ../Modules/Catalog/Infrastructure --startup-project . --context CatalogDbContext && \
|
||||
dotnet ef database update --project ../Modules/Collaboration/Infrastructure --startup-project . --context CollaborationDbContext && \
|
||||
dotnet ef database update --project ../Modules/Order/Infrastructure --startup-project . --context OrderDbContext && \
|
||||
dotnet ef database update --project ../Modules/Reputation/Infrastructure --startup-project . --context ReputationDbContext && \
|
||||
dotnet ef database update --project ../Modules/Geo/Infrastructure --startup-project . --context GeoDbContext && \
|
||||
echo 'All migrations completed successfully!'\
|
||||
"]
|
||||
-171
@@ -1,171 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildingBlocks", "BuildingBlocks", "{90298CBA-BD6F-3A0A-69D5-97CAD7B05E7E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.RF.BuildingBlocks", "src\BuildingBlocks\Nashel.RF.BuildingBlocks.csproj", "{CC3A5E56-8FC3-4C75-932A-ADE592F65515}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Host", "Host", "{981C2CF6-E5BB-602A-511C-234B538302B0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.RF.Host", "src\Host\Nashel.RF.Host.csproj", "{1F5F02BF-AD09-41E9-8130-1A939AE5012D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Identity", "Identity", "{0EC62A1A-9858-3A60-8A0C-FC9AACFA2EC7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.RF.Modules.Identity", "src\Modules\Identity\Nashel.RF.Modules.Identity.csproj", "{A53458FA-F0D6-4666-9D3E-3740665D2BC3}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Geo", "Geo", "{1F785BA6-BCCC-EB5A-C0AC-017D258EF3FD}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.RF.Modules.Geo", "src\Modules\Geo\Nashel.RF.Modules.Geo.csproj", "{946AE1A0-0055-4AEC-A4AC-CB8F9F871079}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Catalog", "Catalog", "{1E1EF545-4C18-AEE2-B997-7EF431518D3F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.RF.Modules.Catalog", "src\Modules\Catalog\Nashel.RF.Modules.Catalog.csproj", "{B209DA77-ABD4-49BE-9FE5-769BE44D8391}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Order", "Order", "{2C821288-5B9D-778E-74EE-053FE87F223E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.RF.Modules.Order", "src\Modules\Order\Nashel.RF.Modules.Order.csproj", "{27619C7F-D02E-4E15-ABFA-8FD59ED23D82}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Collaboration", "Collaboration", "{0D6C7A58-55D3-AEBB-0CCB-984ED0F92F71}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.RF.Modules.Collaboration", "src\Modules\Collaboration\Nashel.RF.Modules.Collaboration.csproj", "{D59D021C-A351-4E12-85A7-D7B4D31ED695}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Reputation", "Reputation", "{305CF822-D9CA-C4BE-7183-DD5447E36C7E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.RF.Modules.Reputation", "src\Modules\Reputation\Nashel.RF.Modules.Reputation.csproj", "{75715051-86CB-472A-BEFA-0E9AAA5EB24F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{CC3A5E56-8FC3-4C75-932A-ADE592F65515}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CC3A5E56-8FC3-4C75-932A-ADE592F65515}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CC3A5E56-8FC3-4C75-932A-ADE592F65515}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{CC3A5E56-8FC3-4C75-932A-ADE592F65515}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{CC3A5E56-8FC3-4C75-932A-ADE592F65515}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{CC3A5E56-8FC3-4C75-932A-ADE592F65515}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{CC3A5E56-8FC3-4C75-932A-ADE592F65515}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CC3A5E56-8FC3-4C75-932A-ADE592F65515}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CC3A5E56-8FC3-4C75-932A-ADE592F65515}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CC3A5E56-8FC3-4C75-932A-ADE592F65515}.Release|x64.Build.0 = Release|Any CPU
|
||||
{CC3A5E56-8FC3-4C75-932A-ADE592F65515}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{CC3A5E56-8FC3-4C75-932A-ADE592F65515}.Release|x86.Build.0 = Release|Any CPU
|
||||
{1F5F02BF-AD09-41E9-8130-1A939AE5012D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1F5F02BF-AD09-41E9-8130-1A939AE5012D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1F5F02BF-AD09-41E9-8130-1A939AE5012D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{1F5F02BF-AD09-41E9-8130-1A939AE5012D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{1F5F02BF-AD09-41E9-8130-1A939AE5012D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{1F5F02BF-AD09-41E9-8130-1A939AE5012D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{1F5F02BF-AD09-41E9-8130-1A939AE5012D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1F5F02BF-AD09-41E9-8130-1A939AE5012D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1F5F02BF-AD09-41E9-8130-1A939AE5012D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{1F5F02BF-AD09-41E9-8130-1A939AE5012D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{1F5F02BF-AD09-41E9-8130-1A939AE5012D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{1F5F02BF-AD09-41E9-8130-1A939AE5012D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A53458FA-F0D6-4666-9D3E-3740665D2BC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A53458FA-F0D6-4666-9D3E-3740665D2BC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A53458FA-F0D6-4666-9D3E-3740665D2BC3}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A53458FA-F0D6-4666-9D3E-3740665D2BC3}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A53458FA-F0D6-4666-9D3E-3740665D2BC3}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A53458FA-F0D6-4666-9D3E-3740665D2BC3}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A53458FA-F0D6-4666-9D3E-3740665D2BC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A53458FA-F0D6-4666-9D3E-3740665D2BC3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A53458FA-F0D6-4666-9D3E-3740665D2BC3}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A53458FA-F0D6-4666-9D3E-3740665D2BC3}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A53458FA-F0D6-4666-9D3E-3740665D2BC3}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A53458FA-F0D6-4666-9D3E-3740665D2BC3}.Release|x86.Build.0 = Release|Any CPU
|
||||
{946AE1A0-0055-4AEC-A4AC-CB8F9F871079}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{946AE1A0-0055-4AEC-A4AC-CB8F9F871079}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{946AE1A0-0055-4AEC-A4AC-CB8F9F871079}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{946AE1A0-0055-4AEC-A4AC-CB8F9F871079}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{946AE1A0-0055-4AEC-A4AC-CB8F9F871079}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{946AE1A0-0055-4AEC-A4AC-CB8F9F871079}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{946AE1A0-0055-4AEC-A4AC-CB8F9F871079}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{946AE1A0-0055-4AEC-A4AC-CB8F9F871079}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{946AE1A0-0055-4AEC-A4AC-CB8F9F871079}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{946AE1A0-0055-4AEC-A4AC-CB8F9F871079}.Release|x64.Build.0 = Release|Any CPU
|
||||
{946AE1A0-0055-4AEC-A4AC-CB8F9F871079}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{946AE1A0-0055-4AEC-A4AC-CB8F9F871079}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B209DA77-ABD4-49BE-9FE5-769BE44D8391}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B209DA77-ABD4-49BE-9FE5-769BE44D8391}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B209DA77-ABD4-49BE-9FE5-769BE44D8391}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B209DA77-ABD4-49BE-9FE5-769BE44D8391}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B209DA77-ABD4-49BE-9FE5-769BE44D8391}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B209DA77-ABD4-49BE-9FE5-769BE44D8391}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B209DA77-ABD4-49BE-9FE5-769BE44D8391}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B209DA77-ABD4-49BE-9FE5-769BE44D8391}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B209DA77-ABD4-49BE-9FE5-769BE44D8391}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B209DA77-ABD4-49BE-9FE5-769BE44D8391}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B209DA77-ABD4-49BE-9FE5-769BE44D8391}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B209DA77-ABD4-49BE-9FE5-769BE44D8391}.Release|x86.Build.0 = Release|Any CPU
|
||||
{27619C7F-D02E-4E15-ABFA-8FD59ED23D82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{27619C7F-D02E-4E15-ABFA-8FD59ED23D82}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{27619C7F-D02E-4E15-ABFA-8FD59ED23D82}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{27619C7F-D02E-4E15-ABFA-8FD59ED23D82}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{27619C7F-D02E-4E15-ABFA-8FD59ED23D82}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{27619C7F-D02E-4E15-ABFA-8FD59ED23D82}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{27619C7F-D02E-4E15-ABFA-8FD59ED23D82}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{27619C7F-D02E-4E15-ABFA-8FD59ED23D82}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{27619C7F-D02E-4E15-ABFA-8FD59ED23D82}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{27619C7F-D02E-4E15-ABFA-8FD59ED23D82}.Release|x64.Build.0 = Release|Any CPU
|
||||
{27619C7F-D02E-4E15-ABFA-8FD59ED23D82}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{27619C7F-D02E-4E15-ABFA-8FD59ED23D82}.Release|x86.Build.0 = Release|Any CPU
|
||||
{D59D021C-A351-4E12-85A7-D7B4D31ED695}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D59D021C-A351-4E12-85A7-D7B4D31ED695}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D59D021C-A351-4E12-85A7-D7B4D31ED695}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D59D021C-A351-4E12-85A7-D7B4D31ED695}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D59D021C-A351-4E12-85A7-D7B4D31ED695}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D59D021C-A351-4E12-85A7-D7B4D31ED695}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D59D021C-A351-4E12-85A7-D7B4D31ED695}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D59D021C-A351-4E12-85A7-D7B4D31ED695}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D59D021C-A351-4E12-85A7-D7B4D31ED695}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D59D021C-A351-4E12-85A7-D7B4D31ED695}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D59D021C-A351-4E12-85A7-D7B4D31ED695}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D59D021C-A351-4E12-85A7-D7B4D31ED695}.Release|x86.Build.0 = Release|Any CPU
|
||||
{75715051-86CB-472A-BEFA-0E9AAA5EB24F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{75715051-86CB-472A-BEFA-0E9AAA5EB24F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{75715051-86CB-472A-BEFA-0E9AAA5EB24F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{75715051-86CB-472A-BEFA-0E9AAA5EB24F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{75715051-86CB-472A-BEFA-0E9AAA5EB24F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{75715051-86CB-472A-BEFA-0E9AAA5EB24F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{75715051-86CB-472A-BEFA-0E9AAA5EB24F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{75715051-86CB-472A-BEFA-0E9AAA5EB24F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{75715051-86CB-472A-BEFA-0E9AAA5EB24F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{75715051-86CB-472A-BEFA-0E9AAA5EB24F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{75715051-86CB-472A-BEFA-0E9AAA5EB24F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{75715051-86CB-472A-BEFA-0E9AAA5EB24F}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{90298CBA-BD6F-3A0A-69D5-97CAD7B05E7E} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
||||
{CC3A5E56-8FC3-4C75-932A-ADE592F65515} = {90298CBA-BD6F-3A0A-69D5-97CAD7B05E7E}
|
||||
{981C2CF6-E5BB-602A-511C-234B538302B0} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
||||
{1F5F02BF-AD09-41E9-8130-1A939AE5012D} = {981C2CF6-E5BB-602A-511C-234B538302B0}
|
||||
{EC447DCF-ABFA-6E24-52A5-D7FD48A5C558} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
||||
{0EC62A1A-9858-3A60-8A0C-FC9AACFA2EC7} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{A53458FA-F0D6-4666-9D3E-3740665D2BC3} = {0EC62A1A-9858-3A60-8A0C-FC9AACFA2EC7}
|
||||
{1F785BA6-BCCC-EB5A-C0AC-017D258EF3FD} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{946AE1A0-0055-4AEC-A4AC-CB8F9F871079} = {1F785BA6-BCCC-EB5A-C0AC-017D258EF3FD}
|
||||
{1E1EF545-4C18-AEE2-B997-7EF431518D3F} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{B209DA77-ABD4-49BE-9FE5-769BE44D8391} = {1E1EF545-4C18-AEE2-B997-7EF431518D3F}
|
||||
{2C821288-5B9D-778E-74EE-053FE87F223E} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{27619C7F-D02E-4E15-ABFA-8FD59ED23D82} = {2C821288-5B9D-778E-74EE-053FE87F223E}
|
||||
{0D6C7A58-55D3-AEBB-0CCB-984ED0F92F71} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{D59D021C-A351-4E12-85A7-D7B4D31ED695} = {0D6C7A58-55D3-AEBB-0CCB-984ED0F92F71}
|
||||
{305CF822-D9CA-C4BE-7183-DD5447E36C7E} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{75715051-86CB-472A-BEFA-0E9AAA5EB24F} = {305CF822-D9CA-C4BE-7183-DD5447E36C7E}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
+564
@@ -0,0 +1,564 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildingBlocks", "BuildingBlocks", "{7266C4A9-E384-DC00-0EB6-47F6002CFBA7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.BuildingBlocks", "src\BuildingBlocks\Nashel.BuildingBlocks.csproj", "{18F5CA61-2478-40DB-A8C3-3CA10BA66F4A}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Host", "Host", "{7226ABEA-787E-1D09-10EA-A2ECF996D6A6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Host", "src\Host\Nashel.Host.csproj", "{4D89232D-7F93-4DA5-9B00-E25A355561EF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Catalog.Infrastructure", "src\Modules\Catalog\Infrastructure\Nashel.Modules.Catalog.Infrastructure.csproj", "{F2C3F1F1-328F-4EA9-BC82-0AF252375E2A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Catalog.Application", "src\Modules\Catalog\Application\Nashel.Modules.Catalog.Application.csproj", "{C47D5462-DA34-4A5E-BCBF-642D702E1ECA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Catalog.Domain", "src\Modules\Catalog\Domain\Nashel.Modules.Catalog.Domain.csproj", "{4C3D1645-4D40-4313-ACB6-079FDD8AA1D2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Catalog.Presentation", "src\Modules\Catalog\Presentation\Nashel.Modules.Catalog.Presentation.csproj", "{937B457D-1C2A-41E3-B7BD-CDFA827E4F76}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Collaboration.Infrastructure", "src\Modules\Collaboration\Infrastructure\Nashel.Modules.Collaboration.Infrastructure.csproj", "{6A825C22-139D-4927-AA08-F9130D4F6845}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Collaboration.Application", "src\Modules\Collaboration\Application\Nashel.Modules.Collaboration.Application.csproj", "{8043FAEB-5AAE-4DF5-9A3F-EF0E3CA6DC89}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Collaboration.Domain", "src\Modules\Collaboration\Domain\Nashel.Modules.Collaboration.Domain.csproj", "{397ADF05-2B2A-497D-A94C-9C40C8C7F7AF}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Collaboration.Presentation", "src\Modules\Collaboration\Presentation\Nashel.Modules.Collaboration.Presentation.csproj", "{01138FAD-D215-45D4-9D52-6A5875516557}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Geo.Infrastructure", "src\Modules\Geo\Infrastructure\Nashel.Modules.Geo.Infrastructure.csproj", "{15A81ACF-D93F-4039-9F67-8D3A96F57756}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Geo.Application", "src\Modules\Geo\Application\Nashel.Modules.Geo.Application.csproj", "{04D91154-1813-4666-93FD-01644023C766}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Geo.Domain", "src\Modules\Geo\Domain\Nashel.Modules.Geo.Domain.csproj", "{0A09480D-13BC-4C4A-863B-EB5A110F4436}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Geo.Presentation", "src\Modules\Geo\Presentation\Nashel.Modules.Geo.Presentation.csproj", "{059BD6B6-39E5-4558-85F7-2E35FEEA36D4}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Identity.Infrastructure", "src\Modules\Identity\Infrastructure\Nashel.Modules.Identity.Infrastructure.csproj", "{33DFFF98-2E80-421C-B0A5-02C7C329B5C1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Identity.Application", "src\Modules\Identity\Application\Nashel.Modules.Identity.Application.csproj", "{88BE5612-F8D3-4E22-A1CE-53520F5B8D13}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Identity.Domain", "src\Modules\Identity\Domain\Nashel.Modules.Identity.Domain.csproj", "{733FC595-BBEF-4B1B-81A8-F3A952820250}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Identity.Presentation", "src\Modules\Identity\Presentation\Nashel.Modules.Identity.Presentation.csproj", "{9458707B-D600-4F2C-9FD9-9195F9EC69DC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Order.Infrastructure", "src\Modules\Order\Infrastructure\Nashel.Modules.Order.Infrastructure.csproj", "{996763EA-95DD-4BC7-8782-19DD630E4F75}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Order.Application", "src\Modules\Order\Application\Nashel.Modules.Order.Application.csproj", "{F9CD05EC-1FFF-4DCC-8806-2FDD9FAD3BBE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Order.Domain", "src\Modules\Order\Domain\Nashel.Modules.Order.Domain.csproj", "{A02E0244-9E52-4DCD-AF42-6FC90E03C4E1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Order.Presentation", "src\Modules\Order\Presentation\Nashel.Modules.Order.Presentation.csproj", "{5FC793DE-0C52-432C-95A9-174919C3E57C}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Reputation.Infrastructure", "src\Modules\Reputation\Infrastructure\Nashel.Modules.Reputation.Infrastructure.csproj", "{6B7E10A1-CE95-4D71-A657-7303FEE7B52A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Reputation.Application", "src\Modules\Reputation\Application\Nashel.Modules.Reputation.Application.csproj", "{C6D6EB9D-D40E-4839-8F78-1024ED4964E1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Reputation.Domain", "src\Modules\Reputation\Domain\Nashel.Modules.Reputation.Domain.csproj", "{2010E82F-B42C-491F-AFD7-4486D4845737}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Reputation.Presentation", "src\Modules\Reputation\Presentation\Nashel.Modules.Reputation.Presentation.csproj", "{EEC2B03A-3172-4EC1-B7E3-8687E436072D}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{0AB3BF05-4346-4AA6-1389-037BE0695223}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Identity.Tests", "src\Modules\Identity\Tests\Nashel.Modules.Identity.Tests.csproj", "{401E3B50-A6B8-4AA1-9DD3-41F9EC78FABD}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Order", "Order", "{2C821288-5B9D-778E-74EE-053FE87F223E}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{FB27511E-CBA6-E343-8CE0-54AAD98AFC9F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Order.Tests", "src\Modules\Order\Tests\Nashel.Modules.Order.Tests.csproj", "{DC1E99E0-6B92-4FBD-B74B-68D202961FB7}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Reputation", "Reputation", "{305CF822-D9CA-C4BE-7183-DD5447E36C7E}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{6FECF8C1-5BB0-731D-B0FE-7CF5A5513390}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Reputation.Tests", "src\Modules\Reputation\Tests\Nashel.Modules.Reputation.Tests.csproj", "{B496E978-09C5-4EFA-9A2A-6984A3F89F77}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Host.Tests", "tests\Nashel.Host.Tests\Nashel.Host.Tests.csproj", "{087C0E53-90E0-415A-A394-6E31E12EF7BF}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Catalog", "Catalog", "{1E1EF545-4C18-AEE2-B997-7EF431518D3F}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{77959D31-1EA8-27CA-126F-40C5E927F925}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Catalog.Tests", "src\Modules\Catalog\Tests\Nashel.Modules.Catalog.Tests.csproj", "{2C29F7A5-8927-4490-BC7A-50B6F5442EEF}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Geo", "Geo", "{1F785BA6-BCCC-EB5A-C0AC-017D258EF3FD}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{9CB3DAB5-483B-9BA7-DF84-97D903318F73}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Geo.Tests", "src\Modules\Geo\Tests\Nashel.Modules.Geo.Tests.csproj", "{06992B63-6D24-4785-8A7D-138E9AC6D38E}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Collaboration", "Collaboration", "{0D6C7A58-55D3-AEBB-0CCB-984ED0F92F71}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{04D8AB37-CCCF-08EA-5F4C-67D97B5A3FDE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nashel.Modules.Collaboration.Tests", "src\Modules\Collaboration\Tests\Nashel.Modules.Collaboration.Tests.csproj", "{4786B22D-13B2-4CC5-8738-EAC9121EF4F0}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Domain", "Domain", "{F7A07CC8-D014-3EFC-E9E0-4BA33974CD0E}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application", "{9B135FC8-DBD1-6BD7-B3C5-FE40E7BAF0CB}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{18F5CA61-2478-40DB-A8C3-3CA10BA66F4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{18F5CA61-2478-40DB-A8C3-3CA10BA66F4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{18F5CA61-2478-40DB-A8C3-3CA10BA66F4A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{18F5CA61-2478-40DB-A8C3-3CA10BA66F4A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{18F5CA61-2478-40DB-A8C3-3CA10BA66F4A}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{18F5CA61-2478-40DB-A8C3-3CA10BA66F4A}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{18F5CA61-2478-40DB-A8C3-3CA10BA66F4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{18F5CA61-2478-40DB-A8C3-3CA10BA66F4A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{18F5CA61-2478-40DB-A8C3-3CA10BA66F4A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{18F5CA61-2478-40DB-A8C3-3CA10BA66F4A}.Release|x64.Build.0 = Release|Any CPU
|
||||
{18F5CA61-2478-40DB-A8C3-3CA10BA66F4A}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{18F5CA61-2478-40DB-A8C3-3CA10BA66F4A}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4D89232D-7F93-4DA5-9B00-E25A355561EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4D89232D-7F93-4DA5-9B00-E25A355561EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4D89232D-7F93-4DA5-9B00-E25A355561EF}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4D89232D-7F93-4DA5-9B00-E25A355561EF}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4D89232D-7F93-4DA5-9B00-E25A355561EF}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4D89232D-7F93-4DA5-9B00-E25A355561EF}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4D89232D-7F93-4DA5-9B00-E25A355561EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4D89232D-7F93-4DA5-9B00-E25A355561EF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4D89232D-7F93-4DA5-9B00-E25A355561EF}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4D89232D-7F93-4DA5-9B00-E25A355561EF}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4D89232D-7F93-4DA5-9B00-E25A355561EF}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4D89232D-7F93-4DA5-9B00-E25A355561EF}.Release|x86.Build.0 = Release|Any CPU
|
||||
{F2C3F1F1-328F-4EA9-BC82-0AF252375E2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F2C3F1F1-328F-4EA9-BC82-0AF252375E2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F2C3F1F1-328F-4EA9-BC82-0AF252375E2A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{F2C3F1F1-328F-4EA9-BC82-0AF252375E2A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{F2C3F1F1-328F-4EA9-BC82-0AF252375E2A}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{F2C3F1F1-328F-4EA9-BC82-0AF252375E2A}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{F2C3F1F1-328F-4EA9-BC82-0AF252375E2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F2C3F1F1-328F-4EA9-BC82-0AF252375E2A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F2C3F1F1-328F-4EA9-BC82-0AF252375E2A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{F2C3F1F1-328F-4EA9-BC82-0AF252375E2A}.Release|x64.Build.0 = Release|Any CPU
|
||||
{F2C3F1F1-328F-4EA9-BC82-0AF252375E2A}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{F2C3F1F1-328F-4EA9-BC82-0AF252375E2A}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C47D5462-DA34-4A5E-BCBF-642D702E1ECA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C47D5462-DA34-4A5E-BCBF-642D702E1ECA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C47D5462-DA34-4A5E-BCBF-642D702E1ECA}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C47D5462-DA34-4A5E-BCBF-642D702E1ECA}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C47D5462-DA34-4A5E-BCBF-642D702E1ECA}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C47D5462-DA34-4A5E-BCBF-642D702E1ECA}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C47D5462-DA34-4A5E-BCBF-642D702E1ECA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C47D5462-DA34-4A5E-BCBF-642D702E1ECA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C47D5462-DA34-4A5E-BCBF-642D702E1ECA}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C47D5462-DA34-4A5E-BCBF-642D702E1ECA}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C47D5462-DA34-4A5E-BCBF-642D702E1ECA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C47D5462-DA34-4A5E-BCBF-642D702E1ECA}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4C3D1645-4D40-4313-ACB6-079FDD8AA1D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4C3D1645-4D40-4313-ACB6-079FDD8AA1D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4C3D1645-4D40-4313-ACB6-079FDD8AA1D2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4C3D1645-4D40-4313-ACB6-079FDD8AA1D2}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4C3D1645-4D40-4313-ACB6-079FDD8AA1D2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4C3D1645-4D40-4313-ACB6-079FDD8AA1D2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4C3D1645-4D40-4313-ACB6-079FDD8AA1D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4C3D1645-4D40-4313-ACB6-079FDD8AA1D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4C3D1645-4D40-4313-ACB6-079FDD8AA1D2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4C3D1645-4D40-4313-ACB6-079FDD8AA1D2}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4C3D1645-4D40-4313-ACB6-079FDD8AA1D2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4C3D1645-4D40-4313-ACB6-079FDD8AA1D2}.Release|x86.Build.0 = Release|Any CPU
|
||||
{937B457D-1C2A-41E3-B7BD-CDFA827E4F76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{937B457D-1C2A-41E3-B7BD-CDFA827E4F76}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{937B457D-1C2A-41E3-B7BD-CDFA827E4F76}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{937B457D-1C2A-41E3-B7BD-CDFA827E4F76}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{937B457D-1C2A-41E3-B7BD-CDFA827E4F76}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{937B457D-1C2A-41E3-B7BD-CDFA827E4F76}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{937B457D-1C2A-41E3-B7BD-CDFA827E4F76}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{937B457D-1C2A-41E3-B7BD-CDFA827E4F76}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{937B457D-1C2A-41E3-B7BD-CDFA827E4F76}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{937B457D-1C2A-41E3-B7BD-CDFA827E4F76}.Release|x64.Build.0 = Release|Any CPU
|
||||
{937B457D-1C2A-41E3-B7BD-CDFA827E4F76}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{937B457D-1C2A-41E3-B7BD-CDFA827E4F76}.Release|x86.Build.0 = Release|Any CPU
|
||||
{6A825C22-139D-4927-AA08-F9130D4F6845}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6A825C22-139D-4927-AA08-F9130D4F6845}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6A825C22-139D-4927-AA08-F9130D4F6845}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6A825C22-139D-4927-AA08-F9130D4F6845}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{6A825C22-139D-4927-AA08-F9130D4F6845}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{6A825C22-139D-4927-AA08-F9130D4F6845}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{6A825C22-139D-4927-AA08-F9130D4F6845}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6A825C22-139D-4927-AA08-F9130D4F6845}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6A825C22-139D-4927-AA08-F9130D4F6845}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6A825C22-139D-4927-AA08-F9130D4F6845}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6A825C22-139D-4927-AA08-F9130D4F6845}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{6A825C22-139D-4927-AA08-F9130D4F6845}.Release|x86.Build.0 = Release|Any CPU
|
||||
{8043FAEB-5AAE-4DF5-9A3F-EF0E3CA6DC89}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8043FAEB-5AAE-4DF5-9A3F-EF0E3CA6DC89}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8043FAEB-5AAE-4DF5-9A3F-EF0E3CA6DC89}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{8043FAEB-5AAE-4DF5-9A3F-EF0E3CA6DC89}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{8043FAEB-5AAE-4DF5-9A3F-EF0E3CA6DC89}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{8043FAEB-5AAE-4DF5-9A3F-EF0E3CA6DC89}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{8043FAEB-5AAE-4DF5-9A3F-EF0E3CA6DC89}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8043FAEB-5AAE-4DF5-9A3F-EF0E3CA6DC89}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8043FAEB-5AAE-4DF5-9A3F-EF0E3CA6DC89}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{8043FAEB-5AAE-4DF5-9A3F-EF0E3CA6DC89}.Release|x64.Build.0 = Release|Any CPU
|
||||
{8043FAEB-5AAE-4DF5-9A3F-EF0E3CA6DC89}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{8043FAEB-5AAE-4DF5-9A3F-EF0E3CA6DC89}.Release|x86.Build.0 = Release|Any CPU
|
||||
{397ADF05-2B2A-497D-A94C-9C40C8C7F7AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{397ADF05-2B2A-497D-A94C-9C40C8C7F7AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{397ADF05-2B2A-497D-A94C-9C40C8C7F7AF}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{397ADF05-2B2A-497D-A94C-9C40C8C7F7AF}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{397ADF05-2B2A-497D-A94C-9C40C8C7F7AF}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{397ADF05-2B2A-497D-A94C-9C40C8C7F7AF}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{397ADF05-2B2A-497D-A94C-9C40C8C7F7AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{397ADF05-2B2A-497D-A94C-9C40C8C7F7AF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{397ADF05-2B2A-497D-A94C-9C40C8C7F7AF}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{397ADF05-2B2A-497D-A94C-9C40C8C7F7AF}.Release|x64.Build.0 = Release|Any CPU
|
||||
{397ADF05-2B2A-497D-A94C-9C40C8C7F7AF}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{397ADF05-2B2A-497D-A94C-9C40C8C7F7AF}.Release|x86.Build.0 = Release|Any CPU
|
||||
{01138FAD-D215-45D4-9D52-6A5875516557}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{01138FAD-D215-45D4-9D52-6A5875516557}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{01138FAD-D215-45D4-9D52-6A5875516557}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{01138FAD-D215-45D4-9D52-6A5875516557}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{01138FAD-D215-45D4-9D52-6A5875516557}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{01138FAD-D215-45D4-9D52-6A5875516557}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{01138FAD-D215-45D4-9D52-6A5875516557}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{01138FAD-D215-45D4-9D52-6A5875516557}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{01138FAD-D215-45D4-9D52-6A5875516557}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{01138FAD-D215-45D4-9D52-6A5875516557}.Release|x64.Build.0 = Release|Any CPU
|
||||
{01138FAD-D215-45D4-9D52-6A5875516557}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{01138FAD-D215-45D4-9D52-6A5875516557}.Release|x86.Build.0 = Release|Any CPU
|
||||
{15A81ACF-D93F-4039-9F67-8D3A96F57756}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{15A81ACF-D93F-4039-9F67-8D3A96F57756}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{15A81ACF-D93F-4039-9F67-8D3A96F57756}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{15A81ACF-D93F-4039-9F67-8D3A96F57756}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{15A81ACF-D93F-4039-9F67-8D3A96F57756}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{15A81ACF-D93F-4039-9F67-8D3A96F57756}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{15A81ACF-D93F-4039-9F67-8D3A96F57756}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{15A81ACF-D93F-4039-9F67-8D3A96F57756}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{15A81ACF-D93F-4039-9F67-8D3A96F57756}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{15A81ACF-D93F-4039-9F67-8D3A96F57756}.Release|x64.Build.0 = Release|Any CPU
|
||||
{15A81ACF-D93F-4039-9F67-8D3A96F57756}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{15A81ACF-D93F-4039-9F67-8D3A96F57756}.Release|x86.Build.0 = Release|Any CPU
|
||||
{04D91154-1813-4666-93FD-01644023C766}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{04D91154-1813-4666-93FD-01644023C766}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{04D91154-1813-4666-93FD-01644023C766}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{04D91154-1813-4666-93FD-01644023C766}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{04D91154-1813-4666-93FD-01644023C766}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{04D91154-1813-4666-93FD-01644023C766}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{04D91154-1813-4666-93FD-01644023C766}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{04D91154-1813-4666-93FD-01644023C766}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{04D91154-1813-4666-93FD-01644023C766}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{04D91154-1813-4666-93FD-01644023C766}.Release|x64.Build.0 = Release|Any CPU
|
||||
{04D91154-1813-4666-93FD-01644023C766}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{04D91154-1813-4666-93FD-01644023C766}.Release|x86.Build.0 = Release|Any CPU
|
||||
{0A09480D-13BC-4C4A-863B-EB5A110F4436}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0A09480D-13BC-4C4A-863B-EB5A110F4436}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0A09480D-13BC-4C4A-863B-EB5A110F4436}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{0A09480D-13BC-4C4A-863B-EB5A110F4436}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{0A09480D-13BC-4C4A-863B-EB5A110F4436}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{0A09480D-13BC-4C4A-863B-EB5A110F4436}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{0A09480D-13BC-4C4A-863B-EB5A110F4436}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0A09480D-13BC-4C4A-863B-EB5A110F4436}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0A09480D-13BC-4C4A-863B-EB5A110F4436}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{0A09480D-13BC-4C4A-863B-EB5A110F4436}.Release|x64.Build.0 = Release|Any CPU
|
||||
{0A09480D-13BC-4C4A-863B-EB5A110F4436}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{0A09480D-13BC-4C4A-863B-EB5A110F4436}.Release|x86.Build.0 = Release|Any CPU
|
||||
{059BD6B6-39E5-4558-85F7-2E35FEEA36D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{059BD6B6-39E5-4558-85F7-2E35FEEA36D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{059BD6B6-39E5-4558-85F7-2E35FEEA36D4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{059BD6B6-39E5-4558-85F7-2E35FEEA36D4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{059BD6B6-39E5-4558-85F7-2E35FEEA36D4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{059BD6B6-39E5-4558-85F7-2E35FEEA36D4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{059BD6B6-39E5-4558-85F7-2E35FEEA36D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{059BD6B6-39E5-4558-85F7-2E35FEEA36D4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{059BD6B6-39E5-4558-85F7-2E35FEEA36D4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{059BD6B6-39E5-4558-85F7-2E35FEEA36D4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{059BD6B6-39E5-4558-85F7-2E35FEEA36D4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{059BD6B6-39E5-4558-85F7-2E35FEEA36D4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{33DFFF98-2E80-421C-B0A5-02C7C329B5C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{33DFFF98-2E80-421C-B0A5-02C7C329B5C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{33DFFF98-2E80-421C-B0A5-02C7C329B5C1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{33DFFF98-2E80-421C-B0A5-02C7C329B5C1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{33DFFF98-2E80-421C-B0A5-02C7C329B5C1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{33DFFF98-2E80-421C-B0A5-02C7C329B5C1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{33DFFF98-2E80-421C-B0A5-02C7C329B5C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{33DFFF98-2E80-421C-B0A5-02C7C329B5C1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{33DFFF98-2E80-421C-B0A5-02C7C329B5C1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{33DFFF98-2E80-421C-B0A5-02C7C329B5C1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{33DFFF98-2E80-421C-B0A5-02C7C329B5C1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{33DFFF98-2E80-421C-B0A5-02C7C329B5C1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{88BE5612-F8D3-4E22-A1CE-53520F5B8D13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{88BE5612-F8D3-4E22-A1CE-53520F5B8D13}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{88BE5612-F8D3-4E22-A1CE-53520F5B8D13}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{88BE5612-F8D3-4E22-A1CE-53520F5B8D13}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{88BE5612-F8D3-4E22-A1CE-53520F5B8D13}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{88BE5612-F8D3-4E22-A1CE-53520F5B8D13}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{88BE5612-F8D3-4E22-A1CE-53520F5B8D13}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{88BE5612-F8D3-4E22-A1CE-53520F5B8D13}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{88BE5612-F8D3-4E22-A1CE-53520F5B8D13}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{88BE5612-F8D3-4E22-A1CE-53520F5B8D13}.Release|x64.Build.0 = Release|Any CPU
|
||||
{88BE5612-F8D3-4E22-A1CE-53520F5B8D13}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{88BE5612-F8D3-4E22-A1CE-53520F5B8D13}.Release|x86.Build.0 = Release|Any CPU
|
||||
{733FC595-BBEF-4B1B-81A8-F3A952820250}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{733FC595-BBEF-4B1B-81A8-F3A952820250}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{733FC595-BBEF-4B1B-81A8-F3A952820250}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{733FC595-BBEF-4B1B-81A8-F3A952820250}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{733FC595-BBEF-4B1B-81A8-F3A952820250}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{733FC595-BBEF-4B1B-81A8-F3A952820250}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{733FC595-BBEF-4B1B-81A8-F3A952820250}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{733FC595-BBEF-4B1B-81A8-F3A952820250}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{733FC595-BBEF-4B1B-81A8-F3A952820250}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{733FC595-BBEF-4B1B-81A8-F3A952820250}.Release|x64.Build.0 = Release|Any CPU
|
||||
{733FC595-BBEF-4B1B-81A8-F3A952820250}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{733FC595-BBEF-4B1B-81A8-F3A952820250}.Release|x86.Build.0 = Release|Any CPU
|
||||
{9458707B-D600-4F2C-9FD9-9195F9EC69DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9458707B-D600-4F2C-9FD9-9195F9EC69DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9458707B-D600-4F2C-9FD9-9195F9EC69DC}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{9458707B-D600-4F2C-9FD9-9195F9EC69DC}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{9458707B-D600-4F2C-9FD9-9195F9EC69DC}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{9458707B-D600-4F2C-9FD9-9195F9EC69DC}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{9458707B-D600-4F2C-9FD9-9195F9EC69DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9458707B-D600-4F2C-9FD9-9195F9EC69DC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9458707B-D600-4F2C-9FD9-9195F9EC69DC}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9458707B-D600-4F2C-9FD9-9195F9EC69DC}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9458707B-D600-4F2C-9FD9-9195F9EC69DC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9458707B-D600-4F2C-9FD9-9195F9EC69DC}.Release|x86.Build.0 = Release|Any CPU
|
||||
{996763EA-95DD-4BC7-8782-19DD630E4F75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{996763EA-95DD-4BC7-8782-19DD630E4F75}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{996763EA-95DD-4BC7-8782-19DD630E4F75}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{996763EA-95DD-4BC7-8782-19DD630E4F75}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{996763EA-95DD-4BC7-8782-19DD630E4F75}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{996763EA-95DD-4BC7-8782-19DD630E4F75}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{996763EA-95DD-4BC7-8782-19DD630E4F75}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{996763EA-95DD-4BC7-8782-19DD630E4F75}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{996763EA-95DD-4BC7-8782-19DD630E4F75}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{996763EA-95DD-4BC7-8782-19DD630E4F75}.Release|x64.Build.0 = Release|Any CPU
|
||||
{996763EA-95DD-4BC7-8782-19DD630E4F75}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{996763EA-95DD-4BC7-8782-19DD630E4F75}.Release|x86.Build.0 = Release|Any CPU
|
||||
{F9CD05EC-1FFF-4DCC-8806-2FDD9FAD3BBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F9CD05EC-1FFF-4DCC-8806-2FDD9FAD3BBE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F9CD05EC-1FFF-4DCC-8806-2FDD9FAD3BBE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{F9CD05EC-1FFF-4DCC-8806-2FDD9FAD3BBE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{F9CD05EC-1FFF-4DCC-8806-2FDD9FAD3BBE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{F9CD05EC-1FFF-4DCC-8806-2FDD9FAD3BBE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{F9CD05EC-1FFF-4DCC-8806-2FDD9FAD3BBE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F9CD05EC-1FFF-4DCC-8806-2FDD9FAD3BBE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F9CD05EC-1FFF-4DCC-8806-2FDD9FAD3BBE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{F9CD05EC-1FFF-4DCC-8806-2FDD9FAD3BBE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{F9CD05EC-1FFF-4DCC-8806-2FDD9FAD3BBE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{F9CD05EC-1FFF-4DCC-8806-2FDD9FAD3BBE}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A02E0244-9E52-4DCD-AF42-6FC90E03C4E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A02E0244-9E52-4DCD-AF42-6FC90E03C4E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A02E0244-9E52-4DCD-AF42-6FC90E03C4E1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A02E0244-9E52-4DCD-AF42-6FC90E03C4E1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A02E0244-9E52-4DCD-AF42-6FC90E03C4E1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A02E0244-9E52-4DCD-AF42-6FC90E03C4E1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A02E0244-9E52-4DCD-AF42-6FC90E03C4E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A02E0244-9E52-4DCD-AF42-6FC90E03C4E1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A02E0244-9E52-4DCD-AF42-6FC90E03C4E1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A02E0244-9E52-4DCD-AF42-6FC90E03C4E1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A02E0244-9E52-4DCD-AF42-6FC90E03C4E1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A02E0244-9E52-4DCD-AF42-6FC90E03C4E1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{5FC793DE-0C52-432C-95A9-174919C3E57C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5FC793DE-0C52-432C-95A9-174919C3E57C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5FC793DE-0C52-432C-95A9-174919C3E57C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{5FC793DE-0C52-432C-95A9-174919C3E57C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{5FC793DE-0C52-432C-95A9-174919C3E57C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{5FC793DE-0C52-432C-95A9-174919C3E57C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{5FC793DE-0C52-432C-95A9-174919C3E57C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5FC793DE-0C52-432C-95A9-174919C3E57C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5FC793DE-0C52-432C-95A9-174919C3E57C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{5FC793DE-0C52-432C-95A9-174919C3E57C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{5FC793DE-0C52-432C-95A9-174919C3E57C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5FC793DE-0C52-432C-95A9-174919C3E57C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{6B7E10A1-CE95-4D71-A657-7303FEE7B52A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6B7E10A1-CE95-4D71-A657-7303FEE7B52A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6B7E10A1-CE95-4D71-A657-7303FEE7B52A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6B7E10A1-CE95-4D71-A657-7303FEE7B52A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{6B7E10A1-CE95-4D71-A657-7303FEE7B52A}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{6B7E10A1-CE95-4D71-A657-7303FEE7B52A}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{6B7E10A1-CE95-4D71-A657-7303FEE7B52A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6B7E10A1-CE95-4D71-A657-7303FEE7B52A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6B7E10A1-CE95-4D71-A657-7303FEE7B52A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6B7E10A1-CE95-4D71-A657-7303FEE7B52A}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6B7E10A1-CE95-4D71-A657-7303FEE7B52A}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{6B7E10A1-CE95-4D71-A657-7303FEE7B52A}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C6D6EB9D-D40E-4839-8F78-1024ED4964E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C6D6EB9D-D40E-4839-8F78-1024ED4964E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C6D6EB9D-D40E-4839-8F78-1024ED4964E1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C6D6EB9D-D40E-4839-8F78-1024ED4964E1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C6D6EB9D-D40E-4839-8F78-1024ED4964E1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C6D6EB9D-D40E-4839-8F78-1024ED4964E1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C6D6EB9D-D40E-4839-8F78-1024ED4964E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C6D6EB9D-D40E-4839-8F78-1024ED4964E1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C6D6EB9D-D40E-4839-8F78-1024ED4964E1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C6D6EB9D-D40E-4839-8F78-1024ED4964E1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C6D6EB9D-D40E-4839-8F78-1024ED4964E1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C6D6EB9D-D40E-4839-8F78-1024ED4964E1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2010E82F-B42C-491F-AFD7-4486D4845737}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2010E82F-B42C-491F-AFD7-4486D4845737}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2010E82F-B42C-491F-AFD7-4486D4845737}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2010E82F-B42C-491F-AFD7-4486D4845737}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2010E82F-B42C-491F-AFD7-4486D4845737}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2010E82F-B42C-491F-AFD7-4486D4845737}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2010E82F-B42C-491F-AFD7-4486D4845737}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2010E82F-B42C-491F-AFD7-4486D4845737}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2010E82F-B42C-491F-AFD7-4486D4845737}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2010E82F-B42C-491F-AFD7-4486D4845737}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2010E82F-B42C-491F-AFD7-4486D4845737}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2010E82F-B42C-491F-AFD7-4486D4845737}.Release|x86.Build.0 = Release|Any CPU
|
||||
{EEC2B03A-3172-4EC1-B7E3-8687E436072D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EEC2B03A-3172-4EC1-B7E3-8687E436072D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EEC2B03A-3172-4EC1-B7E3-8687E436072D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{EEC2B03A-3172-4EC1-B7E3-8687E436072D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{EEC2B03A-3172-4EC1-B7E3-8687E436072D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{EEC2B03A-3172-4EC1-B7E3-8687E436072D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{EEC2B03A-3172-4EC1-B7E3-8687E436072D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EEC2B03A-3172-4EC1-B7E3-8687E436072D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EEC2B03A-3172-4EC1-B7E3-8687E436072D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{EEC2B03A-3172-4EC1-B7E3-8687E436072D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{EEC2B03A-3172-4EC1-B7E3-8687E436072D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{EEC2B03A-3172-4EC1-B7E3-8687E436072D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{401E3B50-A6B8-4AA1-9DD3-41F9EC78FABD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{401E3B50-A6B8-4AA1-9DD3-41F9EC78FABD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{401E3B50-A6B8-4AA1-9DD3-41F9EC78FABD}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{401E3B50-A6B8-4AA1-9DD3-41F9EC78FABD}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{401E3B50-A6B8-4AA1-9DD3-41F9EC78FABD}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{401E3B50-A6B8-4AA1-9DD3-41F9EC78FABD}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{401E3B50-A6B8-4AA1-9DD3-41F9EC78FABD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{401E3B50-A6B8-4AA1-9DD3-41F9EC78FABD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{401E3B50-A6B8-4AA1-9DD3-41F9EC78FABD}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{401E3B50-A6B8-4AA1-9DD3-41F9EC78FABD}.Release|x64.Build.0 = Release|Any CPU
|
||||
{401E3B50-A6B8-4AA1-9DD3-41F9EC78FABD}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{401E3B50-A6B8-4AA1-9DD3-41F9EC78FABD}.Release|x86.Build.0 = Release|Any CPU
|
||||
{DC1E99E0-6B92-4FBD-B74B-68D202961FB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DC1E99E0-6B92-4FBD-B74B-68D202961FB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DC1E99E0-6B92-4FBD-B74B-68D202961FB7}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{DC1E99E0-6B92-4FBD-B74B-68D202961FB7}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{DC1E99E0-6B92-4FBD-B74B-68D202961FB7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{DC1E99E0-6B92-4FBD-B74B-68D202961FB7}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{DC1E99E0-6B92-4FBD-B74B-68D202961FB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DC1E99E0-6B92-4FBD-B74B-68D202961FB7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DC1E99E0-6B92-4FBD-B74B-68D202961FB7}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{DC1E99E0-6B92-4FBD-B74B-68D202961FB7}.Release|x64.Build.0 = Release|Any CPU
|
||||
{DC1E99E0-6B92-4FBD-B74B-68D202961FB7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DC1E99E0-6B92-4FBD-B74B-68D202961FB7}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B496E978-09C5-4EFA-9A2A-6984A3F89F77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B496E978-09C5-4EFA-9A2A-6984A3F89F77}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B496E978-09C5-4EFA-9A2A-6984A3F89F77}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B496E978-09C5-4EFA-9A2A-6984A3F89F77}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B496E978-09C5-4EFA-9A2A-6984A3F89F77}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B496E978-09C5-4EFA-9A2A-6984A3F89F77}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B496E978-09C5-4EFA-9A2A-6984A3F89F77}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B496E978-09C5-4EFA-9A2A-6984A3F89F77}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B496E978-09C5-4EFA-9A2A-6984A3F89F77}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B496E978-09C5-4EFA-9A2A-6984A3F89F77}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B496E978-09C5-4EFA-9A2A-6984A3F89F77}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B496E978-09C5-4EFA-9A2A-6984A3F89F77}.Release|x86.Build.0 = Release|Any CPU
|
||||
{087C0E53-90E0-415A-A394-6E31E12EF7BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{087C0E53-90E0-415A-A394-6E31E12EF7BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{087C0E53-90E0-415A-A394-6E31E12EF7BF}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{087C0E53-90E0-415A-A394-6E31E12EF7BF}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{087C0E53-90E0-415A-A394-6E31E12EF7BF}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{087C0E53-90E0-415A-A394-6E31E12EF7BF}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{087C0E53-90E0-415A-A394-6E31E12EF7BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{087C0E53-90E0-415A-A394-6E31E12EF7BF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{087C0E53-90E0-415A-A394-6E31E12EF7BF}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{087C0E53-90E0-415A-A394-6E31E12EF7BF}.Release|x64.Build.0 = Release|Any CPU
|
||||
{087C0E53-90E0-415A-A394-6E31E12EF7BF}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{087C0E53-90E0-415A-A394-6E31E12EF7BF}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2C29F7A5-8927-4490-BC7A-50B6F5442EEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2C29F7A5-8927-4490-BC7A-50B6F5442EEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2C29F7A5-8927-4490-BC7A-50B6F5442EEF}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2C29F7A5-8927-4490-BC7A-50B6F5442EEF}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2C29F7A5-8927-4490-BC7A-50B6F5442EEF}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2C29F7A5-8927-4490-BC7A-50B6F5442EEF}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2C29F7A5-8927-4490-BC7A-50B6F5442EEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2C29F7A5-8927-4490-BC7A-50B6F5442EEF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2C29F7A5-8927-4490-BC7A-50B6F5442EEF}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2C29F7A5-8927-4490-BC7A-50B6F5442EEF}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2C29F7A5-8927-4490-BC7A-50B6F5442EEF}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2C29F7A5-8927-4490-BC7A-50B6F5442EEF}.Release|x86.Build.0 = Release|Any CPU
|
||||
{06992B63-6D24-4785-8A7D-138E9AC6D38E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{06992B63-6D24-4785-8A7D-138E9AC6D38E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{06992B63-6D24-4785-8A7D-138E9AC6D38E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{06992B63-6D24-4785-8A7D-138E9AC6D38E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{06992B63-6D24-4785-8A7D-138E9AC6D38E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{06992B63-6D24-4785-8A7D-138E9AC6D38E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{06992B63-6D24-4785-8A7D-138E9AC6D38E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{06992B63-6D24-4785-8A7D-138E9AC6D38E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{06992B63-6D24-4785-8A7D-138E9AC6D38E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{06992B63-6D24-4785-8A7D-138E9AC6D38E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{06992B63-6D24-4785-8A7D-138E9AC6D38E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{06992B63-6D24-4785-8A7D-138E9AC6D38E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4786B22D-13B2-4CC5-8738-EAC9121EF4F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4786B22D-13B2-4CC5-8738-EAC9121EF4F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4786B22D-13B2-4CC5-8738-EAC9121EF4F0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4786B22D-13B2-4CC5-8738-EAC9121EF4F0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4786B22D-13B2-4CC5-8738-EAC9121EF4F0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4786B22D-13B2-4CC5-8738-EAC9121EF4F0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4786B22D-13B2-4CC5-8738-EAC9121EF4F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4786B22D-13B2-4CC5-8738-EAC9121EF4F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4786B22D-13B2-4CC5-8738-EAC9121EF4F0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4786B22D-13B2-4CC5-8738-EAC9121EF4F0}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4786B22D-13B2-4CC5-8738-EAC9121EF4F0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4786B22D-13B2-4CC5-8738-EAC9121EF4F0}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{18F5CA61-2478-40DB-A8C3-3CA10BA66F4A} = {7266C4A9-E384-DC00-0EB6-47F6002CFBA7}
|
||||
{4D89232D-7F93-4DA5-9B00-E25A355561EF} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{F2C3F1F1-328F-4EA9-BC82-0AF252375E2A} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{C47D5462-DA34-4A5E-BCBF-642D702E1ECA} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{4C3D1645-4D40-4313-ACB6-079FDD8AA1D2} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{937B457D-1C2A-41E3-B7BD-CDFA827E4F76} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{6A825C22-139D-4927-AA08-F9130D4F6845} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{8043FAEB-5AAE-4DF5-9A3F-EF0E3CA6DC89} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{397ADF05-2B2A-497D-A94C-9C40C8C7F7AF} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{01138FAD-D215-45D4-9D52-6A5875516557} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{15A81ACF-D93F-4039-9F67-8D3A96F57756} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{04D91154-1813-4666-93FD-01644023C766} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{0A09480D-13BC-4C4A-863B-EB5A110F4436} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{059BD6B6-39E5-4558-85F7-2E35FEEA36D4} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{33DFFF98-2E80-421C-B0A5-02C7C329B5C1} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{88BE5612-F8D3-4E22-A1CE-53520F5B8D13} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{733FC595-BBEF-4B1B-81A8-F3A952820250} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{9458707B-D600-4F2C-9FD9-9195F9EC69DC} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{996763EA-95DD-4BC7-8782-19DD630E4F75} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{F9CD05EC-1FFF-4DCC-8806-2FDD9FAD3BBE} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{A02E0244-9E52-4DCD-AF42-6FC90E03C4E1} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{5FC793DE-0C52-432C-95A9-174919C3E57C} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{6B7E10A1-CE95-4D71-A657-7303FEE7B52A} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{C6D6EB9D-D40E-4839-8F78-1024ED4964E1} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{2010E82F-B42C-491F-AFD7-4486D4845737} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{EEC2B03A-3172-4EC1-B7E3-8687E436072D} = {7226ABEA-787E-1D09-10EA-A2ECF996D6A6}
|
||||
{401E3B50-A6B8-4AA1-9DD3-41F9EC78FABD} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||
{EC447DCF-ABFA-6E24-52A5-D7FD48A5C558} = {827E0CD3-B72D-47B6-A68D-7590B98EB39B}
|
||||
{2C821288-5B9D-778E-74EE-053FE87F223E} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{FB27511E-CBA6-E343-8CE0-54AAD98AFC9F} = {2C821288-5B9D-778E-74EE-053FE87F223E}
|
||||
{DC1E99E0-6B92-4FBD-B74B-68D202961FB7} = {FB27511E-CBA6-E343-8CE0-54AAD98AFC9F}
|
||||
{305CF822-D9CA-C4BE-7183-DD5447E36C7E} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{6FECF8C1-5BB0-731D-B0FE-7CF5A5513390} = {305CF822-D9CA-C4BE-7183-DD5447E36C7E}
|
||||
{B496E978-09C5-4EFA-9A2A-6984A3F89F77} = {6FECF8C1-5BB0-731D-B0FE-7CF5A5513390}
|
||||
{087C0E53-90E0-415A-A394-6E31E12EF7BF} = {0AB3BF05-4346-4AA6-1389-037BE0695223}
|
||||
{1E1EF545-4C18-AEE2-B997-7EF431518D3F} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{77959D31-1EA8-27CA-126F-40C5E927F925} = {1E1EF545-4C18-AEE2-B997-7EF431518D3F}
|
||||
{2C29F7A5-8927-4490-BC7A-50B6F5442EEF} = {77959D31-1EA8-27CA-126F-40C5E927F925}
|
||||
{1F785BA6-BCCC-EB5A-C0AC-017D258EF3FD} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{9CB3DAB5-483B-9BA7-DF84-97D903318F73} = {1F785BA6-BCCC-EB5A-C0AC-017D258EF3FD}
|
||||
{06992B63-6D24-4785-8A7D-138E9AC6D38E} = {9CB3DAB5-483B-9BA7-DF84-97D903318F73}
|
||||
{0D6C7A58-55D3-AEBB-0CCB-984ED0F92F71} = {EC447DCF-ABFA-6E24-52A5-D7FD48A5C558}
|
||||
{04D8AB37-CCCF-08EA-5F4C-67D97B5A3FDE} = {0D6C7A58-55D3-AEBB-0CCB-984ED0F92F71}
|
||||
{4786B22D-13B2-4CC5-8738-EAC9121EF4F0} = {04D8AB37-CCCF-08EA-5F4C-67D97B5A3FDE}
|
||||
{F7A07CC8-D014-3EFC-E9E0-4BA33974CD0E} = {0D6C7A58-55D3-AEBB-0CCB-984ED0F92F71}
|
||||
{9B135FC8-DBD1-6BD7-B3C5-FE40E7BAF0CB} = {0D6C7A58-55D3-AEBB-0CCB-984ED0F92F71}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1 +1,112 @@
|
||||
# nashel-backend
|
||||
# 🔮 Nashel — Backend API
|
||||
|
||||
> **ASP.NET Core · Modular Monolith · PostgreSQL (PostGIS) · Docker**
|
||||
|
||||
Серверная часть платформы **Nashel** — инновационного маркетплейса для поиска и найма профессиональных исполнителей. Бэкенд построен по принципу **Модульного Монолита**, что обеспечивает идеальный баланс между скоростью разработки и чистотой архитектуры с четкой доменной изоляцией.
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Миссия Nashel
|
||||
|
||||
Мы создаем прозрачную экосистему, где мастера получают профессиональный инструментарий для ведения бизнеса, а клиенты — надежный сервис поиска по геолокации, реальным отзывам и защищенным сделкам.
|
||||
|
||||
**Ключевые преимущества:**
|
||||
- **Гео-центричность:** Поиск исполнителей в радиусе на карте.
|
||||
- **Интеллектуальный статус:** Проверка доступности мастера в реальном времени.
|
||||
- **Безопасность:** Проработанный жизненный цикл заказа с системой споров.
|
||||
- **Репутация:** Честная система отзывов, привязанная к реальным сделкам.
|
||||
|
||||
---
|
||||
|
||||
## 🧱 Архитектура и Технологии
|
||||
|
||||
Проект реализован как **Modular Monolith**. Каждый модуль — это изолированная единица со своей логикой, данными и API, взаимодействующая с другими через контракты BuildingBlocks.
|
||||
|
||||
### Технологический стек
|
||||
- **Runtime:** .NET 8 / ASP.NET Core
|
||||
- **Database:** PostgreSQL + **PostGIS** (гео-запросы)
|
||||
- **ORM:** Entity Framework Core
|
||||
- **Messaging:** MediatR (In-process commands/queries)
|
||||
- **Security:** JWT Authentication, Role-based Access Control
|
||||
- **Spatial:** NetTopologySuite
|
||||
|
||||
### Структура модуля
|
||||
```
|
||||
Modules/<Module>/
|
||||
├── Domain/ # Сущности, Value Objects, Доменные события
|
||||
├── Application/ # Use Cases (MediatR Handlers), DTOs, Mapping
|
||||
├── Infrastructure/ # EF Core (Persistence), External Services
|
||||
└── Presentation/ # Minimal API Endpoints
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Реализованные Модули
|
||||
|
||||
| Модуль | Статус | Функционал |
|
||||
|--------|--------|------------|
|
||||
| **Identity** | ✅ Ready | Auth (JWT), Профили, Аватары (Base64), Расписание, Статусы доступности |
|
||||
| **Catalog** | ✅ Ready | Управление услугами (CRUD), Multi-image (до 10 фото), Атрибуты |
|
||||
| **Search** | ✅ Ready | Full-text search, сортировка по Geo-дистанции и релевантности |
|
||||
| **Geo** | ✅ Ready | Расчет расстояний, Геозоны, Индексация координат |
|
||||
| **Order** | ✅ Ready | Заказы (Direct/Public), SLA таймеры, Система споров (Disputes), Отклики |
|
||||
| **Reputation** | ✅ Ready | Отзывы, Рейтинги (User/Offer), Дополнения к отзывам |
|
||||
| **Collaboration**| ✅ Ready | HR-инструментарий: Найм, Наложение вето на расписание, Проверки |
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Ключевая Логика
|
||||
|
||||
### 1. Умная доступность (Smart Status)
|
||||
Мастер может управлять своей доступностью двумя способами:
|
||||
- **Расписание:** Настройка рабочих дней и часов.
|
||||
- **Manual Toggle:** Ручное переключение статуса «Готов к заказу». Ручная активация имеет приоритет и действует до конца текущего дня, перекрывая стандартное расписание.
|
||||
|
||||
### 2. Жизненный цикл заказа (Order Flow)
|
||||
Реализована сложная машина состояний:
|
||||
1. **Создание:** Прямой заказ мастеру или публикация заявки в общий доступ.
|
||||
2. **SLA:** Для прямых заказов действует 60-минутный таймер на принятие.
|
||||
3. **Исполнение:** Статусы "В работе", "Выполнено", "Подтверждено".
|
||||
4. **Споры (Disputes):** Многоэтапный процесс разрешения конфликтов (Открытие -> Ответ мастера -> Возражение клиента -> Принятие условий).
|
||||
|
||||
### 3. Поиск и Геолокация
|
||||
- Поиск учитывает не только текст, но и **расстояние**.
|
||||
- В приоритете — конкретные услуги. Если мастер не имеет услуг, он показывается как специалист.
|
||||
- Интеграция с PostGIS позволяет делать сверхбыстрые выборки в радиусе.
|
||||
|
||||
---
|
||||
|
||||
## 🐳 Развертывание
|
||||
|
||||
### Docker (Рекомендуемо)
|
||||
```bash
|
||||
docker-compose up -d --build
|
||||
```
|
||||
Это запустит:
|
||||
- Бэкенд (порт 5000)
|
||||
- PostgreSQL + PostGIS (порт 5432)
|
||||
|
||||
### Локальный запуск
|
||||
1. Установите PostgreSQL и расширение PostGIS.
|
||||
2. Обновите строку подключения в `appsettings.json`.
|
||||
3. Примените миграции:
|
||||
```bash
|
||||
dotnet ef database update -p src/Host -s src/Host
|
||||
```
|
||||
4. Запустите Host:
|
||||
```bash
|
||||
dotnet run --project src/Host
|
||||
```
|
||||
|
||||
Swagger доступен по адресу: `http://localhost:5000/swagger`
|
||||
|
||||
---
|
||||
|
||||
## 🔮 Планы развития
|
||||
|
||||
- [ ] **Real-time:** Интеграция WebSockets для чатов и уведомлений.
|
||||
- [ ] **Verification:** Модуль проверки документов исполнителей.
|
||||
- [ ] **Finances:** Интеграция платежных шлюзов.
|
||||
- [ ] **Analytics:** Сбор метрик просмотров и конверсий для мастеров.
|
||||
- [ ] **Mobile SDK:** API для нативных мобильных приложений.
|
||||
- [ ] **Notifications:** Push и Email уведомления о статусах заказов.
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
SET search_path TO identity;
|
||||
SELECT "WorkingDays" FROM "WorkSchedules" LIMIT 3;
|
||||
@@ -0,0 +1,61 @@
|
||||
services:
|
||||
migrations:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.migrations
|
||||
container_name: nashel-migrations
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Development
|
||||
- ConnectionStrings__DefaultConnection=Host=db;Port=5432;Database=nashel;Username=postgres;Password=postgres
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
networks:
|
||||
- nashel-network
|
||||
|
||||
app:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: nashel-backend
|
||||
ports:
|
||||
- "5000:8080"
|
||||
volumes:
|
||||
- ./uploads:/app/wwwroot/uploads
|
||||
environment:
|
||||
- ASPNETCORE_ENVIRONMENT=Development
|
||||
- ConnectionStrings__DefaultConnection=Host=db;Port=5432;Database=nashel;Username=postgres;Password=postgres
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
migrations:
|
||||
condition: service_completed_successfully
|
||||
networks:
|
||||
- nashel-network
|
||||
|
||||
db:
|
||||
image: postgis/postgis:16-3.4
|
||||
container_name: nashel-db
|
||||
environment:
|
||||
- POSTGRES_DB=nashel
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- nashel-db-data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: [ "CMD-SHELL", "pg_isready -U postgres" ]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
networks:
|
||||
- nashel-network
|
||||
|
||||
volumes:
|
||||
nashel-db-data:
|
||||
|
||||
|
||||
networks:
|
||||
nashel-network:
|
||||
driver: bridge
|
||||
@@ -0,0 +1,2 @@
|
||||
SET search_path TO "identity";
|
||||
SELECT * FROM "WorkSchedules";
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Nashel.BuildingBlocks.Application.Abstractions;
|
||||
|
||||
public interface ICurrentUserService
|
||||
{
|
||||
Guid? UserId { get; }
|
||||
// Other claims if needed
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using FluentValidation;
|
||||
using MediatR;
|
||||
|
||||
namespace Nashel.BuildingBlocks.Application.Behaviors;
|
||||
|
||||
public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
|
||||
where TRequest : IRequest<TResponse>
|
||||
{
|
||||
private readonly IEnumerable<IValidator<TRequest>> _validators;
|
||||
|
||||
public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
|
||||
{
|
||||
_validators = validators;
|
||||
}
|
||||
|
||||
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!_validators.Any())
|
||||
{
|
||||
return await next();
|
||||
}
|
||||
|
||||
var context = new ValidationContext<TRequest>(request);
|
||||
var validationResults = await Task.WhenAll(_validators.Select(v => v.ValidateAsync(context, cancellationToken)));
|
||||
var failures = validationResults.SelectMany(r => r.Errors).Where(f => f != null).ToList();
|
||||
|
||||
if (failures.Count != 0)
|
||||
{
|
||||
throw new ValidationException(failures);
|
||||
}
|
||||
|
||||
return await next();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
namespace Nashel.BuildingBlocks.Application.Configurations;
|
||||
|
||||
/// <summary>
|
||||
/// Настройки работы с медиа-файлами.
|
||||
/// </summary>
|
||||
public class MediaSettings
|
||||
{
|
||||
public const string SectionName = "MediaSettings";
|
||||
|
||||
/// <summary>Максимальный размер файла в байтах.</summary>
|
||||
public long MaxFileSizeInBytes { get; set; }
|
||||
|
||||
/// <summary>Максимальное количество изображений для одной услуги.</summary>
|
||||
public int MaxImagesPerOffer { get; set; }
|
||||
|
||||
/// <summary>Список допустимых расширений файлов.</summary>
|
||||
public string[] AllowedExtensions { get; set; } = Array.Empty<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Настройки модуля заказов.
|
||||
/// </summary>
|
||||
public class OrderSettings
|
||||
{
|
||||
public const string SectionName = "OrderSettings";
|
||||
|
||||
/// <summary>Время на принятие прямого заказа (SLA) в минутах.</summary>
|
||||
public int DirectOrderSlaMinutes { get; set; }
|
||||
|
||||
/// <summary>Время жизни публичной заявки в минутах.</summary>
|
||||
public int PublicOrderSlaMinutes { get; set; }
|
||||
|
||||
/// <summary>Максимальное время на ответ в споре (в часах).</summary>
|
||||
public int MaxDisputeResponseHours { get; set; }
|
||||
|
||||
/// <summary>Максимальное число компетенций у исполнителя.</summary>
|
||||
public int MaxCompetenciesPerPerformer { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Настройки модуля Identity.
|
||||
/// </summary>
|
||||
public class IdentitySettings
|
||||
{
|
||||
public const string SectionName = "IdentitySettings";
|
||||
|
||||
/// <summary>Максимальная длина описания профиля.</summary>
|
||||
public int MaxDescriptionLength { get; set; }
|
||||
|
||||
/// <summary>Минимальная длина описания для роли исполнителя.</summary>
|
||||
public int MinPerformerDescriptionLength { get; set; }
|
||||
|
||||
/// <summary>Максимальное число компетенций.</summary>
|
||||
public int MaxCompetencies { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
namespace Nashel.BuildingBlocks.Application.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
/// Базовый класс для всех доменных исключений и исключений приложения.
|
||||
/// </summary>
|
||||
public abstract class ApplicationExceptionBase : Exception
|
||||
{
|
||||
protected ApplicationExceptionBase(string message) : base(message) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Исключение, выбрасываемое, когда сущность не найдена.
|
||||
/// </summary>
|
||||
public class NotFoundException : ApplicationExceptionBase
|
||||
{
|
||||
public NotFoundException(string name, object key)
|
||||
: base($"Сущность \"{name}\" ({key}) не найдена.") { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Исключение валидации данных.
|
||||
/// </summary>
|
||||
public class ValidationException : ApplicationExceptionBase
|
||||
{
|
||||
public IDictionary<string, string[]> Errors { get; }
|
||||
|
||||
public ValidationException()
|
||||
: base("Произошла одна или несколько ошибок валидации.")
|
||||
{
|
||||
Errors = new Dictionary<string, string[]>();
|
||||
}
|
||||
|
||||
public ValidationException(IDictionary<string, string[]> errors)
|
||||
: base("Произошла одна или несколько ошибок валидации.")
|
||||
{
|
||||
Errors = errors;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Исключение, выбрасываемое при нарушении бизнес-правил или конфликтах.
|
||||
/// </summary>
|
||||
public class BusinessRuleException : ApplicationExceptionBase
|
||||
{
|
||||
public BusinessRuleException(string message) : base(message) { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Исключение отсутствия прав доступа.
|
||||
/// </summary>
|
||||
public class ForbiddenAccessException : ApplicationExceptionBase
|
||||
{
|
||||
public ForbiddenAccessException() : base("У вас недостаточно прав для выполнения этой операции.") { }
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace Nashel.BuildingBlocks.Domain;
|
||||
|
||||
public interface IEntity { }
|
||||
|
||||
public abstract class Entity<TId> : IEntity
|
||||
{
|
||||
public TId Id { get; protected set; }
|
||||
}
|
||||
|
||||
public interface IAggregateRoot { }
|
||||
|
||||
|
||||
|
||||
public abstract class AggregateRoot<TId> : Entity<TId>, IAggregateRoot
|
||||
{
|
||||
private readonly List<IDomainEvent> _domainEvents = new();
|
||||
|
||||
public IReadOnlyCollection<IDomainEvent> DomainEvents => _domainEvents.AsReadOnly();
|
||||
|
||||
public void AddDomainEvent(IDomainEvent domainEvent)
|
||||
{
|
||||
_domainEvents.Add(domainEvent);
|
||||
}
|
||||
|
||||
public void ClearDomainEvents()
|
||||
{
|
||||
_domainEvents.Clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Nashel.BuildingBlocks.Domain;
|
||||
|
||||
/// <summary>
|
||||
/// Базовый класс для исключений доменного слоя.
|
||||
/// </summary>
|
||||
public abstract class DomainException : Exception
|
||||
{
|
||||
protected DomainException(string message) : base(message) { }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using MediatR;
|
||||
|
||||
namespace Nashel.BuildingBlocks.Domain;
|
||||
|
||||
public interface IDomainEvent : INotification
|
||||
{
|
||||
DateTime OccurredOn { get; }
|
||||
}
|
||||
|
||||
public class BaseDomainEvent : IDomainEvent
|
||||
{
|
||||
public DateTime OccurredOn { get; protected set; } = DateTime.UtcNow;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
namespace Nashel.BuildingBlocks.Domain;
|
||||
|
||||
public class Result<T>
|
||||
{
|
||||
public bool IsSuccess { get; }
|
||||
public T? Value { get; }
|
||||
public string? Error { get; }
|
||||
|
||||
protected Result(bool isSuccess, T? value, string? error)
|
||||
{
|
||||
IsSuccess = isSuccess;
|
||||
Value = value;
|
||||
Error = error;
|
||||
}
|
||||
|
||||
public static Result<T> Success(T value) => new Result<T>(true, value, null);
|
||||
public static Result<T> Failure(string error) => new Result<T>(false, default, error);
|
||||
}
|
||||
|
||||
public class Result : Result<object>
|
||||
{
|
||||
protected Result(bool isSuccess, string? error) : base(isSuccess, null, error)
|
||||
{
|
||||
}
|
||||
|
||||
public static Result Success() => new Result(true, null);
|
||||
public static new Result Failure(string error) => new Result(false, error);
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
using System.Text.Json;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Nashel.BuildingBlocks.Application.Abstractions;
|
||||
using Nashel.Modules.Catalog.Infrastructure.Persistence;
|
||||
using Nashel.Modules.Geo.Infrastructure.Persistence;
|
||||
using Nashel.Modules.Identity.Infrastructure.Persistence;
|
||||
using Nashel.Modules.Reputation.Infrastructure.Persistence;
|
||||
using NetTopologySuite.Geometries;
|
||||
|
||||
namespace Nashel.Host.Endpoints;
|
||||
|
||||
public static class SearchEndpoints
|
||||
{
|
||||
public static void MapSearchEndpoints(this IEndpointRouteBuilder app)
|
||||
{
|
||||
app.MapGet("/api/search", async (
|
||||
GeoDbContext geoDb,
|
||||
IdentityDbContext identityDb,
|
||||
CatalogDbContext catalogDb,
|
||||
ReputationDbContext reputationDb,
|
||||
ICurrentUserService currentUserService,
|
||||
CancellationToken ct,
|
||||
[FromQuery] double lat = 0, // Убрали обязательность, чтобы опциональные работали нормально или перенесли в конец
|
||||
[FromQuery] double lon = 0,
|
||||
[FromQuery] string? q = null,
|
||||
[FromQuery] double radius = 10000,
|
||||
[FromQuery] bool inTitle = true,
|
||||
[FromQuery] bool inDesc = true,
|
||||
[FromQuery] bool inComp = true) =>
|
||||
{
|
||||
if (lat == 0 && lon == 0) return Results.BadRequest("Coordinates required");
|
||||
|
||||
var currentUserId = currentUserService.UserId;
|
||||
|
||||
// 1. Ищем ближайших мастеров через GeoDbContext (включая оффлайн, исключая себя)
|
||||
var searchPoint = new Point(lon, lat) { SRID = 4326 };
|
||||
|
||||
var nearbyGeoQuery = geoDb.LiveStatuses
|
||||
.Where(x => x.Location.IsWithinDistance(searchPoint, radius));
|
||||
|
||||
if (currentUserId.HasValue)
|
||||
{
|
||||
nearbyGeoQuery = nearbyGeoQuery.Where(x => x.Id != currentUserId.Value);
|
||||
}
|
||||
|
||||
var nearbyGeoRaw = await nearbyGeoQuery
|
||||
.Select(x => new { x.Id, x.State, Latitude = x.Location.Coordinate.Y, Longitude = x.Location.Coordinate.X, x.LastUpdatedAt })
|
||||
.ToListAsync(ct);
|
||||
|
||||
var nearbyGeo = nearbyGeoRaw.Select(x => new
|
||||
{
|
||||
x.Id,
|
||||
x.State,
|
||||
x.Latitude,
|
||||
x.Longitude,
|
||||
x.LastUpdatedAt,
|
||||
DistanceMeters = CalculateDistanceInMeters(lat, lon, x.Latitude, x.Longitude)
|
||||
}).ToList();
|
||||
|
||||
var nearbyIds = nearbyGeo.Select(x => x.Id).ToList();
|
||||
if (!nearbyIds.Any()) return Results.Ok(new List<object>());
|
||||
|
||||
// 2. Ищем совпадения по услугам (CatalogDbContext)
|
||||
var offersQuery = catalogDb.Offers
|
||||
.Where(o => nearbyIds.Contains(o.PerformerId) && o.IsActive && !o.IsDeleted);
|
||||
|
||||
var qLower = q?.ToLower();
|
||||
if (!string.IsNullOrWhiteSpace(qLower))
|
||||
{
|
||||
// EF Core транслирует Contains в ILIKE
|
||||
offersQuery = offersQuery.Where(o =>
|
||||
(inTitle && o.Title.ToLower().Contains(qLower)) ||
|
||||
(inDesc && o.Description != null && o.Description.ToLower().Contains(qLower)));
|
||||
}
|
||||
|
||||
var matchedOffersRaw = await offersQuery
|
||||
.Select(o => new { o.Id, o.PerformerId, o.Title, Description = o.Description ?? "", o.Price.Amount, o.Price.Currency, o.Images })
|
||||
.ToListAsync(ct);
|
||||
|
||||
var matchedOffers = matchedOffersRaw.Select(o => new { o.Id, o.PerformerId, o.Title, o.Description, PriceAmount = o.Amount, PriceCurrency = "₽", ImageUrl = o.Images.FirstOrDefault() }).ToList();
|
||||
|
||||
var performersWithOffers = matchedOffers.Select(o => o.PerformerId).Distinct().ToList();
|
||||
|
||||
// 3. Ищем пользователей, их расписание и компетенции (IdentityDbContext)
|
||||
var profilesQuery = identityDb.UserProfiles
|
||||
.Include(p => p.WorkSchedule)
|
||||
.Include(p => p.Competencies)
|
||||
.Where(p => nearbyIds.Contains(p.Id));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(qLower) && inComp)
|
||||
{
|
||||
// Фильтр: либо есть нужные офферы, либо подходящие компетенции
|
||||
profilesQuery = profilesQuery.Where(p =>
|
||||
performersWithOffers.Contains(p.Id) ||
|
||||
p.Competencies.Any(c => c.Name.ToLower().Contains(qLower)));
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(qLower))
|
||||
{
|
||||
// Поиск только по услугам, компетенции игнорируем
|
||||
profilesQuery = profilesQuery.Where(p => performersWithOffers.Contains(p.Id));
|
||||
}
|
||||
|
||||
var profiles = await profilesQuery.ToListAsync(ct);
|
||||
var profileIds = profiles.Select(p => p.Id).ToList();
|
||||
|
||||
var accountsRaw = await identityDb.Accounts
|
||||
.Where(a => profileIds.Contains(a.Id))
|
||||
.Select(a => new { a.Id, a.Roles })
|
||||
.ToListAsync(ct);
|
||||
|
||||
var accountsDict = accountsRaw.ToDictionary(a => a.Id, a => a.Roles.Select(r => r.ToString()).ToList());
|
||||
|
||||
// 4. Рейтинги (ReputationDbContext)
|
||||
var performerRatings = await reputationDb.Reviews
|
||||
.Where(r => profileIds.Contains(r.TargetId))
|
||||
.GroupBy(r => r.TargetId)
|
||||
.Select(g => new { TargetId = g.Key, Avg = g.Average(r => r.Rating), Count = g.Count() })
|
||||
.ToDictionaryAsync(x => x.TargetId, x => new { x.Avg, x.Count }, ct);
|
||||
|
||||
var offerIds = matchedOffers.Select(o => o.Id).ToList();
|
||||
var offerRatings = await reputationDb.Reviews
|
||||
.Where(r => offerIds.Contains(r.OfferId))
|
||||
.GroupBy(r => r.OfferId)
|
||||
.Select(g => new { OfferId = g.Key, Avg = g.Average(r => r.Rating), Count = g.Count() })
|
||||
.ToDictionaryAsync(x => x.OfferId, x => new { x.Avg, x.Count }, ct);
|
||||
|
||||
// 5. Сборка результата и логика "Умного статуса"
|
||||
var currentDay = GetRussianDayOfWeek(DateTime.UtcNow.DayOfWeek);
|
||||
var currentTime = DateTime.UtcNow.TimeOfDay;
|
||||
var offersLookup = matchedOffers.GroupBy(o => o.PerformerId).ToDictionary(g => g.Key, g => g.ToList());
|
||||
|
||||
var result = profiles.Join(nearbyGeo, p => p.Id, g => g.Id, (p, g) =>
|
||||
{
|
||||
var names = new[] { p.FirstName, p.LastName }.Where(x => !string.IsNullOrWhiteSpace(x));
|
||||
string fullName = string.Join(" ", names);
|
||||
if (string.IsNullOrWhiteSpace(fullName))
|
||||
fullName = p.CompanyName ?? "Мастер";
|
||||
|
||||
string finalStatus = CalculateSmartStatus(
|
||||
g.State.ToString(), // Передаем реальный статус из Geo
|
||||
g.LastUpdatedAt, // Передаем время последнего обновления
|
||||
p.WorkSchedule?.IsAlwaysReady ?? false,
|
||||
p.WorkSchedule?.WorkingDays,
|
||||
currentDay,
|
||||
currentTime
|
||||
);
|
||||
|
||||
var matchedOffersList = offersLookup.TryGetValue(p.Id, out var oList)
|
||||
? oList.Select(ox => (object)new
|
||||
{
|
||||
ox.Id,
|
||||
ox.PerformerId,
|
||||
ox.Title,
|
||||
ox.Description,
|
||||
ox.PriceAmount,
|
||||
ox.PriceCurrency,
|
||||
ox.ImageUrl,
|
||||
Rating = offerRatings.TryGetValue(ox.Id, out var or) ? Math.Round(or.Avg, 1) : 0,
|
||||
ReviewsCount = offerRatings.TryGetValue(ox.Id, out var orc) ? orc.Count : 0
|
||||
}).ToList()
|
||||
: new List<object>();
|
||||
|
||||
var roles = accountsDict.TryGetValue(p.Id, out var r) ? r : new List<string>();
|
||||
string roleName = "Пользователь";
|
||||
if (roles.Contains("Company")) roleName = "Компания";
|
||||
else if (roles.Contains("Master")) roleName = "Мастер";
|
||||
else if (roles.Contains("Candidate")) roleName = "Кандидат";
|
||||
|
||||
return new
|
||||
{
|
||||
PerformerId = p.Id,
|
||||
Name = fullName,
|
||||
AvatarUrl = p.AvatarUrl,
|
||||
Latitude = g.Latitude,
|
||||
Longitude = g.Longitude,
|
||||
Status = finalStatus, // "Готов к заказу" или "Офлайн"
|
||||
Distance = Math.Round(g.DistanceMeters),
|
||||
Role = roleName,
|
||||
Rating = performerRatings.TryGetValue(p.Id, out var pr) ? Math.Round(pr.Avg, 1) : 0,
|
||||
ReviewsCount = performerRatings.TryGetValue(p.Id, out var prc) ? prc.Count : 0,
|
||||
MatchedCompetencies = p.Competencies
|
||||
.Where(c => string.IsNullOrWhiteSpace(qLower) || !inComp || c.Name.ToLower().Contains(qLower))
|
||||
.Select(c => c.Name).ToList(),
|
||||
MatchedOffers = matchedOffersList
|
||||
};
|
||||
});
|
||||
|
||||
return Results.Ok(result.OrderByDescending(x => x.Status == "Готов к заказу").ThenBy(x => x.Distance));
|
||||
})
|
||||
.WithName("GlobalSearch")
|
||||
.WithOpenApi(operation => new(operation)
|
||||
{
|
||||
Summary = "Поиск мастеров и услуг (EF Core)",
|
||||
Description = "Ищет мастеров по компетенциям и услугам с учетом геолокации и графиков работы."
|
||||
})
|
||||
.WithTags("Search");
|
||||
}
|
||||
|
||||
private static string CalculateSmartStatus(string liveState, DateTime lastUpdatedAt, bool isAlwaysReady, string? workingDaysJson, string currentDay, TimeSpan currentTime)
|
||||
{
|
||||
if (liveState != "Available") return "Офлайн";
|
||||
if (isAlwaysReady) return "Готов к заказу";
|
||||
|
||||
// Если пользователь вручную обновил статус 'Available' сегодня, он остается онлайн до конца дня,
|
||||
// игнорируя расписание на сегодня. В следующий день снова начнет работать расписание.
|
||||
if (lastUpdatedAt.Date == DateTime.UtcNow.Date) return "Готов к заказу";
|
||||
|
||||
if (string.IsNullOrEmpty(workingDaysJson)) return "Готов к заказу"; // Если расписания нет - считаем готовым
|
||||
|
||||
try
|
||||
{
|
||||
using var doc = JsonDocument.Parse(workingDaysJson);
|
||||
if (!doc.RootElement.TryGetProperty(currentDay, out var dayArray) || dayArray.ValueKind != JsonValueKind.Array)
|
||||
return "Офлайн"; // В этот день вообще не работает
|
||||
|
||||
foreach (var period in dayArray.EnumerateArray())
|
||||
{
|
||||
var startStr = period.GetProperty("start").GetString();
|
||||
var endStr = period.GetProperty("end").GetString();
|
||||
|
||||
if (TimeSpan.TryParse(startStr, out var start) && TimeSpan.TryParse(endStr, out var end))
|
||||
{
|
||||
if (currentTime >= start && currentTime <= end) return "Готов к заказу";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
return "Офлайн"; // Если время не попало ни в один интервал - офлайн
|
||||
}
|
||||
|
||||
private static string GetRussianDayOfWeek(DayOfWeek day) => day switch
|
||||
{
|
||||
DayOfWeek.Monday => "Понедельник",
|
||||
DayOfWeek.Tuesday => "Вторник",
|
||||
DayOfWeek.Wednesday => "Среда",
|
||||
DayOfWeek.Thursday => "Четверг",
|
||||
DayOfWeek.Friday => "Пятница",
|
||||
DayOfWeek.Saturday => "Суббота",
|
||||
DayOfWeek.Sunday => "Воскресенье",
|
||||
_ => "Понедельник"
|
||||
};
|
||||
|
||||
private static double CalculateDistanceInMeters(double lat1, double lon1, double lat2, double lon2)
|
||||
{
|
||||
var dLat = (lat2 - lat1) * Math.PI / 180.0;
|
||||
var dLon = (lon2 - lon1) * Math.PI / 180.0;
|
||||
var a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(lat1 * Math.PI / 180.0) * Math.Cos(lat2 * Math.PI / 180.0) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2);
|
||||
return 6371000.0 * 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
using Microsoft.AspNetCore.Diagnostics;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Nashel.BuildingBlocks.Application.Exceptions;
|
||||
|
||||
namespace Nashel.Host.Infrastructure.Exceptions;
|
||||
|
||||
/// <summary>
|
||||
/// Глобальный обработчик исключений для всей системы.
|
||||
/// Перехватывает ошибки и возвращает их в стандарте ProblemDetails (RFC 7807).
|
||||
/// </summary>
|
||||
public class GlobalExceptionHandler : IExceptionHandler
|
||||
{
|
||||
private readonly ILogger<GlobalExceptionHandler> _logger;
|
||||
|
||||
public GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async ValueTask<bool> TryHandleAsync(
|
||||
HttpContext httpContext,
|
||||
Exception exception,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogError(exception, "Произошла необработанная ошибка: {Message}", exception.Message);
|
||||
|
||||
var (statusCode, title, detail, errors) = MapException(exception);
|
||||
|
||||
var problemDetails = new ProblemDetails
|
||||
{
|
||||
Status = statusCode,
|
||||
Title = title,
|
||||
Detail = detail,
|
||||
Instance = $"{httpContext.Request.Method} {httpContext.Request.Path}"
|
||||
};
|
||||
|
||||
if (errors != null)
|
||||
{
|
||||
problemDetails.Extensions["errors"] = errors;
|
||||
}
|
||||
|
||||
httpContext.Response.StatusCode = statusCode;
|
||||
await httpContext.Response.WriteAsJsonAsync(problemDetails, cancellationToken);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static (int StatusCode, string Title, string Detail, IDictionary<string, string[]>? Errors) MapException(Exception exception)
|
||||
{
|
||||
return exception switch
|
||||
{
|
||||
ValidationException validationException => (
|
||||
StatusCodes.Status400BadRequest,
|
||||
"Ошибка валидации",
|
||||
"Один или несколько параметров запроса не прошли проверку.",
|
||||
validationException.Errors),
|
||||
|
||||
NotFoundException notFoundException => (
|
||||
StatusCodes.Status404NotFound,
|
||||
"Ресурс не найден",
|
||||
notFoundException.Message,
|
||||
null),
|
||||
|
||||
Nashel.BuildingBlocks.Domain.DomainException domainException => (
|
||||
StatusCodes.Status409Conflict,
|
||||
"Ошибка в бизнес-логике",
|
||||
domainException.Message,
|
||||
null),
|
||||
|
||||
BusinessRuleException businessRuleException => (
|
||||
StatusCodes.Status409Conflict,
|
||||
"Нарушение бизнес-правила",
|
||||
businessRuleException.Message,
|
||||
null),
|
||||
|
||||
ForbiddenAccessException => (
|
||||
StatusCodes.Status403Forbidden,
|
||||
"Доступ запрещен",
|
||||
"У вас недостаточно прав для выполнения этой операции.",
|
||||
null),
|
||||
|
||||
UnauthorizedAccessException => (
|
||||
StatusCodes.Status401Unauthorized,
|
||||
"Неавторизован",
|
||||
"Требуется авторизация для доступа к этому ресурсу.",
|
||||
null),
|
||||
|
||||
// Обработка стандартных ArgumentException как 400 Bad Request
|
||||
ArgumentException argumentException => (
|
||||
StatusCodes.Status400BadRequest,
|
||||
"Некорректный запрос",
|
||||
argumentException.Message,
|
||||
null),
|
||||
|
||||
_ => (
|
||||
StatusCodes.Status500InternalServerError,
|
||||
"Внутренняя ошибка сервера",
|
||||
"Произошла непредвиденная ошибка на сервере. Пожалуйста, попробуйте позже.",
|
||||
null)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<PublishAot>false</PublishAot>
|
||||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn);1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Grpc.AspNetCore" Version="2.76.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.2">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.OpenApi" Version="1.6.14" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Modules\Catalog\Infrastructure\Nashel.Modules.Catalog.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\Modules\Catalog\Presentation\Nashel.Modules.Catalog.Presentation.csproj" />
|
||||
<ProjectReference Include="..\Modules\Collaboration\Infrastructure\Nashel.Modules.Collaboration.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\Modules\Collaboration\Presentation\Nashel.Modules.Collaboration.Presentation.csproj" />
|
||||
<ProjectReference Include="..\Modules\Geo\Infrastructure\Nashel.Modules.Geo.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\Modules\Geo\Presentation\Nashel.Modules.Geo.Presentation.csproj" />
|
||||
<ProjectReference Include="..\Modules\Identity\Infrastructure\Nashel.Modules.Identity.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\Modules\Identity\Presentation\Nashel.Modules.Identity.Presentation.csproj" />
|
||||
<ProjectReference Include="..\Modules\Order\Infrastructure\Nashel.Modules.Order.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\Modules\Order\Presentation\Nashel.Modules.Order.Presentation.csproj" />
|
||||
<ProjectReference Include="..\Modules\Reputation\Infrastructure\Nashel.Modules.Reputation.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\Modules\Reputation\Presentation\Nashel.Modules.Reputation.Presentation.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,6 @@
|
||||
@Nashel.Host_HostAddress = http://localhost:5232
|
||||
|
||||
GET {{Nashel.Host_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
@@ -1,13 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<PublishAot>true</PublishAot>
|
||||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Grpc.AspNetCore" Version="2.76.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.0-preview.6.25358.103" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,6 +0,0 @@
|
||||
@Nashel.RF.Host_HostAddress = http://localhost:5232
|
||||
|
||||
GET {{Nashel.RF.Host_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
+147
-27
@@ -1,39 +1,159 @@
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Nashel.Host.Endpoints;
|
||||
using Nashel.Modules.Catalog.Infrastructure;
|
||||
using Nashel.Modules.Catalog.Presentation.Endpoints;
|
||||
using Nashel.Modules.Collaboration.Infrastructure;
|
||||
using Nashel.Modules.Collaboration.Presentation;
|
||||
using Nashel.Modules.Geo.Infrastructure;
|
||||
using Nashel.Modules.Geo.Presentation;
|
||||
using Nashel.Modules.Identity.Infrastructure;
|
||||
using Nashel.Modules.Identity.Presentation.Endpoints;
|
||||
using Nashel.Modules.Order.Infrastructure;
|
||||
using Nashel.Modules.Order.Presentation;
|
||||
using Nashel.Modules.Reputation.Infrastructure;
|
||||
using Nashel.Modules.Reputation.Presentation;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// Add services to the container.
|
||||
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
|
||||
builder.Services.AddOpenApi();
|
||||
// Настройка JSON: принимаем строковые значения enum ("Direct" вместо 0)
|
||||
builder.Services.ConfigureHttpJsonOptions(options =>
|
||||
{
|
||||
options.SerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonStringEnumConverter());
|
||||
});
|
||||
|
||||
// Настройка Options
|
||||
builder.Services.Configure<Nashel.BuildingBlocks.Application.Configurations.MediaSettings>(
|
||||
builder.Configuration.GetSection(Nashel.BuildingBlocks.Application.Configurations.MediaSettings.SectionName));
|
||||
builder.Services.Configure<Nashel.BuildingBlocks.Application.Configurations.OrderSettings>(
|
||||
builder.Configuration.GetSection(Nashel.BuildingBlocks.Application.Configurations.OrderSettings.SectionName));
|
||||
builder.Services.Configure<Nashel.BuildingBlocks.Application.Configurations.IdentitySettings>(
|
||||
builder.Configuration.GetSection(Nashel.BuildingBlocks.Application.Configurations.IdentitySettings.SectionName));
|
||||
|
||||
// Добавление сервисов в контейнер.
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen(options =>
|
||||
{
|
||||
// Добавляем поддержку JWT Bearer (кнопка Authorize)
|
||||
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
||||
{
|
||||
Name = "Authorization",
|
||||
Type = SecuritySchemeType.Http,
|
||||
Scheme = "bearer",
|
||||
BearerFormat = "JWT",
|
||||
In = ParameterLocation.Header,
|
||||
Description = "Введите только токен в поле ниже (без 'Bearer ')"
|
||||
});
|
||||
|
||||
options.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||
{
|
||||
{
|
||||
new OpenApiSecurityScheme
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.SecurityScheme,
|
||||
Id = "Bearer"
|
||||
}
|
||||
},
|
||||
new string[] {}
|
||||
}
|
||||
});
|
||||
|
||||
// Подключение XML-документации
|
||||
var xmlFiles = Directory.GetFiles(AppContext.BaseDirectory, "*.xml");
|
||||
foreach (var xmlFile in xmlFiles)
|
||||
{
|
||||
options.IncludeXmlComments(xmlFile);
|
||||
}
|
||||
});
|
||||
|
||||
// Регистрация модуля Identity
|
||||
builder.Services.AddIdentityModule(builder.Configuration);
|
||||
|
||||
// Регистрация модуля Catalog
|
||||
builder.Services.AddCatalogModule(builder.Configuration);
|
||||
|
||||
// Регистрация модуля Geo
|
||||
builder.Services.AddGeoModule(builder.Configuration);
|
||||
|
||||
// Регистрация модуля Collaboartion
|
||||
builder.Services.AddCollaborationModule(builder.Configuration);
|
||||
|
||||
// Регистрация модуля Order
|
||||
builder.Services.AddOrderModule(builder.Configuration);
|
||||
|
||||
// Регистрация модуля Reputation
|
||||
builder.Services.AddReputationModule(builder.Configuration);
|
||||
|
||||
// Настройка аутентификации
|
||||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddJwtBearer(options =>
|
||||
{
|
||||
options.TokenValidationParameters = new TokenValidationParameters
|
||||
{
|
||||
ValidateIssuer = true,
|
||||
ValidateAudience = true,
|
||||
ValidateLifetime = true,
|
||||
ValidateIssuerSigningKey = true,
|
||||
ValidIssuer = builder.Configuration["JwtSettings:Issuer"],
|
||||
ValidAudience = builder.Configuration["JwtSettings:Audience"],
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JwtSettings:Secret"] ?? "super_secret_key_change_me_please_this_is_for_development_only_12345"))
|
||||
};
|
||||
});
|
||||
|
||||
// Регистрация глобального обработчика исключений
|
||||
builder.Services.AddExceptionHandler<Nashel.Host.Infrastructure.Exceptions.GlobalExceptionHandler>();
|
||||
builder.Services.AddProblemDetails();
|
||||
|
||||
builder.Services.AddAuthorization();
|
||||
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("FrontendPolicy", policy =>
|
||||
{
|
||||
policy.WithOrigins("http://localhost:3000", "http://127.0.0.1:3000", "http://localhost:3001", "http://127.0.0.1:3001")
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader()
|
||||
.AllowCredentials();
|
||||
});
|
||||
});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
// Глобальная обработка ошибок в формате ProblemDetails
|
||||
app.UseExceptionHandler();
|
||||
|
||||
// Настройка конвейера HTTP-запросов.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.MapOpenApi();
|
||||
app.UseSwagger();
|
||||
app.UseSwaggerUI(c =>
|
||||
{
|
||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Nashel API v1");
|
||||
});
|
||||
}
|
||||
|
||||
var summaries = new[]
|
||||
{
|
||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||
};
|
||||
app.UseCors("FrontendPolicy");
|
||||
|
||||
app.MapGet("/weatherforecast", () =>
|
||||
{
|
||||
var forecast = Enumerable.Range(1, 5).Select(index =>
|
||||
new WeatherForecast
|
||||
(
|
||||
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
||||
Random.Shared.Next(-20, 55),
|
||||
summaries[Random.Shared.Next(summaries.Length)]
|
||||
))
|
||||
.ToArray();
|
||||
return forecast;
|
||||
})
|
||||
.WithName("GetWeatherForecast");
|
||||
// Включение статических файлов для аватаров
|
||||
app.UseStaticFiles();
|
||||
|
||||
// Включение аутентификации и авторизации
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
// Маппинг эндпоинтов
|
||||
app.MapIdentityEndpoints();
|
||||
app.MapCatalogEndpoints();
|
||||
app.MapGeoEndpoints();
|
||||
app.MapOrderEndpoints();
|
||||
app.MapCollaborationEndpoints();
|
||||
app.MapReputationEndpoints();
|
||||
|
||||
// Глобальный поиск
|
||||
app.MapSearchEndpoints();
|
||||
|
||||
app.Run();
|
||||
|
||||
record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
|
||||
{
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "http://localhost:5232",
|
||||
"applicationUrl": "http://localhost:5000",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,5 +5,29 @@
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Host=localhost;Database=nashel;Username=postgres;Password=postgres"
|
||||
},
|
||||
"JwtSettings": {
|
||||
"Secret": "super_secret_key_change_me_please_this_is_for_development_only_12345",
|
||||
"Issuer": "Nashel",
|
||||
"Audience": "Nashel"
|
||||
},
|
||||
"MediaSettings": {
|
||||
"MaxFileSizeInBytes": 5242880,
|
||||
"MaxImagesPerOffer": 10,
|
||||
"AllowedExtensions": [ ".jpg", ".jpeg", ".png", ".webp" ]
|
||||
},
|
||||
"OrderSettings": {
|
||||
"DirectOrderSlaMinutes": 60,
|
||||
"PublicOrderSlaMinutes": 1440,
|
||||
"MaxDisputeResponseHours": 72,
|
||||
"MaxCompetenciesPerPerformer": 50
|
||||
},
|
||||
"IdentitySettings": {
|
||||
"MaxDescriptionLength": 2048,
|
||||
"MinPerformerDescriptionLength": 50,
|
||||
"MaxCompetencies": 50
|
||||
}
|
||||
}
|
||||
@@ -1,520 +0,0 @@
|
||||
{
|
||||
"format": 1,
|
||||
"restore": {
|
||||
"E:\\GIT\\mvp\\backend\\src\\Host\\Nashel.RF.Host.csproj": {}
|
||||
},
|
||||
"projects": {
|
||||
"E:\\GIT\\mvp\\backend\\src\\Host\\Nashel.RF.Host.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "E:\\GIT\\mvp\\backend\\src\\Host\\Nashel.RF.Host.csproj",
|
||||
"projectName": "Nashel.RF.Host",
|
||||
"projectPath": "E:\\GIT\\mvp\\backend\\src\\Host\\Nashel.RF.Host.csproj",
|
||||
"packagesPath": "C:\\Users\\HomePC\\.nuget\\packages\\",
|
||||
"outputPath": "E:\\GIT\\mvp\\backend\\src\\Host\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\HomePC\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net10.0"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"C:\\Program Files\\dotnet\\library-packs": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "all"
|
||||
},
|
||||
"SdkAnalysisLevel": "10.0.100"
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"targetAlias": "net10.0",
|
||||
"dependencies": {
|
||||
"Grpc.AspNetCore": {
|
||||
"target": "Package",
|
||||
"version": "[2.76.0, )"
|
||||
},
|
||||
"Microsoft.AspNetCore.OpenApi": {
|
||||
"target": "Package",
|
||||
"version": "[10.0.0-preview.6.25358.103, )"
|
||||
},
|
||||
"Microsoft.DotNet.ILCompiler": {
|
||||
"suppressParent": "All",
|
||||
"target": "Package",
|
||||
"version": "[10.0.0-preview.6.25358.103, )",
|
||||
"autoReferenced": true
|
||||
},
|
||||
"Microsoft.NET.ILLink.Tasks": {
|
||||
"suppressParent": "All",
|
||||
"target": "Package",
|
||||
"version": "[10.0.0-preview.6.25358.103, )",
|
||||
"autoReferenced": true
|
||||
}
|
||||
},
|
||||
"imports": [
|
||||
"net461",
|
||||
"net462",
|
||||
"net47",
|
||||
"net471",
|
||||
"net472",
|
||||
"net48",
|
||||
"net481"
|
||||
],
|
||||
"assetTargetFallback": true,
|
||||
"warn": true,
|
||||
"downloadDependencies": [
|
||||
{
|
||||
"name": "runtime.win-x64.Microsoft.DotNet.ILCompiler",
|
||||
"version": "[10.0.0-preview.6.25358.103, 10.0.0-preview.6.25358.103]"
|
||||
}
|
||||
],
|
||||
"frameworkReferences": {
|
||||
"Microsoft.AspNetCore.App": {
|
||||
"privateAssets": "none"
|
||||
},
|
||||
"Microsoft.NETCore.App": {
|
||||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.100-preview.6.25358.103/PortableRuntimeIdentifierGraph.json",
|
||||
"packagesToPrune": {
|
||||
"Microsoft.AspNetCore": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Antiforgery": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.App": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Authentication": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Authentication.Abstractions": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Authentication.BearerToken": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Authentication.Cookies": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Authentication.Core": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Authentication.OAuth": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Authorization": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Authorization.Policy": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Components": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Components.Authorization": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Components.Endpoints": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Components.Forms": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Components.Server": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Components.Web": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Connections.Abstractions": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.CookiePolicy": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Cors": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Cryptography.Internal": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Cryptography.KeyDerivation": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.DataProtection": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.DataProtection.Abstractions": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.DataProtection.Extensions": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Diagnostics": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Diagnostics.Abstractions": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Diagnostics.HealthChecks": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.HostFiltering": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Hosting": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Hosting.Abstractions": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Hosting.Server.Abstractions": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Html.Abstractions": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Http": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Http.Abstractions": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Http.Connections": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Http.Connections.Common": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Http.Extensions": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Http.Features": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Http.Results": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.HttpLogging": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.HttpOverrides": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.HttpsPolicy": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Identity": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Localization": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Localization.Routing": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Metadata": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Mvc": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Mvc.Abstractions": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Mvc.ApiExplorer": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Mvc.Core": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Mvc.Cors": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Mvc.DataAnnotations": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Mvc.Formatters.Json": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Mvc.Formatters.Xml": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Mvc.Localization": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Mvc.Razor": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Mvc.RazorPages": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Mvc.TagHelpers": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Mvc.ViewFeatures": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.OutputCaching": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.RateLimiting": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Razor": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Razor.Runtime": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.RequestDecompression": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.ResponseCaching": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.ResponseCaching.Abstractions": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.ResponseCompression": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Rewrite": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Routing": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Routing.Abstractions": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Server.HttpSys": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Server.IIS": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Server.IISIntegration": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Server.Kestrel": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Server.Kestrel.Core": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Server.Kestrel.Transport.Quic": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.Session": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.SignalR": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.SignalR.Common": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.SignalR.Core": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.SignalR.Protocols.Json": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.StaticAssets": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.StaticFiles": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.WebSockets": "(,10.0.32767]",
|
||||
"Microsoft.AspNetCore.WebUtilities": "(,10.0.32767]",
|
||||
"Microsoft.CSharp": "(,4.7.32767]",
|
||||
"Microsoft.Extensions.Caching.Abstractions": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Caching.Memory": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Configuration": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Configuration.Abstractions": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Configuration.Binder": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Configuration.CommandLine": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Configuration.FileExtensions": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Configuration.Ini": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Configuration.Json": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Configuration.KeyPerFile": "(,10.0.32767]",
|
||||
"Microsoft.Extensions.Configuration.UserSecrets": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Configuration.Xml": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.DependencyInjection": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.DependencyInjection.Abstractions": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Diagnostics": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Diagnostics.Abstractions": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Diagnostics.HealthChecks": "(,10.0.32767]",
|
||||
"Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": "(,10.0.32767]",
|
||||
"Microsoft.Extensions.Features": "(,10.0.32767]",
|
||||
"Microsoft.Extensions.FileProviders.Abstractions": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.FileProviders.Composite": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.FileProviders.Embedded": "(,10.0.32767]",
|
||||
"Microsoft.Extensions.FileProviders.Physical": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.FileSystemGlobbing": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Hosting": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Hosting.Abstractions": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Http": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Identity.Core": "(,10.0.32767]",
|
||||
"Microsoft.Extensions.Identity.Stores": "(,10.0.32767]",
|
||||
"Microsoft.Extensions.Localization": "(,10.0.32767]",
|
||||
"Microsoft.Extensions.Localization.Abstractions": "(,10.0.32767]",
|
||||
"Microsoft.Extensions.Logging": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Logging.Abstractions": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Logging.Configuration": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Logging.Console": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Logging.Debug": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Logging.EventLog": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Logging.EventSource": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Logging.TraceSource": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.ObjectPool": "(,10.0.32767]",
|
||||
"Microsoft.Extensions.Options": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Options.ConfigurationExtensions": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Options.DataAnnotations": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Primitives": "(,10.0.0-preview.6.25358.103]",
|
||||
"Microsoft.Extensions.Validation": "(,10.0.32767]",
|
||||
"Microsoft.Extensions.WebEncoders": "(,10.0.32767]",
|
||||
"Microsoft.JSInterop": "(,10.0.32767]",
|
||||
"Microsoft.Net.Http.Headers": "(,10.0.32767]",
|
||||
"Microsoft.VisualBasic": "(,10.4.32767]",
|
||||
"Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"Microsoft.Win32.Registry": "(,5.0.32767]",
|
||||
"runtime.any.System.Collections": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.any.System.IO": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.any.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.aot.System.Collections": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.aot.System.IO": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.aot.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.unix.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Console": "(,4.3.32767]",
|
||||
"runtime.unix.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.unix.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.unix.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.unix.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Console": "(,4.3.32767]",
|
||||
"runtime.win.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.win.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.win.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win10-arm-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-arm64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win10-x64-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-x86-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7-x86.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.win8-arm.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"System.AppContext": "(,4.3.32767]",
|
||||
"System.Buffers": "(,5.0.32767]",
|
||||
"System.Collections": "(,4.3.32767]",
|
||||
"System.Collections.Concurrent": "(,4.3.32767]",
|
||||
"System.Collections.Immutable": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Collections.NonGeneric": "(,4.3.32767]",
|
||||
"System.Collections.Specialized": "(,4.3.32767]",
|
||||
"System.ComponentModel": "(,4.3.32767]",
|
||||
"System.ComponentModel.Annotations": "(,4.3.32767]",
|
||||
"System.ComponentModel.EventBasedAsync": "(,4.3.32767]",
|
||||
"System.ComponentModel.Primitives": "(,4.3.32767]",
|
||||
"System.ComponentModel.TypeConverter": "(,4.3.32767]",
|
||||
"System.Console": "(,4.3.32767]",
|
||||
"System.Data.Common": "(,4.3.32767]",
|
||||
"System.Data.DataSetExtensions": "(,4.4.32767]",
|
||||
"System.Diagnostics.Contracts": "(,4.3.32767]",
|
||||
"System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"System.Diagnostics.DiagnosticSource": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Diagnostics.EventLog": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Diagnostics.FileVersionInfo": "(,4.3.32767]",
|
||||
"System.Diagnostics.Process": "(,4.3.32767]",
|
||||
"System.Diagnostics.StackTrace": "(,4.3.32767]",
|
||||
"System.Diagnostics.TextWriterTraceListener": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"System.Diagnostics.TraceSource": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"System.Drawing.Primitives": "(,4.3.32767]",
|
||||
"System.Dynamic.Runtime": "(,4.3.32767]",
|
||||
"System.Formats.Asn1": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Formats.Cbor": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Formats.Tar": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Globalization": "(,4.3.32767]",
|
||||
"System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"System.Globalization.Extensions": "(,4.3.32767]",
|
||||
"System.IO": "(,4.3.32767]",
|
||||
"System.IO.Compression": "(,4.3.32767]",
|
||||
"System.IO.Compression.ZipFile": "(,4.3.32767]",
|
||||
"System.IO.FileSystem": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.AccessControl": "(,4.4.32767]",
|
||||
"System.IO.FileSystem.DriveInfo": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Primitives": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Watcher": "(,4.3.32767]",
|
||||
"System.IO.IsolatedStorage": "(,4.3.32767]",
|
||||
"System.IO.MemoryMappedFiles": "(,4.3.32767]",
|
||||
"System.IO.Pipelines": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.IO.Pipes": "(,4.3.32767]",
|
||||
"System.IO.Pipes.AccessControl": "(,5.0.32767]",
|
||||
"System.IO.UnmanagedMemoryStream": "(,4.3.32767]",
|
||||
"System.Linq": "(,4.3.32767]",
|
||||
"System.Linq.AsyncEnumerable": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Linq.Expressions": "(,4.3.32767]",
|
||||
"System.Linq.Parallel": "(,4.3.32767]",
|
||||
"System.Linq.Queryable": "(,4.3.32767]",
|
||||
"System.Memory": "(,5.0.32767]",
|
||||
"System.Net.Http": "(,4.3.32767]",
|
||||
"System.Net.Http.Json": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Net.NameResolution": "(,4.3.32767]",
|
||||
"System.Net.NetworkInformation": "(,4.3.32767]",
|
||||
"System.Net.Ping": "(,4.3.32767]",
|
||||
"System.Net.Primitives": "(,4.3.32767]",
|
||||
"System.Net.Requests": "(,4.3.32767]",
|
||||
"System.Net.Security": "(,4.3.32767]",
|
||||
"System.Net.ServerSentEvents": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Net.Sockets": "(,4.3.32767]",
|
||||
"System.Net.WebHeaderCollection": "(,4.3.32767]",
|
||||
"System.Net.WebSockets": "(,4.3.32767]",
|
||||
"System.Net.WebSockets.Client": "(,4.3.32767]",
|
||||
"System.Numerics.Vectors": "(,5.0.32767]",
|
||||
"System.ObjectModel": "(,4.3.32767]",
|
||||
"System.Private.DataContractSerialization": "(,4.3.32767]",
|
||||
"System.Private.Uri": "(,4.3.32767]",
|
||||
"System.Reflection": "(,4.3.32767]",
|
||||
"System.Reflection.DispatchProxy": "(,6.0.32767]",
|
||||
"System.Reflection.Emit": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.ILGeneration": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.Lightweight": "(,4.7.32767]",
|
||||
"System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"System.Reflection.Metadata": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"System.Reflection.TypeExtensions": "(,4.3.32767]",
|
||||
"System.Resources.Reader": "(,4.3.32767]",
|
||||
"System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"System.Resources.Writer": "(,4.3.32767]",
|
||||
"System.Runtime": "(,4.3.32767]",
|
||||
"System.Runtime.CompilerServices.Unsafe": "(,7.0.32767]",
|
||||
"System.Runtime.CompilerServices.VisualC": "(,4.3.32767]",
|
||||
"System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"System.Runtime.Handles": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "(,4.3.32767]",
|
||||
"System.Runtime.Loader": "(,4.3.32767]",
|
||||
"System.Runtime.Numerics": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Formatters": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Json": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Primitives": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Xml": "(,4.3.32767]",
|
||||
"System.Security.AccessControl": "(,6.0.32767]",
|
||||
"System.Security.Claims": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Algorithms": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Cng": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Csp": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Encoding": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.OpenSsl": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Primitives": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.X509Certificates": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Xml": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Security.Principal": "(,4.3.32767]",
|
||||
"System.Security.Principal.Windows": "(,5.0.32767]",
|
||||
"System.Security.SecureString": "(,4.3.32767]",
|
||||
"System.Text.Encoding": "(,4.3.32767]",
|
||||
"System.Text.Encoding.CodePages": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"System.Text.Encodings.Web": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Text.Json": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Text.RegularExpressions": "(,4.3.32767]",
|
||||
"System.Threading": "(,4.3.32767]",
|
||||
"System.Threading.AccessControl": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Threading.Channels": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Threading.Overlapped": "(,4.3.32767]",
|
||||
"System.Threading.RateLimiting": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Threading.Tasks": "(,4.3.32767]",
|
||||
"System.Threading.Tasks.Dataflow": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Threading.Tasks.Extensions": "(,5.0.32767]",
|
||||
"System.Threading.Tasks.Parallel": "(,4.3.32767]",
|
||||
"System.Threading.Thread": "(,4.3.32767]",
|
||||
"System.Threading.ThreadPool": "(,4.3.32767]",
|
||||
"System.Threading.Timer": "(,4.3.32767]",
|
||||
"System.ValueTuple": "(,4.5.32767]",
|
||||
"System.Xml.ReaderWriter": "(,4.3.32767]",
|
||||
"System.Xml.XDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlSerializer": "(,4.3.32767]",
|
||||
"System.Xml.XPath": "(,4.3.32767]",
|
||||
"System.Xml.XPath.XDocument": "(,5.0.32767]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
||||
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
|
||||
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
|
||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
|
||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\HomePC\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
|
||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.15.0</NuGetToolVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<SourceRoot Include="C:\Users\HomePC\.nuget\packages\" />
|
||||
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
|
||||
</ItemGroup>
|
||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.net.illink.tasks\10.0.0-preview.6.25358.103\build\Microsoft.NET.ILLink.Tasks.props" Condition="Exists('$(NuGetPackageRoot)microsoft.net.illink.tasks\10.0.0-preview.6.25358.103\build\Microsoft.NET.ILLink.Tasks.props')" />
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.dotnet.ilcompiler\10.0.0-preview.6.25358.103\build\Microsoft.DotNet.ILCompiler.props" Condition="Exists('$(NuGetPackageRoot)microsoft.dotnet.ilcompiler\10.0.0-preview.6.25358.103\build\Microsoft.DotNet.ILCompiler.props')" />
|
||||
<Import Project="$(NuGetPackageRoot)grpc.tools\2.76.0\build\Grpc.Tools.props" Condition="Exists('$(NuGetPackageRoot)grpc.tools\2.76.0\build\Grpc.Tools.props')" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<PkgMicrosoft_NET_ILLink_Tasks Condition=" '$(PkgMicrosoft_NET_ILLink_Tasks)' == '' ">C:\Users\HomePC\.nuget\packages\microsoft.net.illink.tasks\10.0.0-preview.6.25358.103</PkgMicrosoft_NET_ILLink_Tasks>
|
||||
<PkgMicrosoft_DotNet_ILCompiler Condition=" '$(PkgMicrosoft_DotNet_ILCompiler)' == '' ">C:\Users\HomePC\.nuget\packages\microsoft.dotnet.ilcompiler\10.0.0-preview.6.25358.103</PkgMicrosoft_DotNet_ILCompiler>
|
||||
<PkgGrpc_Tools Condition=" '$(PkgGrpc_Tools)' == '' ">C:\Users\HomePC\.nuget\packages\grpc.tools\2.76.0</PkgGrpc_Tools>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.aspnetcore.openapi\10.0.0-preview.6.25358.103\build\Microsoft.AspNetCore.OpenApi.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.aspnetcore.openapi\10.0.0-preview.6.25358.103\build\Microsoft.AspNetCore.OpenApi.targets')" />
|
||||
<Import Project="$(NuGetPackageRoot)grpc.tools\2.76.0\build\Grpc.Tools.targets" Condition="Exists('$(NuGetPackageRoot)grpc.tools\2.76.0\build\Grpc.Tools.targets')" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,76 @@
|
||||
using System.Text.Json;
|
||||
using MediatR;
|
||||
using Nashel.BuildingBlocks.Domain;
|
||||
using Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
using Nashel.Modules.Catalog.Domain.Repositories;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Application.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// Команда создания категории.
|
||||
/// </summary>
|
||||
public record CreateCategoryCommand : IRequest<Result<Guid>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Название категории.
|
||||
/// </summary>
|
||||
public string Name { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// URL-friendly идентификатор (слаг).
|
||||
/// </summary>
|
||||
public string Slug { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// ID родительской категории (null для корневых).
|
||||
/// </summary>
|
||||
public Guid? ParentId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон характеристик (JSON).
|
||||
/// </summary>
|
||||
public JsonDocument? AttributeSchema { get; init; }
|
||||
|
||||
public CreateCategoryCommand(string name, string slug, Guid? parentId, JsonDocument? attributeSchema)
|
||||
{
|
||||
Name = name;
|
||||
Slug = slug;
|
||||
ParentId = parentId;
|
||||
AttributeSchema = attributeSchema;
|
||||
}
|
||||
|
||||
public CreateCategoryCommand() { } // For deserialization
|
||||
}
|
||||
|
||||
public class CreateCategoryCommandHandler : IRequestHandler<CreateCategoryCommand, Result<Guid>>
|
||||
{
|
||||
private readonly ICategoryRepository _repository;
|
||||
|
||||
public CreateCategoryCommandHandler(ICategoryRepository repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
public async Task<Result<Guid>> Handle(CreateCategoryCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
if (request.ParentId.HasValue)
|
||||
{
|
||||
var parentCategory = await _repository.GetByIdAsync(request.ParentId.Value, cancellationToken);
|
||||
if (parentCategory == null)
|
||||
{
|
||||
return Result<Guid>.Failure($"Родительская категория с ID {request.ParentId} не найдена.");
|
||||
}
|
||||
}
|
||||
|
||||
var category = new Category(
|
||||
request.Name,
|
||||
request.Slug,
|
||||
request.ParentId,
|
||||
request.AttributeSchema
|
||||
);
|
||||
|
||||
await _repository.AddAsync(category, cancellationToken);
|
||||
|
||||
return Result<Guid>.Success(category.Id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
using System.Text.Json;
|
||||
using MediatR;
|
||||
using Nashel.BuildingBlocks.Application.Abstractions;
|
||||
using Nashel.BuildingBlocks.Domain;
|
||||
using Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
using Nashel.Modules.Catalog.Domain.Repositories;
|
||||
using Nashel.Modules.Catalog.Domain.ValueObjects;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Application.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// Команда создания услуги (оффера).
|
||||
/// </summary>
|
||||
public record CreateOfferCommand : IRequest<Result<Guid>>
|
||||
{
|
||||
public Guid CategoryId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Заголовок объявления.
|
||||
/// </summary>
|
||||
public string Title { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Полное описание услуги.
|
||||
/// </summary>
|
||||
public string Description { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Цена услуги.
|
||||
/// </summary>
|
||||
public Price Price { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Характеристики услуги (JSON).
|
||||
/// </summary>
|
||||
public JsonDocument? Attributes { get; init; }
|
||||
|
||||
public List<string>? Images { get; init; }
|
||||
|
||||
public CreateOfferCommand(Guid categoryId, string title, string description, Price price, JsonDocument? attributes, List<string>? images)
|
||||
{
|
||||
CategoryId = categoryId;
|
||||
Title = title;
|
||||
Description = description;
|
||||
Price = price;
|
||||
Attributes = attributes;
|
||||
Images = images;
|
||||
}
|
||||
|
||||
public CreateOfferCommand() { }
|
||||
}
|
||||
|
||||
public class CreateOfferCommandHandler : IRequestHandler<CreateOfferCommand, Result<Guid>>
|
||||
{
|
||||
private readonly IOfferRepository _repository;
|
||||
private readonly ICurrentUserService _currentUserService;
|
||||
|
||||
public CreateOfferCommandHandler(IOfferRepository repository, ICurrentUserService currentUserService)
|
||||
{
|
||||
_repository = repository;
|
||||
_currentUserService = currentUserService;
|
||||
}
|
||||
|
||||
public async Task<Result<Guid>> Handle(CreateOfferCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var userId = _currentUserService.UserId;
|
||||
if (userId == null) return Result<Guid>.Failure("Неавторизован");
|
||||
|
||||
var offer = new Offer(
|
||||
userId.Value,
|
||||
request.CategoryId,
|
||||
request.Title,
|
||||
request.Description,
|
||||
request.Price,
|
||||
request.Attributes,
|
||||
request.Images
|
||||
);
|
||||
|
||||
await _repository.AddAsync(offer, cancellationToken);
|
||||
|
||||
return Result<Guid>.Success(offer.Id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using MediatR;
|
||||
using Nashel.BuildingBlocks.Application.Abstractions;
|
||||
using Nashel.Modules.Catalog.Domain.Repositories;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Application.Commands;
|
||||
|
||||
public record DeleteOfferCommand(Guid OfferId) : IRequest<bool>;
|
||||
|
||||
public class DeleteOfferCommandHandler : IRequestHandler<DeleteOfferCommand, bool>
|
||||
{
|
||||
private readonly IOfferRepository _repository;
|
||||
private readonly ICurrentUserService _currentUser;
|
||||
|
||||
public DeleteOfferCommandHandler(IOfferRepository repository, ICurrentUserService currentUser)
|
||||
{
|
||||
_repository = repository;
|
||||
_currentUser = currentUser;
|
||||
}
|
||||
|
||||
public async Task<bool> Handle(DeleteOfferCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var offer = await _repository.GetByIdAsync(request.OfferId, cancellationToken);
|
||||
if (offer == null) throw new Exception("Offer not found");
|
||||
|
||||
if (offer.PerformerId != _currentUser.UserId)
|
||||
throw new UnauthorizedAccessException("Not your offer");
|
||||
|
||||
offer.Delete();
|
||||
await _repository.UpdateAsync(offer, cancellationToken);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using MediatR;
|
||||
using Nashel.BuildingBlocks.Application.Abstractions;
|
||||
using Nashel.Modules.Catalog.Domain.Repositories;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Application.Commands;
|
||||
|
||||
public record ToggleOfferStatusCommand(Guid OfferId) : IRequest<bool>;
|
||||
|
||||
public class ToggleOfferStatusCommandHandler : IRequestHandler<ToggleOfferStatusCommand, bool>
|
||||
{
|
||||
private readonly IOfferRepository _repository;
|
||||
private readonly ICurrentUserService _currentUser;
|
||||
|
||||
public ToggleOfferStatusCommandHandler(IOfferRepository repository, ICurrentUserService currentUser)
|
||||
{
|
||||
_repository = repository;
|
||||
_currentUser = currentUser;
|
||||
}
|
||||
|
||||
public async Task<bool> Handle(ToggleOfferStatusCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var offer = await _repository.GetByIdAsync(request.OfferId, cancellationToken);
|
||||
if (offer == null) throw new Exception("Offer not found");
|
||||
|
||||
if (offer.PerformerId != _currentUser.UserId)
|
||||
throw new UnauthorizedAccessException("Not your offer");
|
||||
|
||||
offer.ToggleActive();
|
||||
await _repository.UpdateAsync(offer, cancellationToken);
|
||||
return offer.IsActive;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System.Text.Json;
|
||||
using MediatR;
|
||||
using Nashel.BuildingBlocks.Application.Abstractions;
|
||||
using Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
using Nashel.Modules.Catalog.Domain.Repositories;
|
||||
using Nashel.Modules.Catalog.Domain.ValueObjects;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Application.Commands;
|
||||
|
||||
public record UpdateOfferCommand(
|
||||
Guid OfferId,
|
||||
string Title,
|
||||
string Description,
|
||||
decimal PriceAmount,
|
||||
int PriceType, // 0-Fixed, 1-Hourly, 2-Negotiable
|
||||
Dictionary<string, string>? Attributes,
|
||||
List<string>? Images) : IRequest<bool>;
|
||||
|
||||
public class UpdateOfferCommandHandler : IRequestHandler<UpdateOfferCommand, bool>
|
||||
{
|
||||
private readonly IOfferRepository _repository;
|
||||
private readonly ICurrentUserService _currentUser;
|
||||
|
||||
public UpdateOfferCommandHandler(IOfferRepository repository, ICurrentUserService currentUser)
|
||||
{
|
||||
_repository = repository;
|
||||
_currentUser = currentUser;
|
||||
}
|
||||
|
||||
public async Task<bool> Handle(UpdateOfferCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var offer = await _repository.GetByIdAsync(request.OfferId, cancellationToken);
|
||||
if (offer == null) throw new Exception("Offer not found");
|
||||
|
||||
if (offer.PerformerId != _currentUser.UserId)
|
||||
throw new UnauthorizedAccessException("Not your offer");
|
||||
|
||||
var price = new Price(request.PriceAmount, (Nashel.Modules.Catalog.Domain.Enums.OfferType)request.PriceType);
|
||||
var jsonAttrs = request.Attributes != null && request.Attributes.Count > 0
|
||||
? JsonDocument.Parse(JsonSerializer.Serialize(request.Attributes))
|
||||
: null;
|
||||
|
||||
offer.Update(request.Title, request.Description, price, jsonAttrs, request.Images);
|
||||
|
||||
await _repository.UpdateAsync(offer, cancellationToken);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Nashel.BuildingBlocks.Application.Abstractions;
|
||||
using Nashel.BuildingBlocks.Application.Configurations;
|
||||
using Nashel.BuildingBlocks.Application.Exceptions;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Application.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// Команда загрузки изображения услуги.
|
||||
/// </summary>
|
||||
public record UploadOfferImageCommand(byte[] Content, string FileName) : IRequest<string>;
|
||||
|
||||
public class UploadOfferImageCommandHandler : IRequestHandler<UploadOfferImageCommand, string>
|
||||
{
|
||||
private readonly ICurrentUserService _currentUserService;
|
||||
private readonly MediaSettings _settings;
|
||||
|
||||
public UploadOfferImageCommandHandler(
|
||||
ICurrentUserService currentUserService,
|
||||
IOptions<MediaSettings> settings)
|
||||
{
|
||||
_currentUserService = currentUserService;
|
||||
_settings = settings.Value;
|
||||
}
|
||||
|
||||
public Task<string> Handle(UploadOfferImageCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var userId = _currentUserService.UserId;
|
||||
if (userId == null)
|
||||
{
|
||||
throw new UnauthorizedAccessException();
|
||||
}
|
||||
|
||||
if (request.Content.Length > _settings.MaxFileSizeInBytes)
|
||||
{
|
||||
throw new BusinessRuleException($"Размер файла слишком велик. Максимум: {_settings.MaxFileSizeInBytes / 1024 / 1024} МБ.");
|
||||
}
|
||||
|
||||
var extension = Path.GetExtension(request.FileName).ToLowerInvariant();
|
||||
if (!_settings.AllowedExtensions.Contains(extension))
|
||||
{
|
||||
throw new BusinessRuleException($"Допустимые форматы: {string.Join(", ", _settings.AllowedExtensions)}.");
|
||||
}
|
||||
|
||||
var base64String = Convert.ToBase64String(request.Content);
|
||||
|
||||
var mimeType = extension switch
|
||||
{
|
||||
".png" => "image/png",
|
||||
".webp" => "image/webp",
|
||||
_ => "image/jpeg"
|
||||
};
|
||||
|
||||
return Task.FromResult($"data:{mimeType};base64,{base64String}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
using System.Text.Json;
|
||||
using Nashel.Modules.Catalog.Domain.ValueObjects;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Application.Common;
|
||||
|
||||
/// <summary>
|
||||
/// DTO категории.
|
||||
/// </summary>
|
||||
public record CategoryDto
|
||||
{
|
||||
/// <summary>
|
||||
/// Уникальный идентификатор категории.
|
||||
/// </summary>
|
||||
public Guid Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Название категории.
|
||||
/// </summary>
|
||||
public string Name { get; private set; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// URL-совместимый идентификатор (slug).
|
||||
/// </summary>
|
||||
public string Slug { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Идентификатор родительской категории (null, если корневая).
|
||||
/// </summary>
|
||||
public Guid? ParentId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// JSON-схема характеристик, специфичных для категории.
|
||||
/// </summary>
|
||||
public JsonDocument? AttributeSchema { get; init; }
|
||||
|
||||
public CategoryDto(Guid id, string name, string slug, Guid? parentId, JsonDocument? attributeSchema)
|
||||
{
|
||||
Id = id;
|
||||
Name = name;
|
||||
Slug = slug;
|
||||
ParentId = parentId;
|
||||
AttributeSchema = attributeSchema;
|
||||
}
|
||||
|
||||
public CategoryDto() { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DTO услуги/оффера.
|
||||
/// </summary>
|
||||
public record OfferDto
|
||||
{
|
||||
/// <summary>
|
||||
/// Уникальный идентификатор услуги.
|
||||
/// </summary>
|
||||
public Guid Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Идентификатор владельца (исполнителя).
|
||||
/// </summary>
|
||||
public Guid PerformerId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Идентификатор категории.
|
||||
/// </summary>
|
||||
public Guid CategoryId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Заголовок услуги.
|
||||
/// </summary>
|
||||
public string Title { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Подробное описание услуги.
|
||||
/// </summary>
|
||||
public string Description { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Цена услуги.
|
||||
/// </summary>
|
||||
public Price Price { get; init; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// JSON-объект с характеристиками услуги.
|
||||
/// </summary>
|
||||
public JsonDocument? Attributes { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Флаг активности услуги.
|
||||
/// </summary>
|
||||
public bool IsActive { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Изображения услуги.
|
||||
/// </summary>
|
||||
public List<string> Images { get; init; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Имя исполнителя.
|
||||
/// </summary>
|
||||
public string? PerformerName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Роль исполнителя (Мастер, Специалист и т.д.).
|
||||
/// </summary>
|
||||
public string? PerformerRole { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Средний рейтинг услуги.
|
||||
/// </summary>
|
||||
public double Rating { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Количество отзывов об услуге.
|
||||
/// </summary>
|
||||
public int ReviewsCount { get; init; }
|
||||
|
||||
public OfferDto(Guid id, Guid performerId, Guid categoryId, string title, string description, Price price, JsonDocument? attributes, bool isActive, List<string>? images = null, string? performerName = null, string? performerRole = null, double rating = 0, int reviewsCount = 0)
|
||||
{
|
||||
Id = id;
|
||||
PerformerId = performerId;
|
||||
CategoryId = categoryId;
|
||||
Title = title;
|
||||
Description = description;
|
||||
Price = price;
|
||||
Attributes = attributes;
|
||||
IsActive = isActive;
|
||||
if (images != null)
|
||||
{
|
||||
Images.AddRange(images);
|
||||
}
|
||||
PerformerName = performerName;
|
||||
PerformerRole = performerRole;
|
||||
Rating = rating;
|
||||
ReviewsCount = reviewsCount;
|
||||
}
|
||||
|
||||
public OfferDto() { }
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\Nashel.BuildingBlocks.csproj" />
|
||||
<ProjectReference Include="..\Domain\Nashel.Modules.Catalog.Domain.csproj" />
|
||||
<ProjectReference Include="..\..\Identity\Application\Nashel.Modules.Identity.Application.csproj" />
|
||||
<ProjectReference Include="..\..\Reputation\Application\Nashel.Modules.Reputation.Application.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MediatR" Version="14.0.0" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<RootNamespace>Nashel.Modules.Catalog.Application</RootNamespace>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn);1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,41 @@
|
||||
using System.Text.Json;
|
||||
using MediatR;
|
||||
using Nashel.BuildingBlocks.Domain;
|
||||
using Nashel.Modules.Catalog.Application.Common;
|
||||
using Nashel.Modules.Catalog.Domain.Repositories;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Application.Queries;
|
||||
|
||||
/// <summary>
|
||||
/// Запрос дерева категорий.
|
||||
/// </summary>
|
||||
public record GetCategoriesQuery() : IRequest<Result<List<CategoryDto>>>;
|
||||
|
||||
public class GetCategoriesQueryHandler : IRequestHandler<GetCategoriesQuery, Result<List<CategoryDto>>>
|
||||
{
|
||||
private readonly ICategoryRepository _repository;
|
||||
|
||||
public GetCategoriesQueryHandler(ICategoryRepository repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
public async Task<Result<List<CategoryDto>>> Handle(GetCategoriesQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var rawCategories = await _repository.GetAllAsync(cancellationToken);
|
||||
|
||||
// Преобразование в DTO (для дерева логика нужна сложнее, но пока плоский список для старта)
|
||||
// Если нужно дерево: нужно иметь DTO с List<CategoryDto> Children
|
||||
// Для MVP возвращаем плоский список, фронтенд сам строит дерево по ParentId
|
||||
|
||||
var list = rawCategories.Select(c => new CategoryDto(
|
||||
c.Id,
|
||||
c.Name,
|
||||
c.Slug,
|
||||
c.ParentId,
|
||||
c.AttributeSchema
|
||||
)).ToList();
|
||||
|
||||
return Result<List<CategoryDto>>.Success(list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using MediatR;
|
||||
using Nashel.BuildingBlocks.Application.Abstractions;
|
||||
using Nashel.BuildingBlocks.Domain;
|
||||
using Nashel.Modules.Catalog.Application.Common;
|
||||
using Nashel.Modules.Catalog.Domain.Repositories;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Application.Queries;
|
||||
|
||||
/// <summary>
|
||||
/// Запрос получения услуг текущего пользователя.
|
||||
/// </summary>
|
||||
public record GetMyOffersQuery() : IRequest<Result<List<OfferDto>>>;
|
||||
|
||||
public class GetMyOffersQueryHandler : IRequestHandler<GetMyOffersQuery, Result<List<OfferDto>>>
|
||||
{
|
||||
private readonly IOfferRepository _repository;
|
||||
private readonly ICurrentUserService _currentUserService;
|
||||
|
||||
public GetMyOffersQueryHandler(IOfferRepository repository, ICurrentUserService currentUserService)
|
||||
{
|
||||
_repository = repository;
|
||||
_currentUserService = currentUserService;
|
||||
}
|
||||
|
||||
public async Task<Result<List<OfferDto>>> Handle(GetMyOffersQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var userId = _currentUserService.UserId;
|
||||
if (userId == null) return Result<List<OfferDto>>.Failure("Неавторизован");
|
||||
|
||||
var offers = await _repository.GetByPerformerIdAsync(userId.Value, cancellationToken);
|
||||
|
||||
var list = offers.Select(offer => new OfferDto(
|
||||
offer.Id,
|
||||
offer.PerformerId,
|
||||
offer.CategoryId,
|
||||
offer.Title,
|
||||
offer.Description ?? string.Empty,
|
||||
offer.Price,
|
||||
offer.Attributes,
|
||||
offer.IsActive,
|
||||
offer.Images
|
||||
)).ToList();
|
||||
|
||||
return Result<List<OfferDto>>.Success(list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using MediatR;
|
||||
using Nashel.BuildingBlocks.Domain;
|
||||
using Nashel.Modules.Catalog.Application.Common;
|
||||
using Nashel.Modules.Catalog.Domain.Repositories;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Application.Queries;
|
||||
|
||||
/// <summary>
|
||||
/// Запрос деталей услуги по ID.
|
||||
/// </summary>
|
||||
public record GetOfferByIdQuery(Guid Id) : IRequest<Result<OfferDto>>;
|
||||
|
||||
public class GetOfferByIdQueryHandler : IRequestHandler<GetOfferByIdQuery, Result<OfferDto>>
|
||||
{
|
||||
private readonly IOfferRepository _repository;
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
public GetOfferByIdQueryHandler(IOfferRepository repository, IMediator mediator)
|
||||
{
|
||||
_repository = repository;
|
||||
_mediator = mediator;
|
||||
}
|
||||
|
||||
public async Task<Result<OfferDto>> Handle(GetOfferByIdQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var offer = await _repository.GetByIdAsync(request.Id, cancellationToken);
|
||||
if (offer == null)
|
||||
{
|
||||
throw new Nashel.BuildingBlocks.Application.Exceptions.NotFoundException("Offer", request.Id);
|
||||
}
|
||||
|
||||
// Получаем данные исполнителя и рейтинги
|
||||
var userDetailsResult = await _mediator.Send(new Nashel.Modules.Identity.Application.Queries.GetUserDetailsQuery(offer.PerformerId), cancellationToken);
|
||||
var profileRatingResult = await _mediator.Send(new Nashel.Modules.Reputation.Application.Queries.GetProfileRatingQuery(offer.PerformerId), cancellationToken);
|
||||
|
||||
var dto = new OfferDto(
|
||||
offer.Id,
|
||||
offer.PerformerId,
|
||||
offer.CategoryId,
|
||||
offer.Title,
|
||||
offer.Description ?? string.Empty,
|
||||
offer.Price,
|
||||
offer.Attributes,
|
||||
offer.IsActive,
|
||||
offer.Images,
|
||||
performerName: (userDetailsResult != null && userDetailsResult.IsSuccess && userDetailsResult.Value != null) ? userDetailsResult.Value.FullName : "Неизвестный исполнитель",
|
||||
performerRole: (userDetailsResult != null && userDetailsResult.IsSuccess && userDetailsResult.Value != null) ? userDetailsResult.Value.PrimaryRole : "Пользователь",
|
||||
rating: profileRatingResult?.AverageRating ?? 0,
|
||||
reviewsCount: profileRatingResult?.TotalReviews ?? 0
|
||||
);
|
||||
|
||||
return Result<OfferDto>.Success(dto);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
|
||||
/// <summary>
|
||||
/// Категория услуг.
|
||||
/// </summary>
|
||||
public class Category
|
||||
{
|
||||
/// <summary>
|
||||
/// Уникальный идентификатор.
|
||||
/// </summary>
|
||||
public Guid Id { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Название категории.
|
||||
/// </summary>
|
||||
public string Name { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// URL-friendly идентификатор (слаг).
|
||||
/// </summary>
|
||||
public string Slug { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// ID родительской категории (null для корневых).
|
||||
/// </summary>
|
||||
public Guid? ParentId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Шаблон характеристик (JSON).
|
||||
/// </summary>
|
||||
public JsonDocument? AttributeSchema { get; private set; }
|
||||
|
||||
// Конструктор по умолчанию для EF Core
|
||||
private Category() { }
|
||||
|
||||
/// <summary>
|
||||
/// Создает новую категорию.
|
||||
/// </summary>
|
||||
public Category(string name, string slug, Guid? parentId, JsonDocument? attributeSchema = null)
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
Name = name;
|
||||
Slug = slug;
|
||||
ParentId = parentId;
|
||||
AttributeSchema = attributeSchema;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
using System.Text.Json;
|
||||
using Nashel.Modules.Catalog.Domain.ValueObjects;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
|
||||
/// <summary>
|
||||
/// Услуга или оффер исполнителя.
|
||||
/// </summary>
|
||||
public class Offer
|
||||
{
|
||||
/// <summary>
|
||||
/// Уникальный идентификатор оффера.
|
||||
/// </summary>
|
||||
public Guid Id { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// ID владельца (пользователя/исполнителя).
|
||||
/// </summary>
|
||||
public Guid PerformerId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// ID услуги/категории.
|
||||
/// </summary>
|
||||
public Guid CategoryId { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Заголовок объявления.
|
||||
/// </summary>
|
||||
public string Title { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Полное описание.
|
||||
/// </summary>
|
||||
public string? Description { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Цена (сумма, валюта, тип оплаты).
|
||||
/// </summary>
|
||||
public Price Price { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Характеристики (JSONB).
|
||||
/// </summary>
|
||||
public JsonDocument? Attributes { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Активно ли объявление.
|
||||
/// </summary>
|
||||
public bool IsActive { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Удалено ли объявление (Soft Delete).
|
||||
/// </summary>
|
||||
public bool IsDeleted { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Дата создания.
|
||||
/// </summary>
|
||||
public DateTimeOffset CreatedAt { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Коллекция изображений (Base64 URL)
|
||||
/// </summary>
|
||||
public List<string> Images { get; private set; } = new();
|
||||
|
||||
// Конструктор по умолчанию для EF Core
|
||||
private Offer() { }
|
||||
|
||||
/// <summary>
|
||||
/// Создает новый оффер.
|
||||
/// </summary>
|
||||
public Offer(Guid performerId, Guid categoryId, string title, string description, Price price, JsonDocument? attributes = null, List<string>? images = null)
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
PerformerId = performerId;
|
||||
CategoryId = categoryId;
|
||||
Title = title;
|
||||
Description = description;
|
||||
Price = price;
|
||||
Attributes = attributes;
|
||||
IsActive = true;
|
||||
IsDeleted = false;
|
||||
CreatedAt = DateTimeOffset.UtcNow;
|
||||
if (images != null)
|
||||
{
|
||||
Images.AddRange(images);
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(string title, string description, Price price, JsonDocument? attributes, List<string>? images)
|
||||
{
|
||||
Title = title;
|
||||
Description = description;
|
||||
Price = price;
|
||||
Attributes = attributes;
|
||||
|
||||
Images.Clear();
|
||||
if (images != null)
|
||||
{
|
||||
Images.AddRange(images);
|
||||
}
|
||||
}
|
||||
|
||||
public void ToggleActive()
|
||||
{
|
||||
IsActive = !IsActive;
|
||||
}
|
||||
|
||||
public void Delete()
|
||||
{
|
||||
IsDeleted = true;
|
||||
IsActive = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace Nashel.Modules.Catalog.Domain.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Тип оплаты услуги.
|
||||
/// </summary>
|
||||
public enum OfferType
|
||||
{
|
||||
/// <summary>
|
||||
/// Фиксированная цена.
|
||||
/// </summary>
|
||||
Fixed,
|
||||
|
||||
/// <summary>
|
||||
/// Почасовая оплата.
|
||||
/// </summary>
|
||||
Hourly,
|
||||
|
||||
/// <summary>
|
||||
/// Договорная цена.
|
||||
/// </summary>
|
||||
Negotiable
|
||||
}
|
||||
+4
-6
@@ -1,18 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\BuildingBlocks\Nashel.RF.BuildingBlocks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MediatR" Version="14.0.0" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\Nashel.BuildingBlocks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<RootNamespace>Nashel.Modules.Catalog.Domain</RootNamespace>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn);1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,10 @@
|
||||
using Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Domain.Repositories;
|
||||
|
||||
public interface ICategoryRepository
|
||||
{
|
||||
Task<Category?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default);
|
||||
Task<List<Category>> GetAllAsync(CancellationToken cancellationToken = default);
|
||||
Task AddAsync(Category category, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Domain.Repositories;
|
||||
|
||||
public interface IOfferRepository
|
||||
{
|
||||
Task<Offer?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default);
|
||||
Task<List<Offer>> GetByPerformerIdAsync(Guid performerId, CancellationToken cancellationToken = default);
|
||||
Task AddAsync(Offer offer, CancellationToken cancellationToken = default);
|
||||
Task UpdateAsync(Offer offer, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using Nashel.Modules.Catalog.Domain.Enums;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Domain.ValueObjects;
|
||||
|
||||
/// <summary>
|
||||
/// Значение цены услуги.
|
||||
/// </summary>
|
||||
public record Price
|
||||
{
|
||||
/// <summary>
|
||||
/// Сумма.
|
||||
/// </summary>
|
||||
public decimal Amount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Валюта (по умолчанию RUB).
|
||||
/// </summary>
|
||||
public string Currency { get; init; } = "RUB";
|
||||
|
||||
/// <summary>
|
||||
/// Тип оплаты (фиксированная, почасовая, договорная).
|
||||
/// </summary>
|
||||
public OfferType Type { get; init; }
|
||||
|
||||
// Конструктор по умолчанию для EF Core и сериализации
|
||||
public Price() { }
|
||||
|
||||
public Price(decimal amount, OfferType type, string currency = "RUB")
|
||||
{
|
||||
Amount = amount;
|
||||
Type = type;
|
||||
Currency = currency;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Nashel.Modules.Catalog.Application.Commands;
|
||||
using Nashel.Modules.Catalog.Domain.Repositories;
|
||||
using Nashel.Modules.Catalog.Infrastructure.Persistence;
|
||||
using Nashel.Modules.Catalog.Infrastructure.Repositories;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Infrastructure;
|
||||
|
||||
public static class DependencyInjection
|
||||
{
|
||||
public static IServiceCollection AddCatalogModule(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
// 1. Регистрация DbContext
|
||||
services.AddDbContext<CatalogDbContext>(options =>
|
||||
{
|
||||
options.UseNpgsql(configuration.GetConnectionString("DefaultConnection"));
|
||||
});
|
||||
|
||||
// 2. Репозитории
|
||||
services.AddScoped<ICategoryRepository, CategoryRepository>();
|
||||
services.AddScoped<IOfferRepository, OfferRepository>();
|
||||
|
||||
// 3. MediatR (сканируем сборку Application)
|
||||
services.AddMediatR(cfg =>
|
||||
{
|
||||
cfg.RegisterServicesFromAssembly(typeof(CreateCategoryCommand).Assembly);
|
||||
});
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\Nashel.BuildingBlocks.csproj" />
|
||||
<ProjectReference Include="..\Application\Nashel.Modules.Catalog.Application.csproj" />
|
||||
<ProjectReference Include="..\Domain\Nashel.Modules.Catalog.Domain.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<RootNamespace>Nashel.Modules.Catalog.Infrastructure</RootNamespace>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,55 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Infrastructure.Persistence;
|
||||
|
||||
public class CatalogDbContext : DbContext
|
||||
{
|
||||
public DbSet<Category> Categories { get; set; } = null!;
|
||||
public DbSet<Offer> Offers { get; set; } = null!;
|
||||
|
||||
public CatalogDbContext(DbContextOptions<CatalogDbContext> options) : base(options) { }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.HasPostgresExtension("postgis"); // Если нужно для чего-то еще, но вообще JSONB встроен.
|
||||
// Но лучше просто не трогать расширения если не уверены.
|
||||
// Для JSONB ничего особенного не нужно, кроме HasColumnType("jsonb").
|
||||
|
||||
modelBuilder.Entity<Category>(entity =>
|
||||
{
|
||||
entity.ToTable("Categories", "catalog");
|
||||
entity.HasKey(e => e.Id);
|
||||
entity.HasIndex(e => e.Slug).IsUnique();
|
||||
|
||||
// Self-referencing
|
||||
entity.HasOne<Category>()
|
||||
.WithMany() // Навигационное свойство Children не добавлено в доменную модель явно, но связь есть
|
||||
.HasForeignKey(e => e.ParentId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
entity.Property(e => e.AttributeSchema)
|
||||
.HasColumnType("jsonb");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Offer>(entity =>
|
||||
{
|
||||
entity.ToTable("Offers", "catalog");
|
||||
entity.HasKey(e => e.Id);
|
||||
|
||||
entity.Property(e => e.Attributes)
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
// GIN Index
|
||||
entity.HasIndex(e => e.Attributes)
|
||||
.HasMethod("gin");
|
||||
|
||||
entity.OwnsOne(e => e.Price, price =>
|
||||
{
|
||||
price.Property(p => p.Amount).HasColumnName("PriceAmount");
|
||||
price.Property(p => p.Currency).HasColumnName("PriceCurrency").HasMaxLength(3);
|
||||
price.Property(p => p.Type).HasColumnName("PriceType"); // Enum as int by default
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Generated
+137
@@ -0,0 +1,137 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Nashel.Modules.Catalog.Infrastructure.Persistence;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Catalog.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(CatalogDbContext))]
|
||||
[Migration("20260210114511_InitialCreate")]
|
||||
partial class InitialCreate
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.2")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis");
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Category", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<JsonDocument>("AttributeSchema")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<Guid?>("ParentId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ParentId");
|
||||
|
||||
b.HasIndex("Slug")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Categories", "catalog");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Offer", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<JsonDocument>("Attributes")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<Guid>("CategoryId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<Guid>("OwnerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Attributes");
|
||||
|
||||
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Attributes"), "gin");
|
||||
|
||||
b.ToTable("Offers", "catalog");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Category", b =>
|
||||
{
|
||||
b.HasOne("Nashel.Modules.Catalog.Domain.Aggregates.Category", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ParentId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Offer", b =>
|
||||
{
|
||||
b.OwnsOne("Nashel.Modules.Catalog.Domain.ValueObjects.Price", "Price", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("OfferId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<decimal>("Amount")
|
||||
.HasColumnType("numeric")
|
||||
.HasColumnName("PriceAmount");
|
||||
|
||||
b1.Property<string>("Currency")
|
||||
.IsRequired()
|
||||
.HasMaxLength(3)
|
||||
.HasColumnType("character varying(3)")
|
||||
.HasColumnName("PriceCurrency");
|
||||
|
||||
b1.Property<int>("Type")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("PriceType");
|
||||
|
||||
b1.HasKey("OfferId");
|
||||
|
||||
b1.ToTable("Offers", "catalog");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("OfferId");
|
||||
});
|
||||
|
||||
b.Navigation("Price")
|
||||
.IsRequired();
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Catalog.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class InitialCreate : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.EnsureSchema(
|
||||
name: "catalog");
|
||||
|
||||
migrationBuilder.AlterDatabase()
|
||||
.Annotation("Npgsql:PostgresExtension:postgis", ",,");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Categories",
|
||||
schema: "catalog",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Title = table.Column<string>(type: "text", nullable: false),
|
||||
Slug = table.Column<string>(type: "text", nullable: false),
|
||||
ParentId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||
AttributeSchema = table.Column<JsonDocument>(type: "jsonb", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Categories", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Categories_Categories_ParentId",
|
||||
column: x => x.ParentId,
|
||||
principalSchema: "catalog",
|
||||
principalTable: "Categories",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Offers",
|
||||
schema: "catalog",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
OwnerId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
CategoryId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Title = table.Column<string>(type: "text", nullable: false),
|
||||
Description = table.Column<string>(type: "text", nullable: true),
|
||||
PriceAmount = table.Column<decimal>(type: "numeric", nullable: false),
|
||||
PriceCurrency = table.Column<string>(type: "character varying(3)", maxLength: 3, nullable: false),
|
||||
PriceType = table.Column<int>(type: "integer", nullable: false),
|
||||
Attributes = table.Column<JsonDocument>(type: "jsonb", nullable: true),
|
||||
IsActive = table.Column<bool>(type: "boolean", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Offers", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Categories_ParentId",
|
||||
schema: "catalog",
|
||||
table: "Categories",
|
||||
column: "ParentId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Categories_Slug",
|
||||
schema: "catalog",
|
||||
table: "Categories",
|
||||
column: "Slug",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Offers_Attributes",
|
||||
schema: "catalog",
|
||||
table: "Offers",
|
||||
column: "Attributes")
|
||||
.Annotation("Npgsql:IndexMethod", "gin");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Categories",
|
||||
schema: "catalog");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Offers",
|
||||
schema: "catalog");
|
||||
}
|
||||
}
|
||||
}
|
||||
src/Modules/Catalog/Infrastructure/Persistence/Migrations/20260302095500_CatalogRefactor.Designer.cs
Generated
+140
@@ -0,0 +1,140 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Nashel.Modules.Catalog.Infrastructure.Persistence;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Catalog.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(CatalogDbContext))]
|
||||
[Migration("20260302095500_CatalogRefactor")]
|
||||
partial class CatalogRefactor
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.2")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis");
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Category", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<JsonDocument>("AttributeSchema")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("ParentId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ParentId");
|
||||
|
||||
b.HasIndex("Slug")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Categories", "catalog");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Offer", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<JsonDocument>("Attributes")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<Guid>("CategoryId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<Guid>("PerformerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Attributes");
|
||||
|
||||
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Attributes"), "gin");
|
||||
|
||||
b.ToTable("Offers", "catalog");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Category", b =>
|
||||
{
|
||||
b.HasOne("Nashel.Modules.Catalog.Domain.Aggregates.Category", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ParentId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Offer", b =>
|
||||
{
|
||||
b.OwnsOne("Nashel.Modules.Catalog.Domain.ValueObjects.Price", "Price", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("OfferId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<decimal>("Amount")
|
||||
.HasColumnType("numeric")
|
||||
.HasColumnName("PriceAmount");
|
||||
|
||||
b1.Property<string>("Currency")
|
||||
.IsRequired()
|
||||
.HasMaxLength(3)
|
||||
.HasColumnType("character varying(3)")
|
||||
.HasColumnName("PriceCurrency");
|
||||
|
||||
b1.Property<int>("Type")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("PriceType");
|
||||
|
||||
b1.HasKey("OfferId");
|
||||
|
||||
b1.ToTable("Offers", "catalog");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("OfferId");
|
||||
});
|
||||
|
||||
b.Navigation("Price")
|
||||
.IsRequired();
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Catalog.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class CatalogRefactor : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "OwnerId",
|
||||
schema: "catalog",
|
||||
table: "Offers",
|
||||
newName: "PerformerId");
|
||||
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "Title",
|
||||
schema: "catalog",
|
||||
table: "Categories",
|
||||
newName: "Name");
|
||||
|
||||
migrationBuilder.AddColumn<DateTimeOffset>(
|
||||
name: "CreatedAt",
|
||||
schema: "catalog",
|
||||
table: "Offers",
|
||||
type: "timestamp with time zone",
|
||||
nullable: false,
|
||||
defaultValue: new DateTimeOffset(new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), new TimeSpan(0, 0, 0, 0, 0)));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "CreatedAt",
|
||||
schema: "catalog",
|
||||
table: "Offers");
|
||||
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "PerformerId",
|
||||
schema: "catalog",
|
||||
table: "Offers",
|
||||
newName: "OwnerId");
|
||||
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "Name",
|
||||
schema: "catalog",
|
||||
table: "Categories",
|
||||
newName: "Title");
|
||||
}
|
||||
}
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Nashel.Modules.Catalog.Infrastructure.Persistence;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Catalog.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(CatalogDbContext))]
|
||||
[Migration("20260306185654_AddOfferImagesAndSoftDelete")]
|
||||
partial class AddOfferImagesAndSoftDelete
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.2")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis");
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Category", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<JsonDocument>("AttributeSchema")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("ParentId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ParentId");
|
||||
|
||||
b.HasIndex("Slug")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Categories", "catalog");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Offer", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<JsonDocument>("Attributes")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<Guid>("CategoryId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.PrimitiveCollection<List<string>>("Images")
|
||||
.IsRequired()
|
||||
.HasColumnType("text[]");
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<Guid>("PerformerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Attributes");
|
||||
|
||||
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Attributes"), "gin");
|
||||
|
||||
b.ToTable("Offers", "catalog");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Category", b =>
|
||||
{
|
||||
b.HasOne("Nashel.Modules.Catalog.Domain.Aggregates.Category", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ParentId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Offer", b =>
|
||||
{
|
||||
b.OwnsOne("Nashel.Modules.Catalog.Domain.ValueObjects.Price", "Price", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("OfferId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<decimal>("Amount")
|
||||
.HasColumnType("numeric")
|
||||
.HasColumnName("PriceAmount");
|
||||
|
||||
b1.Property<string>("Currency")
|
||||
.IsRequired()
|
||||
.HasMaxLength(3)
|
||||
.HasColumnType("character varying(3)")
|
||||
.HasColumnName("PriceCurrency");
|
||||
|
||||
b1.Property<int>("Type")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("PriceType");
|
||||
|
||||
b1.HasKey("OfferId");
|
||||
|
||||
b1.ToTable("Offers", "catalog");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("OfferId");
|
||||
});
|
||||
|
||||
b.Navigation("Price")
|
||||
.IsRequired();
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Catalog.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddOfferImagesAndSoftDelete : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<List<string>>(
|
||||
name: "Images",
|
||||
schema: "catalog",
|
||||
table: "Offers",
|
||||
type: "text[]",
|
||||
nullable: false,
|
||||
defaultValueSql: "'{}'");
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsDeleted",
|
||||
schema: "catalog",
|
||||
table: "Offers",
|
||||
type: "boolean",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Images",
|
||||
schema: "catalog",
|
||||
table: "Offers");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsDeleted",
|
||||
schema: "catalog",
|
||||
table: "Offers");
|
||||
}
|
||||
}
|
||||
}
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Nashel.Modules.Catalog.Infrastructure.Persistence;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Catalog.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(CatalogDbContext))]
|
||||
[Migration("20260310145100_BackendUpdate_Catalog")]
|
||||
partial class BackendUpdate_Catalog
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.2")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis");
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Category", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<JsonDocument>("AttributeSchema")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("ParentId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ParentId");
|
||||
|
||||
b.HasIndex("Slug")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Categories", "catalog");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Offer", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<JsonDocument>("Attributes")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<Guid>("CategoryId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.PrimitiveCollection<List<string>>("Images")
|
||||
.IsRequired()
|
||||
.HasColumnType("text[]");
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<Guid>("PerformerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Attributes");
|
||||
|
||||
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Attributes"), "gin");
|
||||
|
||||
b.ToTable("Offers", "catalog");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Category", b =>
|
||||
{
|
||||
b.HasOne("Nashel.Modules.Catalog.Domain.Aggregates.Category", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ParentId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Offer", b =>
|
||||
{
|
||||
b.OwnsOne("Nashel.Modules.Catalog.Domain.ValueObjects.Price", "Price", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("OfferId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<decimal>("Amount")
|
||||
.HasColumnType("numeric")
|
||||
.HasColumnName("PriceAmount");
|
||||
|
||||
b1.Property<string>("Currency")
|
||||
.IsRequired()
|
||||
.HasMaxLength(3)
|
||||
.HasColumnType("character varying(3)")
|
||||
.HasColumnName("PriceCurrency");
|
||||
|
||||
b1.Property<int>("Type")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("PriceType");
|
||||
|
||||
b1.HasKey("OfferId");
|
||||
|
||||
b1.ToTable("Offers", "catalog");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("OfferId");
|
||||
});
|
||||
|
||||
b.Navigation("Price")
|
||||
.IsRequired();
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Catalog.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class BackendUpdate_Catalog : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Nashel.Modules.Catalog.Infrastructure.Persistence;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Catalog.Infrastructure.Persistence.Migrations
|
||||
{
|
||||
[DbContext(typeof(CatalogDbContext))]
|
||||
partial class CatalogDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.2")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis");
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Category", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<JsonDocument>("AttributeSchema")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("ParentId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Slug")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ParentId");
|
||||
|
||||
b.HasIndex("Slug")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Categories", "catalog");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Offer", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<JsonDocument>("Attributes")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<Guid>("CategoryId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.PrimitiveCollection<List<string>>("Images")
|
||||
.IsRequired()
|
||||
.HasColumnType("text[]");
|
||||
|
||||
b.Property<bool>("IsActive")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<Guid>("PerformerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Attributes");
|
||||
|
||||
NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Attributes"), "gin");
|
||||
|
||||
b.ToTable("Offers", "catalog");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Category", b =>
|
||||
{
|
||||
b.HasOne("Nashel.Modules.Catalog.Domain.Aggregates.Category", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("ParentId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Catalog.Domain.Aggregates.Offer", b =>
|
||||
{
|
||||
b.OwnsOne("Nashel.Modules.Catalog.Domain.ValueObjects.Price", "Price", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("OfferId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<decimal>("Amount")
|
||||
.HasColumnType("numeric")
|
||||
.HasColumnName("PriceAmount");
|
||||
|
||||
b1.Property<string>("Currency")
|
||||
.IsRequired()
|
||||
.HasMaxLength(3)
|
||||
.HasColumnType("character varying(3)")
|
||||
.HasColumnName("PriceCurrency");
|
||||
|
||||
b1.Property<int>("Type")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("PriceType");
|
||||
|
||||
b1.HasKey("OfferId");
|
||||
|
||||
b1.ToTable("Offers", "catalog");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("OfferId");
|
||||
});
|
||||
|
||||
b.Navigation("Price")
|
||||
.IsRequired();
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
using Nashel.Modules.Catalog.Domain.Repositories;
|
||||
using Nashel.Modules.Catalog.Infrastructure.Persistence;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Infrastructure.Repositories;
|
||||
|
||||
public class CategoryRepository : ICategoryRepository
|
||||
{
|
||||
private readonly CatalogDbContext _context;
|
||||
|
||||
public CategoryRepository(CatalogDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<Category?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _context.Categories
|
||||
.Include(c => c.AttributeSchema) // Not needed as it's a property now, but sometimes needed if navigation property (JsonDocument is property)
|
||||
.FirstOrDefaultAsync(c => c.Id == id, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<List<Category>> GetAllAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _context.Categories.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task AddAsync(Category category, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _context.Categories.AddAsync(category, cancellationToken);
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
using Nashel.Modules.Catalog.Domain.Repositories;
|
||||
using Nashel.Modules.Catalog.Infrastructure.Persistence;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Infrastructure.Repositories;
|
||||
|
||||
public class OfferRepository : IOfferRepository
|
||||
{
|
||||
private readonly CatalogDbContext _context;
|
||||
|
||||
public OfferRepository(CatalogDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<Offer?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _context.Offers
|
||||
.FirstOrDefaultAsync(o => o.Id == id, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<List<Offer>> GetByPerformerIdAsync(Guid performerId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _context.Offers
|
||||
.Where(o => o.PerformerId == performerId)
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task AddAsync(Offer offer, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _context.Offers.AddAsync(offer, cancellationToken);
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task UpdateAsync(Offer offer, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_context.Offers.Update(offer);
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Nashel.Modules.Catalog.Application.Commands;
|
||||
using Nashel.Modules.Catalog.Application.Queries;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Presentation.Endpoints;
|
||||
|
||||
/// <summary>
|
||||
/// API Каталога (Категории и Услуги).
|
||||
/// </summary>
|
||||
public static class CatalogEndpoints
|
||||
{
|
||||
public static void MapCatalogEndpoints(this IEndpointRouteBuilder app)
|
||||
{
|
||||
var catalogGroup = app.MapGroup("/api/catalog").WithTags("Catalog");
|
||||
|
||||
// --- Категории ---
|
||||
|
||||
catalogGroup.MapPost("/categories", async ([FromBody] CreateCategoryCommand command, ISender sender) =>
|
||||
{
|
||||
var result = await sender.Send(command);
|
||||
return result.IsSuccess ? Results.Ok(result.Value) : Results.BadRequest(result.Error);
|
||||
})
|
||||
.WithName("CreateCategory")
|
||||
.WithOpenApi(operation => new(operation) { Summary = "Создать категорию (Admin)", Description = "Создает новую категорию. Требуются права администратора." });
|
||||
|
||||
catalogGroup.MapGet("/categories", async (ISender sender) =>
|
||||
{
|
||||
var result = await sender.Send(new GetCategoriesQuery());
|
||||
return result.IsSuccess ? Results.Ok(result.Value) : Results.BadRequest(result.Error);
|
||||
})
|
||||
.WithName("GetCategories")
|
||||
.WithOpenApi(operation => new(operation) { Summary = "Получить все категории", Description = "Возвращает плоский список категорий с указанием ParentId для иерархии." });
|
||||
|
||||
// --- Услуги (Offers) ---
|
||||
|
||||
var protectedOffersGroup = catalogGroup.MapGroup("").RequireAuthorization();
|
||||
|
||||
protectedOffersGroup.MapGet("/offers/my", async (ISender sender) =>
|
||||
{
|
||||
var result = await sender.Send(new GetMyOffersQuery());
|
||||
return result.IsSuccess ? Results.Ok(result.Value) : Results.BadRequest(result.Error);
|
||||
})
|
||||
.WithName("GetMyOffers")
|
||||
.WithOpenApi(operation => new(operation) { Summary = "Получить мои услуги", Description = "Возвращает список услуг текущего пользователя." });
|
||||
|
||||
protectedOffersGroup.MapPost("/offers", async ([FromBody] CreateOfferCommand command, ISender sender) =>
|
||||
{
|
||||
var result = await sender.Send(command);
|
||||
return result.IsSuccess ? Results.Ok(result.Value) : Results.BadRequest(result.Error);
|
||||
})
|
||||
.WithName("CreateOffer")
|
||||
.WithOpenApi(operation => new(operation) { Summary = "Создать оффер/услугу", Description = "Создает новое предложение услуги в указанной категории." });
|
||||
|
||||
catalogGroup.MapGet("/offers/{id:guid}", async (Guid id, ISender sender) =>
|
||||
{
|
||||
var result = await sender.Send(new GetOfferByIdQuery(id));
|
||||
return result.IsSuccess && result.Value is not null ? Results.Ok(result.Value) : Results.NotFound();
|
||||
})
|
||||
.WithName("GetOfferById")
|
||||
.WithOpenApi(operation => new(operation) { Summary = "Получить детали услуги по ID", Description = "Возвращает полную информацию об услуге." });
|
||||
|
||||
protectedOffersGroup.MapPut("/offers/{id:guid}", async (Guid id, [FromBody] UpdateOfferPayload payload, ISender sender) =>
|
||||
{
|
||||
var command = new UpdateOfferCommand(id, payload.Title, payload.Description, payload.Price.Amount, payload.Price.Type, payload.Attributes, payload.Images);
|
||||
await sender.Send(command);
|
||||
return Results.NoContent();
|
||||
})
|
||||
.WithName("UpdateOffer")
|
||||
.WithOpenApi(operation => new(operation) { Summary = "Обновить услугу" });
|
||||
|
||||
protectedOffersGroup.MapPatch("/offers/{id:guid}/toggle", async (Guid id, ISender sender) =>
|
||||
{
|
||||
var isActive = await sender.Send(new ToggleOfferStatusCommand(id));
|
||||
return Results.Ok(new { IsActive = isActive });
|
||||
})
|
||||
.WithName("ToggleOfferStatus")
|
||||
.WithOpenApi(operation => new(operation) { Summary = "Приостановить/активировать услугу" });
|
||||
|
||||
protectedOffersGroup.MapDelete("/offers/{id:guid}", async (Guid id, ISender sender) =>
|
||||
{
|
||||
await sender.Send(new DeleteOfferCommand(id));
|
||||
return Results.NoContent();
|
||||
})
|
||||
.WithName("DeleteOffer")
|
||||
.WithOpenApi(operation => new(operation) { Summary = "Удалить услугу" });
|
||||
|
||||
protectedOffersGroup.MapPost("/offers/image", async (IFormFile file, ISender sender) =>
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
await file.CopyToAsync(ms);
|
||||
var url = await sender.Send(new UploadOfferImageCommand(ms.ToArray(), file.FileName));
|
||||
return Results.Ok(new { url });
|
||||
})
|
||||
.WithName("UploadOfferImage")
|
||||
.WithOpenApi(operation => new(operation) { Summary = "Загрузить изображение для услуги" })
|
||||
.DisableAntiforgery();
|
||||
}
|
||||
}
|
||||
|
||||
public record UpdateOfferPayload(
|
||||
string Title,
|
||||
string Description,
|
||||
PricePayload Price,
|
||||
Dictionary<string, string>? Attributes,
|
||||
List<string>? Images);
|
||||
public record PricePayload(decimal Amount, int Type);
|
||||
@@ -0,0 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Application\Nashel.Modules.Catalog.Application.csproj" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<RootNamespace>Nashel.Modules.Catalog.Presentation</RootNamespace>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<NoWarn>$(NoWarn);1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.4" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,48 @@
|
||||
using FluentAssertions;
|
||||
using NSubstitute;
|
||||
using Nashel.Modules.Catalog.Application.Commands;
|
||||
using Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
using Nashel.Modules.Catalog.Domain.Repositories;
|
||||
using Xunit;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Tests.Application;
|
||||
|
||||
public class CreateCategoryCommandHandlerTests
|
||||
{
|
||||
private readonly ICategoryRepository _categoryRepository;
|
||||
private readonly CreateCategoryCommandHandler _handler;
|
||||
|
||||
public CreateCategoryCommandHandlerTests()
|
||||
{
|
||||
// Инициализация мока через NSubstitute
|
||||
_categoryRepository = Substitute.For<ICategoryRepository>();
|
||||
_handler = new CreateCategoryCommandHandler(_categoryRepository);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldCreateCategory_WhenCommandIsValid()
|
||||
{
|
||||
// Arrange (Подготовка)
|
||||
var command = new CreateCategoryCommand(
|
||||
"Test Category",
|
||||
"test-category",
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
// Act (Действие)
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert (Проверка)
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
result.Value.Should().NotBeEmpty();
|
||||
|
||||
// Проверяем вызов репозитория
|
||||
await _categoryRepository.Received(1).AddAsync(Arg.Is<Category>(c =>
|
||||
c.Name == command.Name &&
|
||||
c.Slug == command.Slug &&
|
||||
c.ParentId == command.ParentId &&
|
||||
c.AttributeSchema == command.AttributeSchema
|
||||
), Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using FluentAssertions;
|
||||
using NSubstitute;
|
||||
using Nashel.BuildingBlocks.Application.Abstractions;
|
||||
using Nashel.Modules.Catalog.Application.Commands;
|
||||
using Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
using Nashel.Modules.Catalog.Domain.Enums;
|
||||
using Nashel.Modules.Catalog.Domain.Repositories;
|
||||
using Nashel.Modules.Catalog.Domain.ValueObjects;
|
||||
using System.Text.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Tests.Application;
|
||||
|
||||
public class CreateOfferCommandHandlerTests
|
||||
{
|
||||
private readonly IOfferRepository _offerRepository;
|
||||
private readonly ICurrentUserService _currentUserService;
|
||||
private readonly CreateOfferCommandHandler _handler;
|
||||
|
||||
public CreateOfferCommandHandlerTests()
|
||||
{
|
||||
// Инициализация моков через NSubstitute
|
||||
_offerRepository = Substitute.For<IOfferRepository>();
|
||||
_currentUserService = Substitute.For<ICurrentUserService>();
|
||||
_handler = new CreateOfferCommandHandler(_offerRepository, _currentUserService);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldCreateOffer_WhenCommandIsValid()
|
||||
{
|
||||
// Arrange (Подготовка)
|
||||
var userId = Guid.NewGuid();
|
||||
var categoryId = Guid.NewGuid();
|
||||
var command = new CreateOfferCommand(
|
||||
categoryId,
|
||||
"Test Offer",
|
||||
"Test Description",
|
||||
new Price(100, OfferType.Fixed, "RUB"),
|
||||
JsonDocument.Parse("{}"),
|
||||
null
|
||||
);
|
||||
|
||||
_currentUserService.UserId.Returns(userId);
|
||||
|
||||
// Act (Действие)
|
||||
var result = await _handler.Handle(command, CancellationToken.None);
|
||||
|
||||
// Assert (Проверка)
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
result.Value.Should().NotBeEmpty();
|
||||
|
||||
// Проверяем, что метод AddAsync был вызван ровно один раз с правильными параметрами
|
||||
await _offerRepository.Received(1).AddAsync(Arg.Is<Offer>(o =>
|
||||
o.Title == command.Title &&
|
||||
o.PerformerId == userId &&
|
||||
o.CategoryId == command.CategoryId &&
|
||||
o.Description == command.Description &&
|
||||
o.Price.Amount == command.Price.Amount &&
|
||||
o.Price.Type == command.Price.Type &&
|
||||
o.Price.Currency == command.Price.Currency &&
|
||||
o.Attributes == command.Attributes
|
||||
), Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
using FluentAssertions;
|
||||
using NSubstitute;
|
||||
using Nashel.Modules.Catalog.Application.Common;
|
||||
using Nashel.Modules.Catalog.Application.Queries;
|
||||
using Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
using Nashel.Modules.Catalog.Domain.Repositories;
|
||||
using System.Text.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Tests.Application;
|
||||
|
||||
public class GetCategoriesQueryHandlerTests
|
||||
{
|
||||
private readonly ICategoryRepository _categoryRepository;
|
||||
private readonly GetCategoriesQueryHandler _handler;
|
||||
|
||||
public GetCategoriesQueryHandlerTests()
|
||||
{
|
||||
// Инициализация мока репозитория через NSubstitute
|
||||
_categoryRepository = Substitute.For<ICategoryRepository>();
|
||||
_handler = new GetCategoriesQueryHandler(_categoryRepository);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldReturnCategories_WhenCategoriesExist()
|
||||
{
|
||||
// Arrange (Подготовка)
|
||||
var categories = new List<Category>
|
||||
{
|
||||
new Category("Category 1", "category-1", null),
|
||||
new Category("Category 2", "category-2", null)
|
||||
};
|
||||
_categoryRepository.GetAllAsync(Arg.Any<CancellationToken>())
|
||||
.Returns(categories);
|
||||
|
||||
var query = new GetCategoriesQuery();
|
||||
|
||||
// Act (Действие)
|
||||
var result = await _handler.Handle(query, CancellationToken.None);
|
||||
|
||||
// Assert (Проверка)
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
result.Value.Should().NotBeNull();
|
||||
result.Value.Should().HaveCount(2);
|
||||
|
||||
// Сверяем DTO с данными из доменных сущностей
|
||||
result.Value.Should().ContainEquivalentOf(new { Name = "Category 1", Slug = "category-1" });
|
||||
result.Value.Should().ContainEquivalentOf(new { Name = "Category 2", Slug = "category-2" });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldReturnEmptyList_WhenNoCategoriesExist()
|
||||
{
|
||||
// Arrange (Подготовка)
|
||||
_categoryRepository.GetAllAsync(Arg.Any<CancellationToken>())
|
||||
.Returns(new List<Category>());
|
||||
|
||||
var query = new GetCategoriesQuery();
|
||||
|
||||
// Act (Действие)
|
||||
var result = await _handler.Handle(query, CancellationToken.None);
|
||||
|
||||
// Assert (Проверка)
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
result.Value.Should().NotBeNull();
|
||||
result.Value.Should().BeEmpty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using FluentAssertions;
|
||||
using NSubstitute;
|
||||
using MediatR;
|
||||
using Nashel.Modules.Catalog.Application.Common;
|
||||
using Nashel.Modules.Catalog.Application.Queries;
|
||||
using Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
using Nashel.Modules.Catalog.Domain.Repositories;
|
||||
using Nashel.Modules.Catalog.Domain.ValueObjects;
|
||||
using Nashel.Modules.Catalog.Domain.Enums;
|
||||
using Nashel.BuildingBlocks.Application.Exceptions;
|
||||
using System.Text.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Tests.Application;
|
||||
|
||||
public class GetOfferByIdQueryHandlerTests
|
||||
{
|
||||
private readonly IOfferRepository _offerRepository;
|
||||
private readonly IMediator _mediator;
|
||||
private readonly GetOfferByIdQueryHandler _handler;
|
||||
|
||||
public GetOfferByIdQueryHandlerTests()
|
||||
{
|
||||
_offerRepository = Substitute.For<IOfferRepository>();
|
||||
_mediator = Substitute.For<IMediator>();
|
||||
_handler = new GetOfferByIdQueryHandler(_offerRepository, _mediator);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldReturnOffer_WhenOfferExists()
|
||||
{
|
||||
// Arrange (Подготовка)
|
||||
var offer = new Offer(
|
||||
Guid.NewGuid(),
|
||||
Guid.NewGuid(),
|
||||
"Test Offer",
|
||||
"Test Description",
|
||||
new Price(100, OfferType.Fixed, "RUB"),
|
||||
JsonDocument.Parse("{}")
|
||||
);
|
||||
|
||||
_offerRepository.GetByIdAsync(offer.Id, Arg.Any<CancellationToken>())
|
||||
.Returns(offer);
|
||||
|
||||
// Настройка мока Mediator для внутренних запросов
|
||||
_mediator.Send(Arg.Any<Nashel.Modules.Identity.Application.Queries.GetUserDetailsQuery>(), Arg.Any<CancellationToken>())
|
||||
.Returns(Nashel.BuildingBlocks.Domain.Result<Nashel.Modules.Identity.Application.Queries.UserDetailsDto>.Success(
|
||||
new Nashel.Modules.Identity.Application.Queries.UserDetailsDto(offer.PerformerId, "Исполнитель", null, "Мастер")));
|
||||
|
||||
_mediator.Send(Arg.Any<Nashel.Modules.Reputation.Application.Queries.GetProfileRatingQuery>(), Arg.Any<CancellationToken>())
|
||||
.Returns(new Nashel.Modules.Reputation.Application.Queries.ProfileRatingDto(4.5, 10));
|
||||
|
||||
var query = new GetOfferByIdQuery(offer.Id);
|
||||
|
||||
// Act (Действие)
|
||||
var result = await _handler.Handle(query, CancellationToken.None);
|
||||
|
||||
// Assert (Проверка)
|
||||
result.IsSuccess.Should().BeTrue();
|
||||
result.Value.Id.Should().Be(offer.Id);
|
||||
result.Value.Title.Should().Be("Test Offer");
|
||||
result.Value.Rating.Should().Be(4.5);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ShouldThrowNotFoundException_WhenOfferDoesNotExist()
|
||||
{
|
||||
// Arrange (Подготовка)
|
||||
_offerRepository.GetByIdAsync(Arg.Any<Guid>(), Arg.Any<CancellationToken>())
|
||||
.Returns((Offer?)null);
|
||||
|
||||
var query = new GetOfferByIdQuery(Guid.NewGuid());
|
||||
|
||||
// Act & Assert (Действие и Проверка)
|
||||
var act = async () => await _handler.Handle(query, CancellationToken.None);
|
||||
await act.Should().ThrowAsync<NotFoundException>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using FluentAssertions;
|
||||
using Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
using System.Text.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Tests.Domain;
|
||||
|
||||
public class CategoryTests
|
||||
{
|
||||
[Fact]
|
||||
public void Constructor_ShouldSetPropertiesCorrectly()
|
||||
{
|
||||
// Arrange (Подготовка)
|
||||
var title = "Test Category";
|
||||
var slug = "test-category";
|
||||
var parentId = Guid.NewGuid();
|
||||
var jsonDoc = JsonDocument.Parse("{}");
|
||||
|
||||
// Act (Действие)
|
||||
var category = new Category(title, slug, parentId, jsonDoc);
|
||||
|
||||
// Assert (Проверка)
|
||||
category.Id.Should().NotBeEmpty();
|
||||
category.Name.Should().Be(title);
|
||||
category.Slug.Should().Be(slug);
|
||||
category.ParentId.Should().Be(parentId);
|
||||
category.AttributeSchema.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_ShouldSetDefaultValues_WhenOptionalParametersAreNull()
|
||||
{
|
||||
// Act (Действие)
|
||||
var category = new Category("Test", "test", null, null);
|
||||
|
||||
// Assert (Проверка)
|
||||
category.ParentId.Should().BeNull();
|
||||
category.AttributeSchema.Should().BeNull();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using FluentAssertions;
|
||||
using Nashel.Modules.Catalog.Domain.Aggregates;
|
||||
using Nashel.Modules.Catalog.Domain.ValueObjects;
|
||||
using Nashel.Modules.Catalog.Domain.Enums;
|
||||
using System.Text.Json;
|
||||
using Xunit;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Tests.Domain;
|
||||
|
||||
public class OfferTests
|
||||
{
|
||||
[Fact]
|
||||
public void Constructor_ShouldSetPropertiesCorrectly()
|
||||
{
|
||||
// Arrange (Подготовка)
|
||||
var performerId = Guid.NewGuid();
|
||||
var categoryId = Guid.NewGuid();
|
||||
var title = "Test Offer";
|
||||
var description = "Test Description";
|
||||
var price = new Price(100, OfferType.Fixed, "RUB");
|
||||
var attributes = JsonDocument.Parse("{}");
|
||||
|
||||
// Act (Действие)
|
||||
var offer = new Offer(performerId, categoryId, title, description, price, attributes);
|
||||
|
||||
// Assert (Проверка)
|
||||
offer.Id.Should().NotBeEmpty();
|
||||
offer.PerformerId.Should().Be(performerId);
|
||||
offer.CategoryId.Should().Be(categoryId);
|
||||
offer.Title.Should().Be(title);
|
||||
offer.Description.Should().Be(description);
|
||||
offer.Price.Should().BeEquivalentTo(price);
|
||||
offer.Attributes.Should().NotBeNull();
|
||||
offer.IsActive.Should().BeTrue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using FluentAssertions;
|
||||
using Nashel.Modules.Catalog.Domain.Enums;
|
||||
using Nashel.Modules.Catalog.Domain.ValueObjects;
|
||||
using Xunit;
|
||||
|
||||
namespace Nashel.Modules.Catalog.Tests.Domain;
|
||||
|
||||
public class PriceTests
|
||||
{
|
||||
[Fact]
|
||||
public void Constructor_ShouldSetPropertiesCorrectly()
|
||||
{
|
||||
// Arrange (Подготовка)
|
||||
var amount = 100m;
|
||||
var type = OfferType.Fixed;
|
||||
var currency = "USD";
|
||||
|
||||
// Act (Действие)
|
||||
var price = new Price(amount, type, currency);
|
||||
|
||||
// Assert (Проверка)
|
||||
price.Amount.Should().Be(amount);
|
||||
price.Type.Should().Be(type);
|
||||
price.Currency.Should().Be(currency);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_ShouldSetDefaultCurrency_WhenNotProvided()
|
||||
{
|
||||
// Act (Действие)
|
||||
var price = new Price(100m, OfferType.Fixed);
|
||||
|
||||
// Assert (Проверка)
|
||||
price.Currency.Should().Be("RUB");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Equality_ShouldBeTrue_WhenValuesAreSame()
|
||||
{
|
||||
// Arrange (Подготовка)
|
||||
var price1 = new Price(100m, OfferType.Fixed, "USD");
|
||||
var price2 = new Price(100m, OfferType.Fixed, "USD");
|
||||
|
||||
// Act & Assert (Действие и Проверка)
|
||||
price1.Should().Be(price2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Equality_ShouldBeFalse_WhenValuesAreDifferent()
|
||||
{
|
||||
// Arrange (Подготовка)
|
||||
var price1 = new Price(100m, OfferType.Fixed, "USD");
|
||||
var price2 = new Price(200m, OfferType.Fixed, "USD");
|
||||
|
||||
// Act & Assert (Действие и Проверка)
|
||||
price1.Should().NotBe(price2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="xunit" Version="2.5.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
|
||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
||||
<PackageReference Include="NSubstitute" Version="5.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Domain\Nashel.Modules.Catalog.Domain.csproj" />
|
||||
<ProjectReference Include="..\Application\Nashel.Modules.Catalog.Application.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\Nashel.BuildingBlocks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -1,714 +0,0 @@
|
||||
{
|
||||
"format": 1,
|
||||
"restore": {
|
||||
"E:\\GIT\\mvp\\backend\\src\\Modules\\Catalog\\Nashel.RF.Modules.Catalog.csproj": {}
|
||||
},
|
||||
"projects": {
|
||||
"E:\\GIT\\mvp\\backend\\src\\BuildingBlocks\\Nashel.RF.BuildingBlocks.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "E:\\GIT\\mvp\\backend\\src\\BuildingBlocks\\Nashel.RF.BuildingBlocks.csproj",
|
||||
"projectName": "Nashel.RF.BuildingBlocks",
|
||||
"projectPath": "E:\\GIT\\mvp\\backend\\src\\BuildingBlocks\\Nashel.RF.BuildingBlocks.csproj",
|
||||
"packagesPath": "C:\\Users\\HomePC\\.nuget\\packages\\",
|
||||
"outputPath": "E:\\GIT\\mvp\\backend\\src\\BuildingBlocks\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\HomePC\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net10.0"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"C:\\Program Files\\dotnet\\library-packs": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "all"
|
||||
},
|
||||
"SdkAnalysisLevel": "10.0.100"
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"targetAlias": "net10.0",
|
||||
"dependencies": {
|
||||
"FluentValidation": {
|
||||
"target": "Package",
|
||||
"version": "[12.1.1, )"
|
||||
},
|
||||
"MediatR": {
|
||||
"target": "Package",
|
||||
"version": "[14.0.0, )"
|
||||
},
|
||||
"Microsoft.EntityFrameworkCore.Relational": {
|
||||
"target": "Package",
|
||||
"version": "[10.0.2, )"
|
||||
}
|
||||
},
|
||||
"imports": [
|
||||
"net461",
|
||||
"net462",
|
||||
"net47",
|
||||
"net471",
|
||||
"net472",
|
||||
"net48",
|
||||
"net481"
|
||||
],
|
||||
"assetTargetFallback": true,
|
||||
"warn": true,
|
||||
"frameworkReferences": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.100-preview.6.25358.103/PortableRuntimeIdentifierGraph.json",
|
||||
"packagesToPrune": {
|
||||
"Microsoft.CSharp": "(,4.7.32767]",
|
||||
"Microsoft.VisualBasic": "(,10.4.32767]",
|
||||
"Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"Microsoft.Win32.Registry": "(,5.0.32767]",
|
||||
"runtime.any.System.Collections": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.any.System.IO": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.any.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.aot.System.Collections": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.aot.System.IO": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.aot.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.unix.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Console": "(,4.3.32767]",
|
||||
"runtime.unix.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.unix.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.unix.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.unix.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Console": "(,4.3.32767]",
|
||||
"runtime.win.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.win.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.win.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win10-arm-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-arm64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win10-x64-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-x86-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7-x86.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.win8-arm.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"System.AppContext": "(,4.3.32767]",
|
||||
"System.Buffers": "(,5.0.32767]",
|
||||
"System.Collections": "(,4.3.32767]",
|
||||
"System.Collections.Concurrent": "(,4.3.32767]",
|
||||
"System.Collections.Immutable": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Collections.NonGeneric": "(,4.3.32767]",
|
||||
"System.Collections.Specialized": "(,4.3.32767]",
|
||||
"System.ComponentModel": "(,4.3.32767]",
|
||||
"System.ComponentModel.Annotations": "(,4.3.32767]",
|
||||
"System.ComponentModel.EventBasedAsync": "(,4.3.32767]",
|
||||
"System.ComponentModel.Primitives": "(,4.3.32767]",
|
||||
"System.ComponentModel.TypeConverter": "(,4.3.32767]",
|
||||
"System.Console": "(,4.3.32767]",
|
||||
"System.Data.Common": "(,4.3.32767]",
|
||||
"System.Data.DataSetExtensions": "(,4.4.32767]",
|
||||
"System.Diagnostics.Contracts": "(,4.3.32767]",
|
||||
"System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"System.Diagnostics.DiagnosticSource": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Diagnostics.FileVersionInfo": "(,4.3.32767]",
|
||||
"System.Diagnostics.Process": "(,4.3.32767]",
|
||||
"System.Diagnostics.StackTrace": "(,4.3.32767]",
|
||||
"System.Diagnostics.TextWriterTraceListener": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"System.Diagnostics.TraceSource": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"System.Drawing.Primitives": "(,4.3.32767]",
|
||||
"System.Dynamic.Runtime": "(,4.3.32767]",
|
||||
"System.Formats.Asn1": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Formats.Tar": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Globalization": "(,4.3.32767]",
|
||||
"System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"System.Globalization.Extensions": "(,4.3.32767]",
|
||||
"System.IO": "(,4.3.32767]",
|
||||
"System.IO.Compression": "(,4.3.32767]",
|
||||
"System.IO.Compression.ZipFile": "(,4.3.32767]",
|
||||
"System.IO.FileSystem": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.AccessControl": "(,4.4.32767]",
|
||||
"System.IO.FileSystem.DriveInfo": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Primitives": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Watcher": "(,4.3.32767]",
|
||||
"System.IO.IsolatedStorage": "(,4.3.32767]",
|
||||
"System.IO.MemoryMappedFiles": "(,4.3.32767]",
|
||||
"System.IO.Pipelines": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.IO.Pipes": "(,4.3.32767]",
|
||||
"System.IO.Pipes.AccessControl": "(,5.0.32767]",
|
||||
"System.IO.UnmanagedMemoryStream": "(,4.3.32767]",
|
||||
"System.Linq": "(,4.3.32767]",
|
||||
"System.Linq.AsyncEnumerable": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Linq.Expressions": "(,4.3.32767]",
|
||||
"System.Linq.Parallel": "(,4.3.32767]",
|
||||
"System.Linq.Queryable": "(,4.3.32767]",
|
||||
"System.Memory": "(,5.0.32767]",
|
||||
"System.Net.Http": "(,4.3.32767]",
|
||||
"System.Net.Http.Json": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Net.NameResolution": "(,4.3.32767]",
|
||||
"System.Net.NetworkInformation": "(,4.3.32767]",
|
||||
"System.Net.Ping": "(,4.3.32767]",
|
||||
"System.Net.Primitives": "(,4.3.32767]",
|
||||
"System.Net.Requests": "(,4.3.32767]",
|
||||
"System.Net.Security": "(,4.3.32767]",
|
||||
"System.Net.ServerSentEvents": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Net.Sockets": "(,4.3.32767]",
|
||||
"System.Net.WebHeaderCollection": "(,4.3.32767]",
|
||||
"System.Net.WebSockets": "(,4.3.32767]",
|
||||
"System.Net.WebSockets.Client": "(,4.3.32767]",
|
||||
"System.Numerics.Vectors": "(,5.0.32767]",
|
||||
"System.ObjectModel": "(,4.3.32767]",
|
||||
"System.Private.DataContractSerialization": "(,4.3.32767]",
|
||||
"System.Private.Uri": "(,4.3.32767]",
|
||||
"System.Reflection": "(,4.3.32767]",
|
||||
"System.Reflection.DispatchProxy": "(,6.0.32767]",
|
||||
"System.Reflection.Emit": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.ILGeneration": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.Lightweight": "(,4.7.32767]",
|
||||
"System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"System.Reflection.Metadata": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"System.Reflection.TypeExtensions": "(,4.3.32767]",
|
||||
"System.Resources.Reader": "(,4.3.32767]",
|
||||
"System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"System.Resources.Writer": "(,4.3.32767]",
|
||||
"System.Runtime": "(,4.3.32767]",
|
||||
"System.Runtime.CompilerServices.Unsafe": "(,7.0.32767]",
|
||||
"System.Runtime.CompilerServices.VisualC": "(,4.3.32767]",
|
||||
"System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"System.Runtime.Handles": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "(,4.3.32767]",
|
||||
"System.Runtime.Loader": "(,4.3.32767]",
|
||||
"System.Runtime.Numerics": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Formatters": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Json": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Primitives": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Xml": "(,4.3.32767]",
|
||||
"System.Security.AccessControl": "(,6.0.32767]",
|
||||
"System.Security.Claims": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Algorithms": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Cng": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Csp": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Encoding": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.OpenSsl": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Primitives": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.X509Certificates": "(,4.3.32767]",
|
||||
"System.Security.Principal": "(,4.3.32767]",
|
||||
"System.Security.Principal.Windows": "(,5.0.32767]",
|
||||
"System.Security.SecureString": "(,4.3.32767]",
|
||||
"System.Text.Encoding": "(,4.3.32767]",
|
||||
"System.Text.Encoding.CodePages": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"System.Text.Encodings.Web": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Text.Json": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Text.RegularExpressions": "(,4.3.32767]",
|
||||
"System.Threading": "(,4.3.32767]",
|
||||
"System.Threading.Channels": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Threading.Overlapped": "(,4.3.32767]",
|
||||
"System.Threading.Tasks": "(,4.3.32767]",
|
||||
"System.Threading.Tasks.Dataflow": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Threading.Tasks.Extensions": "(,5.0.32767]",
|
||||
"System.Threading.Tasks.Parallel": "(,4.3.32767]",
|
||||
"System.Threading.Thread": "(,4.3.32767]",
|
||||
"System.Threading.ThreadPool": "(,4.3.32767]",
|
||||
"System.Threading.Timer": "(,4.3.32767]",
|
||||
"System.ValueTuple": "(,4.5.32767]",
|
||||
"System.Xml.ReaderWriter": "(,4.3.32767]",
|
||||
"System.Xml.XDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlSerializer": "(,4.3.32767]",
|
||||
"System.Xml.XPath": "(,4.3.32767]",
|
||||
"System.Xml.XPath.XDocument": "(,5.0.32767]"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"E:\\GIT\\mvp\\backend\\src\\Modules\\Catalog\\Nashel.RF.Modules.Catalog.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "E:\\GIT\\mvp\\backend\\src\\Modules\\Catalog\\Nashel.RF.Modules.Catalog.csproj",
|
||||
"projectName": "Nashel.RF.Modules.Catalog",
|
||||
"projectPath": "E:\\GIT\\mvp\\backend\\src\\Modules\\Catalog\\Nashel.RF.Modules.Catalog.csproj",
|
||||
"packagesPath": "C:\\Users\\HomePC\\.nuget\\packages\\",
|
||||
"outputPath": "E:\\GIT\\mvp\\backend\\src\\Modules\\Catalog\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\HomePC\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net10.0"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"C:\\Program Files\\dotnet\\library-packs": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"targetAlias": "net10.0",
|
||||
"projectReferences": {
|
||||
"E:\\GIT\\mvp\\backend\\src\\BuildingBlocks\\Nashel.RF.BuildingBlocks.csproj": {
|
||||
"projectPath": "E:\\GIT\\mvp\\backend\\src\\BuildingBlocks\\Nashel.RF.BuildingBlocks.csproj"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "all"
|
||||
},
|
||||
"SdkAnalysisLevel": "10.0.100"
|
||||
},
|
||||
"frameworks": {
|
||||
"net10.0": {
|
||||
"targetAlias": "net10.0",
|
||||
"dependencies": {
|
||||
"MediatR": {
|
||||
"target": "Package",
|
||||
"version": "[14.0.0, )"
|
||||
},
|
||||
"Npgsql.EntityFrameworkCore.PostgreSQL": {
|
||||
"target": "Package",
|
||||
"version": "[10.0.0, )"
|
||||
}
|
||||
},
|
||||
"imports": [
|
||||
"net461",
|
||||
"net462",
|
||||
"net47",
|
||||
"net471",
|
||||
"net472",
|
||||
"net48",
|
||||
"net481"
|
||||
],
|
||||
"assetTargetFallback": true,
|
||||
"warn": true,
|
||||
"frameworkReferences": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\10.0.100-preview.6.25358.103/PortableRuntimeIdentifierGraph.json",
|
||||
"packagesToPrune": {
|
||||
"Microsoft.CSharp": "(,4.7.32767]",
|
||||
"Microsoft.VisualBasic": "(,10.4.32767]",
|
||||
"Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"Microsoft.Win32.Registry": "(,5.0.32767]",
|
||||
"runtime.any.System.Collections": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.any.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.any.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.any.System.IO": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.any.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.any.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.any.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.any.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.aot.System.Collections": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"runtime.aot.System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization": "(,4.3.32767]",
|
||||
"runtime.aot.System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"runtime.aot.System.IO": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"runtime.aot.System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.Handles": "(,4.3.32767]",
|
||||
"runtime.aot.System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding": "(,4.3.32767]",
|
||||
"runtime.aot.System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Tasks": "(,4.3.32767]",
|
||||
"runtime.aot.System.Threading.Timer": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.debian.9-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.27-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.fedora.28-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.opensuse.42.3-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "(,4.3.32767]",
|
||||
"runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography": "(,4.3.32767]",
|
||||
"runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Http": "(,4.3.32767]",
|
||||
"runtime.ubuntu.18.04-x64.runtime.native.System.Net.Security": "(,4.3.32767]",
|
||||
"runtime.unix.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Console": "(,4.3.32767]",
|
||||
"runtime.unix.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.unix.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.unix.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.unix.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.unix.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win.Microsoft.Win32.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Console": "(,4.3.32767]",
|
||||
"runtime.win.System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"runtime.win.System.IO.FileSystem": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Primitives": "(,4.3.32767]",
|
||||
"runtime.win.System.Net.Sockets": "(,4.3.32767]",
|
||||
"runtime.win.System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"runtime.win10-arm-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-arm64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win10-x64-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win10-x86-aot.runtime.native.System.IO.Compression": "(,4.0.32767]",
|
||||
"runtime.win7-x64.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7-x86.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"runtime.win7.System.Private.Uri": "(,4.3.32767]",
|
||||
"runtime.win8-arm.runtime.native.System.IO.Compression": "(,4.3.32767]",
|
||||
"System.AppContext": "(,4.3.32767]",
|
||||
"System.Buffers": "(,5.0.32767]",
|
||||
"System.Collections": "(,4.3.32767]",
|
||||
"System.Collections.Concurrent": "(,4.3.32767]",
|
||||
"System.Collections.Immutable": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Collections.NonGeneric": "(,4.3.32767]",
|
||||
"System.Collections.Specialized": "(,4.3.32767]",
|
||||
"System.ComponentModel": "(,4.3.32767]",
|
||||
"System.ComponentModel.Annotations": "(,4.3.32767]",
|
||||
"System.ComponentModel.EventBasedAsync": "(,4.3.32767]",
|
||||
"System.ComponentModel.Primitives": "(,4.3.32767]",
|
||||
"System.ComponentModel.TypeConverter": "(,4.3.32767]",
|
||||
"System.Console": "(,4.3.32767]",
|
||||
"System.Data.Common": "(,4.3.32767]",
|
||||
"System.Data.DataSetExtensions": "(,4.4.32767]",
|
||||
"System.Diagnostics.Contracts": "(,4.3.32767]",
|
||||
"System.Diagnostics.Debug": "(,4.3.32767]",
|
||||
"System.Diagnostics.DiagnosticSource": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Diagnostics.FileVersionInfo": "(,4.3.32767]",
|
||||
"System.Diagnostics.Process": "(,4.3.32767]",
|
||||
"System.Diagnostics.StackTrace": "(,4.3.32767]",
|
||||
"System.Diagnostics.TextWriterTraceListener": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tools": "(,4.3.32767]",
|
||||
"System.Diagnostics.TraceSource": "(,4.3.32767]",
|
||||
"System.Diagnostics.Tracing": "(,4.3.32767]",
|
||||
"System.Drawing.Primitives": "(,4.3.32767]",
|
||||
"System.Dynamic.Runtime": "(,4.3.32767]",
|
||||
"System.Formats.Asn1": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Formats.Tar": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Globalization": "(,4.3.32767]",
|
||||
"System.Globalization.Calendars": "(,4.3.32767]",
|
||||
"System.Globalization.Extensions": "(,4.3.32767]",
|
||||
"System.IO": "(,4.3.32767]",
|
||||
"System.IO.Compression": "(,4.3.32767]",
|
||||
"System.IO.Compression.ZipFile": "(,4.3.32767]",
|
||||
"System.IO.FileSystem": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.AccessControl": "(,4.4.32767]",
|
||||
"System.IO.FileSystem.DriveInfo": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Primitives": "(,4.3.32767]",
|
||||
"System.IO.FileSystem.Watcher": "(,4.3.32767]",
|
||||
"System.IO.IsolatedStorage": "(,4.3.32767]",
|
||||
"System.IO.MemoryMappedFiles": "(,4.3.32767]",
|
||||
"System.IO.Pipelines": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.IO.Pipes": "(,4.3.32767]",
|
||||
"System.IO.Pipes.AccessControl": "(,5.0.32767]",
|
||||
"System.IO.UnmanagedMemoryStream": "(,4.3.32767]",
|
||||
"System.Linq": "(,4.3.32767]",
|
||||
"System.Linq.AsyncEnumerable": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Linq.Expressions": "(,4.3.32767]",
|
||||
"System.Linq.Parallel": "(,4.3.32767]",
|
||||
"System.Linq.Queryable": "(,4.3.32767]",
|
||||
"System.Memory": "(,5.0.32767]",
|
||||
"System.Net.Http": "(,4.3.32767]",
|
||||
"System.Net.Http.Json": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Net.NameResolution": "(,4.3.32767]",
|
||||
"System.Net.NetworkInformation": "(,4.3.32767]",
|
||||
"System.Net.Ping": "(,4.3.32767]",
|
||||
"System.Net.Primitives": "(,4.3.32767]",
|
||||
"System.Net.Requests": "(,4.3.32767]",
|
||||
"System.Net.Security": "(,4.3.32767]",
|
||||
"System.Net.ServerSentEvents": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Net.Sockets": "(,4.3.32767]",
|
||||
"System.Net.WebHeaderCollection": "(,4.3.32767]",
|
||||
"System.Net.WebSockets": "(,4.3.32767]",
|
||||
"System.Net.WebSockets.Client": "(,4.3.32767]",
|
||||
"System.Numerics.Vectors": "(,5.0.32767]",
|
||||
"System.ObjectModel": "(,4.3.32767]",
|
||||
"System.Private.DataContractSerialization": "(,4.3.32767]",
|
||||
"System.Private.Uri": "(,4.3.32767]",
|
||||
"System.Reflection": "(,4.3.32767]",
|
||||
"System.Reflection.DispatchProxy": "(,6.0.32767]",
|
||||
"System.Reflection.Emit": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.ILGeneration": "(,4.7.32767]",
|
||||
"System.Reflection.Emit.Lightweight": "(,4.7.32767]",
|
||||
"System.Reflection.Extensions": "(,4.3.32767]",
|
||||
"System.Reflection.Metadata": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Reflection.Primitives": "(,4.3.32767]",
|
||||
"System.Reflection.TypeExtensions": "(,4.3.32767]",
|
||||
"System.Resources.Reader": "(,4.3.32767]",
|
||||
"System.Resources.ResourceManager": "(,4.3.32767]",
|
||||
"System.Resources.Writer": "(,4.3.32767]",
|
||||
"System.Runtime": "(,4.3.32767]",
|
||||
"System.Runtime.CompilerServices.Unsafe": "(,7.0.32767]",
|
||||
"System.Runtime.CompilerServices.VisualC": "(,4.3.32767]",
|
||||
"System.Runtime.Extensions": "(,4.3.32767]",
|
||||
"System.Runtime.Handles": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices": "(,4.3.32767]",
|
||||
"System.Runtime.InteropServices.RuntimeInformation": "(,4.3.32767]",
|
||||
"System.Runtime.Loader": "(,4.3.32767]",
|
||||
"System.Runtime.Numerics": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Formatters": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Json": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Primitives": "(,4.3.32767]",
|
||||
"System.Runtime.Serialization.Xml": "(,4.3.32767]",
|
||||
"System.Security.AccessControl": "(,6.0.32767]",
|
||||
"System.Security.Claims": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Algorithms": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Cng": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Csp": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.Encoding": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.OpenSsl": "(,5.0.32767]",
|
||||
"System.Security.Cryptography.Primitives": "(,4.3.32767]",
|
||||
"System.Security.Cryptography.X509Certificates": "(,4.3.32767]",
|
||||
"System.Security.Principal": "(,4.3.32767]",
|
||||
"System.Security.Principal.Windows": "(,5.0.32767]",
|
||||
"System.Security.SecureString": "(,4.3.32767]",
|
||||
"System.Text.Encoding": "(,4.3.32767]",
|
||||
"System.Text.Encoding.CodePages": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Text.Encoding.Extensions": "(,4.3.32767]",
|
||||
"System.Text.Encodings.Web": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Text.Json": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Text.RegularExpressions": "(,4.3.32767]",
|
||||
"System.Threading": "(,4.3.32767]",
|
||||
"System.Threading.Channels": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Threading.Overlapped": "(,4.3.32767]",
|
||||
"System.Threading.Tasks": "(,4.3.32767]",
|
||||
"System.Threading.Tasks.Dataflow": "(,10.0.0-preview.6.25358.103]",
|
||||
"System.Threading.Tasks.Extensions": "(,5.0.32767]",
|
||||
"System.Threading.Tasks.Parallel": "(,4.3.32767]",
|
||||
"System.Threading.Thread": "(,4.3.32767]",
|
||||
"System.Threading.ThreadPool": "(,4.3.32767]",
|
||||
"System.Threading.Timer": "(,4.3.32767]",
|
||||
"System.ValueTuple": "(,4.5.32767]",
|
||||
"System.Xml.ReaderWriter": "(,4.3.32767]",
|
||||
"System.Xml.XDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlDocument": "(,4.3.32767]",
|
||||
"System.Xml.XmlSerializer": "(,4.3.32767]",
|
||||
"System.Xml.XPath": "(,4.3.32767]",
|
||||
"System.Xml.XPath.XDocument": "(,5.0.32767]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
||||
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
|
||||
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">$(MSBuildThisFileDirectory)project.assets.json</ProjectAssetsFile>
|
||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
|
||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\HomePC\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
|
||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.15.0</NuGetToolVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<SourceRoot Include="C:\Users\HomePC\.nuget\packages\" />
|
||||
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
|
||||
</ItemGroup>
|
||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore\10.0.2\buildTransitive\net10.0\Microsoft.EntityFrameworkCore.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore\10.0.2\buildTransitive\net10.0\Microsoft.EntityFrameworkCore.props')" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\10.0.2\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\10.0.2\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.extensions.options\10.0.2\buildTransitive\net8.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\10.0.2\buildTransitive\net8.0\Microsoft.Extensions.Options.targets')" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,31 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"dgSpecHash": "5oOdKeOvG+M=",
|
||||
"success": true,
|
||||
"projectFilePath": "E:\\GIT\\mvp\\backend\\src\\Modules\\Catalog\\Nashel.RF.Modules.Catalog.csproj",
|
||||
"expectedPackageFiles": [
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\fluentvalidation\\12.1.1\\fluentvalidation.12.1.1.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\mediatr\\14.0.0\\mediatr.14.0.0.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\mediatr.contracts\\2.0.1\\mediatr.contracts.2.0.1.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.entityframeworkcore\\10.0.2\\microsoft.entityframeworkcore.10.0.2.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.entityframeworkcore.abstractions\\10.0.2\\microsoft.entityframeworkcore.abstractions.10.0.2.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.entityframeworkcore.analyzers\\10.0.2\\microsoft.entityframeworkcore.analyzers.10.0.2.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.entityframeworkcore.relational\\10.0.2\\microsoft.entityframeworkcore.relational.10.0.2.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.caching.abstractions\\10.0.2\\microsoft.extensions.caching.abstractions.10.0.2.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.caching.memory\\10.0.2\\microsoft.extensions.caching.memory.10.0.2.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.configuration.abstractions\\10.0.2\\microsoft.extensions.configuration.abstractions.10.0.2.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.dependencyinjection\\10.0.2\\microsoft.extensions.dependencyinjection.10.0.2.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.dependencyinjection.abstractions\\10.0.2\\microsoft.extensions.dependencyinjection.abstractions.10.0.2.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.logging\\10.0.2\\microsoft.extensions.logging.10.0.2.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.logging.abstractions\\10.0.2\\microsoft.extensions.logging.abstractions.10.0.2.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.options\\10.0.2\\microsoft.extensions.options.10.0.2.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.extensions.primitives\\10.0.2\\microsoft.extensions.primitives.10.0.2.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.identitymodel.abstractions\\8.14.0\\microsoft.identitymodel.abstractions.8.14.0.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.identitymodel.jsonwebtokens\\8.14.0\\microsoft.identitymodel.jsonwebtokens.8.14.0.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.identitymodel.logging\\8.14.0\\microsoft.identitymodel.logging.8.14.0.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\microsoft.identitymodel.tokens\\8.14.0\\microsoft.identitymodel.tokens.8.14.0.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\npgsql\\10.0.0\\npgsql.10.0.0.nupkg.sha512",
|
||||
"C:\\Users\\HomePC\\.nuget\\packages\\npgsql.entityframeworkcore.postgresql\\10.0.0\\npgsql.entityframeworkcore.postgresql.10.0.0.nupkg.sha512"
|
||||
],
|
||||
"logs": []
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using MediatR;
|
||||
using Nashel.Modules.Collaboration.Domain.Entities;
|
||||
using Nashel.Modules.Collaboration.Domain.Repositories;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Application.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// Команда найма сотрудника (создание контракта).
|
||||
/// </summary>
|
||||
public record HireEmployeeCommand(Guid EmployerId, Guid EmployeeId, string Role) : IRequest<Guid>;
|
||||
|
||||
public class HireEmployeeHandler : IRequestHandler<HireEmployeeCommand, Guid>
|
||||
{
|
||||
private readonly IContractRepository _repository;
|
||||
|
||||
public HireEmployeeHandler(IContractRepository repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
public async Task<Guid> Handle(HireEmployeeCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// Здесь можно добавить проверку, не существует ли уже активный контракт между этими сторонами
|
||||
// Но пока просто создаем новый.
|
||||
|
||||
var contract = Contract.Create(request.EmployerId, request.EmployeeId, request.Role);
|
||||
await _repository.AddAsync(contract, cancellationToken);
|
||||
return contract.Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using MediatR;
|
||||
using Nashel.Modules.Collaboration.Domain.Repositories;
|
||||
using Nashel.Modules.Collaboration.Domain.ValueObjects;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Application.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// Команда установки вето (блокировки) на контракт.
|
||||
/// </summary>
|
||||
public record SetVetoCommand(Guid ContractId, DateTime Start, DateTime End) : IRequest;
|
||||
|
||||
public class SetVetoHandler : IRequestHandler<SetVetoCommand>
|
||||
{
|
||||
private readonly IContractRepository _repository;
|
||||
|
||||
public SetVetoHandler(IContractRepository repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
public async Task Handle(SetVetoCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var contract = await _repository.GetByIdAsync(request.ContractId, cancellationToken);
|
||||
if (contract == null)
|
||||
{
|
||||
throw new ApplicationException($"Contract with ID {request.ContractId} not found.");
|
||||
}
|
||||
|
||||
var range = new DateRange(request.Start, request.End);
|
||||
contract.ImposeVeto(range);
|
||||
|
||||
await _repository.UpdateAsync(contract, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-8
@@ -1,18 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\BuildingBlocks\Nashel.RF.BuildingBlocks.csproj" />
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\Nashel.BuildingBlocks.csproj" />
|
||||
<ProjectReference Include="..\Domain\Nashel.Modules.Collaboration.Domain.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MediatR" Version="14.0.0" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<RootNamespace>Nashel.Modules.Collaboration.Application</RootNamespace>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -0,0 +1,30 @@
|
||||
using MediatR;
|
||||
using Nashel.Modules.Collaboration.Domain.Services;
|
||||
using Nashel.Modules.Collaboration.Domain.ValueObjects;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Application.Queries
|
||||
{
|
||||
/// <summary>
|
||||
/// Проверка доступности сотрудника (Query).
|
||||
/// </summary>
|
||||
public record CheckAvailabilityQuery(Guid EmployeeId, DateTime Start, DateTime End) : IRequest<bool>;
|
||||
|
||||
public class CheckAvailabilityHandler : IRequestHandler<CheckAvailabilityQuery, bool>
|
||||
{
|
||||
private readonly ScheduleConflictService _conflictService;
|
||||
|
||||
public CheckAvailabilityHandler(ScheduleConflictService conflictService)
|
||||
{
|
||||
_conflictService = conflictService;
|
||||
}
|
||||
|
||||
public async Task<bool> Handle(CheckAvailabilityQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var range = new DateRange(request.Start, request.End);
|
||||
return await _conflictService.CheckAvailability(request.EmployeeId, range, cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using Nashel.BuildingBlocks.Domain;
|
||||
using Nashel.Modules.Collaboration.Domain.Enums;
|
||||
using Nashel.Modules.Collaboration.Domain.ValueObjects;
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Контракт найма между Компанией и Сотрудником (Мастером).
|
||||
/// </summary>
|
||||
public class Contract : AggregateRoot<Guid>
|
||||
{
|
||||
public Guid EmployerId { get; private set; }
|
||||
public Guid EmployeeId { get; private set; }
|
||||
public string Role { get; private set; }
|
||||
public ContractStatus Status { get; private set; }
|
||||
|
||||
private readonly List<VetoLock> _vetoLocks = new();
|
||||
public IReadOnlyCollection<VetoLock> VetoLocks => _vetoLocks.AsReadOnly();
|
||||
|
||||
private Contract() { }
|
||||
|
||||
private Contract(Guid id, Guid employerId, Guid employeeId, string role)
|
||||
{
|
||||
Id = id;
|
||||
EmployerId = employerId;
|
||||
EmployeeId = employeeId;
|
||||
Role = role;
|
||||
Status = ContractStatus.Active;
|
||||
}
|
||||
|
||||
public static Contract Create(Guid employerId, Guid employeeId, string role)
|
||||
{
|
||||
return new Contract(Guid.NewGuid(), employerId, employeeId, role);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Накладывает вето (блокировку) на указанный период.
|
||||
/// </summary>
|
||||
public void ImposeVeto(DateRange period)
|
||||
{
|
||||
if (Status == ContractStatus.Terminated)
|
||||
{
|
||||
throw new InvalidOperationException("Нельзя наложить вето на расторгнутый контракт.");
|
||||
}
|
||||
|
||||
// Проверяем пересечение с существующими блокировками в этом же контракте (опционально, но логично)
|
||||
var hasOverlap = _vetoLocks.Any(v => v.Period.Overlaps(period));
|
||||
if (hasOverlap)
|
||||
{
|
||||
// Здесь можно бросать ошибку или просто игнорировать/мерджить.
|
||||
// Для упрощения: бросаем ошибку, чтобы фронт знал о дублировании.
|
||||
throw new InvalidOperationException("Период вето пересекается с уже существующей блокировкой в этом контракте.");
|
||||
}
|
||||
|
||||
_vetoLocks.Add(new VetoLock(Id, period));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Снимает вето (блокировку) на указанный период.
|
||||
/// Логика удаления по полному совпадению.
|
||||
/// </summary>
|
||||
public void RemoveVeto(DateRange period)
|
||||
{
|
||||
var existingLock = _vetoLocks.FirstOrDefault(v => v.Period == period);
|
||||
if (existingLock != null)
|
||||
{
|
||||
_vetoLocks.Remove(existingLock);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Завершает контракт.
|
||||
/// </summary>
|
||||
public void Terminate()
|
||||
{
|
||||
Status = ContractStatus.Terminated;
|
||||
_vetoLocks.Clear(); // При расторжении контракта все блокировки снимаются?
|
||||
// Допустим, да, так как работодатель больше не имеет прав.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using Nashel.BuildingBlocks.Domain;
|
||||
using Nashel.Modules.Collaboration.Domain.Enums;
|
||||
using Nashel.Modules.Collaboration.Domain.ValueObjects;
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Domain.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// Сущестность блокировки (Вето) на доступность сотрудника.
|
||||
/// </summary>
|
||||
public class VetoLock : Entity<Guid>
|
||||
{
|
||||
public DateRange Period { get; private set; }
|
||||
public Guid ContractId { get; private set; }
|
||||
|
||||
private VetoLock() { }
|
||||
|
||||
public VetoLock(Guid contractId, DateRange period)
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
ContractId = contractId;
|
||||
Period = period;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Nashel.Modules.Collaboration.Domain.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Статус контракта найма.
|
||||
/// </summary>
|
||||
public enum ContractStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Контракт активен.
|
||||
/// </summary>
|
||||
Active,
|
||||
|
||||
/// <summary>
|
||||
/// Контракт расторгнут.
|
||||
/// </summary>
|
||||
Terminated
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\Nashel.BuildingBlocks.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<RootNamespace>Nashel.Modules.Collaboration.Domain</RootNamespace>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Nashel.Modules.Collaboration.Domain.Entities;
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Domain.Repositories
|
||||
{
|
||||
public interface IContractRepository
|
||||
{
|
||||
Task<Contract?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default);
|
||||
Task<List<Contract>> GetAllByEmployeeIdAsync(Guid employeeId, CancellationToken cancellationToken = default);
|
||||
Task AddAsync(Contract contract, CancellationToken cancellationToken = default);
|
||||
Task UpdateAsync(Contract contract, CancellationToken cancellationToken = default);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Nashel.Modules.Collaboration.Domain.Enums;
|
||||
using Nashel.Modules.Collaboration.Domain.Repositories;
|
||||
using Nashel.Modules.Collaboration.Domain.ValueObjects;
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Domain.Services
|
||||
{
|
||||
public class ScheduleConflictService
|
||||
{
|
||||
private readonly IContractRepository _repository;
|
||||
|
||||
public ScheduleConflictService(IContractRepository repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Проверяет доступность сотрудника, анализируя все активные контракты на наличие блокировок.
|
||||
/// </summary>
|
||||
/// <returns>True - если сотрудник свободен, False - если заблокирован хотя бы одним Вето.</returns>
|
||||
public async Task<bool> CheckAvailability(Guid employeeId, DateRange requestedPeriod, CancellationToken ct = default)
|
||||
{
|
||||
var contracts = await _repository.GetAllByEmployeeIdAsync(employeeId, ct);
|
||||
|
||||
// Фильтруем только активные контракты
|
||||
var activeContracts = contracts.Where(c => c.Status == ContractStatus.Active);
|
||||
|
||||
foreach (var contract in activeContracts)
|
||||
{
|
||||
// Если есть хоть одно пересекающееся вето - сотрудник занят
|
||||
if (contract.VetoLocks.Any(veto => veto.Period.Overlaps(requestedPeriod)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using Nashel.BuildingBlocks.Domain;
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Domain.ValueObjects;
|
||||
|
||||
/// <summary>
|
||||
/// Диапазон дат.
|
||||
/// </summary>
|
||||
public record DateRange(DateTime Start, DateTime End)
|
||||
{
|
||||
private DateRange() : this(default, default) { } // For EF Core
|
||||
|
||||
public bool Overlaps(DateRange other)
|
||||
{
|
||||
return Start < other.End && End > other.Start;
|
||||
}
|
||||
|
||||
public bool Includes(DateTime date)
|
||||
{
|
||||
return date >= Start && date <= End;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Nashel.Modules.Collaboration.Domain.Repositories;
|
||||
using Nashel.Modules.Collaboration.Domain.Services;
|
||||
using Nashel.Modules.Collaboration.Infrastructure.Persistence;
|
||||
using Nashel.Modules.Collaboration.Infrastructure.Persistence.Repositories;
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Infrastructure
|
||||
{
|
||||
public static class DependencyInjection
|
||||
{
|
||||
public static IServiceCollection AddCollaborationModule(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var connectionString = configuration.GetConnectionString("DefaultConnection");
|
||||
|
||||
services.AddDbContext<CollaborationDbContext>(options =>
|
||||
options.UseNpgsql(connectionString));
|
||||
|
||||
services.AddScoped<IContractRepository, ContractRepository>();
|
||||
services.AddScoped<ScheduleConflictService>();
|
||||
|
||||
// Register MediatR
|
||||
services.AddMediatR(cfg =>
|
||||
{
|
||||
// Register handlers from Application layer
|
||||
cfg.RegisterServicesFromAssembly(Assembly.Load("Nashel.Modules.Collaboration.Application"));
|
||||
});
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+104
@@ -0,0 +1,104 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Nashel.Modules.Collaboration.Infrastructure.Persistence;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Infrastructure.Migrations
|
||||
{
|
||||
[DbContext(typeof(CollaborationDbContext))]
|
||||
[Migration("20260211111004_InitialCreate")]
|
||||
partial class InitialCreate
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("collaboration")
|
||||
.HasAnnotation("ProductVersion", "10.0.2")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Collaboration.Domain.Entities.Contract", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("EmployeeId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("EmployerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Role")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Contracts", "collaboration");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Collaboration.Domain.Entities.Contract", b =>
|
||||
{
|
||||
b.OwnsMany("Nashel.Modules.Collaboration.Domain.Entities.VetoLock", "VetoLocks", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<Guid>("ContractId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.HasKey("Id");
|
||||
|
||||
b1.HasIndex("ContractId");
|
||||
|
||||
b1.ToTable("VetoLocks", "collaboration");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("ContractId");
|
||||
|
||||
b1.OwnsOne("Nashel.Modules.Collaboration.Domain.ValueObjects.DateRange", "Period", b2 =>
|
||||
{
|
||||
b2.Property<Guid>("VetoLockId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b2.Property<DateTime>("End")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("VetoEnd");
|
||||
|
||||
b2.Property<DateTime>("Start")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("VetoStart");
|
||||
|
||||
b2.HasKey("VetoLockId");
|
||||
|
||||
b2.ToTable("VetoLocks", "collaboration");
|
||||
|
||||
b2.WithOwner()
|
||||
.HasForeignKey("VetoLockId");
|
||||
});
|
||||
|
||||
b1.Navigation("Period")
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
b.Navigation("VetoLocks");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Infrastructure.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class InitialCreate : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.EnsureSchema(
|
||||
name: "collaboration");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Contracts",
|
||||
schema: "collaboration",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
EmployerId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
EmployeeId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Role = table.Column<string>(type: "text", nullable: false),
|
||||
Status = table.Column<string>(type: "text", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Contracts", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "VetoLocks",
|
||||
schema: "collaboration",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
VetoStart = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
VetoEnd = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
ContractId = table.Column<Guid>(type: "uuid", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_VetoLocks", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_VetoLocks_Contracts_ContractId",
|
||||
column: x => x.ContractId,
|
||||
principalSchema: "collaboration",
|
||||
principalTable: "Contracts",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_VetoLocks_ContractId",
|
||||
schema: "collaboration",
|
||||
table: "VetoLocks",
|
||||
column: "ContractId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "VetoLocks",
|
||||
schema: "collaboration");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Contracts",
|
||||
schema: "collaboration");
|
||||
}
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Nashel.Modules.Collaboration.Infrastructure.Persistence;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Infrastructure.Migrations
|
||||
{
|
||||
[DbContext(typeof(CollaborationDbContext))]
|
||||
[Migration("20260310145106_BackendUpdate_Collaboration")]
|
||||
partial class BackendUpdate_Collaboration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("collaboration")
|
||||
.HasAnnotation("ProductVersion", "10.0.2")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Collaboration.Domain.Entities.Contract", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("EmployeeId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("EmployerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Role")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Contracts", "collaboration");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Collaboration.Domain.Entities.Contract", b =>
|
||||
{
|
||||
b.OwnsMany("Nashel.Modules.Collaboration.Domain.Entities.VetoLock", "VetoLocks", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<Guid>("ContractId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.HasKey("Id");
|
||||
|
||||
b1.HasIndex("ContractId");
|
||||
|
||||
b1.ToTable("VetoLocks", "collaboration");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("ContractId");
|
||||
|
||||
b1.OwnsOne("Nashel.Modules.Collaboration.Domain.ValueObjects.DateRange", "Period", b2 =>
|
||||
{
|
||||
b2.Property<Guid>("VetoLockId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b2.Property<DateTime>("End")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("VetoEnd");
|
||||
|
||||
b2.Property<DateTime>("Start")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("VetoStart");
|
||||
|
||||
b2.HasKey("VetoLockId");
|
||||
|
||||
b2.ToTable("VetoLocks", "collaboration");
|
||||
|
||||
b2.WithOwner()
|
||||
.HasForeignKey("VetoLockId");
|
||||
});
|
||||
|
||||
b1.Navigation("Period")
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
b.Navigation("VetoLocks");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Infrastructure.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class BackendUpdate_Collaboration : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Nashel.Modules.Collaboration.Infrastructure.Persistence;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Infrastructure.Migrations
|
||||
{
|
||||
[DbContext(typeof(CollaborationDbContext))]
|
||||
partial class CollaborationDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasDefaultSchema("collaboration")
|
||||
.HasAnnotation("ProductVersion", "10.0.2")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Collaboration.Domain.Entities.Contract", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("EmployeeId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("EmployerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Role")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Contracts", "collaboration");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Nashel.Modules.Collaboration.Domain.Entities.Contract", b =>
|
||||
{
|
||||
b.OwnsMany("Nashel.Modules.Collaboration.Domain.Entities.VetoLock", "VetoLocks", b1 =>
|
||||
{
|
||||
b1.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.Property<Guid>("ContractId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b1.HasKey("Id");
|
||||
|
||||
b1.HasIndex("ContractId");
|
||||
|
||||
b1.ToTable("VetoLocks", "collaboration");
|
||||
|
||||
b1.WithOwner()
|
||||
.HasForeignKey("ContractId");
|
||||
|
||||
b1.OwnsOne("Nashel.Modules.Collaboration.Domain.ValueObjects.DateRange", "Period", b2 =>
|
||||
{
|
||||
b2.Property<Guid>("VetoLockId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b2.Property<DateTime>("End")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("VetoEnd");
|
||||
|
||||
b2.Property<DateTime>("Start")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasColumnName("VetoStart");
|
||||
|
||||
b2.HasKey("VetoLockId");
|
||||
|
||||
b2.ToTable("VetoLocks", "collaboration");
|
||||
|
||||
b2.WithOwner()
|
||||
.HasForeignKey("VetoLockId");
|
||||
});
|
||||
|
||||
b1.Navigation("Period")
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
b.Navigation("VetoLocks");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\BuildingBlocks\Nashel.BuildingBlocks.csproj" />
|
||||
<ProjectReference Include="..\Application\Nashel.Modules.Collaboration.Application.csproj" />
|
||||
<ProjectReference Include="..\Domain\Nashel.Modules.Collaboration.Domain.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.0" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<RootNamespace>Nashel.Modules.Collaboration.Infrastructure</RootNamespace>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,22 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Nashel.Modules.Collaboration.Domain.Entities;
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Infrastructure.Persistence
|
||||
{
|
||||
public class CollaborationDbContext : DbContext
|
||||
{
|
||||
public DbSet<Contract> Contracts { get; set; }
|
||||
|
||||
public CollaborationDbContext(DbContextOptions<CollaborationDbContext> options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.HasDefaultSchema("collaboration");
|
||||
modelBuilder.ApplyConfigurationsFromAssembly(typeof(CollaborationDbContext).Assembly);
|
||||
base.OnModelCreating(modelBuilder);
|
||||
}
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Nashel.Modules.Collaboration.Domain.Entities;
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Infrastructure.Persistence.Configurations
|
||||
{
|
||||
public class ContractConfiguration : IEntityTypeConfiguration<Contract>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Contract> builder)
|
||||
{
|
||||
builder.HasKey(c => c.Id);
|
||||
builder.Property(c => c.Role).IsRequired();
|
||||
builder.Property(c => c.Status).HasConversion<string>();
|
||||
|
||||
// Настройка VetoLocks как Owned Collection (или таблицы связи)
|
||||
// Вариант с отдельной таблицей "VetoLocks"
|
||||
builder.OwnsMany(c => c.VetoLocks, a =>
|
||||
{
|
||||
a.ToTable("VetoLocks");
|
||||
a.HasKey("Id"); // Теневое свойство или явное
|
||||
a.WithOwner().HasForeignKey("ContractId");
|
||||
|
||||
a.OwnsOne(v => v.Period, p =>
|
||||
{
|
||||
p.Property(d => d.Start).HasColumnName("VetoStart");
|
||||
p.Property(d => d.End).HasColumnName("VetoEnd");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Nashel.Modules.Collaboration.Domain.Entities;
|
||||
using Nashel.Modules.Collaboration.Domain.Repositories;
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Infrastructure.Persistence.Repositories
|
||||
{
|
||||
public class ContractRepository : IContractRepository
|
||||
{
|
||||
private readonly CollaborationDbContext _context;
|
||||
|
||||
public ContractRepository(CollaborationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task AddAsync(Contract contract, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await _context.Contracts.AddAsync(contract, cancellationToken);
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<List<Contract>> GetAllByEmployeeIdAsync(Guid employeeId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _context.Contracts
|
||||
.Include(c => c.VetoLocks)
|
||||
.Where(c => c.EmployeeId == employeeId)
|
||||
.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<Contract?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _context.Contracts
|
||||
.Include(c => c.VetoLocks)
|
||||
.FirstOrDefaultAsync(c => c.Id == id, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task UpdateAsync(Contract contract, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_context.Contracts.Update(contract);
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Nashel.Modules.Collaboration.Application.Commands;
|
||||
using Nashel.Modules.Collaboration.Application.Queries;
|
||||
|
||||
namespace Nashel.Modules.Collaboration.Presentation
|
||||
{
|
||||
public static class CollaborationEndpoints
|
||||
{
|
||||
public static void MapCollaborationEndpoints(this IEndpointRouteBuilder app)
|
||||
{
|
||||
var group = app.MapGroup("/api/hr").WithTags("Collaboration (HR)");
|
||||
|
||||
// POST /api/hr/hire
|
||||
group.MapPost("/hire", async ([FromBody] HireEmployeeRequest request, ISender sender) =>
|
||||
{
|
||||
var command = new HireEmployeeCommand(request.EmployerId, request.EmployeeId, request.Role);
|
||||
var contractId = await sender.Send(command);
|
||||
return Results.Ok(contractId);
|
||||
})
|
||||
.WithName("HireEmployee")
|
||||
.WithOpenApi(operation => new(operation) { Summary = "Нанять сотрудника", Description = "Создает контракт между работодателем и сотрудником." });
|
||||
|
||||
// POST /api/hr/veto
|
||||
group.MapPost("/veto", async ([FromBody] SetVetoRequest request, ISender sender) =>
|
||||
{
|
||||
var command = new SetVetoCommand(request.ContractId, request.Start, request.End);
|
||||
await sender.Send(command);
|
||||
return Results.Ok();
|
||||
})
|
||||
.WithName("SetVeto")
|
||||
.WithOpenApi(operation => new(operation) { Summary = "Наложить вето", Description = "Блокирует расписание сотрудника на указанный период." });
|
||||
|
||||
// GET /api/hr/check-availability
|
||||
group.MapGet("/check-availability", async (
|
||||
[FromQuery] Guid employeeId,
|
||||
[FromQuery] DateTime start,
|
||||
[FromQuery] DateTime end,
|
||||
ISender sender) =>
|
||||
{
|
||||
var query = new CheckAvailabilityQuery(employeeId, start, end);
|
||||
var isAvailable = await sender.Send(query);
|
||||
return Results.Ok(new { IsAvailable = isAvailable });
|
||||
})
|
||||
.WithName("CheckAvailability")
|
||||
.WithOpenApi(operation => new(operation) { Summary = "Проверить доступность", Description = "Проверяет, свободен ли сотрудник в указанный период (нет ли вето)." });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Запрос на найм сотрудника.
|
||||
/// </summary>
|
||||
public record HireEmployeeRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// ID работодателя.
|
||||
/// </summary>
|
||||
public Guid EmployerId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// ID сотрудника.
|
||||
/// </summary>
|
||||
public Guid EmployeeId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Роль сотрудника (прораб, мастер и т.д.).
|
||||
/// </summary>
|
||||
public string Role { get; init; } = default!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Запрос на установку вето.
|
||||
/// </summary>
|
||||
public record SetVetoRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// ID контракта.
|
||||
/// </summary>
|
||||
public Guid ContractId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Начало периода блокировки.
|
||||
/// </summary>
|
||||
public DateTime Start { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Конец периода блокировки.
|
||||
/// </summary>
|
||||
public DateTime End { get; init; }
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user