Refactor and enhance product and order handling
- Updated `DiscountActionDialogBoxViewModel` and `FastProductCreateDialogBoxViewModel` to create command objects directly from properties and improved error handling. - Added meta tag management UI and logic in `ProductActionDialogBox.razor` and `ProductActionDialogBoxViewModel`. - Increased max file read stream size to 8 MB in `StorageDialogBoxViewModel`. - Incremented `AssemblyVersion` and `FileVersion` to `1.7.20.34` in `Netina.AdminPanel.PWA.csproj`. - Updated `BrandsPage.razor` and `BrandsPageViewModel` for pagination and service injection. - Updated `CategoriesPageViewModel` to create command objects directly from properties. - Updated `ProductsPage.razor` for service injection and added a button for product details. - Updated `ICrudApiRest` and `ICrudDtoApiRest` interfaces to use generic `Create` methods. - Updated `appsettings.Development.json` for `StorageBaseUrl` and commented out `IsShop`. - Added new project `AppHost.csproj` targeting .NET 8.0 with Aspire hosting. - Added new `appsettings.Development.json` and `appsettings.json` for logging. - Added new `Program.cs` to create and run a distributed application. - Added new `launchSettings.json` for application launch settings. - Added `Extensions.cs` for common .NET Aspire services. - Added new project `ServiceDefaults.csproj` for shared service defaults. - Introduced `ProductMetaTag` class and related migration for meta tag handling. - Updated `OrderController.cs` for additional authorization requirements. - Updated target frameworks to `net8.0` in various projects. - Enhanced `SiteMapService.cs` to include brand site maps. - Added new properties to DTOs for customer and meta tag handling. - Enhanced `Product` class with meta tag management methods. - Refactored `OrderMapper.g.cs` and `ProductMapper.g.cs` for improved mapping logic. - Enhanced command handlers to manage meta tags. - Added `ICurrentUserService` for user permissions in query handlers. - Refactored `StorageService.cs` for paginated storage file fetching.subProduct
parent
82f9d604da
commit
53dc2eac0c
|
@ -16,7 +16,10 @@ public class OrderController : ICarterModule
|
|||
|
||||
group.MapGet("{id}", GetAsync)
|
||||
.WithDisplayName("Get Order")
|
||||
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission, ApplicationPermission.ViewAllOrders, ApplicationPermission.ManageOrders))
|
||||
.RequireAuthorization(builder => builder.AddAuthenticationSchemes("Bearer").RequireAuthenticatedUser().RequireClaim(CustomClaimType.Permission,
|
||||
ApplicationPermission.ViewAllOrders,
|
||||
ApplicationPermission.ManageOrders,
|
||||
ApplicationPermission.ViewMineOrders))
|
||||
.HasApiVersion(1.0);
|
||||
|
||||
group.MapPost("{id}/confirm", ConfirmOrderStepAsync)
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
<AssemblyVersion>1.6.18.28</AssemblyVersion>
|
||||
<FileVersion>1.6.18.28</FileVersion>
|
||||
<AssemblyVersion>1.7.20.34</AssemblyVersion>
|
||||
<FileVersion>1.7.20.34</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<!--<PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
@ -12,9 +12,9 @@
|
|||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.0.2" />
|
||||
</ItemGroup>-->
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!--<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<LangVersion>10</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
@ -25,7 +25,7 @@
|
|||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
|
||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.3.1" />
|
||||
</ItemGroup>
|
||||
</ItemGroup>-->
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="MD.PersianDateTime.Standard" />
|
||||
|
|
|
@ -99,7 +99,7 @@ public class SiteMapService(
|
|||
await CreateCategoriesSiteMapsAsync();
|
||||
await CreateProductsSiteMapsAsync();
|
||||
await CreateBlogsSiteMapsAsync();
|
||||
//await CreateBrandsSiteMapsAsync();
|
||||
await CreateBrandsSiteMapsAsync();
|
||||
await CreateBlogCategoriesSiteMapsAsync();
|
||||
await CreatePagesSiteMapsAsync();
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ public class OrderLDto : BaseDto<OrderLDto,Order>
|
|||
public string DiscountCode { get; set; } = string.Empty;
|
||||
public long TotalPriceWithoutDiscount => TotalPrice + DiscountPrice;
|
||||
|
||||
public Guid CustomerId { get; set; }
|
||||
public string CustomerFullName { get; set; } = string.Empty;
|
||||
public string CustomerPhoneNumber { get; set; } = string.Empty;
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ public class ProductLDto : BaseDto<ProductLDto,Product>
|
|||
|
||||
public List<SpecificationSDto> Specifications { get; set; } = new();
|
||||
public List<StorageFileSDto> Files { get; set; } = new();
|
||||
public List<MetaTagSDto> MetaTags { get; set; } = new();
|
||||
|
||||
public DiscountSDto? SpecialOffer { get; set; }
|
||||
public Guid AuthorId { get; set; }
|
||||
|
|
|
@ -21,4 +21,5 @@ public class OrderSDto : BaseDto<OrderSDto, Order>
|
|||
public string CustomerFullName { get; set; } = string.Empty;
|
||||
public string CustomerPhoneNumber { get; set; } = string.Empty;
|
||||
public Guid CustomerId { get; set; }
|
||||
public string DeliveryTrackingCode { get; set; } = string.Empty;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ public partial class ProductCategoryMetaTag : MetaTag
|
|||
{
|
||||
|
||||
}
|
||||
|
||||
public ProductCategoryMetaTag(string type, string value, Guid productCategoryId) : base(type, value)
|
||||
{
|
||||
ProductCategoryId = productCategoryId;
|
||||
|
|
|
@ -60,6 +60,9 @@ public partial class Product
|
|||
Specifications.Add(ent);
|
||||
return ent;
|
||||
}
|
||||
|
||||
public void AddMetaTag(string key, string value)
|
||||
=> MetaTags.Add(ProductMetaTag.Create(key, value, Id));
|
||||
}
|
||||
|
||||
public partial class ProductComment
|
||||
|
@ -67,6 +70,11 @@ public partial class ProductComment
|
|||
public static ProductComment Create(string title, string content, float rate, bool isBuyer, bool isAdmin, Guid userId, Guid productId)
|
||||
=> new(title, content, rate, isBuyer, isAdmin, userId, productId);
|
||||
}
|
||||
public partial class ProductMetaTag
|
||||
{
|
||||
public static ProductMetaTag Create(string key, string value, Guid productId)
|
||||
=> new ProductMetaTag(key, value, productId);
|
||||
}
|
||||
|
||||
public partial class ProductStorageFile
|
||||
{
|
||||
|
|
|
@ -85,5 +85,7 @@ public partial class Product : ApiEntity
|
|||
public List<ProductComment> Comments { get; internal set; } = new();
|
||||
public List<ProductStorageFile> Files { get; internal set; } = new();
|
||||
|
||||
public List<ProductMetaTag> MetaTags { get; internal set; } = new();
|
||||
|
||||
public List<OrderProduct> OrderProducts { get; internal set; } = new();
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
namespace Netina.Domain.Entities.Products;
|
||||
|
||||
public partial class ProductMetaTag : MetaTag
|
||||
{
|
||||
public ProductMetaTag()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public ProductMetaTag(string type, string value, Guid productId) : base(type, value)
|
||||
{
|
||||
ProductId = productId;
|
||||
}
|
||||
|
||||
public Guid ProductId { get; set; }
|
||||
public Product? Product { get; set; }
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,6 @@
|
|||
namespace Netina.Domain.Mappers
|
||||
{
|
||||
public static partial class ProductMetaTagMapper
|
||||
{
|
||||
}
|
||||
}
|
|
@ -100,6 +100,7 @@ public class MapsterRegister : IRegister
|
|||
config.NewConfig<Order, OrderSDto>()
|
||||
.Map("CustomerFullName", o => o.Customer != null && o.Customer.User != null ? o.Customer.User.FirstName + " " + o.Customer.User.LastName : string.Empty)
|
||||
.Map("CustomerPhoneNumber", o => o.Customer != null && o.Customer.User != null ? o.Customer.User.PhoneNumber : string.Empty)
|
||||
.Map(d=>d.DeliveryTrackingCode,o=>o.OrderDelivery!=null ? o.OrderDelivery.TrackingCode : string.Empty)
|
||||
.IgnoreNullValues(false)
|
||||
.TwoWays();
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<!--<PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
@ -15,9 +15,9 @@
|
|||
<PackageReference Include="Microsoft.EntityFrameworkCore.Abstractions" Version="8.0.8" />
|
||||
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="8.0.8" />
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" />
|
||||
</ItemGroup>-->
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!--<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<LangVersion>10</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
@ -33,7 +33,7 @@
|
|||
<PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.0" />
|
||||
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" />
|
||||
</ItemGroup>
|
||||
</ItemGroup>-->
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -81,7 +81,7 @@ public class StorageService(IOptionsSnapshot<SiteSettings> snapshot) : IStorageS
|
|||
public async Task<List<StorageFileSDto>> GetStorageFiles(StorageFileType fileType)
|
||||
{
|
||||
var client = GetClientAsync();
|
||||
ListObjectsRequest request = new() { BucketName = _bucketName};
|
||||
ListObjectsV2Request request = new() { BucketName = _bucketName, MaxKeys = 3000 };
|
||||
switch (fileType)
|
||||
{
|
||||
case StorageFileType.Image:
|
||||
|
@ -93,33 +93,22 @@ public class StorageService(IOptionsSnapshot<SiteSettings> snapshot) : IStorageS
|
|||
default:
|
||||
break;
|
||||
}
|
||||
var files = new List<StorageFileSDto>();
|
||||
do
|
||||
var pagination = client.Paginators.ListObjectsV2(request);
|
||||
var s3Files = new List<S3Object>();
|
||||
await foreach (var listObjectsV2Response in pagination.Responses)
|
||||
{
|
||||
ListObjectsResponse response = await client.ListObjectsAsync(request);
|
||||
|
||||
// Process the response.
|
||||
foreach (var s3Object in response.S3Objects.Where(s=>s.Size>0))
|
||||
{
|
||||
files.Add(new StorageFileSDto
|
||||
{
|
||||
FileLocation = s3Object.Key,
|
||||
FileName = s3Object.Key.Split('/').Last()
|
||||
});
|
||||
s3Files.AddRange(listObjectsV2Response.S3Objects);
|
||||
}
|
||||
|
||||
// If the response is truncated, set the marker to get the next
|
||||
// set of keys.
|
||||
if (response.IsTruncated)
|
||||
var files = s3Files
|
||||
.OrderByDescending(s => s.LastModified)
|
||||
.Take(100)
|
||||
.Select(s => new StorageFileSDto
|
||||
{
|
||||
request.Marker = response.NextMarker;
|
||||
}
|
||||
else
|
||||
{
|
||||
request = null;
|
||||
}
|
||||
} while (request != null);
|
||||
FileLocation = s.Key,
|
||||
FileName = s.Key.Split('/').Last()
|
||||
}).ToList();
|
||||
|
||||
return files.OrderByDescending(o=>o.CreatedAt).ToList();
|
||||
return files.ToList();
|
||||
}
|
||||
}
|
|
@ -1,19 +1,35 @@
|
|||
using Netina.Domain.Entities.Orders;
|
||||
using Netina.Repository.Abstracts;
|
||||
|
||||
namespace Netina.Repository.Handlers.Orders;
|
||||
|
||||
public class GetOrderLDtoQueryHandler(IRepositoryWrapper repositoryWrapper)
|
||||
public class GetOrderLDtoQueryHandler(IRepositoryWrapper repositoryWrapper,ICurrentUserService currentUserService)
|
||||
: IRequestHandler<GetOrderLDtoQuery, OrderLDto>
|
||||
{
|
||||
public async Task<OrderLDto> Handle(GetOrderLDtoQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
if (currentUserService.Permissions == null)
|
||||
throw new BaseApiException(ApiResultStatusCode.UnAuthorized);
|
||||
if (request.Id == default)
|
||||
throw new AppException("Order id is null");
|
||||
|
||||
var order = await repositoryWrapper.SetRepository<Order>()
|
||||
.TableNoTracking
|
||||
.Where(o => o.Id == request.Id)
|
||||
.Select(OrderMapper.ProjectToLDto)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
if (currentUserService.Permissions.Contains(ApplicationPermission.ViewMineOrders) && !currentUserService.Permissions.Contains(ApplicationPermission.ViewAllOrders))
|
||||
{
|
||||
if (currentUserService.UserId.IsNullOrEmpty() || !Guid.TryParse(currentUserService.UserId, out Guid userId))
|
||||
throw new BaseApiException(ApiResultStatusCode.UnAuthorized);
|
||||
|
||||
var customer = await repositoryWrapper.SetRepository<Customer>()
|
||||
.TableNoTracking
|
||||
.FirstOrDefaultAsync(c => c.UserId == userId, cancellationToken);
|
||||
|
||||
if (customer == null || order.CustomerId != customer.Id)
|
||||
throw new BaseApiException(ApiResultStatusCode.UnAuthorized);
|
||||
}
|
||||
if (order == null)
|
||||
throw new AppException("Order not found", ApiResultStatusCode.NotFound);
|
||||
return order;
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
|
||||
namespace Netina.Repository.Handlers.Orders;
|
||||
|
||||
public class GetOrderQueryHandler(IRepositoryWrapper repositoryWrapper) : IRequestHandler<GetOrderQuery, Order>
|
||||
public class GetOrderQueryHandler(IRepositoryWrapper repositoryWrapper, ICurrentUserService currentUserService) : IRequestHandler<GetOrderQuery, Order>
|
||||
{
|
||||
public async Task<Order> Handle(GetOrderQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
|
||||
var order = await repositoryWrapper.SetRepository<Order>()
|
||||
.TableNoTracking
|
||||
.FirstOrDefaultAsync(o => o.Id == request.Id, cancellationToken);
|
||||
|
||||
if (order == null)
|
||||
throw new AppException("Order not found", ApiResultStatusCode.NotFound);
|
||||
|
||||
var orderProducts = await repositoryWrapper.SetRepository<OrderProduct>()
|
||||
.TableNoTracking
|
||||
.Where(op => op.OrderId == order.Id)
|
||||
|
@ -20,7 +20,7 @@ public class GetOrderQueryHandler(IRepositoryWrapper repositoryWrapper) : IReque
|
|||
|
||||
orderProducts.ForEach(op => order.AddOrderProduct(op));
|
||||
|
||||
var orderDelivery= await repositoryWrapper.SetRepository<OrderDelivery>()
|
||||
var orderDelivery = await repositoryWrapper.SetRepository<OrderDelivery>()
|
||||
.TableNoTracking
|
||||
.FirstOrDefaultAsync(od => od.OrderId == request.Id, cancellationToken);
|
||||
if (orderDelivery != null)
|
||||
|
|
|
@ -56,6 +56,9 @@ public class CreateProductCommandHandler(IRepositoryWrapper repositoryWrapper,IM
|
|||
|
||||
await UpdateFaqAsync(ent, request.Faqs, cancellationToken);
|
||||
|
||||
foreach (var (key, value) in request.MetaTags)
|
||||
ent.AddMetaTag(key, value);
|
||||
|
||||
return ent.AdaptToLDto();
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ public class UpdateProductCommandHandler(IRepositoryWrapper repositoryWrapper,IM
|
|||
newEnt.CreatedAt = ent.CreatedAt;
|
||||
newEnt.CreatedBy = ent.CreatedBy;
|
||||
|
||||
//Check Specifications
|
||||
var dbSpecifications = await repositoryWrapper.SetRepository<Specification>().TableNoTracking
|
||||
.Where(s => s.ProductId == ent.Id).ToListAsync(cancellationToken);
|
||||
foreach (var dbSpecification in dbSpecifications)
|
||||
|
@ -44,8 +45,22 @@ public class UpdateProductCommandHandler(IRepositoryWrapper repositoryWrapper,IM
|
|||
newEnt.AddSpecification(specification.Title, specification.Detail, specification.Value, specification.IsFeature, specification.ParentId);
|
||||
}
|
||||
|
||||
//Check MetaTags
|
||||
var dbMetaTags = await repositoryWrapper.SetRepository<ProductMetaTag>()
|
||||
.TableNoTracking
|
||||
.Where(f => f.ProductId == ent.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
foreach (var feature in dbMetaTags.Where(feature => request.MetaTags.Any(f => f.Key == feature.Type) == false))
|
||||
{
|
||||
repositoryWrapper.SetRepository<ProductMetaTag>()
|
||||
.Delete(feature);
|
||||
await repositoryWrapper.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
foreach (var (key, value) in request.MetaTags.Where(f => dbMetaTags.Any(dbf => dbf.Type == f.Key) == false))
|
||||
newEnt.AddMetaTag(key, value);
|
||||
|
||||
|
||||
//Check Files
|
||||
var dbFiles = await repositoryWrapper.SetRepository<ProductStorageFile>().TableNoTracking
|
||||
.Where(s => s.ProductId == ent.Id).ToListAsync(cancellationToken);
|
||||
foreach (var dbFile in dbFiles)
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace NetinaShop.Repository.Migrations
|
|||
table: "Products",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("8723f1d2-e091-4812-9110-5161c9e23586"));
|
||||
defaultValue: new Guid("11c47231-4f8b-4a73-b848-d2edf3c2d9ab"));
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "AuthorId",
|
||||
|
@ -25,7 +25,7 @@ namespace NetinaShop.Repository.Migrations
|
|||
table: "Blogs",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("8723f1d2-e091-4812-9110-5161c9e23586"));
|
||||
defaultValue: new Guid("11c47231-4f8b-4a73-b848-d2edf3c2d9ab"));
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Products_AuthorId",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,57 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NetinaShop.Repository.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddProductMetaTag : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "ProductId",
|
||||
schema: "public",
|
||||
table: "MetaTags",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_MetaTags_ProductId",
|
||||
schema: "public",
|
||||
table: "MetaTags",
|
||||
column: "ProductId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_MetaTags_Products_ProductId",
|
||||
schema: "public",
|
||||
table: "MetaTags",
|
||||
column: "ProductId",
|
||||
principalSchema: "public",
|
||||
principalTable: "Products",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_MetaTags_Products_ProductId",
|
||||
schema: "public",
|
||||
table: "MetaTags");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_MetaTags_ProductId",
|
||||
schema: "public",
|
||||
table: "MetaTags");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ProductId",
|
||||
schema: "public",
|
||||
table: "MetaTags");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1698,6 +1698,18 @@ namespace NetinaShop.Repository.Migrations
|
|||
b.HasDiscriminator().HasValue("ProductCategoryMetaTag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Netina.Domain.Entities.Products.ProductMetaTag", b =>
|
||||
{
|
||||
b.HasBaseType("Netina.Domain.Entities.Seo.MetaTag");
|
||||
|
||||
b.Property<Guid>("ProductId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasIndex("ProductId");
|
||||
|
||||
b.HasDiscriminator().HasValue("ProductMetaTag");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Netina.Domain.Entities.Blogs.BlogStorageFile", b =>
|
||||
{
|
||||
b.HasBaseType("Netina.Domain.Entities.StorageFiles.StorageFile");
|
||||
|
@ -2070,6 +2082,16 @@ namespace NetinaShop.Repository.Migrations
|
|||
b.Navigation("ProductCategory");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Netina.Domain.Entities.Products.ProductMetaTag", b =>
|
||||
{
|
||||
b.HasOne("Netina.Domain.Entities.Products.Product", "Product")
|
||||
.WithMany("MetaTags")
|
||||
.HasForeignKey("ProductId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Netina.Domain.Entities.Blogs.BlogStorageFile", b =>
|
||||
{
|
||||
b.HasOne("Netina.Domain.Entities.Blogs.Blog", "Blog")
|
||||
|
@ -2161,6 +2183,8 @@ namespace NetinaShop.Repository.Migrations
|
|||
|
||||
b.Navigation("Files");
|
||||
|
||||
b.Navigation("MetaTags");
|
||||
|
||||
b.Navigation("OrderProducts");
|
||||
|
||||
b.Navigation("Specifications");
|
||||
|
|
Loading…
Reference in New Issue