From fdd14db53d6e812241e6f19023f2df1167afbac2 Mon Sep 17 00:00:00 2001 From: "Amir.H Khademi" Date: Sun, 25 Feb 2024 18:21:01 +0330 Subject: [PATCH] feat & fix : add version 0.17.16.23 , fix respons home page , add changelog add change log dialog , add home page view model --- .../Production/appsettings.Production.json | 3 +- .../AppSettings/appsettings.Development.json | 1 + .../Controller/DashboardController.cs | 19 + NetinaShop.Api/Controller/PageController.cs | 6 +- NetinaShop.Api/Controller/UserController.cs | 7 + NetinaShop.Api/NetinaShop.Api.csproj | 1 + .../Abstracts/IExternalFilesService.cs | 6 + .../Abstracts/IDashboardService.cs | 6 + .../BaseServices/DashboardService.cs | 45 + .../EntityServices/Abstracts/IUserService.cs | 1 + NetinaShop.Core/EntityServices/UserService.cs | 27 +- NetinaShop.Core/NetinaShop.Core.csproj | 2 +- .../Dtos/DashboardDtos/HomeDashboardDto.cs | 11 + .../ResponseDtos/AdminChangeLogResponseDto.cs | 14 + .../Entities/Users/ApplicationUser.cs | 2 + .../Models/Settings/SiteSettings.cs | 1 + NetinaShop.Domain/NetinaShop.Domain.csproj | 1 + .../Models/RestAddress.cs | 1 + .../RestServices/IFileRestApi.cs | 9 + .../RestServices/IRestApiWrapper.cs | 7 + .../Services/ExternalFilesService.cs | 19 + ...40225133310_AddUserVersionUsed.Designer.cs | 1752 +++++++++++++++++ .../20240225133310_AddUserVersionUsed.cs | 31 + .../ApplicationContextModelSnapshot.cs | 3 + 24 files changed, 1962 insertions(+), 13 deletions(-) create mode 100644 NetinaShop.Api/Controller/DashboardController.cs create mode 100644 NetinaShop.Core/Abstracts/IExternalFilesService.cs create mode 100644 NetinaShop.Core/BaseServices/Abstracts/IDashboardService.cs create mode 100644 NetinaShop.Core/BaseServices/DashboardService.cs create mode 100644 NetinaShop.Domain/Dtos/DashboardDtos/HomeDashboardDto.cs create mode 100644 NetinaShop.Domain/Dtos/ResponseDtos/AdminChangeLogResponseDto.cs create mode 100644 NetinaShop.Infrastructure/RestServices/IFileRestApi.cs create mode 100644 NetinaShop.Infrastructure/Services/ExternalFilesService.cs create mode 100644 NetinaShop.Repository/Migrations/20240225133310_AddUserVersionUsed.Designer.cs create mode 100644 NetinaShop.Repository/Migrations/20240225133310_AddUserVersionUsed.cs diff --git a/NetinaShop.Api/AppSettings/Production/appsettings.Production.json b/NetinaShop.Api/AppSettings/Production/appsettings.Production.json index 0200ef8..1c1342c 100644 --- a/NetinaShop.Api/AppSettings/Production/appsettings.Production.json +++ b/NetinaShop.Api/AppSettings/Production/appsettings.Production.json @@ -17,7 +17,8 @@ "TaxesFee": 9 }, "SiteSettings": { - "BaseUrl": "https://api.vesmeh.com", + "BaseUrl": "https://api.vesmook.com", + "AdminPanelBaseUrl": "https://admin.vesmook.com", "KaveNegarApiKey": "3735494B4143727A794346457461576A2B4B6668414973424E333561505A694B", "UserSetting": { "Username": "09214802813", diff --git a/NetinaShop.Api/AppSettings/appsettings.Development.json b/NetinaShop.Api/AppSettings/appsettings.Development.json index bb62ed0..1e6b2e5 100644 --- a/NetinaShop.Api/AppSettings/appsettings.Development.json +++ b/NetinaShop.Api/AppSettings/appsettings.Development.json @@ -18,6 +18,7 @@ }, "SiteSettings": { "BaseUrl": "http://192.168.88.251:32770", + "AdminPanelBaseUrl": "https://admin.vesmook.com", "KaveNegarApiKey": "3735494B4143727A794346457461576A2B4B6668414973424E333561505A694B", "UserSetting": { "Username": "netinashop", diff --git a/NetinaShop.Api/Controller/DashboardController.cs b/NetinaShop.Api/Controller/DashboardController.cs new file mode 100644 index 0000000..cccdc41 --- /dev/null +++ b/NetinaShop.Api/Controller/DashboardController.cs @@ -0,0 +1,19 @@ +namespace NetinaShop.Api.Controller; + +public class DashboardController : ICarterModule +{ + public void AddRoutes(IEndpointRouteBuilder app) + { + var group = app.NewVersionedApi("Dashboard") + .MapGroup("api/dashboard") + .RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser()); + + group.MapGet("home", GetHomeDashboardAsync) + .WithDisplayName("Get Home Dashboard") + .HasApiVersion(1.0); + + } + + private async Task GetHomeDashboardAsync([FromServices] IDashboardService dashboardService, CancellationToken cancellationToken) + => TypedResults.Ok(await dashboardService.GetHomeDashboardAsyncTask(cancellationToken)); +} \ No newline at end of file diff --git a/NetinaShop.Api/Controller/PageController.cs b/NetinaShop.Api/Controller/PageController.cs index 3cfe0a0..349821c 100644 --- a/NetinaShop.Api/Controller/PageController.cs +++ b/NetinaShop.Api/Controller/PageController.cs @@ -1,8 +1,4 @@ -using NetinaShop.Repository.Repositories.Entity.Abstracts; -using System.Reflection; -using System.Text.Json; - -namespace NetinaShop.Api.Controller; +namespace NetinaShop.Api.Controller; public class PageController : ICarterModule { diff --git a/NetinaShop.Api/Controller/UserController.cs b/NetinaShop.Api/Controller/UserController.cs index cea61e4..83653a6 100644 --- a/NetinaShop.Api/Controller/UserController.cs +++ b/NetinaShop.Api/Controller/UserController.cs @@ -26,6 +26,10 @@ public class UserController : ICarterModule .WithDisplayName("GetUser") .HasApiVersion(1.0); + group.MapGet("/changelog", GetChangeLogAsync) + .WithDisplayName("GetChangeLog") + .HasApiVersion(1.0); + group.MapPost("", Post) .HasApiVersion(1.0); @@ -36,6 +40,9 @@ public class UserController : ICarterModule .HasApiVersion(1.0); } + private async Task GetChangeLogAsync(IUserService userService, CancellationToken cancellationToken) + => TypedResults.Ok(await userService.GetAdminChangeLogAsync(cancellationToken)); + public async Task GetUserInfoAsync(IUserService userService,ICurrentUserService currentUserService, CancellationToken cancellationToken) { diff --git a/NetinaShop.Api/NetinaShop.Api.csproj b/NetinaShop.Api/NetinaShop.Api.csproj index 745fbc1..9a94a5d 100644 --- a/NetinaShop.Api/NetinaShop.Api.csproj +++ b/NetinaShop.Api/NetinaShop.Api.csproj @@ -74,6 +74,7 @@ + diff --git a/NetinaShop.Core/Abstracts/IExternalFilesService.cs b/NetinaShop.Core/Abstracts/IExternalFilesService.cs new file mode 100644 index 0000000..2e1399f --- /dev/null +++ b/NetinaShop.Core/Abstracts/IExternalFilesService.cs @@ -0,0 +1,6 @@ +namespace NetinaShop.Core.Abstracts; + +public interface IExternalFilesService : IScopedDependency +{ + Task GetAdminChangeLogAsync(CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/NetinaShop.Core/BaseServices/Abstracts/IDashboardService.cs b/NetinaShop.Core/BaseServices/Abstracts/IDashboardService.cs new file mode 100644 index 0000000..79bd5b6 --- /dev/null +++ b/NetinaShop.Core/BaseServices/Abstracts/IDashboardService.cs @@ -0,0 +1,6 @@ +namespace NetinaShop.Core.BaseServices.Abstracts; + +public interface IDashboardService : IScopedDependency +{ + public Task GetHomeDashboardAsyncTask(CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/NetinaShop.Core/BaseServices/DashboardService.cs b/NetinaShop.Core/BaseServices/DashboardService.cs new file mode 100644 index 0000000..33b7e46 --- /dev/null +++ b/NetinaShop.Core/BaseServices/DashboardService.cs @@ -0,0 +1,45 @@ +using NetinaShop.Domain.Entities.Blogs; +using NetinaShop.Domain.Entities.Brands; + +namespace NetinaShop.Core.BaseServices; + +public class DashboardService : IDashboardService +{ + private readonly IRepositoryWrapper _repositoryWrapper; + private readonly UserManager _userManager; + + public DashboardService(IRepositoryWrapper repositoryWrapper,UserManager userManager) + { + _repositoryWrapper = repositoryWrapper; + _userManager = userManager; + } + public async Task GetHomeDashboardAsyncTask(CancellationToken cancellationToken = default) + { + var response = new HomeDashboardDto(); + response.BlogsCount = await _repositoryWrapper.SetRepository() + .TableNoTracking + .CountAsync(cancellationToken); + + response.ProductsCount = await _repositoryWrapper.SetRepository() + .TableNoTracking + .CountAsync(cancellationToken); + + response.TodayOrdersCount = await _repositoryWrapper.SetRepository() + .TableNoTracking + .Where(o => o.OrderAt.Date == DateTime.Today.Date) + .CountAsync(cancellationToken); + + response.UnSubmittedOrdersCount = await _repositoryWrapper.SetRepository() + .TableNoTracking + .Where(o => o.OrderStatus == OrderStatus.Paid || o.OrderStatus == OrderStatus.Submitted) + .CountAsync(cancellationToken); + + response.BrandsCount = await _repositoryWrapper.SetRepository() + .TableNoTracking + .CountAsync(cancellationToken); + + response.SubscribersCount = await _userManager.Users.CountAsync(cancellationToken); + + return response; + } +} \ No newline at end of file diff --git a/NetinaShop.Core/EntityServices/Abstracts/IUserService.cs b/NetinaShop.Core/EntityServices/Abstracts/IUserService.cs index 86a9c24..41e0d11 100644 --- a/NetinaShop.Core/EntityServices/Abstracts/IUserService.cs +++ b/NetinaShop.Core/EntityServices/Abstracts/IUserService.cs @@ -10,6 +10,7 @@ public interface IUserService : IScopedDependency Task EditUserAsync(UserActionRequestDto request, CancellationToken cancellationToken); Task EditUserProfileAsync(UserActionRequestDto request, CancellationToken cancellationToken); Task RemoveUserAsync(Guid userId, CancellationToken cancellationToken); + Task GetAdminChangeLogAsync(CancellationToken cancellationToken = default); Task> GetRolesAsync(int page = 0, CancellationToken cancellationToken = default); diff --git a/NetinaShop.Core/EntityServices/UserService.cs b/NetinaShop.Core/EntityServices/UserService.cs index e5292dc..dc55894 100644 --- a/NetinaShop.Core/EntityServices/UserService.cs +++ b/NetinaShop.Core/EntityServices/UserService.cs @@ -10,20 +10,17 @@ public class UserService : IUserService private readonly ICurrentUserService _currentUserService; private readonly UserManager _userManager; private readonly RoleManager _roleManager; - private readonly IRepositoryWrapper _repositoryWrapper; - private readonly IJwtService _jwtService; + private readonly IExternalFilesService _externalFilesService; public UserService(ICurrentUserService currentUserService, UserManager userManager, RoleManager roleManager, - IRepositoryWrapper repositoryWrapper, - IJwtService jwtService) + IExternalFilesService externalFilesService) { _currentUserService = currentUserService; _userManager = userManager; _roleManager = roleManager; - _repositoryWrapper = repositoryWrapper; - _jwtService = jwtService; + _externalFilesService = externalFilesService; } @@ -256,8 +253,26 @@ public class UserService : IUserService return true; } + public async Task GetAdminChangeLogAsync(CancellationToken cancellationToken = default) + { + if (!Guid.TryParse(_currentUserService.UserId, out var userId)) + throw new AppException("Wrong Token", ApiResultStatusCode.UnAuthorized); + var user = await _userManager.FindByIdAsync(userId.ToString()); + if (user == null) + throw new AppException("User NotFound", ApiResultStatusCode.NotFound); + var currentVersion = await _externalFilesService.GetAdminChangeLogAsync(cancellationToken); + + if (!(user.LatestVersionUsed < currentVersion.VersionNumber)) return currentVersion; + + currentVersion.IsNewVersion = true; + user.LatestVersionUsed = currentVersion.VersionNumber; + //await _userManager.UpdateAsync(user); + + return currentVersion; + } + public async Task> GetRolesAsync(int page = 0, CancellationToken cancellationToken = default) { diff --git a/NetinaShop.Core/NetinaShop.Core.csproj b/NetinaShop.Core/NetinaShop.Core.csproj index 2e00427..028f512 100644 --- a/NetinaShop.Core/NetinaShop.Core.csproj +++ b/NetinaShop.Core/NetinaShop.Core.csproj @@ -23,7 +23,6 @@ - @@ -50,6 +49,7 @@ + diff --git a/NetinaShop.Domain/Dtos/DashboardDtos/HomeDashboardDto.cs b/NetinaShop.Domain/Dtos/DashboardDtos/HomeDashboardDto.cs new file mode 100644 index 0000000..e681b3e --- /dev/null +++ b/NetinaShop.Domain/Dtos/DashboardDtos/HomeDashboardDto.cs @@ -0,0 +1,11 @@ +namespace NetinaShop.Domain.Dtos.DashboardDtos; + +public class HomeDashboardDto +{ + public int ProductsCount { get; set; } + public int BlogsCount { get; set; } + public int TodayOrdersCount { get; set; } + public int UnSubmittedOrdersCount { get; set; } + public int BrandsCount { get; set; } + public int SubscribersCount { get; set; } +} \ No newline at end of file diff --git a/NetinaShop.Domain/Dtos/ResponseDtos/AdminChangeLogResponseDto.cs b/NetinaShop.Domain/Dtos/ResponseDtos/AdminChangeLogResponseDto.cs new file mode 100644 index 0000000..a5f5c98 --- /dev/null +++ b/NetinaShop.Domain/Dtos/ResponseDtos/AdminChangeLogResponseDto.cs @@ -0,0 +1,14 @@ +namespace NetinaShop.Domain.Dtos.ResponseDtos; + +public class AdminChangeLogResponseDto +{ + public string Version { get; set; } = string.Empty; + public double VersionNumber { get; set; } + public string VersionName { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + public List Features { get; set; } = new(); + public List BugFixes { get; set; } = new(); + + public bool IsNewVersion { get; set; } = false; + +} \ No newline at end of file diff --git a/NetinaShop.Domain/Entities/Users/ApplicationUser.cs b/NetinaShop.Domain/Entities/Users/ApplicationUser.cs index 9dde1b4..dba0e7c 100644 --- a/NetinaShop.Domain/Entities/Users/ApplicationUser.cs +++ b/NetinaShop.Domain/Entities/Users/ApplicationUser.cs @@ -10,6 +10,8 @@ public class ApplicationUser : IdentityUser public string LastName { get; set; } = string.Empty; public string NationalId { get; set; } = string.Empty; + public double LatestVersionUsed { get; set; } + public DateTime BirthDate { get; set; } public Gender Gender { get; set; } public SignUpStatus SignUpStatus { get; set; } diff --git a/NetinaShop.Domain/Models/Settings/SiteSettings.cs b/NetinaShop.Domain/Models/Settings/SiteSettings.cs index 1aebd7c..490445a 100644 --- a/NetinaShop.Domain/Models/Settings/SiteSettings.cs +++ b/NetinaShop.Domain/Models/Settings/SiteSettings.cs @@ -10,6 +10,7 @@ public class SiteSettings { public JwtSettings JwtSettings { get; set; } = new JwtSettings(); public string BaseUrl { get; set; } = string.Empty; + public string AdminPanelBaseUrl { get; set; } = string.Empty; public RedisSettings MasterRedisConfiguration { get; set; } = new RedisSettings(); public UserSetting UserSetting { get; set; } = new UserSetting(); public string KaveNegarApiKey { get; set; } = string.Empty; diff --git a/NetinaShop.Domain/NetinaShop.Domain.csproj b/NetinaShop.Domain/NetinaShop.Domain.csproj index 821ce48..a525d20 100644 --- a/NetinaShop.Domain/NetinaShop.Domain.csproj +++ b/NetinaShop.Domain/NetinaShop.Domain.csproj @@ -37,6 +37,7 @@ + diff --git a/NetinaShop.Infrastructure/Models/RestAddress.cs b/NetinaShop.Infrastructure/Models/RestAddress.cs index 22f1fd1..15d8292 100644 --- a/NetinaShop.Infrastructure/Models/RestAddress.cs +++ b/NetinaShop.Infrastructure/Models/RestAddress.cs @@ -5,4 +5,5 @@ public static class RestAddress public static string BaseKaveNegar => "https://api.kavenegar.com/v1/"; public static string BaseZarinpal => "https://api.zarinpal.com/pg"; public static string DigikalaApi => "https://api.digikala.com"; + public static string AdminPanel => "https://admin.vesmook.com"; } \ No newline at end of file diff --git a/NetinaShop.Infrastructure/RestServices/IFileRestApi.cs b/NetinaShop.Infrastructure/RestServices/IFileRestApi.cs new file mode 100644 index 0000000..a62d330 --- /dev/null +++ b/NetinaShop.Infrastructure/RestServices/IFileRestApi.cs @@ -0,0 +1,9 @@ +using NetinaShop.Domain.Dtos.ResponseDtos; + +namespace NetinaShop.Infrastructure.RestServices; + +public interface IFileRestApi +{ + [Get("/version.json")] + Task GetAdminChangeLog(); +} \ No newline at end of file diff --git a/NetinaShop.Infrastructure/RestServices/IRestApiWrapper.cs b/NetinaShop.Infrastructure/RestServices/IRestApiWrapper.cs index 2c5dfa8..df4a64c 100644 --- a/NetinaShop.Infrastructure/RestServices/IRestApiWrapper.cs +++ b/NetinaShop.Infrastructure/RestServices/IRestApiWrapper.cs @@ -7,6 +7,7 @@ public interface IRestApiWrapper : IScopedDependency IKaveNegarRestApi KaveNegarRestApi { get; } IZarinpalRestApi ZarinpalRestApi { get; } IDigikalaRestApi DigikalaRestApi { get; } + IFileRestApi FileRestApi(string address); } public class RestApiWrapper : IRestApiWrapper @@ -14,4 +15,10 @@ public class RestApiWrapper : IRestApiWrapper public IKaveNegarRestApi KaveNegarRestApi => RestService.For(RestAddress.BaseKaveNegar); public IZarinpalRestApi ZarinpalRestApi => RestService.For(RestAddress.BaseZarinpal); public IDigikalaRestApi DigikalaRestApi => RestService.For(RestAddress.DigikalaApi); + + public IFileRestApi FileRestApi(string address) + { + return RestService.For(address); + } + } \ No newline at end of file diff --git a/NetinaShop.Infrastructure/Services/ExternalFilesService.cs b/NetinaShop.Infrastructure/Services/ExternalFilesService.cs new file mode 100644 index 0000000..97a608b --- /dev/null +++ b/NetinaShop.Infrastructure/Services/ExternalFilesService.cs @@ -0,0 +1,19 @@ +using NetinaShop.Domain.Dtos.ResponseDtos; + +namespace NetinaShop.Infrastructure.Services; + +public class ExternalFilesService : IExternalFilesService +{ + private readonly IRestApiWrapper _restApiWrapper; + private readonly SiteSettings _siteSetting; + + public ExternalFilesService(IRestApiWrapper restApiWrapper,IOptionsSnapshot snapshot) + { + _restApiWrapper = restApiWrapper; + _siteSetting = snapshot.Value; + } + public Task GetAdminChangeLogAsync(CancellationToken cancellationToken = default) + { + return _restApiWrapper.FileRestApi(_siteSetting.AdminPanelBaseUrl).GetAdminChangeLog(); + } +} \ No newline at end of file diff --git a/NetinaShop.Repository/Migrations/20240225133310_AddUserVersionUsed.Designer.cs b/NetinaShop.Repository/Migrations/20240225133310_AddUserVersionUsed.Designer.cs new file mode 100644 index 0000000..9572113 --- /dev/null +++ b/NetinaShop.Repository/Migrations/20240225133310_AddUserVersionUsed.Designer.cs @@ -0,0 +1,1752 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NetinaShop.Repository.Models; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace NetinaShop.Repository.Migrations +{ + [DbContext(typeof(ApplicationContext))] + [Migration("20240225133310_AddUserVersionUsed")] + partial class AddUserVersionUsed + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("public") + .HasAnnotation("ProductVersion", "8.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleClaims", "public"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Claims", "public"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("Logins", "public"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("UserRoles", "public"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("Tokens", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Accounting.Payment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("double precision"); + + b.Property("Authority") + .IsRequired() + .HasColumnType("text"); + + b.Property("CardPan") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("FactorNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("OrderId") + .HasColumnType("uuid"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("TransactionCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("OrderId"); + + b.HasIndex("UserId"); + + b.ToTable("Payments", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Blogs.Blog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("IsSuggested") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("ReadingTime") + .HasColumnType("integer"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.Property("Summery") + .IsRequired() + .HasColumnType("text"); + + b.Property("Tags") + .IsRequired() + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.ToTable("Blogs", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Blogs.BlogCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("BlogCategories", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Brands.Brand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EnglishName") + .IsRequired() + .HasColumnType("text"); + + b.Property("HasSpecialPage") + .HasColumnType("boolean"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("PageUrl") + .IsRequired() + .HasColumnType("text"); + + b.Property("PersianName") + .IsRequired() + .HasColumnType("text"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Brands", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Discounts.Discount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AmountType") + .HasColumnType("integer"); + + b.Property("Code") + .IsRequired() + .HasColumnType("text"); + + b.Property("CorporateUserId") + .HasColumnType("uuid"); + + b.Property("Count") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("DiscountAmount") + .HasColumnType("bigint"); + + b.Property("DiscountPercent") + .HasColumnType("integer"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(21) + .HasColumnType("character varying(21)"); + + b.Property("ExpireDate") + .HasColumnType("timestamp without time zone"); + + b.Property("HasCode") + .HasColumnType("boolean"); + + b.Property("HasPriceCeiling") + .HasColumnType("boolean"); + + b.Property("HasPriceFloor") + .HasColumnType("boolean"); + + b.Property("Immortal") + .HasColumnType("boolean"); + + b.Property("IsForInvitation") + .HasColumnType("boolean"); + + b.Property("IsForSaleCooperation") + .HasColumnType("boolean"); + + b.Property("IsInfinity") + .HasColumnType("boolean"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("IsSpecialOffer") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("PriceCeiling") + .HasColumnType("bigint"); + + b.Property("PriceFloor") + .HasColumnType("bigint"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.Property("StartDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UseCount") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("CorporateUserId"); + + b.ToTable("Discounts", "public"); + + b.HasDiscriminator("Discriminator").HasValue("Discount"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Orders.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("DeliveryPrice") + .HasColumnType("double precision"); + + b.Property("DiscountCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("DiscountCodePrice") + .HasColumnType("double precision"); + + b.Property("DiscountId") + .HasColumnType("uuid"); + + b.Property("DiscountPrice") + .HasColumnType("double precision"); + + b.Property("DoneAt") + .HasColumnType("timestamp without time zone"); + + b.Property("FactorCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsPayed") + .HasColumnType("boolean"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("OrderAt") + .HasColumnType("timestamp without time zone"); + + b.Property("OrderStatus") + .HasColumnType("integer"); + + b.Property("PackingPrice") + .HasColumnType("double precision"); + + b.Property("PayedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("PaymentMethod") + .HasColumnType("integer"); + + b.Property("PreparingMinute") + .HasColumnType("integer"); + + b.Property("ProductDiscountPrice") + .HasColumnType("double precision"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.Property("ServicePrice") + .HasColumnType("double precision"); + + b.Property("TaxesPrice") + .HasColumnType("double precision"); + + b.Property("TotalPrice") + .HasColumnType("double precision"); + + b.Property("TotalProductsPrice") + .HasColumnType("double precision"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("DiscountId"); + + b.HasIndex("UserId"); + + b.ToTable("Orders", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Orders.OrderDelivery", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AddressId") + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("DeliveryCost") + .HasColumnType("double precision"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("OrderId") + .HasColumnType("uuid"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.Property("ShippingId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AddressId"); + + b.HasIndex("OrderId") + .IsUnique(); + + b.HasIndex("ShippingId"); + + b.ToTable("OrderDeliveries", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Orders.OrderProduct", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Count") + .HasColumnType("integer"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("HasDiscount") + .HasColumnType("boolean"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("OrderId") + .HasColumnType("uuid"); + + b.Property("OrderProductStatus") + .HasColumnType("integer"); + + b.Property("PackingCost") + .HasColumnType("double precision"); + + b.Property("PackingFee") + .HasColumnType("double precision"); + + b.Property("ProductCategoryId") + .HasColumnType("uuid"); + + b.Property("ProductCost") + .HasColumnType("double precision"); + + b.Property("ProductFee") + .HasColumnType("double precision"); + + b.Property("ProductFeeWithDiscount") + .HasColumnType("double precision"); + + b.Property("ProductId") + .HasColumnType("uuid"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OrderId"); + + b.HasIndex("ProductId"); + + b.ToTable("OrderProducts", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.ProductCategories.ProductCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsMain") + .HasColumnType("boolean"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.ToTable("ProductCategories", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Products.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("BeDisplayed") + .HasColumnType("boolean"); + + b.Property("BrandId") + .HasColumnType("uuid"); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.Property("Cost") + .HasColumnType("double precision"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("EnglishName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ExpertCheck") + .IsRequired() + .HasColumnType("text"); + + b.Property("HasExpressDelivery") + .HasColumnType("boolean"); + + b.Property("IsEnable") + .HasColumnType("boolean"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("MaxOrderCount") + .HasColumnType("integer"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("PackingCost") + .HasColumnType("double precision"); + + b.Property("PersianName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Rate") + .HasColumnType("real"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.Property("ReviewCount") + .HasColumnType("integer"); + + b.Property("Stock") + .HasColumnType("integer"); + + b.Property("Summery") + .IsRequired() + .HasColumnType("text"); + + b.Property("Tags") + .IsRequired() + .HasColumnType("text"); + + b.Property("Viewed") + .HasColumnType("integer"); + + b.Property("Warranty") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("BrandId"); + + b.HasIndex("CategoryId"); + + b.ToTable("Products", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Products.Review", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("IsBuyer") + .HasColumnType("boolean"); + + b.Property("IsConfirmed") + .HasColumnType("boolean"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("ProductId") + .HasColumnType("uuid"); + + b.Property("Rate") + .HasColumnType("real"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ProductId"); + + b.HasIndex("UserId"); + + b.ToTable("Reviews", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Products.Specification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("Detail") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsFeature") + .HasColumnType("boolean"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("ParentId") + .HasColumnType("uuid"); + + b.Property("ProductId") + .HasColumnType("uuid"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.HasIndex("ProductId"); + + b.ToTable("Specifications", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.StorageFiles.StorageFile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("Discriminator") + .IsRequired() + .HasMaxLength(34) + .HasColumnType("character varying(34)"); + + b.Property("FileLocation") + .IsRequired() + .HasColumnType("text"); + + b.Property("FileName") + .IsRequired() + .HasColumnType("text"); + + b.Property("FileType") + .HasColumnType("integer"); + + b.Property("IsHeader") + .HasColumnType("boolean"); + + b.Property("IsPrimary") + .HasColumnType("boolean"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("StorageFiles", "public"); + + b.HasDiscriminator("Discriminator").HasValue("StorageFile"); + + b.UseTphMappingStrategy(); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Users.ApplicationRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("EnglishName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PersianName") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("Roles", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Users.ApplicationUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("BirthDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Gender") + .HasColumnType("integer"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("text"); + + b.Property("LatestVersionUsed") + .HasColumnType("double precision"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NationalId") + .IsRequired() + .HasColumnType("text"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("SignUpStatus") + .HasColumnType("integer"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.ToTable("Users", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Users.NewsletterMember", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("Email") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("NewsletterMembers", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Users.UserAddress", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Address") + .IsRequired() + .HasColumnType("text"); + + b.Property("BuildingUnit") + .IsRequired() + .HasColumnType("text"); + + b.Property("City") + .IsRequired() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("LocationLat") + .HasColumnType("real"); + + b.Property("LocationLong") + .HasColumnType("real"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Plaque") + .IsRequired() + .HasColumnType("text"); + + b.Property("PostalCode") + .IsRequired() + .HasColumnType("text"); + + b.Property("Province") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReceiverFullName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReceiverPhoneNumber") + .IsRequired() + .HasColumnType("text"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserAddresses", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Users.UserFavoriteProduct", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("ProductId") + .HasColumnType("uuid"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ProductId"); + + b.HasIndex("UserId"); + + b.ToTable("UserFavoriteProducts", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Warehouses.Shipping", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatedBy") + .HasColumnType("text"); + + b.Property("DeliveryCost") + .HasColumnType("double precision"); + + b.Property("IsExpressShipping") + .HasColumnType("boolean"); + + b.Property("IsOriginalWarehouse") + .HasColumnType("boolean"); + + b.Property("IsRemoved") + .HasColumnType("boolean"); + + b.Property("IsShipBySeller") + .HasColumnType("boolean"); + + b.Property("ModifiedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("ModifiedBy") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("RemovedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RemovedBy") + .HasColumnType("text"); + + b.Property("WarehouseName") + .IsRequired() + .HasColumnType("text"); + + b.Property("WorkingDays") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Shippings", "public"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Discounts.CategoryDiscount", b => + { + b.HasBaseType("NetinaShop.Domain.Entities.Discounts.Discount"); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.HasIndex("CategoryId"); + + b.HasDiscriminator().HasValue("CategoryDiscount"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Discounts.ProductDiscount", b => + { + b.HasBaseType("NetinaShop.Domain.Entities.Discounts.Discount"); + + b.Property("ProductId") + .HasColumnType("uuid"); + + b.HasIndex("ProductId"); + + b.HasDiscriminator().HasValue("ProductDiscount"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Blogs.BlogStorageFile", b => + { + b.HasBaseType("NetinaShop.Domain.Entities.StorageFiles.StorageFile"); + + b.Property("BlogId") + .HasColumnType("uuid"); + + b.HasIndex("BlogId"); + + b.HasDiscriminator().HasValue("BlogStorageFile"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Brands.BrandStorageFile", b => + { + b.HasBaseType("NetinaShop.Domain.Entities.StorageFiles.StorageFile"); + + b.Property("BrandId") + .HasColumnType("uuid"); + + b.HasIndex("BrandId"); + + b.HasDiscriminator().HasValue("BrandStorageFile"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.ProductCategories.ProductCategoryStorageFile", b => + { + b.HasBaseType("NetinaShop.Domain.Entities.StorageFiles.StorageFile"); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.HasIndex("CategoryId"); + + b.HasDiscriminator().HasValue("ProductCategoryStorageFile"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Products.ProductStorageFile", b => + { + b.HasBaseType("NetinaShop.Domain.Entities.StorageFiles.StorageFile"); + + b.Property("ProductId") + .HasColumnType("uuid"); + + b.HasIndex("ProductId"); + + b.HasDiscriminator().HasValue("ProductStorageFile"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("NetinaShop.Domain.Entities.Users.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("NetinaShop.Domain.Entities.Users.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("NetinaShop.Domain.Entities.Users.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("NetinaShop.Domain.Entities.Users.ApplicationRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NetinaShop.Domain.Entities.Users.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("NetinaShop.Domain.Entities.Users.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Accounting.Payment", b => + { + b.HasOne("NetinaShop.Domain.Entities.Orders.Order", "Order") + .WithMany("Payments") + .HasForeignKey("OrderId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NetinaShop.Domain.Entities.Users.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Order"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Blogs.Blog", b => + { + b.HasOne("NetinaShop.Domain.Entities.Blogs.BlogCategory", "Category") + .WithMany("Blogs") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Discounts.Discount", b => + { + b.HasOne("NetinaShop.Domain.Entities.Users.ApplicationUser", "CorporateUser") + .WithMany() + .HasForeignKey("CorporateUserId"); + + b.Navigation("CorporateUser"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Orders.Order", b => + { + b.HasOne("NetinaShop.Domain.Entities.Discounts.Discount", null) + .WithMany("Orders") + .HasForeignKey("DiscountId"); + + b.HasOne("NetinaShop.Domain.Entities.Users.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Orders.OrderDelivery", b => + { + b.HasOne("NetinaShop.Domain.Entities.Users.UserAddress", "Address") + .WithMany() + .HasForeignKey("AddressId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NetinaShop.Domain.Entities.Orders.Order", "Order") + .WithOne("OrderDelivery") + .HasForeignKey("NetinaShop.Domain.Entities.Orders.OrderDelivery", "OrderId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NetinaShop.Domain.Entities.Warehouses.Shipping", "Shipping") + .WithMany() + .HasForeignKey("ShippingId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Address"); + + b.Navigation("Order"); + + b.Navigation("Shipping"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Orders.OrderProduct", b => + { + b.HasOne("NetinaShop.Domain.Entities.Orders.Order", "Order") + .WithMany("OrderProducts") + .HasForeignKey("OrderId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NetinaShop.Domain.Entities.Products.Product", "Product") + .WithMany("OrderProducts") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Order"); + + b.Navigation("Product"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.ProductCategories.ProductCategory", b => + { + b.HasOne("NetinaShop.Domain.Entities.ProductCategories.ProductCategory", "Parent") + .WithMany() + .HasForeignKey("ParentId"); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Products.Product", b => + { + b.HasOne("NetinaShop.Domain.Entities.Brands.Brand", "Brand") + .WithMany("Products") + .HasForeignKey("BrandId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NetinaShop.Domain.Entities.ProductCategories.ProductCategory", "Category") + .WithMany("Products") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Brand"); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Products.Review", b => + { + b.HasOne("NetinaShop.Domain.Entities.Products.Product", "Product") + .WithMany("Reviews") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NetinaShop.Domain.Entities.Users.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Product"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Products.Specification", b => + { + b.HasOne("NetinaShop.Domain.Entities.Products.Specification", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId"); + + b.HasOne("NetinaShop.Domain.Entities.Products.Product", "Product") + .WithMany("Specifications") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Parent"); + + b.Navigation("Product"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Users.UserAddress", b => + { + b.HasOne("NetinaShop.Domain.Entities.Users.ApplicationUser", "User") + .WithMany("Addresses") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Users.UserFavoriteProduct", b => + { + b.HasOne("NetinaShop.Domain.Entities.Products.Product", "Product") + .WithMany() + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("NetinaShop.Domain.Entities.Users.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Product"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Discounts.CategoryDiscount", b => + { + b.HasOne("NetinaShop.Domain.Entities.ProductCategories.ProductCategory", "Category") + .WithMany() + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Discounts.ProductDiscount", b => + { + b.HasOne("NetinaShop.Domain.Entities.Products.Product", "Product") + .WithMany() + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Product"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Blogs.BlogStorageFile", b => + { + b.HasOne("NetinaShop.Domain.Entities.Blogs.Blog", "Blog") + .WithMany("Files") + .HasForeignKey("BlogId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Blog"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Brands.BrandStorageFile", b => + { + b.HasOne("NetinaShop.Domain.Entities.Brands.Brand", "Brand") + .WithMany("Files") + .HasForeignKey("BrandId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Brand"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.ProductCategories.ProductCategoryStorageFile", b => + { + b.HasOne("NetinaShop.Domain.Entities.ProductCategories.ProductCategory", "Category") + .WithMany("Files") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Products.ProductStorageFile", b => + { + b.HasOne("NetinaShop.Domain.Entities.Products.Product", "Product") + .WithMany("Files") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("Product"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Blogs.Blog", b => + { + b.Navigation("Files"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Blogs.BlogCategory", b => + { + b.Navigation("Blogs"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Brands.Brand", b => + { + b.Navigation("Files"); + + b.Navigation("Products"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Discounts.Discount", b => + { + b.Navigation("Orders"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Orders.Order", b => + { + b.Navigation("OrderDelivery"); + + b.Navigation("OrderProducts"); + + b.Navigation("Payments"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.ProductCategories.ProductCategory", b => + { + b.Navigation("Files"); + + b.Navigation("Products"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Products.Product", b => + { + b.Navigation("Files"); + + b.Navigation("OrderProducts"); + + b.Navigation("Reviews"); + + b.Navigation("Specifications"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Products.Specification", b => + { + b.Navigation("Children"); + }); + + modelBuilder.Entity("NetinaShop.Domain.Entities.Users.ApplicationUser", b => + { + b.Navigation("Addresses"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/NetinaShop.Repository/Migrations/20240225133310_AddUserVersionUsed.cs b/NetinaShop.Repository/Migrations/20240225133310_AddUserVersionUsed.cs new file mode 100644 index 0000000..dd64ff4 --- /dev/null +++ b/NetinaShop.Repository/Migrations/20240225133310_AddUserVersionUsed.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace NetinaShop.Repository.Migrations +{ + /// + public partial class AddUserVersionUsed : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "LatestVersionUsed", + schema: "public", + table: "Users", + type: "double precision", + nullable: false, + defaultValue: 0.0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "LatestVersionUsed", + schema: "public", + table: "Users"); + } + } +} diff --git a/NetinaShop.Repository/Migrations/ApplicationContextModelSnapshot.cs b/NetinaShop.Repository/Migrations/ApplicationContextModelSnapshot.cs index 304c5d1..fcba2d8 100644 --- a/NetinaShop.Repository/Migrations/ApplicationContextModelSnapshot.cs +++ b/NetinaShop.Repository/Migrations/ApplicationContextModelSnapshot.cs @@ -1064,6 +1064,9 @@ namespace NetinaShop.Repository.Migrations .IsRequired() .HasColumnType("text"); + b.Property("LatestVersionUsed") + .HasColumnType("double precision"); + b.Property("LockoutEnabled") .HasColumnType("boolean");