Compare commits
68 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 50a8a59d92 | |||
| 70c6e0bfbc | |||
| b70d9559b0 | |||
| 032b9e1818 | |||
| 424c1c6f8c | |||
| 81d5e8f07c | |||
| 7d5e9a18d8 | |||
| 20a53942b5 | |||
| 3656223b5f | |||
| 9edb2aa4aa | |||
| ccf30ac36b | |||
| 6ed023f2cf | |||
| d6fdf1b9c8 | |||
| 2c9f5a846c | |||
| 89a343a85f | |||
| 41f7c05be3 | |||
| 52d204e286 | |||
| 1a03355e84 | |||
| f245bc94e1 | |||
| 7743c3178e | |||
| da141311ff | |||
| ab3d8e6e9a | |||
| 97bde73777 | |||
| db4c348288 | |||
| a65e926a53 | |||
| 6683234642 | |||
| 1471d9e597 | |||
| 6ddbb9479a | |||
| e978aa17f8 | |||
| 6c7349a0f8 | |||
| a31f75c5ef | |||
| e97fd6cd3f | |||
| 7f4246ac63 | |||
| 184c7c252a | |||
| dfc62c8fe1 | |||
| bfe8c458d6 | |||
| 0f91f102e5 | |||
| e6e0475db1 | |||
| be9c83c8a3 | |||
| 65687d231e | |||
| 5090c60797 | |||
| 4523ef6151 | |||
| 9432252e15 | |||
| 36b3656886 | |||
| 47111a1a3a | |||
| f606b8fd3c | |||
| 2610275bef | |||
| 134d8429c0 | |||
| 42001998d6 | |||
| a42c51d7b2 | |||
| 6eb3d50375 | |||
| 26075cd9a7 | |||
| 4deb732804 | |||
| 20d9387d0b | |||
| 9f6d0ccaa0 | |||
| 1acbc4d213 | |||
| 8c99668fac | |||
| ad44f46204 | |||
| 49d999c1e3 | |||
| 9ed4777a18 | |||
| 0cf44f68cc | |||
| 41ed5a4288 | |||
| bbcba5e06c | |||
| 502cc326dd | |||
| 4675d4c5fc | |||
| f80bb2fff9 | |||
| 6767906b0d | |||
| a344af4498 |
+5
-23
@@ -16,30 +16,11 @@ steps:
|
|||||||
NEXUS_KEY: { from_secret: nexus_api_key }
|
NEXUS_KEY: { from_secret: nexus_api_key }
|
||||||
NEXUS_URL: https://nexus.khongisa.co.za/repository/nuget-hosted/
|
NEXUS_URL: https://nexus.khongisa.co.za/repository/nuget-hosted/
|
||||||
VERSION: 1.${DRONE_BUILD_NUMBER}.0
|
VERSION: 1.${DRONE_BUILD_NUMBER}.0
|
||||||
commands:
|
commands:
|
||||||
# Abstractions
|
|
||||||
- dotnet pack LiteCharms.Abstractions/LiteCharms.Abstractions.csproj -c Release -p:PackageVersion=$VERSION -o dist/
|
|
||||||
- dotnet nuget push dist/LiteCharms.Abstractions.$VERSION.nupkg --api-key $NEXUS_KEY --source $NEXUS_URL
|
|
||||||
|
|
||||||
# Models
|
|
||||||
- dotnet pack LiteCharms.Models/LiteCharms.Models.csproj -c Release -p:PackageVersion=$VERSION -o dist/
|
|
||||||
- dotnet nuget push dist/LiteCharms.Models.$VERSION.nupkg --api-key $NEXUS_KEY --source $NEXUS_URL
|
|
||||||
|
|
||||||
# Infrastructure
|
|
||||||
- dotnet pack LiteCharms.Infrastructure/LiteCharms.Infrastructure.csproj -c Release -p:PackageVersion=$VERSION -o dist/
|
|
||||||
- dotnet nuget push dist/LiteCharms.Infrastructure.$VERSION.nupkg --api-key $NEXUS_KEY --source $NEXUS_URL
|
|
||||||
|
|
||||||
# Features
|
|
||||||
- dotnet pack LiteCharms.Features/LiteCharms.Features.csproj -c Release -p:PackageVersion=$VERSION -o dist/
|
- dotnet pack LiteCharms.Features/LiteCharms.Features.csproj -c Release -p:PackageVersion=$VERSION -o dist/
|
||||||
- dotnet nuget push dist/LiteCharms.Features.$VERSION.nupkg --api-key $NEXUS_KEY --source $NEXUS_URL
|
- dotnet nuget push dist/LiteCharms.Features.$VERSION.nupkg --api-key $NEXUS_KEY --source $NEXUS_URL
|
||||||
|
- dotnet pack LiteCharms.Features.TechShop/LiteCharms.Features.TechShop.csproj -c Release -p:PackageVersion=$VERSION -o dist/
|
||||||
# Extensions
|
- dotnet nuget push dist/LiteCharms.Features.TechShop.$VERSION.nupkg --api-key $NEXUS_KEY --source $NEXUS_URL
|
||||||
- dotnet pack LiteCharms.Extensions/LiteCharms.Extensions.csproj -c Release -p:PackageVersion=$VERSION -o dist/
|
|
||||||
- dotnet nuget push dist/LiteCharms.Extensions.$VERSION.nupkg --api-key $NEXUS_KEY --source $NEXUS_URL
|
|
||||||
|
|
||||||
# Entities
|
|
||||||
- dotnet pack LiteCharms.Entities/LiteCharms.Entities.csproj -c Release -p:PackageVersion=$VERSION -o dist/
|
|
||||||
- dotnet nuget push dist/LiteCharms.Entities.$VERSION.nupkg --api-key $NEXUS_KEY --source $NEXUS_URL
|
|
||||||
|
|
||||||
- name: gitea-tag-release
|
- name: gitea-tag-release
|
||||||
image: alpine/git
|
image: alpine/git
|
||||||
@@ -49,6 +30,7 @@ steps:
|
|||||||
GITEA_PASS: { from_secret: git_password }
|
GITEA_PASS: { from_secret: git_password }
|
||||||
VERSION: 1.${DRONE_BUILD_NUMBER}.0
|
VERSION: 1.${DRONE_BUILD_NUMBER}.0
|
||||||
commands:
|
commands:
|
||||||
|
- echo "169.255.58.144 gitea.khongisa.co.za" >> /etc/hosts
|
||||||
- apk add --no-cache curl
|
- apk add --no-cache curl
|
||||||
- git remote set-url origin https://$${GITEA_USER}:$${GITEA_PASS}@gitea.khongisa.co.za/litecharms/components.git
|
- git remote set-url origin https://$${GITEA_USER}:$${GITEA_PASS}@gitea.khongisa.co.za/litecharms/components.git
|
||||||
- git tag $VERSION
|
- git tag $VERSION
|
||||||
@@ -61,7 +43,7 @@ steps:
|
|||||||
\"tag_name\": \"$VERSION\",
|
\"tag_name\": \"$VERSION\",
|
||||||
\"target_commitish\": \"${DRONE_COMMIT_SHA}\",
|
\"target_commitish\": \"${DRONE_COMMIT_SHA}\",
|
||||||
\"name\": \"Library Suite $VERSION\",
|
\"name\": \"Library Suite $VERSION\",
|
||||||
\"body\": \"### Published NuGet Packages\nAll packages versioned as **$VERSION**:\n* LiteCharms.Abstractions\n* LiteCharms.Models\n* LiteCharms.Infrastructure\n* LiteCharms.Features\n* LiteCharms.Extensions\n* LiteCharms.Entities\n\n[View in Nexus](https://nexus.khongisa.co.za/repository/nuget-group/)\",
|
\"body\": \"### Published NuGet Packages\nAll packages versioned as **$VERSION**:\n* LiteCharms.Features\n* LiteCharms.Features.TechShop\n\n[View in Nexus](https://nexus.khongisa.co.za/repository/nuget-group/)\",
|
||||||
\"draft\": false,
|
\"draft\": false,
|
||||||
\"prerelease\": false
|
\"prerelease\": false
|
||||||
}"
|
}"
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net10.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<SignAssembly>True</SignAssembly>
|
|
||||||
<AssemblyOriginatorKeyFile>..\LiteCharms.snk</AssemblyOriginatorKeyFile>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<!-- Nuget Package Details -->
|
|
||||||
<PropertyGroup>
|
|
||||||
<PackageId>LiteCharms.Abstractions</PackageId>
|
|
||||||
<Version>1.0.20</Version>
|
|
||||||
<Authors>Khwezi Mngoma</Authors>
|
|
||||||
<Company>Lite Charms (PTY) Ltd</Company>
|
|
||||||
<Description>Shared abstractions for Lite Charms applications.</Description>
|
|
||||||
<PackageProjectUrl>https://gitea.khongisa.co.za/litecharms/components</PackageProjectUrl>
|
|
||||||
<RepositoryUrl>https://gitea.khongisa.co.za/litecharms/components.git</RepositoryUrl>
|
|
||||||
<RepositoryType>git</RepositoryType>
|
|
||||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
|
||||||
<PackageTags>utility;dotnet</PackageTags>
|
|
||||||
<PackageIcon>icon.png</PackageIcon>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="..\LICENSE" Pack="true" PackagePath="\" />
|
|
||||||
<None Include="..\icon.png" Pack="true" PackagePath="\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="FluentResults" Version="4.0.0" />
|
|
||||||
<PackageReference Include="Mediator.Abstractions" Version="3.0.2" />
|
|
||||||
|
|
||||||
<Using Include="Mediator" />
|
|
||||||
<Using Include="FluentResults" />
|
|
||||||
<Using Include="System.Threading.Channels" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
namespace LiteCharms.Entities.Configuration;
|
|
||||||
|
|
||||||
public class OrderConfiguration : IEntityTypeConfiguration<Order>
|
|
||||||
{
|
|
||||||
public void Configure(EntityTypeBuilder<Order> builder)
|
|
||||||
{
|
|
||||||
builder.ToTable(nameof(Order));
|
|
||||||
|
|
||||||
builder.HasKey(f => f.Id);
|
|
||||||
builder.Property(f => f.CreatedAt).ValueGeneratedOnAdd();
|
|
||||||
builder.Property(f => f.UpdatedAt).IsRequired(false).ValueGeneratedOnUpdate();
|
|
||||||
builder.Property(f => f.CustomerId).IsRequired();
|
|
||||||
builder.Property(f => f.QuoteId).IsRequired(false);
|
|
||||||
builder.Property(f => f.RefundId).IsRequired(false);
|
|
||||||
builder.Property(f => f.ShoppingCartId).IsRequired();
|
|
||||||
builder.Property(f => f.Status).HasConversion<int>().IsRequired();
|
|
||||||
builder.Property(f => f.Requirements).HasColumnType("jsonb").IsRequired(false);
|
|
||||||
builder.Property(f => f.Notes).HasColumnType("jsonb").IsRequired(false);
|
|
||||||
builder.Property(f => f.Terms).HasColumnType("jsonb").IsRequired(false);
|
|
||||||
builder.Property(f => f.DepositRequired);
|
|
||||||
|
|
||||||
builder.HasOne(f => f.Quote)
|
|
||||||
.WithOne(f => f.Order)
|
|
||||||
.HasForeignKey<Order>(f => f.QuoteId)
|
|
||||||
.OnDelete(DeleteBehavior.Restrict);
|
|
||||||
|
|
||||||
builder.HasOne(f => f.Customer)
|
|
||||||
.WithMany(f => f.Orders)
|
|
||||||
.HasForeignKey(f => f.CustomerId)
|
|
||||||
.OnDelete(DeleteBehavior.Restrict);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
namespace LiteCharms.Entities.Configuration;
|
|
||||||
|
|
||||||
public class PackageConfirguration : IEntityTypeConfiguration<Package>
|
|
||||||
{
|
|
||||||
public void Configure(EntityTypeBuilder<Package> builder)
|
|
||||||
{
|
|
||||||
builder.ToTable(nameof(Package));
|
|
||||||
|
|
||||||
builder.HasKey(f => f.Id);
|
|
||||||
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd();
|
|
||||||
builder.Property(f => f.UpdatedAt).IsRequired(false).ValueGeneratedOnUpdate();
|
|
||||||
builder.Property(f => f.Name).IsRequired();
|
|
||||||
builder.Property(f => f.Description).IsRequired();
|
|
||||||
builder.Property(f => f.Active);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
namespace LiteCharms.Entities.Configuration;
|
|
||||||
|
|
||||||
public class ProductConfiguration : IEntityTypeConfiguration<Product>
|
|
||||||
{
|
|
||||||
public void Configure(EntityTypeBuilder<Product> builder)
|
|
||||||
{
|
|
||||||
builder.ToTable(nameof(Product));
|
|
||||||
|
|
||||||
builder.HasKey(f => f.Id);
|
|
||||||
builder.Property(f => f.Name).IsRequired();
|
|
||||||
builder.Property(f => f.Description).IsRequired();
|
|
||||||
builder.Property(f => f.Active).HasDefaultValue(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
namespace LiteCharms.Entities.Configuration;
|
|
||||||
|
|
||||||
public class QuoteConfiguration : IEntityTypeConfiguration<Quote>
|
|
||||||
{
|
|
||||||
public void Configure(EntityTypeBuilder<Quote> builder)
|
|
||||||
{
|
|
||||||
builder.ToTable(nameof(Quote));
|
|
||||||
|
|
||||||
builder.HasKey(f => f.Id);
|
|
||||||
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd();
|
|
||||||
builder.Property(f => f.UpdatedAt).IsRequired(false).ValueGeneratedOnUpdate();
|
|
||||||
builder.Property(f => f.ExpiredAt).IsRequired(false);
|
|
||||||
builder.Property(f => f.CustomerId).IsRequired();
|
|
||||||
builder.Property(f => f.Status).IsRequired().HasConversion<int>();
|
|
||||||
builder.Property(f => f.ShoppingCartId).IsRequired();
|
|
||||||
builder.Property(f => f.Reason).IsRequired(false);
|
|
||||||
|
|
||||||
builder.HasOne(f => f.Customer)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey(f => f.CustomerId)
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
namespace LiteCharms.Entities.Configuration;
|
|
||||||
|
|
||||||
public class ShoppingCartConfiguration : IEntityTypeConfiguration<ShoppingCart>
|
|
||||||
{
|
|
||||||
public void Configure(EntityTypeBuilder<ShoppingCart> builder)
|
|
||||||
{
|
|
||||||
builder.ToTable(nameof(ShoppingCart));
|
|
||||||
|
|
||||||
builder.HasKey(f => f.Id);
|
|
||||||
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd();
|
|
||||||
builder.Property(f => f.UpdatedAt).IsRequired(false).ValueGeneratedOnUpdate();
|
|
||||||
builder.Property(f => f.CustomerId).IsRequired(false);
|
|
||||||
builder.Property(f => f.OrderId).IsRequired(false);
|
|
||||||
builder.Property(f => f.QuoteId).IsRequired(false);
|
|
||||||
|
|
||||||
builder.HasOne(f => f.Customer)
|
|
||||||
.WithMany(c => c.ShoppingCarts)
|
|
||||||
.HasForeignKey(f => f.CustomerId)
|
|
||||||
.OnDelete(DeleteBehavior.NoAction);
|
|
||||||
|
|
||||||
builder.HasOne(f => f.Order)
|
|
||||||
.WithOne(o => o.ShoppingCart)
|
|
||||||
.HasForeignKey<Order>(o => o.ShoppingCartId)
|
|
||||||
.OnDelete(DeleteBehavior.NoAction);
|
|
||||||
|
|
||||||
builder.HasOne(f => f.Quote)
|
|
||||||
.WithOne(o => o.ShoppingCart)
|
|
||||||
.HasForeignKey<Quote>(o => o.ShoppingCartId)
|
|
||||||
.OnDelete(DeleteBehavior.NoAction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
namespace LiteCharms.Entities.Configuration;
|
|
||||||
|
|
||||||
public class ShoppingCartItemConfiguration : IEntityTypeConfiguration<ShoppingCartItem>
|
|
||||||
{
|
|
||||||
public void Configure(EntityTypeBuilder<ShoppingCartItem> builder)
|
|
||||||
{
|
|
||||||
builder.ToTable(nameof(ShoppingCartItem));
|
|
||||||
|
|
||||||
builder.HasKey(f => f.Id);
|
|
||||||
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd();
|
|
||||||
builder.Property(f => f.UpdatedAt).IsRequired(false).ValueGeneratedOnUpdate();
|
|
||||||
builder.Property(f => f.Quantity).IsRequired().HasDefaultValue(1);
|
|
||||||
builder.Property(f => f.ProductPriceId).IsRequired();
|
|
||||||
|
|
||||||
builder.HasOne(f => f.ProductPrice)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey(f => f.ProductPriceId)
|
|
||||||
.OnDelete(DeleteBehavior.NoAction);
|
|
||||||
|
|
||||||
builder.HasOne(f => f.ShoppingCart)
|
|
||||||
.WithMany(f => f.ShoppingCartItems)
|
|
||||||
.HasForeignKey(f => f.ShoppingCartId)
|
|
||||||
.OnDelete(DeleteBehavior.NoAction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
namespace LiteCharms.Entities.Configuration;
|
|
||||||
|
|
||||||
public class ShoppingCartPackageConfiguration : IEntityTypeConfiguration<ShoppingCartPackage>
|
|
||||||
{
|
|
||||||
public void Configure(EntityTypeBuilder<ShoppingCartPackage> builder)
|
|
||||||
{
|
|
||||||
builder.ToTable(nameof(ShoppingCartPackage));
|
|
||||||
|
|
||||||
builder.HasKey(f => f.Id);
|
|
||||||
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd();
|
|
||||||
builder.Property(f => f.ShoppingCartId).IsRequired();
|
|
||||||
builder.Property(f => f.PackageId).IsRequired();
|
|
||||||
|
|
||||||
builder.HasOne(f => f.Package)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey(f => f.PackageId)
|
|
||||||
.OnDelete(DeleteBehavior.NoAction);
|
|
||||||
|
|
||||||
builder.HasOne(f => f.ShoppingCart)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey(f => f.ShoppingCartId)
|
|
||||||
.OnDelete(DeleteBehavior.NoAction);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net10.0</TargetFramework>
|
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
|
||||||
<Nullable>enable</Nullable>
|
|
||||||
<SignAssembly>True</SignAssembly>
|
|
||||||
<AssemblyOriginatorKeyFile>..\LiteCharms.snk</AssemblyOriginatorKeyFile>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<!-- Nuget Package Details -->
|
|
||||||
<PropertyGroup>
|
|
||||||
<PackageId>LiteCharms.Entities</PackageId>
|
|
||||||
<Version>1.0.20</Version>
|
|
||||||
<Authors>Khwezi Mngoma</Authors>
|
|
||||||
<Company>Lite Charms (PTY) Ltd</Company>
|
|
||||||
<Description>Shared entities for Lite Charms applications.</Description>
|
|
||||||
<PackageProjectUrl>https://gitea.khongisa.co.za/litecharms/components</PackageProjectUrl>
|
|
||||||
<RepositoryUrl>https://gitea.khongisa.co.za/litecharms/components.git</RepositoryUrl>
|
|
||||||
<RepositoryType>git</RepositoryType>
|
|
||||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
|
||||||
<PackageTags>utility;dotnet</PackageTags>
|
|
||||||
<PackageIcon>icon.png</PackageIcon>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Include="..\LICENSE" Pack="true" PackagePath="\"/>
|
|
||||||
<None Include="..\icon.png" Pack="true" PackagePath="\" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<!-- Database -->
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.7" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.7" />
|
|
||||||
|
|
||||||
<!-- Global Usings -->
|
|
||||||
<Using Include="Microsoft.EntityFrameworkCore" />
|
|
||||||
<Using Include="Microsoft.EntityFrameworkCore.Metadata.Builders" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\LiteCharms.Models\LiteCharms.Models.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using LiteCharms.Entities.Configuration;
|
|
||||||
|
|
||||||
namespace LiteCharms.Entities;
|
|
||||||
|
|
||||||
[EntityTypeConfiguration<OrderConfiguration, Order>]
|
|
||||||
public class Order : Models.Order
|
|
||||||
{
|
|
||||||
public virtual OrderRefund? Refund { get; set; }
|
|
||||||
|
|
||||||
public virtual Customer? Customer { get; set; }
|
|
||||||
|
|
||||||
public virtual Quote? Quote { get; set; }
|
|
||||||
|
|
||||||
public virtual ShoppingCart? ShoppingCart { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
using LiteCharms.Entities.Configuration;
|
|
||||||
|
|
||||||
namespace LiteCharms.Entities;
|
|
||||||
|
|
||||||
[EntityTypeConfiguration<PackageItemConfiguration, PackageItem>]
|
|
||||||
public class PackageItem : Models.PackageItem
|
|
||||||
{
|
|
||||||
public virtual Package? Package { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
namespace LiteCharms.Entities;
|
|
||||||
|
|
||||||
public class ShoppingCartItem : Models.ShoppingCartItem
|
|
||||||
{
|
|
||||||
public virtual ShoppingCart? ShoppingCart { get; set; }
|
|
||||||
|
|
||||||
public virtual ProductPrice? ProductPrice { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
using LiteCharms.Models.Configuraton.Email;
|
|
||||||
|
|
||||||
namespace LiteCharms.Extensions;
|
|
||||||
|
|
||||||
public static class Email
|
|
||||||
{
|
|
||||||
public static IServiceCollection AddEmailServices(this IServiceCollection services, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
services.Configure<SmtpSettings>(configuration.GetSection("Email"));
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
using LiteCharms.Infrastructure.Database;
|
|
||||||
|
|
||||||
namespace LiteCharms.Extensions;
|
|
||||||
|
|
||||||
public static class Postgres
|
|
||||||
{
|
|
||||||
public static IServiceCollection AddShopDatabase(this IServiceCollection services, IConfiguration configuration)
|
|
||||||
{
|
|
||||||
services.AddPooledDbContextFactory<ShopDbContext>(options =>
|
|
||||||
options.UseNpgsql(configuration.GetConnectionString("PostgresShop")));
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using LiteCharms.Features.Extensions;
|
||||||
|
using LiteCharms.Features.TechShop.Extensions;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Tests;
|
||||||
|
|
||||||
|
public class Fixture : IDisposable
|
||||||
|
{
|
||||||
|
public IConfiguration Configuration { get; set; }
|
||||||
|
|
||||||
|
public IServiceProvider Services { get; set; }
|
||||||
|
|
||||||
|
public IMediator Mediator { get; set; }
|
||||||
|
|
||||||
|
public Fixture()
|
||||||
|
{
|
||||||
|
Configuration = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(Directory.GetCurrentDirectory())
|
||||||
|
.AddUserSecrets<Fixture>()
|
||||||
|
.AddJsonFile(Path.Combine(Directory.GetCurrentDirectory(), "appsettings.json"), optional: true, reloadOnChange: true)
|
||||||
|
.AddEnvironmentVariables()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
Services = new ServiceCollection()
|
||||||
|
.AddMediator()
|
||||||
|
.AddLogging()
|
||||||
|
.AddTechShopServices()
|
||||||
|
.AddEmailServiceBus()
|
||||||
|
.AddGarageS3(Configuration)
|
||||||
|
.AddTechShopDatabase(Configuration)
|
||||||
|
.AddEmailServices(Configuration)
|
||||||
|
.AddSingleton(Configuration)
|
||||||
|
.BuildServiceProvider();
|
||||||
|
|
||||||
|
Mediator = Services.GetRequiredService<IMediator>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() { }
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<UserSecretsId>fa06c1a6-2ba8-4c47-b19b-11e0f78e7b92</UserSecretsId>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="10.0.1">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Mediator.SourceGenerator" Version="3.0.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.5.1" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.3" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Global Usings -->
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Mediator" />
|
||||||
|
<Using Include="Xunit.Abstractions" />
|
||||||
|
<Using Include="Microsoft.Extensions.DependencyInjection" />
|
||||||
|
<Using Include="Microsoft.Extensions.Configuration" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\LiteCharms.Features.TechShop\LiteCharms.Features.TechShop.csproj" />
|
||||||
|
<ProjectReference Include="..\LiteCharms.Features\LiteCharms.Features.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="appsettings.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="appsettings.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
using LiteCharms.Features.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Notifications;
|
||||||
|
using LiteCharms.Features.TechShop.Notifications.Events;
|
||||||
|
using static LiteCharms.Features.Extensions.Email;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Tests;
|
||||||
|
|
||||||
|
public class NotificationsFeatureTests(Fixture fixture, ITestOutputHelper output) : IClassFixture<Fixture>
|
||||||
|
{
|
||||||
|
private readonly NotificationService notificationService = fixture.Services.GetRequiredService<NotificationService>();
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CreateNotificationCommand_ShouldSucceed()
|
||||||
|
{
|
||||||
|
Notifications.Models.CreateNotification request = new()
|
||||||
|
{
|
||||||
|
CorrelationId = Guid.CreateVersion7().ToString(),
|
||||||
|
CorrelationIdType = CorrelationIdTypes.None,
|
||||||
|
Direction = NotificationDirection.Outgoing,
|
||||||
|
Platform = NotificationPlatforms.Email,
|
||||||
|
Priority = Priorities.Medium,
|
||||||
|
Sender = "xUnit Test",
|
||||||
|
SenderAddress = "khwezi@mngoma.africa",
|
||||||
|
Recipient = $"{ShopEmailFromName} [Test]",
|
||||||
|
RecipientAddress = ShopEmailFromAddress,
|
||||||
|
Subject = "Test Message",
|
||||||
|
Message = "This is an automation test",
|
||||||
|
IsHtml = false,
|
||||||
|
IsInternal = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
var createResult = await notificationService.CreateNotificationAsync(request);
|
||||||
|
|
||||||
|
Assert.True(createResult.IsSuccess);
|
||||||
|
|
||||||
|
foreach (var error in createResult.Errors) output.WriteLine(error.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task GetNotifications_ShouldReturn_AllNotifications()
|
||||||
|
{
|
||||||
|
DateRange range = new()
|
||||||
|
{
|
||||||
|
From = DateOnly.FromDateTime(new DateTime(2026, 04, 01, 0, 0, 0, DateTimeKind.Utc)),
|
||||||
|
To = DateOnly.FromDateTime(DateTime.UtcNow),
|
||||||
|
MaxRecords = 10
|
||||||
|
};
|
||||||
|
|
||||||
|
var getResult = await notificationService.GetNotificationsAsync(range);
|
||||||
|
|
||||||
|
Assert.True(getResult.IsSuccess);
|
||||||
|
|
||||||
|
foreach (var error in getResult.Errors) output.WriteLine(error.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ProcessEmailNotificationsEvent_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var notification = ProcessEmailNotificationsEvent.Create();
|
||||||
|
|
||||||
|
await fixture.Mediator.Publish(notification);
|
||||||
|
|
||||||
|
Assert.True(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using LiteCharms.Features.TechShop.Products;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Tests;
|
||||||
|
|
||||||
|
public class ProductsFeatureTests(Fixture fixture, ITestOutputHelper output) : IClassFixture<Fixture>
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task GetProductsAsync_ReturnsProducts()
|
||||||
|
{
|
||||||
|
var productService = fixture.Services.GetRequiredService<ProductService>();
|
||||||
|
|
||||||
|
var result = await productService.GetProductsAsync();
|
||||||
|
|
||||||
|
Assert.True(result.IsSuccess);
|
||||||
|
Assert.NotNull(result.Value);
|
||||||
|
|
||||||
|
output.WriteLine($"Retrieved {result.Value.Length} products.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"BookshopS3Settings": {
|
||||||
|
"ServiceUrl": "http://192.168.1.177:30900",
|
||||||
|
"Region": "garage",
|
||||||
|
"BucketName": "bookshop",
|
||||||
|
"CdnBaseUrl": "https://bookshop.cdn.khongisa.co.za"
|
||||||
|
},
|
||||||
|
"BookshopQuotesS3Settings": {
|
||||||
|
"ServiceUrl": "http://192.168.1.177:30900",
|
||||||
|
"Region": "garage",
|
||||||
|
"BucketName": "bookshop.quotes",
|
||||||
|
"CdnBaseUrl": "https://bookshop.quotes.cdn.khongisa.co.za"
|
||||||
|
},
|
||||||
|
"Email": {
|
||||||
|
"Credentials": {
|
||||||
|
"Username": "shop@litecharms.co.za"
|
||||||
|
},
|
||||||
|
"Port": 465,
|
||||||
|
"Host": "mail.litecharms.co.za",
|
||||||
|
"UseSsl": true
|
||||||
|
},
|
||||||
|
"Monitoring": {
|
||||||
|
"ApiKey": "",
|
||||||
|
"Address": "http://aspire-dashboard-service.aspire.svc.cluster.local:18889",
|
||||||
|
"ServiceName": "LiteCharms.LeadGenerator"
|
||||||
|
},
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
||||||
+1
-3
@@ -1,6 +1,4 @@
|
|||||||
using LiteCharms.Entities.Configuration;
|
namespace LiteCharms.Features.TechShop.CartPackages.Entities;
|
||||||
|
|
||||||
namespace LiteCharms.Entities;
|
|
||||||
|
|
||||||
[EntityTypeConfiguration<PackageConfirguration, Package>]
|
[EntityTypeConfiguration<PackageConfirguration, Package>]
|
||||||
public class Package : Models.Package
|
public class Package : Models.Package
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.CartPackages.Entities;
|
||||||
|
|
||||||
|
public class PackageConfirguration : IEntityTypeConfiguration<Package>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<Package> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable(nameof(Package));
|
||||||
|
|
||||||
|
builder.HasKey(f => f.Id);
|
||||||
|
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
|
builder.Property(f => f.UpdatedAt).IsRequired(false).HasDefaultValueSql(null);
|
||||||
|
builder.Property(f => f.Name).IsRequired();
|
||||||
|
builder.Property(f => f.Summary).IsRequired().HasMaxLength(512);
|
||||||
|
builder.Property(f => f.Description).IsRequired().HasMaxLength(2048);
|
||||||
|
builder.Property(f => f.ImageUrl).IsRequired(false).HasMaxLength(2048);
|
||||||
|
builder.Property(f => f.Active);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using LiteCharms.Features.TechShop.Products.Entities;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.CartPackages.Entities;
|
||||||
|
|
||||||
|
[EntityTypeConfiguration<PackageItemConfiguration, PackageItem>]
|
||||||
|
public class PackageItem : Models.PackageItem
|
||||||
|
{
|
||||||
|
public virtual Package? Package { get; set; }
|
||||||
|
|
||||||
|
public virtual ProductPrice? ProductPrice { get; set; }
|
||||||
|
}
|
||||||
+12
-5
@@ -1,4 +1,4 @@
|
|||||||
namespace LiteCharms.Entities.Configuration;
|
namespace LiteCharms.Features.TechShop.CartPackages.Entities;
|
||||||
|
|
||||||
public class PackageItemConfiguration : IEntityTypeConfiguration<PackageItem>
|
public class PackageItemConfiguration : IEntityTypeConfiguration<PackageItem>
|
||||||
{
|
{
|
||||||
@@ -7,14 +7,21 @@ public class PackageItemConfiguration : IEntityTypeConfiguration<PackageItem>
|
|||||||
builder.ToTable(nameof(PackageItem));
|
builder.ToTable(nameof(PackageItem));
|
||||||
|
|
||||||
builder.HasKey(f => f.Id);
|
builder.HasKey(f => f.Id);
|
||||||
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd();
|
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
builder.Property(f => f.PackageId).IsRequired();
|
builder.Property(f => f.PackageId).IsRequired();
|
||||||
builder.Property(f => f.ProductPriceId).IsRequired();
|
builder.Property(f => f.ProductPriceId).IsRequired();
|
||||||
builder.Property(f => f.Active);
|
builder.Property(f => f.Active);
|
||||||
|
|
||||||
builder.HasOne(f => f.Package)
|
builder.HasOne(f => f.Package)
|
||||||
.WithMany()
|
.WithMany(f => f.PackageItems)
|
||||||
.HasForeignKey(f => f.PackageId)
|
.HasForeignKey(pi => pi.PackageId)
|
||||||
.OnDelete(DeleteBehavior.NoAction);
|
.IsRequired()
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
builder.HasOne(f => f.ProductPrice)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(pi => pi.ProductPriceId)
|
||||||
|
.IsRequired()
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.CartPackages.Models;
|
||||||
|
|
||||||
|
public class Package
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
public string? Summary { get; set; }
|
||||||
|
|
||||||
|
public string? Description { get; set; }
|
||||||
|
|
||||||
|
public string? ImageUrl { get; set; }
|
||||||
|
|
||||||
|
public bool Active { get; set; }
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
namespace LiteCharms.Models;
|
namespace LiteCharms.Features.TechShop.CartPackages.Models;
|
||||||
|
|
||||||
public class PackageItem
|
public class PackageItem
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
using LiteCharms.Features.Extensions;
|
||||||
|
using LiteCharms.Features.Models;
|
||||||
|
using LiteCharms.Features.TechShop.CartPackages.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Extensions;
|
||||||
|
using LiteCharms.Features.TechShop.Postgres;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.CartPackages;
|
||||||
|
|
||||||
|
public class PackageService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||||
|
{
|
||||||
|
public async ValueTask<Result<Guid>> AddPackageItemAsync(Guid packageId, Guid productPriceId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Packages.AnyAsync(p => p.Id == packageId, cancellationToken))
|
||||||
|
return Result.Fail($"Could not find package by ID {packageId}");
|
||||||
|
|
||||||
|
if (!await context.ProductPrices.AnyAsync(p => p.Id == productPriceId && p.Active == true, cancellationToken))
|
||||||
|
return Result.Fail($"Could not find an active product price by ID {productPriceId}");
|
||||||
|
|
||||||
|
if (await context.PackageItems.AnyAsync(p => p.ProductPriceId == productPriceId && p.PackageId == packageId, cancellationToken))
|
||||||
|
return Result.Fail<Guid>($"Product price {productPriceId} is already added to this package {packageId}");
|
||||||
|
|
||||||
|
var newPackageItem = context.PackageItems.Add(new Entities.PackageItem
|
||||||
|
{
|
||||||
|
PackageId = packageId,
|
||||||
|
ProductPriceId = productPriceId,
|
||||||
|
Active = true
|
||||||
|
});
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok(newPackageItem.Entity.Id)
|
||||||
|
: Result.Fail<Guid>($"Failed to add new package item by ID {productPriceId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Guid>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Guid>> CreatePackageAsync(string? name, string? summary, string? description, string? ImageUrl, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (await context.Packages.AnyAsync(p => p.Name == name, cancellationToken))
|
||||||
|
return Result.Fail($"A package by the same name already exists: {name}");
|
||||||
|
|
||||||
|
var newPackage = context.Packages.Add(new Entities.Package
|
||||||
|
{
|
||||||
|
Name = name,
|
||||||
|
Summary = summary,
|
||||||
|
Description = description,
|
||||||
|
ImageUrl = ImageUrl,
|
||||||
|
Active = true
|
||||||
|
});
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok(newPackage.Entity.Id)
|
||||||
|
: Result.Fail($"Failed to create a new package by the name: {name}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Guid>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> DeletePackageItemAsync(Guid packageId, Guid packageItemId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Packages.AnyAsync(p => p.Id == packageId, cancellationToken))
|
||||||
|
return Result.Fail($"Could not find package by ID {packageId}");
|
||||||
|
|
||||||
|
var item = await context.PackageItems.FirstOrDefaultAsync(p => p.Id == packageItemId && p.PackageId == packageId, cancellationToken);
|
||||||
|
|
||||||
|
if (item is null)
|
||||||
|
return Result.Fail($"Product item {packageItemId} is already added to this package {packageId}");
|
||||||
|
|
||||||
|
context.PackageItems.Remove(item);
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail($"Failed to delete package item by id {packageItemId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> DeletePackageItemsAsync(Guid packageId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Packages.AnyAsync(p => p.Id == packageId, cancellationToken))
|
||||||
|
return Result.Fail($"Could not find package by ID {packageId}");
|
||||||
|
|
||||||
|
var items = await context.PackageItems.Where(i => i.PackageId == packageId).ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
context.PackageItems.RemoveRange(items);
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail($"Failed to delete package {packageId} items");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Package>> GetPackageAsync(Guid packageId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var package = await context.Packages.FirstOrDefaultAsync(p => p.Id == packageId, cancellationToken);
|
||||||
|
|
||||||
|
return package is not null
|
||||||
|
? Result.Ok(package.ToModel())
|
||||||
|
: Result.Fail($"Failed to find package by ID {packageId}");
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Package>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<PackageItem[]>> GetPackageItemsAsync(Guid packageId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Packages.AnyAsync(p => p.Id == packageId, cancellationToken))
|
||||||
|
return Result.Fail<PackageItem[]>($"Package could not be found with ID {packageId}");
|
||||||
|
|
||||||
|
var items = await context.PackageItems.AsNoTracking()
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.Where(p => p.PackageId == packageId)
|
||||||
|
.ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return items?.Length > 0
|
||||||
|
? Result.Ok(items.Select(i => i.ToModel()).ToArray())
|
||||||
|
: Result.Fail<PackageItem[]>($"Could not find package items by package ID {packageId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<PackageItem[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Package[]>> GetPackagesAsync(Guid packageId, DateRange range, bool active, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var fromDate = range.From.ToDateTime(TimeOnly.MinValue);
|
||||||
|
var toDate = range.To.ToDateTime(TimeOnly.MaxValue);
|
||||||
|
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var packages = await context.Packages
|
||||||
|
.AsNoTracking()
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.Where(p => p.CreatedAt >= fromDate && p.CreatedAt <= toDate)
|
||||||
|
.Where(p => p.Active == active)
|
||||||
|
.Take(range.MaxRecords)
|
||||||
|
.ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return packages?.Length > 0
|
||||||
|
? Result.Ok(packages.Select(o => o.ToModel()).ToArray())
|
||||||
|
: Result.Fail<Package[]>(new Error($"No packages found for the specified date range {range.From} - {range.To}."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Package[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Guid>> UpdatePackageAsync(Guid packageId, string? name, string? summary, string? description, string? ImageUrl, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (await context.Packages.AnyAsync(p => p.Name == name, cancellationToken))
|
||||||
|
return Result.Fail($"A package by the same name already exists: {name}");
|
||||||
|
|
||||||
|
var package = await context.Packages.FirstOrDefaultAsync(p => p.Id == packageId, cancellationToken);
|
||||||
|
|
||||||
|
if (package is null)
|
||||||
|
return Result.Fail($"Could not find package by id {packageId}");
|
||||||
|
|
||||||
|
package.Name = name;
|
||||||
|
package.Summary = summary;
|
||||||
|
package.Description = description;
|
||||||
|
package.ImageUrl = ImageUrl;
|
||||||
|
package.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail($"Failed to update package with id {packageId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Guid>> UpdatePackageStatusAsync(Guid packageId, bool active, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var package = await context.Packages.FirstOrDefaultAsync(p => p.Id == packageId, cancellationToken);
|
||||||
|
|
||||||
|
if (package is null)
|
||||||
|
return Result.Fail($"Could not find package by id {packageId}");
|
||||||
|
|
||||||
|
package.Active = active;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail($"Failed to update package with id {packageId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
using LiteCharms.Features.Extensions;
|
||||||
|
using LiteCharms.Features.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Customers.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Extensions;
|
||||||
|
using LiteCharms.Features.TechShop.Postgres;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Customers;
|
||||||
|
|
||||||
|
public class CustomerService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||||
|
{
|
||||||
|
public async ValueTask<Result<Guid>> CreateCustomerAsync(CreateCustomer request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var customerEmail = request.Email.ToLower().Trim();
|
||||||
|
|
||||||
|
if (await context.Customers.AnyAsync(c => c.Email == customerEmail, cancellationToken))
|
||||||
|
return Result.Fail<Guid>(new Error($"A customer with the email {customerEmail} already exists"));
|
||||||
|
|
||||||
|
var newCustomer = context.Customers.Add(new Entities.Customer
|
||||||
|
{
|
||||||
|
Company = request.Company,
|
||||||
|
Name = request.Name,
|
||||||
|
LastName = request.LastName,
|
||||||
|
Tax = request.Tax,
|
||||||
|
Email = customerEmail,
|
||||||
|
Discord = request.Discord,
|
||||||
|
Slack = request.Slack,
|
||||||
|
LinkedIn = request.LinkedIn,
|
||||||
|
Whatsapp = request.Whatsapp,
|
||||||
|
Website = request.Website,
|
||||||
|
Phone = request.Phone,
|
||||||
|
Address = request.Address,
|
||||||
|
City = request.City,
|
||||||
|
Region = request.Region,
|
||||||
|
Country = request.Country,
|
||||||
|
PostalCode = request.PostalCode,
|
||||||
|
Active = true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok(newCustomer.Entity.Id)
|
||||||
|
: Result.Fail<Guid>(new Error($"Failed to create customer {customerEmail}"));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Guid>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Customer>> GetCustomerAsync(Guid customerId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var customer = await context.Customers.FirstOrDefaultAsync(c => c.Id == customerId, cancellationToken);
|
||||||
|
|
||||||
|
return customer is not null
|
||||||
|
? Result.Ok(customer.ToModel())
|
||||||
|
: Result.Fail<Customer>($"Customer not found with id {customerId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Customer>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Customer[]>> GetCustomersAsync(DateRange range, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var fromDate = range.From.ToDateTime(TimeOnly.MinValue);
|
||||||
|
var toDate = range.To.ToDateTime(TimeOnly.MaxValue);
|
||||||
|
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var customers = await context.Customers.AsNoTracking()
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.Where(c => c.CreatedAt >= fromDate && c.CreatedAt <= toDate)
|
||||||
|
.Take(range.MaxRecords)
|
||||||
|
.ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return customers?.Length > 0
|
||||||
|
? Result.Ok(customers.Select(c => c.ToModel()).ToArray())
|
||||||
|
: Result.Fail<Customer[]>(new Error("No customers found in the specified date range."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Customer[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateCustomerAsync(UpdateCustomer request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var customer = await context.Customers.FirstOrDefaultAsync(c => c.Id == request.CustomerId, cancellationToken);
|
||||||
|
|
||||||
|
if (customer is null)
|
||||||
|
return Result.Fail(new Error($"Customer with ID {request.CustomerId} not found."));
|
||||||
|
|
||||||
|
customer.Name = request.Name;
|
||||||
|
customer.LastName = request.LastName;
|
||||||
|
customer.Email = request.Email;
|
||||||
|
customer.Company = request.Company;
|
||||||
|
customer.Address = request.Address;
|
||||||
|
customer.City = request.City;
|
||||||
|
customer.Region = request.Region;
|
||||||
|
customer.Country = request.Country;
|
||||||
|
customer.PostalCode = request.PostalCode;
|
||||||
|
customer.Phone = request.Phone;
|
||||||
|
customer.Tax = request.Tax;
|
||||||
|
customer.City = request.City;
|
||||||
|
customer.Discord = request.Discord;
|
||||||
|
customer.Slack = request.Slack;
|
||||||
|
customer.LinkedIn = request.LinkedIn;
|
||||||
|
customer.Whatsapp = request.Whatsapp;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail(new Error($"Failed to update the customer {request.CustomerId}."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-2
@@ -1,6 +1,9 @@
|
|||||||
using LiteCharms.Entities.Configuration;
|
using LiteCharms.Features.TechShop.Leads.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.Orders.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.Quotes.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.ShoppingCarts.Entities;
|
||||||
|
|
||||||
namespace LiteCharms.Entities;
|
namespace LiteCharms.Features.TechShop.Customers.Entities;
|
||||||
|
|
||||||
[EntityTypeConfiguration<CustomerConfiguration, Customer>]
|
[EntityTypeConfiguration<CustomerConfiguration, Customer>]
|
||||||
public class Customer : Models.Customer
|
public class Customer : Models.Customer
|
||||||
+4
-9
@@ -1,14 +1,14 @@
|
|||||||
namespace LiteCharms.Entities.Configuration;
|
namespace LiteCharms.Features.TechShop.Customers.Entities;
|
||||||
|
|
||||||
public class CustomerConfiguration : IEntityTypeConfiguration<Customer>
|
public class CustomerConfiguration : IEntityTypeConfiguration<Customer>
|
||||||
{
|
{
|
||||||
public void Configure(EntityTypeBuilder<Customer> builder)
|
public void Configure(EntityTypeBuilder<Customer> builder)
|
||||||
{
|
{
|
||||||
builder.ToTable(nameof(Customer));
|
builder.ToTable("Customers");
|
||||||
|
|
||||||
builder.HasKey(f => f.Id);
|
builder.HasKey(f => f.Id);
|
||||||
builder.Property(f => f.CreatedAt).ValueGeneratedOnAdd();
|
builder.Property(f => f.CreatedAt).ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
builder.Property(f => f.UpdatedAt).IsRequired(false).ValueGeneratedOnUpdate();
|
builder.Property(f => f.UpdatedAt).IsRequired(false).HasDefaultValueSql(null);
|
||||||
builder.Property(f => f.Company);
|
builder.Property(f => f.Company);
|
||||||
builder.Property(f => f.Name).IsRequired();
|
builder.Property(f => f.Name).IsRequired();
|
||||||
builder.Property(f => f.LastName).IsRequired();
|
builder.Property(f => f.LastName).IsRequired();
|
||||||
@@ -26,10 +26,5 @@ public class CustomerConfiguration : IEntityTypeConfiguration<Customer>
|
|||||||
builder.Property(f => f.Country);
|
builder.Property(f => f.Country);
|
||||||
builder.Property(f => f.PostalCode);
|
builder.Property(f => f.PostalCode);
|
||||||
builder.Property(f => f.Active).HasDefaultValue(true);
|
builder.Property(f => f.Active).HasDefaultValue(true);
|
||||||
|
|
||||||
builder.HasMany(f => f.Leads)
|
|
||||||
.WithOne(f => f.Customer)
|
|
||||||
.HasForeignKey(f => f.CustomerId)
|
|
||||||
.OnDelete(DeleteBehavior.NoAction);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-3
@@ -1,12 +1,12 @@
|
|||||||
namespace LiteCharms.Models;
|
namespace LiteCharms.Features.TechShop.Customers.Models;
|
||||||
|
|
||||||
public class Customer
|
public class Customer
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
public DateTimeOffset CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
public DateTimeOffset? UpdatedAt { get; set; }
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
public string? Company { get; set; }
|
public string? Company { get; set; }
|
||||||
|
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.Customers.Models;
|
||||||
|
|
||||||
|
public record CreateCustomer
|
||||||
|
{
|
||||||
|
public string? Company { get; set; }
|
||||||
|
|
||||||
|
public required string Name { get; set; }
|
||||||
|
|
||||||
|
public required string LastName { get; set; }
|
||||||
|
|
||||||
|
public string? Tax { get; set; }
|
||||||
|
|
||||||
|
public required string Email { get; set; }
|
||||||
|
|
||||||
|
public string? Discord { get; set; }
|
||||||
|
|
||||||
|
public string? Slack { get; set; }
|
||||||
|
|
||||||
|
public string? LinkedIn { get; set; }
|
||||||
|
|
||||||
|
public string? Whatsapp { get; set; }
|
||||||
|
|
||||||
|
public string? Website { get; set; }
|
||||||
|
|
||||||
|
public string? Phone { get; set; }
|
||||||
|
|
||||||
|
public string? Address { get; set; }
|
||||||
|
|
||||||
|
public string? City { get; set; }
|
||||||
|
|
||||||
|
public string? Region { get; set; }
|
||||||
|
|
||||||
|
public string? Country { get; set; }
|
||||||
|
|
||||||
|
public string? PostalCode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public record UpdateCustomer
|
||||||
|
{
|
||||||
|
public required Guid CustomerId { get; set; }
|
||||||
|
|
||||||
|
public string? Company { get; set; }
|
||||||
|
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
public string? LastName { get; set; }
|
||||||
|
|
||||||
|
public string? Tax { get; set; }
|
||||||
|
|
||||||
|
public string? Email { get; set; }
|
||||||
|
|
||||||
|
public string? Discord { get; set; }
|
||||||
|
|
||||||
|
public string? Slack { get; set; }
|
||||||
|
|
||||||
|
public string? LinkedIn { get; set; }
|
||||||
|
|
||||||
|
public string? Whatsapp { get; set; }
|
||||||
|
|
||||||
|
public string? Website { get; set; }
|
||||||
|
|
||||||
|
public string? Phone { get; set; }
|
||||||
|
|
||||||
|
public string? Address { get; set; }
|
||||||
|
|
||||||
|
public string? City { get; set; }
|
||||||
|
|
||||||
|
public string? Region { get; set; }
|
||||||
|
|
||||||
|
public string? Country { get; set; }
|
||||||
|
|
||||||
|
public string? PostalCode { get; set; }
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace LiteCharms.Models;
|
namespace LiteCharms.Features.TechShop;
|
||||||
|
|
||||||
public enum CorrelationIdTypes : int
|
public enum CorrelationIdTypes : int
|
||||||
{
|
{
|
||||||
@@ -15,13 +15,6 @@ public enum CorrelationIdTypes : int
|
|||||||
LinkedIn = 10
|
LinkedIn = 10
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Priorities : int
|
|
||||||
{
|
|
||||||
Low = 0,
|
|
||||||
Medium = 1,
|
|
||||||
High = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum NotificationPlatforms : int
|
public enum NotificationPlatforms : int
|
||||||
{
|
{
|
||||||
Email = 1,
|
Email = 1,
|
||||||
@@ -66,3 +59,4 @@ public enum NotificationDirection : int
|
|||||||
Outgoing = 1,
|
Outgoing = 1,
|
||||||
Neutral = 2
|
Neutral = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
using LiteCharms.Features.TechShop.HealthChecks;
|
||||||
|
using static LiteCharms.Features.TechShop.Extensions.Postgres;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Extensions;
|
||||||
|
|
||||||
|
public static class HealthChecks
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddShopQuartzHealthCheck(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddHealthChecks().AddCheck<ShopQuartzHealthCheck>("ShopQuartz");
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static IServiceCollection AddShopPostgresHealthCheck(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddHealthChecks().AddCheck<PostgresShopHealthCheck>(ShopDbConfigName);
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
+48
-35
@@ -1,29 +1,37 @@
|
|||||||
using LiteCharms.Models;
|
using LiteCharms.Features.TechShop.CartPackages.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Customers.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Leads.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Notifications.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Orders.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Products.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.Products.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Quotes.Models;
|
||||||
|
using LiteCharms.Features.TechShop.ShoppingCarts.Models;
|
||||||
|
|
||||||
namespace LiteCharms.Extensions;
|
namespace LiteCharms.Features.TechShop.Extensions;
|
||||||
|
|
||||||
public static class EntityModeMappers
|
public static class Mappers
|
||||||
{
|
{
|
||||||
public static ShoppingCartPackage ToModel(this Entities.ShoppingCartPackage entity) =>
|
public static ShoppingCartPackage ToModel(this ShoppingCarts.Entities.ShoppingCartPackage entity) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
CreatedAt = entity.CreatedAt,
|
CreatedAt = entity.CreatedAt,
|
||||||
PackageId = entity.PackageId,
|
PackageId = entity.PackageId,
|
||||||
ShoppingCartId = entity.ShoppingCartId
|
ShoppingCartId = entity.ShoppingCartId
|
||||||
};
|
};
|
||||||
|
|
||||||
public static PackageItem ToModel(this Entities.PackageItem entity) =>
|
public static PackageItem ToModel(this CartPackages.Entities.PackageItem entity) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
Active = entity.Active,
|
Active = entity.Active,
|
||||||
CreatedAt = entity.CreatedAt,
|
CreatedAt = entity.CreatedAt,
|
||||||
PackageId = entity.PackageId,
|
PackageId = entity.PackageId,
|
||||||
ProductPriceId = entity.ProductPriceId
|
ProductPriceId = entity.ProductPriceId
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Package ToModel(this Entities.Package entity) =>
|
public static Package ToModel(this CartPackages.Entities.Package entity) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
@@ -31,10 +39,12 @@ public static class EntityModeMappers
|
|||||||
Active = entity.Active,
|
Active = entity.Active,
|
||||||
Description = entity.Description,
|
Description = entity.Description,
|
||||||
Name = entity.Name,
|
Name = entity.Name,
|
||||||
UpdatedAt = entity.UpdatedAt
|
UpdatedAt = entity.UpdatedAt,
|
||||||
|
ImageUrl = entity.ImageUrl,
|
||||||
|
Summary = entity.Summary
|
||||||
};
|
};
|
||||||
|
|
||||||
public static ShoppingCartItem ToModel(this Entities.ShoppingCartItem entity) =>
|
public static ShoppingCartItem ToModel(this ShoppingCarts.Entities.ShoppingCartItem entity) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
@@ -42,21 +52,20 @@ public static class EntityModeMappers
|
|||||||
UpdatedAt = entity.UpdatedAt,
|
UpdatedAt = entity.UpdatedAt,
|
||||||
ProductPriceId = entity.ProductPriceId,
|
ProductPriceId = entity.ProductPriceId,
|
||||||
Quantity = entity.Quantity,
|
Quantity = entity.Quantity,
|
||||||
ShoppingCartId = entity.ShoppingCartId
|
ShoppingCartId = entity.ShoppingCartId
|
||||||
};
|
};
|
||||||
|
|
||||||
public static ShoppingCart ToModel(this Entities.ShoppingCart entity) =>
|
public static ShoppingCart ToModel(this ShoppingCarts.Entities.ShoppingCart entity) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
CreatedAt = entity.CreatedAt,
|
CreatedAt = entity.CreatedAt,
|
||||||
UpdatedAt = entity.UpdatedAt,
|
UpdatedAt = entity.UpdatedAt,
|
||||||
CustomerId = entity.CustomerId,
|
CustomerId = entity.CustomerId,
|
||||||
OrderId = entity.OrderId,
|
OrderId = entity.OrderId
|
||||||
QuoteId = entity.QuoteId
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Quote ToModel(this Entities.Quote entity) =>
|
public static Quote ToModel(this Quotes.Entities.Quote entity) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
@@ -66,10 +75,12 @@ public static class EntityModeMappers
|
|||||||
ExpiredAt = entity.ExpiredAt,
|
ExpiredAt = entity.ExpiredAt,
|
||||||
Reason = entity.Reason,
|
Reason = entity.Reason,
|
||||||
ShoppingCartId = entity.ShoppingCartId,
|
ShoppingCartId = entity.ShoppingCartId,
|
||||||
Status = entity.Status
|
Status = entity.Status,
|
||||||
|
InvoiceUrl = entity.InvoiceUrl,
|
||||||
|
OrderId = entity.OrderId
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Notification ToModel(this Entities.Notification entity) =>
|
public static Notification ToModel(this Notifications.Entities.Notification entity) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
@@ -79,9 +90,9 @@ public static class EntityModeMappers
|
|||||||
CorrelationId = entity.CorrelationId,
|
CorrelationId = entity.CorrelationId,
|
||||||
CorrelationIdType = entity.CorrelationIdType,
|
CorrelationIdType = entity.CorrelationIdType,
|
||||||
IsInternal = entity.IsInternal,
|
IsInternal = entity.IsInternal,
|
||||||
Sender = entity.Sender,
|
SenderAddress = entity.SenderAddress,
|
||||||
Platform = entity.Platform,
|
Platform = entity.Platform,
|
||||||
Recipient = entity.Recipient,
|
RecipientName = entity.RecipientName,
|
||||||
Subject = entity.Subject,
|
Subject = entity.Subject,
|
||||||
Processed = entity.Processed,
|
Processed = entity.Processed,
|
||||||
SenderName = entity.SenderName,
|
SenderName = entity.SenderName,
|
||||||
@@ -93,7 +104,7 @@ public static class EntityModeMappers
|
|||||||
Errors = entity.Errors
|
Errors = entity.Errors
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Customer ToModel(this Entities.Customer entity) =>
|
public static Customer ToModel(this Customers.Entities.Customer entity) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
@@ -118,7 +129,7 @@ public static class EntityModeMappers
|
|||||||
Whatsapp = entity.Whatsapp
|
Whatsapp = entity.Whatsapp
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Lead ToModel(this Entities.Lead entity) =>
|
public static Lead ToModel(this Leads.Entities.Lead entity) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
@@ -136,10 +147,10 @@ public static class EntityModeMappers
|
|||||||
ClickId = entity.ClickId,
|
ClickId = entity.ClickId,
|
||||||
TargetId = entity.TargetId,
|
TargetId = entity.TargetId,
|
||||||
WebClickId = entity.WebClickId,
|
WebClickId = entity.WebClickId,
|
||||||
Status = entity.Status
|
Status = entity.Status
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Order ToModel(this Entities.Order entity) =>
|
public static Order ToModel(this Orders.Entities.Order entity) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
@@ -147,35 +158,37 @@ public static class EntityModeMappers
|
|||||||
UpdatedAt = entity.UpdatedAt,
|
UpdatedAt = entity.UpdatedAt,
|
||||||
CustomerId = entity.CustomerId,
|
CustomerId = entity.CustomerId,
|
||||||
Notes = entity.Notes,
|
Notes = entity.Notes,
|
||||||
RefundId = entity.RefundId,
|
|
||||||
QuoteId = entity.QuoteId,
|
|
||||||
Status = entity.Status,
|
Status = entity.Status,
|
||||||
ShoppingCartId = entity.ShoppingCartId,
|
|
||||||
DepositRequired = entity.DepositRequired,
|
|
||||||
Requirements = entity.Requirements,
|
Requirements = entity.Requirements,
|
||||||
Terms = entity.Terms
|
Terms = entity.Terms,
|
||||||
|
InvoiceUrl = entity.InvoiceUrl
|
||||||
};
|
};
|
||||||
|
|
||||||
public static OrderRefund ToModel(this Entities.OrderRefund entity) =>
|
public static OrderRefund ToModel(this Orders.Entities.OrderRefund entity) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
CreatedAt = entity.CreatedAt,
|
CreatedAt = entity.CreatedAt,
|
||||||
OrderId = entity.OrderId,
|
OrderId = entity.OrderId,
|
||||||
Reason = entity.Reason,
|
Reason = entity.Reason,
|
||||||
Amount = entity.Amount
|
Amount = entity.Amount
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Product ToModel(this Entities.Product entity) =>
|
public static Products.Models.Product ToModel(this Products.Entities.Product entity) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
|
CreatedAt = entity.CreatedAt,
|
||||||
Name = entity.Name,
|
Name = entity.Name,
|
||||||
Description = entity.Description,
|
Description = entity.Description,
|
||||||
Active = entity.Active
|
Active = entity.Active,
|
||||||
|
Summary = entity.Summary,
|
||||||
|
ImageUrl = entity.ImageUrl,
|
||||||
|
Thumbnails = entity.Thumbnails,
|
||||||
|
Metadata = entity.Metadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
public static ProductPrice ToModel(this Entities.ProductPrice entity) =>
|
public static Products.Models.ProductPrice ToModel(this Products.Entities.ProductPrice entity) =>
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
@@ -184,6 +197,6 @@ public static class EntityModeMappers
|
|||||||
Active = entity.Active,
|
Active = entity.Active,
|
||||||
CreatedAt = entity.CreatedAt,
|
CreatedAt = entity.CreatedAt,
|
||||||
Discount = entity.Discount,
|
Discount = entity.Discount,
|
||||||
UpdatedAt = entity.UpdatedAt
|
UpdatedAt = entity.UpdatedAt
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using LiteCharms.Features.TechShop.Postgres;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Extensions;
|
||||||
|
|
||||||
|
public static class Postgres
|
||||||
|
{
|
||||||
|
public const string ShopDbConfigName = "PostgresShop";
|
||||||
|
|
||||||
|
public static IServiceCollection AddTechShopDatabase(this IServiceCollection services, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
services.AddPooledDbContextFactory<ShopDbContext>(options =>
|
||||||
|
options.UseNpgsql(configuration.GetConnectionString(ShopDbConfigName)));
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using LiteCharms.Features.TechShop.CartPackages;
|
||||||
|
using LiteCharms.Features.TechShop.Customers;
|
||||||
|
using LiteCharms.Features.TechShop.Leads;
|
||||||
|
using LiteCharms.Features.TechShop.Notifications;
|
||||||
|
using LiteCharms.Features.TechShop.Orders;
|
||||||
|
using LiteCharms.Features.TechShop.Products;
|
||||||
|
using LiteCharms.Features.TechShop.Quotes;
|
||||||
|
using LiteCharms.Features.TechShop.ShoppingCarts;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Extensions;
|
||||||
|
|
||||||
|
public static class Shop
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddTechShopServices(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<PackageService>()
|
||||||
|
.AddSingleton<LeadService>()
|
||||||
|
.AddSingleton<NotificationService>()
|
||||||
|
.AddSingleton<OrderService>()
|
||||||
|
.AddSingleton<ProductService>()
|
||||||
|
.AddSingleton<QuoteService>()
|
||||||
|
.AddSingleton<ShoppingCartService>()
|
||||||
|
.AddSingleton<CustomerService>();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
-5
@@ -1,8 +1,10 @@
|
|||||||
namespace LiteCharms.Infrastructure.HealthChecks;
|
using static LiteCharms.Features.TechShop.Extensions.Postgres;
|
||||||
|
|
||||||
public class PostgresHealthCheck(IConfiguration configuration) : IHealthCheck
|
namespace LiteCharms.Features.TechShop.HealthChecks;
|
||||||
|
|
||||||
|
public class PostgresShopHealthCheck(IConfiguration configuration) : IHealthCheck
|
||||||
{
|
{
|
||||||
private readonly string connectionString = configuration.GetConnectionString("PostgresShop")!;
|
private readonly string connectionString = configuration.GetConnectionString(ShopDbConfigName)!;
|
||||||
|
|
||||||
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
|
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
@@ -16,11 +18,11 @@ public class PostgresHealthCheck(IConfiguration configuration) : IHealthCheck
|
|||||||
|
|
||||||
await command.ExecuteScalarAsync(cancellationToken);
|
await command.ExecuteScalarAsync(cancellationToken);
|
||||||
|
|
||||||
return HealthCheckResult.Healthy("PostgreSQL is responsive.");
|
return HealthCheckResult.Healthy($"{ShopDbConfigName} is responsive.");
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
return HealthCheckResult.Unhealthy("PostgreSQL is unreachable.", ex);
|
return HealthCheckResult.Unhealthy($"{ShopDbConfigName} is unreachable.", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using static LiteCharms.Features.Extensions.Quartz;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.HealthChecks;
|
||||||
|
|
||||||
|
public class ShopQuartzHealthCheck(ISchedulerFactory schedulerFactory) : IHealthCheck
|
||||||
|
{
|
||||||
|
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var scheduler = await schedulerFactory.GetScheduler(ShopSchedulerName, cancellationToken);
|
||||||
|
|
||||||
|
if(scheduler == null)
|
||||||
|
return HealthCheckResult.Unhealthy($"Scheduler with name '{ShopSchedulerName}' not found.");
|
||||||
|
|
||||||
|
if (!scheduler.IsStarted)
|
||||||
|
return HealthCheckResult.Unhealthy($"{ShopSchedulerName} Quartz scheduler is not running");
|
||||||
|
|
||||||
|
await scheduler.CheckExists(new JobKey(Guid.NewGuid().ToString()), cancellationToken);
|
||||||
|
|
||||||
|
return HealthCheckResult.Healthy($"{ShopSchedulerName} Quartz scheduler is ready");
|
||||||
|
}
|
||||||
|
catch (SchedulerException)
|
||||||
|
{
|
||||||
|
return HealthCheckResult.Unhealthy($"{ShopSchedulerName} Quartz scheduler cannot connect to the store");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using LiteCharms.Entities.Configuration;
|
using LiteCharms.Features.TechShop.Customers.Entities;
|
||||||
|
|
||||||
namespace LiteCharms.Entities;
|
namespace LiteCharms.Features.TechShop.Leads.Entities;
|
||||||
|
|
||||||
[EntityTypeConfiguration<LeadConfiguration, Lead>]
|
[EntityTypeConfiguration<LeadConfiguration, Lead>]
|
||||||
public class Lead : Models.Lead
|
public class Lead : Models.Lead
|
||||||
+10
-5
@@ -1,15 +1,15 @@
|
|||||||
namespace LiteCharms.Entities.Configuration;
|
namespace LiteCharms.Features.TechShop.Leads.Entities;
|
||||||
|
|
||||||
public class LeadConfiguration : IEntityTypeConfiguration<Lead>
|
public class LeadConfiguration : IEntityTypeConfiguration<Lead>
|
||||||
{
|
{
|
||||||
public void Configure(EntityTypeBuilder<Lead> builder)
|
public void Configure(EntityTypeBuilder<Lead> builder)
|
||||||
{
|
{
|
||||||
builder.ToTable(nameof(Lead));
|
builder.ToTable("Leads");
|
||||||
|
|
||||||
builder.HasKey(f => f.Id);
|
builder.HasKey(f => f.Id);
|
||||||
builder.Property(f => f.CreatedAt).ValueGeneratedOnAdd();
|
builder.Property(f => f.CreatedAt).ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
builder.Property(f => f.UpdatedAt).IsRequired(false).ValueGeneratedOnUpdate();
|
builder.Property(f => f.UpdatedAt).IsRequired(false).HasDefaultValueSql(null);
|
||||||
builder.Property(f => f.CustomerId).IsRequired(false);
|
builder.Property(f => f.CustomerId);
|
||||||
builder.Property(f => f.Source);
|
builder.Property(f => f.Source);
|
||||||
builder.Property(f => f.ClickId);
|
builder.Property(f => f.ClickId);
|
||||||
builder.Property(f => f.WebClickId);
|
builder.Property(f => f.WebClickId);
|
||||||
@@ -22,5 +22,10 @@ public class LeadConfiguration : IEntityTypeConfiguration<Lead>
|
|||||||
builder.Property(f => f.ClickLocation);
|
builder.Property(f => f.ClickLocation);
|
||||||
builder.Property(f => f.Status).IsRequired();
|
builder.Property(f => f.Status).IsRequired();
|
||||||
builder.Property(f => f.AttributionHash).IsRequired(true);
|
builder.Property(f => f.AttributionHash).IsRequired(true);
|
||||||
|
|
||||||
|
builder.HasOne(f => f.Customer)
|
||||||
|
.WithMany(f => f.Leads)
|
||||||
|
.HasForeignKey(f => f.CustomerId)
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
using LiteCharms.Features.Extensions;
|
||||||
|
using LiteCharms.Features.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Extensions;
|
||||||
|
using LiteCharms.Features.TechShop.Leads.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Postgres;
|
||||||
|
using static LiteCharms.Features.Extensions.Hash;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Leads;
|
||||||
|
|
||||||
|
public class LeadService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||||
|
{
|
||||||
|
public async ValueTask<Result<Guid>> CreateLeadAsync(CreateLead request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var newLead = context.Leads.Add(new Entities.Lead
|
||||||
|
{
|
||||||
|
WebClickId = request.WebClickId,
|
||||||
|
AppClickId = request.AppClickId,
|
||||||
|
Source = request.Source,
|
||||||
|
ClickId = request.ClickId,
|
||||||
|
AdGroupId = request.AdGroupId,
|
||||||
|
AdName = request.AdName,
|
||||||
|
CampaignId = request.CampaignId,
|
||||||
|
ClickLocation = request.ClickLocation,
|
||||||
|
CustomerId = request.CustomerId,
|
||||||
|
FeedItemId = request.FeedItemId,
|
||||||
|
Status = LeadStatus.New,
|
||||||
|
TargetId = request.TargetId,
|
||||||
|
AttributionHash = StringToSha256Hash.Invoke($"{request.ClickId}{request.AppClickId}{request.WebClickId}")
|
||||||
|
});
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok(newLead.Entity.Id)
|
||||||
|
: Result.Fail<Guid>(new Error($"Failed to create lead -> Google ClickId: {request.ClickId}, App ClickId: {request.AppClickId}, Web ClickId: {request.WebClickId}"));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Guid>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Lead[]>> GetCustomerLeadsAsync(Guid customerId, DateRange range, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var fromDate = range.From.ToDateTime(TimeOnly.MinValue);
|
||||||
|
var toDate = range.To.ToDateTime(TimeOnly.MaxValue);
|
||||||
|
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var leads = await context.Leads.AsNoTracking()
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.Where(lead => lead.CustomerId == customerId)
|
||||||
|
.Where(lead => lead.CreatedAt.Date >= fromDate && lead.CreatedAt.Date <= toDate)
|
||||||
|
.ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return leads?.Length > 0
|
||||||
|
? Result.Ok(leads.Select(l => l.ToModel()).ToArray())
|
||||||
|
: Result.Fail(new Error($"No customer {customerId} leads found for the specified date range {range.From} to {range.To}."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Lead[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Lead[]>> GetLeadsAsync(DateRange range, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var fromDate = range.From.ToDateTime(TimeOnly.MinValue);
|
||||||
|
var toDate = range.To.ToDateTime(TimeOnly.MaxValue);
|
||||||
|
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var leads = await context.Leads.AsNoTracking()
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.Where(l => l.CreatedAt.Date >= fromDate && l.CreatedAt.Date <= toDate)
|
||||||
|
.Take(range.MaxRecords)
|
||||||
|
.ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return leads?.Length > 0
|
||||||
|
? Result.Ok(leads.Select(l => l.ToModel()).ToArray())
|
||||||
|
: Result.Fail(new Error($"No leads found for the specified date range {range.From} to {range.To}."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateLeadAsync(Guid leadId, LeadStatus status, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var lead = await context.Leads.FirstOrDefaultAsync(l => l.Id == leadId, cancellationToken);
|
||||||
|
|
||||||
|
if (lead is null)
|
||||||
|
return Result.Fail(new Error($"Lead with ID {leadId} not found."));
|
||||||
|
|
||||||
|
lead.Status = status;
|
||||||
|
lead.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail(new Error($"Failed to update the lead {leadId}."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
namespace LiteCharms.Models;
|
namespace LiteCharms.Features.TechShop.Leads.Models;
|
||||||
|
|
||||||
public class Lead
|
public class Lead
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
public DateTimeOffset CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
public DateTimeOffset? UpdatedAt { get; set; }
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
public Guid? CustomerId { get; set; }
|
public Guid? CustomerId { get; set; }
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.Leads.Models;
|
||||||
|
|
||||||
|
public record CreateLead
|
||||||
|
{
|
||||||
|
public Guid? CustomerId { get; set; }
|
||||||
|
|
||||||
|
public required string Source { get; set; }
|
||||||
|
|
||||||
|
public required string ClickId { get; set; }
|
||||||
|
|
||||||
|
public required string WebClickId { get; set; }
|
||||||
|
|
||||||
|
public required string AppClickId { get; set; }
|
||||||
|
|
||||||
|
public long? CampaignId { get; set; }
|
||||||
|
|
||||||
|
public long? AdGroupId { get; set; }
|
||||||
|
|
||||||
|
public long? AdName { get; set; }
|
||||||
|
|
||||||
|
public long? TargetId { get; set; }
|
||||||
|
|
||||||
|
public long? FeedItemId { get; set; }
|
||||||
|
|
||||||
|
public string? ClickLocation { get; set; }
|
||||||
|
|
||||||
|
public string? AttribusionHash { get; set; }
|
||||||
|
}
|
||||||
+81
-28
@@ -6,26 +6,16 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<SignAssembly>True</SignAssembly>
|
<SignAssembly>True</SignAssembly>
|
||||||
<AssemblyOriginatorKeyFile>..\LiteCharms.snk</AssemblyOriginatorKeyFile>
|
<AssemblyOriginatorKeyFile>..\LiteCharms.snk</AssemblyOriginatorKeyFile>
|
||||||
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
|
<UserSecretsId>fbd8f4a2-0420-44e2-baff-4678d9e7eee1</UserSecretsId>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- Warnings And Exclusions -->
|
|
||||||
<PropertyGroup>
|
|
||||||
<NoWarn>$(NoWarn);MA0004</NoWarn>
|
|
||||||
<!-- https://github.com/dotnet/aspnetcore/issues/50836 -->
|
|
||||||
<NoWarn>$(NoWarn);AD0001</NoWarn>
|
|
||||||
<PublishTrimmed>true</PublishTrimmed>
|
|
||||||
<NoWarn>$(NoWarn);IL2080;IL2065;IL2075;IL2087;IL2057;IL2060;IL2070;IL2067;IL2072;IL2026;IL2104</NoWarn>
|
|
||||||
<NoWarn>$(NoWarn);IL2110;IL2111</NoWarn>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<!-- Nuget Package Details -->
|
<!-- Nuget Package Details -->
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PackageId>LiteCharms.Extensions</PackageId>
|
<PackageId>LiteCharms.Features.TechShop</PackageId>
|
||||||
<Version>1.0.20</Version>
|
<Version>1.0.20</Version>
|
||||||
<Authors>Khwezi Mngoma</Authors>
|
<Authors>Khwezi Mngoma</Authors>
|
||||||
<Company>Lite Charms (PTY) Ltd</Company>
|
<Company>Lite Charms (PTY) Ltd</Company>
|
||||||
<Description>Extension components for Lite Charms applications.</Description>
|
<Description>TechShop feature components for Lite Charms applications.</Description>
|
||||||
<PackageProjectUrl>https://gitea.khongisa.co.za/litecharms/components</PackageProjectUrl>
|
<PackageProjectUrl>https://gitea.khongisa.co.za/litecharms/components</PackageProjectUrl>
|
||||||
<RepositoryUrl>https://gitea.khongisa.co.za/litecharms/components.git</RepositoryUrl>
|
<RepositoryUrl>https://gitea.khongisa.co.za/litecharms/components.git</RepositoryUrl>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
@@ -39,6 +29,32 @@
|
|||||||
<None Include="..\icon.png" Pack="true" PackagePath="\" />
|
<None Include="..\icon.png" Pack="true" PackagePath="\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Quartz Scheduler-->
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="OpenTelemetry" Version="1.15.3" />
|
||||||
|
<PackageReference Include="Quartz" Version="3.18.1" />
|
||||||
|
<PackageReference Include="Quartz.Plugins" Version="3.18.1" />
|
||||||
|
<PackageReference Include="Quartz.Plugins.TimeZoneConverter" Version="3.18.1" />
|
||||||
|
<PackageReference Include="Quartz.Serialization.SystemTextJson" Version="3.18.1" />
|
||||||
|
<PackageReference Include="Quartz.AspNetCore" Version="3.18.1" />
|
||||||
|
<PackageReference Include="Quartz.Extensions.DependencyInjection" Version="3.18.1" />
|
||||||
|
|
||||||
|
<!-- Global Usings -->
|
||||||
|
<Using Include="Quartz" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Configuration -->
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="10.0.8" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.8" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="10.0.8" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="10.0.8" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="10.0.8" />
|
||||||
|
|
||||||
|
<!-- Global Usings -->
|
||||||
|
<Using Include="Microsoft.Extensions.Configuration" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Health Checks -->
|
<!-- Health Checks -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="9.0.0" />
|
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="9.0.0" />
|
||||||
@@ -46,10 +62,9 @@
|
|||||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Core" Version="9.0.0" />
|
<PackageReference Include="AspNetCore.HealthChecks.UI.Core" Version="9.0.0" />
|
||||||
<PackageReference Include="AspNetCore.HealthChecks.UI.Data" Version="9.0.0" />
|
<PackageReference Include="AspNetCore.HealthChecks.UI.Data" Version="9.0.0" />
|
||||||
<PackageReference Include="AspNetCore.HealthChecks.UI.InMemory.Storage" Version="9.0.0" />
|
<PackageReference Include="AspNetCore.HealthChecks.UI.InMemory.Storage" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.7" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.8" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.7" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.8" />
|
||||||
<PackageReference Include="Quartz.AspNetCore" Version="3.18.1" />
|
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="10.0.8" />
|
||||||
<PackageReference Include="Quartz.Extensions.DependencyInjection" Version="3.18.1" />
|
|
||||||
|
|
||||||
<!-- Global Usings -->
|
<!-- Global Usings -->
|
||||||
<Using Include="Microsoft.Extensions.Diagnostics.HealthChecks" />
|
<Using Include="Microsoft.Extensions.Diagnostics.HealthChecks" />
|
||||||
@@ -75,13 +90,13 @@
|
|||||||
|
|
||||||
<!-- Database -->
|
<!-- Database -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.7" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.8" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.7">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.8">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.7" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="10.0.8" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.7">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.8">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
@@ -94,20 +109,58 @@
|
|||||||
<Using Include="Microsoft.EntityFrameworkCore.Metadata.Builders" />
|
<Using Include="Microsoft.EntityFrameworkCore.Metadata.Builders" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Email -->
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MailKit" Version="4.16.0" />
|
||||||
|
<PackageReference Include="MimeKit" Version="4.16.0" />
|
||||||
|
|
||||||
|
<!-- Global Usings-->
|
||||||
|
<Using Include="MimeKit" />
|
||||||
|
<Using Include="MailKit.Net.Smtp" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- CQRS -->
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="FluentResults" Version="4.0.0" />
|
||||||
|
<PackageReference Include="Mediator.Abstractions" Version="3.0.2" />
|
||||||
|
|
||||||
|
<!-- Global Usings -->
|
||||||
|
<Using Include="FluentResults" />
|
||||||
|
<Using Include="Mediator" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Amazon S3 SDK -->
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AWSSDK.Extensions.NetCore.Setup" Version="4.0.4.1" />
|
||||||
|
<PackageReference Include="AWSSDK.S3" Version="4.0.23.4" />
|
||||||
|
<ProjectReference Include="..\LiteCharms.Features\LiteCharms.Features.csproj" />
|
||||||
|
|
||||||
|
<!-- global Usings -->
|
||||||
|
<Using Include="Amazon.S3" />
|
||||||
|
<Using Include="Amazon.S3.Model" />
|
||||||
|
<Using Include="Amazon.Runtime" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Shared Usings -->
|
<!-- Shared Usings -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Using Include="Quartz" />
|
|
||||||
<Using Include="Microsoft.AspNetCore.Builder" />
|
<Using Include="Microsoft.AspNetCore.Builder" />
|
||||||
<Using Include="Microsoft.Extensions.Configuration" />
|
<Using Include="Microsoft.Extensions.Hosting" />
|
||||||
|
<Using Include="System.Text" />
|
||||||
|
<Using Include="System.Text.Json" />
|
||||||
|
<Using Include="System.Threading.Channels" />
|
||||||
|
<Using Include="System.Collections.ObjectModel" />
|
||||||
|
<Using Include="System.Diagnostics" />
|
||||||
|
<Using Include="System.Diagnostics.Metrics" />
|
||||||
<Using Include="Microsoft.Extensions.DependencyInjection" />
|
<Using Include="Microsoft.Extensions.DependencyInjection" />
|
||||||
|
<Using Include="System.Security.Cryptography" />
|
||||||
|
<Using Include="Microsoft.Extensions.Options" />
|
||||||
<Using Include="Microsoft.Extensions.Logging" />
|
<Using Include="Microsoft.Extensions.Logging" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Project References -->
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\LiteCharms.Entities\LiteCharms.Entities.csproj" />
|
<None Update="appsettings.json">
|
||||||
<ProjectReference Include="..\LiteCharms.Infrastructure\LiteCharms.Infrastructure.csproj" />
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<ProjectReference Include="..\LiteCharms.Models\LiteCharms.Models.csproj" />
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
+1
-3
@@ -1,6 +1,4 @@
|
|||||||
using LiteCharms.Entities.Configuration;
|
namespace LiteCharms.Features.TechShop.Notifications.Entities;
|
||||||
|
|
||||||
namespace LiteCharms.Entities;
|
|
||||||
|
|
||||||
[EntityTypeConfiguration<NotificationConfiguration, Notification>]
|
[EntityTypeConfiguration<NotificationConfiguration, Notification>]
|
||||||
public class Notification : Models.Notification;
|
public class Notification : Models.Notification;
|
||||||
+6
-8
@@ -1,24 +1,22 @@
|
|||||||
using LiteCharms.Models;
|
namespace LiteCharms.Features.TechShop.Notifications.Entities;
|
||||||
|
|
||||||
namespace LiteCharms.Entities.Configuration;
|
|
||||||
|
|
||||||
public class NotificationConfiguration : IEntityTypeConfiguration<Notification>
|
public class NotificationConfiguration : IEntityTypeConfiguration<Notification>
|
||||||
{
|
{
|
||||||
public void Configure(EntityTypeBuilder<Notification> builder)
|
public void Configure(EntityTypeBuilder<Notification> builder)
|
||||||
{
|
{
|
||||||
builder.ToTable(nameof(Notification));
|
builder.ToTable("Notification");
|
||||||
|
|
||||||
builder.HasKey(f => f.Id);
|
builder.HasKey(f => f.Id);
|
||||||
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd();
|
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
builder.Property(f => f.UpdatedAt).IsRequired(false).ValueGeneratedOnUpdate();
|
builder.Property(f => f.UpdatedAt).IsRequired(false).HasDefaultValueSql(null);
|
||||||
builder.Property(f => f.Direction).IsRequired().HasConversion<int>();
|
builder.Property(f => f.Direction).IsRequired().HasConversion<int>();
|
||||||
builder.Property(f => f.Platform).IsRequired().HasConversion<int>();
|
builder.Property(f => f.Platform).IsRequired().HasConversion<int>();
|
||||||
builder.Property(f => f.Priority).IsRequired().HasConversion<int>();
|
builder.Property(f => f.Priority).IsRequired().HasConversion<int>();
|
||||||
builder.Property(f => f.CorrelationIdType).IsRequired().HasConversion<int>();
|
builder.Property(f => f.CorrelationIdType).IsRequired().HasConversion<int>();
|
||||||
builder.Property(f => f.Sender).IsRequired();
|
builder.Property(f => f.SenderAddress).IsRequired();
|
||||||
builder.Property(f => f.Subject).IsRequired();
|
builder.Property(f => f.Subject).IsRequired();
|
||||||
builder.Property(f => f.Message).IsRequired();
|
builder.Property(f => f.Message).IsRequired();
|
||||||
builder.Property(f => f.Recipient).IsRequired();
|
builder.Property(f => f.RecipientName).IsRequired();
|
||||||
builder.Property(f => f.RecipientAddress).IsRequired();
|
builder.Property(f => f.RecipientAddress).IsRequired();
|
||||||
builder.Property(f => f.CorrelationId).IsRequired();
|
builder.Property(f => f.CorrelationId).IsRequired();
|
||||||
builder.Property(f => f.IsHtml).HasDefaultValue(false);
|
builder.Property(f => f.IsHtml).HasDefaultValue(false);
|
||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
using LiteCharms.Features.Email;
|
||||||
|
using LiteCharms.Features.TechShop.Notifications.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Postgres;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Notifications.Events.Handlers;
|
||||||
|
|
||||||
|
public class ProcessEmailNotificationsEventHandler(IDbContextFactory<ShopDbContext> contextFactory, ILogger<ProcessEmailNotificationsEvent> logger,
|
||||||
|
EmailService emailService) : INotificationHandler<ProcessEmailNotificationsEvent>
|
||||||
|
{
|
||||||
|
private bool dropBatch = false;
|
||||||
|
|
||||||
|
public async ValueTask Handle(ProcessEmailNotificationsEvent message, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (emailService.Status != EmailStatuses.Connected)
|
||||||
|
await emailService.ConnectAsync(cancellationToken);
|
||||||
|
|
||||||
|
var notifications = await context.Notifications
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.ThenBy(o => o.Priority)
|
||||||
|
.Where(n => n.Platform == NotificationPlatforms.Email &&
|
||||||
|
n.Direction == NotificationDirection.Outgoing && n.Processed == false)
|
||||||
|
.Take(message.MaxRecords)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
foreach (var notification in notifications)
|
||||||
|
{
|
||||||
|
if (dropBatch) break;
|
||||||
|
|
||||||
|
var sendResult = await SendEmailAsync(notification,emailService, cancellationToken);
|
||||||
|
|
||||||
|
if(sendResult.IsFailed)
|
||||||
|
{
|
||||||
|
var errors = new List<string>(1000);
|
||||||
|
|
||||||
|
errors.AddRange(sendResult.Errors.Select(e => e.Message));
|
||||||
|
|
||||||
|
if (sendResult.Reasons?.Count > 0)
|
||||||
|
errors.AddRange(sendResult.Reasons.Select(e => e.Message));
|
||||||
|
|
||||||
|
notification.HasError = true;
|
||||||
|
notification.Errors = [.. errors];
|
||||||
|
}
|
||||||
|
|
||||||
|
notification.Processed = true;
|
||||||
|
notification.UpdatedAt = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
await context.SaveChangesAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.LogError(ex, ex.Message);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
await emailService.DisconnectAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<Result> SendEmailAsync(Notification notification, EmailService service, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using Email.Models.Message message = CreateMessage(notification);
|
||||||
|
|
||||||
|
var sendResult = await service.SendEmailAsync(message, cancellationToken);
|
||||||
|
|
||||||
|
if (sendResult.IsFailed)
|
||||||
|
{
|
||||||
|
if (emailService.Status != EmailStatuses.Success && emailService.Status != EmailStatuses.Connected) dropBatch = true;
|
||||||
|
|
||||||
|
return Result.Fail(sendResult.Errors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sendResult.IsFailed
|
||||||
|
? Result.Fail(sendResult.Errors)
|
||||||
|
: Result.Ok();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Email.Models.Message CreateMessage(Notification notification) =>
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Sender = new Email.Models.Party
|
||||||
|
{
|
||||||
|
Name = notification.SenderName,
|
||||||
|
Address = notification.SenderAddress
|
||||||
|
},
|
||||||
|
Recipient = new Email.Models.Party
|
||||||
|
{
|
||||||
|
Name = notification.RecipientName,
|
||||||
|
Address = notification.RecipientAddress
|
||||||
|
},
|
||||||
|
Subject = notification.Subject,
|
||||||
|
Body = new Email.Models.Body
|
||||||
|
{
|
||||||
|
Properties = new Email.Models.BodyProperties
|
||||||
|
{
|
||||||
|
HasAttachments = false,
|
||||||
|
IsHtml = notification.IsHtml
|
||||||
|
},
|
||||||
|
Message = notification.Message
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
using static LiteCharms.Features.Extensions.Email;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Notifications.Events.Handlers;
|
||||||
|
|
||||||
|
public class SendShopEmailEnquiryEventHandler(NotificationService notificationService) :
|
||||||
|
INotificationHandler<SendShopEmailEnquiryEvent>
|
||||||
|
{
|
||||||
|
public async ValueTask Handle(SendShopEmailEnquiryEvent notification, CancellationToken cancellationToken) =>
|
||||||
|
await notificationService.CreateNotificationAsync(new Models.CreateNotification
|
||||||
|
{
|
||||||
|
CorrelationId = notification.CorrelationId,
|
||||||
|
CorrelationIdType = CorrelationIdTypes.None,
|
||||||
|
Direction = NotificationDirection.Outgoing,
|
||||||
|
IsHtml = false,
|
||||||
|
IsInternal = true,
|
||||||
|
Message = notification.Message,
|
||||||
|
Platform = NotificationPlatforms.Email,
|
||||||
|
Priority = notification.Priority,
|
||||||
|
Subject = notification.Subject!,
|
||||||
|
Sender = notification.SenderName!,
|
||||||
|
SenderAddress = notification.SenderAddress!,
|
||||||
|
Recipient = ShopEmailFromName,
|
||||||
|
RecipientAddress = ShopEmailFromAddress
|
||||||
|
}, cancellationToken);
|
||||||
|
}
|
||||||
+4
-2
@@ -1,6 +1,6 @@
|
|||||||
using LiteCharms.Abstractions;
|
using LiteCharms.Features.Abstractions;
|
||||||
|
|
||||||
namespace LiteCharms.Features.Notifications.Events;
|
namespace LiteCharms.Features.TechShop.Notifications.Events;
|
||||||
|
|
||||||
public class ProcessEmailNotificationsEvent : EventBase, IEvent
|
public class ProcessEmailNotificationsEvent : EventBase, IEvent
|
||||||
{
|
{
|
||||||
@@ -8,6 +8,8 @@ public class ProcessEmailNotificationsEvent : EventBase, IEvent
|
|||||||
|
|
||||||
public int MaxRecords { get; set; }
|
public int MaxRecords { get; set; }
|
||||||
|
|
||||||
|
public ProcessEmailNotificationsEvent() { MaxRecords = 1000; }
|
||||||
|
|
||||||
private ProcessEmailNotificationsEvent(int maxRecords = 1000) => MaxRecords = maxRecords;
|
private ProcessEmailNotificationsEvent(int maxRecords = 1000) => MaxRecords = maxRecords;
|
||||||
|
|
||||||
public static ProcessEmailNotificationsEvent Create(int maxRecords = 1000) => new(maxRecords);
|
public static ProcessEmailNotificationsEvent Create(int maxRecords = 1000) => new(maxRecords);
|
||||||
+2
-3
@@ -1,7 +1,6 @@
|
|||||||
using LiteCharms.Abstractions;
|
using LiteCharms.Features.Abstractions;
|
||||||
using LiteCharms.Models;
|
|
||||||
|
|
||||||
namespace LiteCharms.Features.Email.Events;
|
namespace LiteCharms.Features.TechShop.Notifications.Events;
|
||||||
|
|
||||||
public class SendShopEmailEnquiryEvent : EventBase, IEvent
|
public class SendShopEmailEnquiryEvent : EventBase, IEvent
|
||||||
{
|
{
|
||||||
+7
-5
@@ -1,12 +1,14 @@
|
|||||||
namespace LiteCharms.Models;
|
using LiteCharms.Features.TechShop;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Notifications.Models;
|
||||||
|
|
||||||
public class Notification
|
public class Notification
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
public DateTimeOffset CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
public DateTimeOffset? UpdatedAt { get; set; }
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
public NotificationDirection Direction { get; set; }
|
public NotificationDirection Direction { get; set; }
|
||||||
|
|
||||||
@@ -16,7 +18,7 @@ public class Notification
|
|||||||
|
|
||||||
public CorrelationIdTypes CorrelationIdType { get; set; }
|
public CorrelationIdTypes CorrelationIdType { get; set; }
|
||||||
|
|
||||||
public string? Sender { get; set; }
|
public string? SenderAddress { get; set; }
|
||||||
|
|
||||||
public string? SenderName { get; set; }
|
public string? SenderName { get; set; }
|
||||||
|
|
||||||
@@ -24,7 +26,7 @@ public class Notification
|
|||||||
|
|
||||||
public string? Message { get; set; }
|
public string? Message { get; set; }
|
||||||
|
|
||||||
public string? Recipient { get; set; }
|
public string? RecipientName { get; set; }
|
||||||
|
|
||||||
public string? RecipientAddress { get; set; }
|
public string? RecipientAddress { get; set; }
|
||||||
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.Notifications.Models;
|
||||||
|
|
||||||
|
public record CreateNotification
|
||||||
|
{
|
||||||
|
public required NotificationDirection Direction { get; set; }
|
||||||
|
|
||||||
|
public required string Sender { get; set; }
|
||||||
|
|
||||||
|
public required string SenderAddress { get; set; }
|
||||||
|
|
||||||
|
public required string Subject { get; set; }
|
||||||
|
|
||||||
|
public string? Message { get; set; }
|
||||||
|
|
||||||
|
public required NotificationPlatforms Platform { get; set; }
|
||||||
|
|
||||||
|
public required Priorities Priority { get; set; }
|
||||||
|
|
||||||
|
public required string Recipient { get; set; }
|
||||||
|
|
||||||
|
public required string RecipientAddress { get; set; }
|
||||||
|
|
||||||
|
public string? CorrelationId { get; set; }
|
||||||
|
|
||||||
|
public CorrelationIdTypes CorrelationIdType { get; set; }
|
||||||
|
|
||||||
|
public bool IsInternal { get; set; }
|
||||||
|
|
||||||
|
public bool IsHtml { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UpdateNotification
|
||||||
|
{
|
||||||
|
public required Guid NotificationId { get; set; }
|
||||||
|
|
||||||
|
public required bool Processed { get; set; }
|
||||||
|
|
||||||
|
public bool HasError { get; set; }
|
||||||
|
|
||||||
|
public string[]? Errors { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
using LiteCharms.Features.Extensions;
|
||||||
|
using LiteCharms.Features.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Extensions;
|
||||||
|
using LiteCharms.Features.TechShop.Notifications.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Postgres;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Notifications;
|
||||||
|
|
||||||
|
public class NotificationService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||||
|
{
|
||||||
|
public async ValueTask<Result<Guid>> CreateNotificationAsync(CreateNotification request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var newNotification = context.Notifications.Add(new Entities.Notification
|
||||||
|
{
|
||||||
|
Direction = request.Direction,
|
||||||
|
SenderName = request.Sender,
|
||||||
|
SenderAddress = request.SenderAddress,
|
||||||
|
RecipientName = request.Recipient,
|
||||||
|
RecipientAddress = request.RecipientAddress,
|
||||||
|
Subject = request.Subject,
|
||||||
|
Message = request.Message,
|
||||||
|
Platform = request.Platform,
|
||||||
|
Priority = request.Priority,
|
||||||
|
CorrelationId = request.CorrelationId,
|
||||||
|
CorrelationIdType = request.CorrelationIdType,
|
||||||
|
IsInternal = request.IsInternal,
|
||||||
|
IsHtml = request.IsHtml,
|
||||||
|
Processed = false
|
||||||
|
});
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok(newNotification.Entity.Id)
|
||||||
|
: Result.Fail(new Error("Failed to create notification"));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Notification>> GetNotificationAsync(Guid notificationId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var notification = await context.Notifications.FirstOrDefaultAsync(n => n.Id == notificationId, cancellationToken);
|
||||||
|
|
||||||
|
return notification is not null
|
||||||
|
? Result.Ok(notification.ToModel())
|
||||||
|
: Result.Fail<Notification>(new Error($"Notification with id {notificationId} not found"));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Notification>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Notification[]>> GetNotificationsAsync(DateRange range, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var fromDate = range.From.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc);
|
||||||
|
var toDate = range.To.ToDateTime(TimeOnly.MaxValue, DateTimeKind.Utc);
|
||||||
|
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var notifications = await context.Notifications.AsNoTracking()
|
||||||
|
.Where(n => n.CreatedAt >= fromDate && n.CreatedAt <= toDate)
|
||||||
|
.OrderByDescending(n => n.CreatedAt)
|
||||||
|
.Take(range.MaxRecords)
|
||||||
|
.ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return notifications?.Length > 0
|
||||||
|
? Result.Ok(notifications.Select(n => n.ToModel()).ToArray())
|
||||||
|
: Result.Fail(new Error($"No notifications found for the specified date range {range.From} to {range.To}."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateNotificationAsync(UpdateNotification request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var notification = await context.Notifications.FirstOrDefaultAsync(n => n.Id == request.NotificationId, cancellationToken);
|
||||||
|
|
||||||
|
if (notification is null)
|
||||||
|
return Result.Fail(new Error($"Notification with id {request.NotificationId} not found."));
|
||||||
|
|
||||||
|
notification.Processed = request.Processed;
|
||||||
|
notification.UpdatedAt = DateTime.UtcNow;
|
||||||
|
notification.HasError = request.HasError;
|
||||||
|
notification.Errors = request.Errors;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail(new Error($"Failed to update notification with id {request.NotificationId}."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using LiteCharms.Features.TechShop.Customers.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.Quotes.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.ShoppingCarts.Entities;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Orders.Entities;
|
||||||
|
|
||||||
|
[EntityTypeConfiguration<OrderConfiguration, Order>]
|
||||||
|
public class Order : Models.Order
|
||||||
|
{
|
||||||
|
public virtual ICollection<OrderRefund>? Refunds { get; set; }
|
||||||
|
|
||||||
|
public virtual Customer? Customer { get; set; }
|
||||||
|
|
||||||
|
public virtual Quote? Quote { get; set; }
|
||||||
|
|
||||||
|
public virtual ShoppingCart? ShoppingCart { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.Orders.Entities;
|
||||||
|
|
||||||
|
public class OrderConfiguration : IEntityTypeConfiguration<Order>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<Order> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("Orders");
|
||||||
|
|
||||||
|
builder.HasKey(f => f.Id);
|
||||||
|
builder.Property(f => f.CreatedAt).ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
|
builder.Property(f => f.UpdatedAt).IsRequired(false).HasDefaultValueSql(null);
|
||||||
|
builder.Property(f => f.CustomerId).IsRequired();
|
||||||
|
builder.Property(f => f.Status).HasConversion<int>().IsRequired();
|
||||||
|
builder.Property(f => f.Requirements).HasColumnType("jsonb").IsRequired(false);
|
||||||
|
builder.Property(f => f.Notes).HasColumnType("jsonb").IsRequired(false);
|
||||||
|
builder.Property(f => f.Terms).HasColumnType("jsonb").IsRequired(false);
|
||||||
|
builder.Property(f => f.InvoiceUrl).IsRequired(false).HasMaxLength(2048);
|
||||||
|
|
||||||
|
builder.HasOne(o => o.Customer)
|
||||||
|
.WithMany(c => c.Orders)
|
||||||
|
.HasForeignKey(o => o.CustomerId)
|
||||||
|
.IsRequired()
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-3
@@ -1,9 +1,8 @@
|
|||||||
using LiteCharms.Entities.Configuration;
|
namespace LiteCharms.Features.TechShop.Orders.Entities;
|
||||||
|
|
||||||
namespace LiteCharms.Entities;
|
|
||||||
|
|
||||||
[EntityTypeConfiguration<OrderRefundConfiguration, OrderRefund>]
|
[EntityTypeConfiguration<OrderRefundConfiguration, OrderRefund>]
|
||||||
public class OrderRefund : Models.OrderRefund
|
public class OrderRefund : Models.OrderRefund
|
||||||
{
|
{
|
||||||
|
|
||||||
public virtual Order? Order { get; set; }
|
public virtual Order? Order { get; set; }
|
||||||
}
|
}
|
||||||
+8
-6
@@ -1,19 +1,21 @@
|
|||||||
namespace LiteCharms.Entities.Configuration;
|
namespace LiteCharms.Features.TechShop.Orders.Entities;
|
||||||
|
|
||||||
public class OrderRefundConfiguration : IEntityTypeConfiguration<OrderRefund>
|
public class OrderRefundConfiguration : IEntityTypeConfiguration<OrderRefund>
|
||||||
{
|
{
|
||||||
public void Configure(EntityTypeBuilder<OrderRefund> builder)
|
public void Configure(EntityTypeBuilder<OrderRefund> builder)
|
||||||
{
|
{
|
||||||
builder.ToTable(nameof(OrderRefund));
|
builder.ToTable("OrderRefunds");
|
||||||
|
|
||||||
builder.HasKey(f => f.Id);
|
builder.HasKey(f => f.Id);
|
||||||
builder.Property(f => f.CreatedAt).ValueGeneratedOnAdd();
|
builder.Property(f => f.CreatedAt).ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
builder.Property(f => f.OrderId).IsRequired();
|
builder.Property(f => f.OrderId).IsRequired();
|
||||||
builder.Property(f => f.Reason).IsRequired();
|
builder.Property(f => f.Reason).IsRequired();
|
||||||
builder.Property(f => f.Amount).IsRequired().HasPrecision(18, 2);
|
builder.Property(f => f.Amount).IsRequired().HasPrecision(18, 2);
|
||||||
|
|
||||||
builder.HasOne(f => f.Order)
|
builder.HasOne(r => r.Order)
|
||||||
.WithOne(o => o.Refund)
|
.WithMany(o => o.Refunds)
|
||||||
.HasForeignKey<OrderRefund>(o => o.OrderId);
|
.HasForeignKey(r => r.OrderId)
|
||||||
|
.IsRequired()
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using LiteCharms.Features.TechShop;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Orders.Models;
|
||||||
|
|
||||||
|
public class Order
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
|
public Guid CustomerId { get; set; }
|
||||||
|
|
||||||
|
public OrderStatus Status { get; set; }
|
||||||
|
|
||||||
|
public string[]? Requirements { get; set; }
|
||||||
|
|
||||||
|
public string[]? Notes { get; set; }
|
||||||
|
|
||||||
|
public string[]? Terms { get; set; }
|
||||||
|
|
||||||
|
public string? InvoiceUrl { get; set; }
|
||||||
|
}
|
||||||
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
namespace LiteCharms.Models;
|
namespace LiteCharms.Features.TechShop.Orders.Models;
|
||||||
|
|
||||||
public class OrderRefund
|
public class OrderRefund
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
public DateTimeOffset CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
public Guid OrderId { get; set; }
|
public Guid OrderId { get; set; }
|
||||||
|
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using LiteCharms.Features.TechShop;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Orders.Models;
|
||||||
|
|
||||||
|
public record CreateOrder
|
||||||
|
{
|
||||||
|
public required Guid CustomerId { get; set; }
|
||||||
|
|
||||||
|
public required Guid ShoppingCartId { get; set; }
|
||||||
|
|
||||||
|
public Guid? QuoteId { get; set; }
|
||||||
|
|
||||||
|
public string[]? Requirements { get; set; }
|
||||||
|
|
||||||
|
public string[]? Notes { get; set; }
|
||||||
|
|
||||||
|
public string[]? Terms { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public record UpdateOrder
|
||||||
|
{
|
||||||
|
public required Guid OrderId { get; set; }
|
||||||
|
|
||||||
|
public required OrderStatus Status { get; set; }
|
||||||
|
|
||||||
|
public string? InvoiceUrl { get; set; }
|
||||||
|
|
||||||
|
public string[]? Notes { get; set; }
|
||||||
|
|
||||||
|
public string[]? Requirements { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public record RefundCustomer
|
||||||
|
{
|
||||||
|
public required Guid OrderId { get; set; }
|
||||||
|
|
||||||
|
public required Guid CustomerId { get; set; }
|
||||||
|
|
||||||
|
public required string Reason { get; set; }
|
||||||
|
|
||||||
|
public required decimal Amount { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,260 @@
|
|||||||
|
using LiteCharms.Features.Extensions;
|
||||||
|
using LiteCharms.Features.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Extensions;
|
||||||
|
using LiteCharms.Features.TechShop.Orders.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Postgres;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Orders;
|
||||||
|
|
||||||
|
public class OrderService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||||
|
{
|
||||||
|
public async ValueTask<Result<Guid>> CreateOrderAsync(CreateOrder request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Customers.AnyAsync(c => c.Id == request.CustomerId, cancellationToken))
|
||||||
|
return Result.Fail<Guid>(new Error($"Customer {request.CustomerId} does not exist."));
|
||||||
|
|
||||||
|
if (!await context.ShoppingCarts.AnyAsync(sc => sc.Id == request.ShoppingCartId, cancellationToken))
|
||||||
|
return Result.Fail<Guid>(new Error($"Shopping cart {request.ShoppingCartId} does not exist."));
|
||||||
|
|
||||||
|
if (request.QuoteId.HasValue && !await context.Quotes.AnyAsync(q => q.Id == request.QuoteId.Value, cancellationToken))
|
||||||
|
return Result.Fail<Guid>(new Error($"Quote {request.QuoteId.Value} does not exist."));
|
||||||
|
|
||||||
|
var newOrder = context.Orders.Add(new Entities.Order
|
||||||
|
{
|
||||||
|
Status = OrderStatus.Pending,
|
||||||
|
CustomerId = request.CustomerId,
|
||||||
|
Requirements = request.Requirements,
|
||||||
|
Notes = request.Notes,
|
||||||
|
Terms = request.Terms
|
||||||
|
});
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok(newOrder.Entity.Id)
|
||||||
|
: Result.Fail<Guid>(new Error($"Failed to create customer {request.CustomerId} order using shopping cart {request.ShoppingCartId}."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Guid>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<OrderRefund[]>> GetCustomerOrderRefundsAsync(Guid customerId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Customers.AnyAsync(c => c.Id == customerId, cancellationToken))
|
||||||
|
return Result.Fail<OrderRefund[]>(new Error($"Customer with Id {customerId} does not exist."));
|
||||||
|
|
||||||
|
var refunds = await context.OrderRefunds.AsNoTracking().AsSplitQuery()
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.Where(r => r.Order!.CustomerId == customerId).ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return refunds?.Length > 0
|
||||||
|
? Result.Ok(refunds.Select(r => r.ToModel()).ToArray())
|
||||||
|
: Result.Fail<OrderRefund[]>(new Error($"No refunds found for customer with Id {customerId}."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<OrderRefund[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Order[]>> GetCustomerOrdersAsync(Guid customerId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Customers.AsNoTracking().AnyAsync(c => c.Id == customerId, cancellationToken))
|
||||||
|
return Result.Fail<Order[]>(new Error($"Customer with Id {customerId} does not exist."));
|
||||||
|
|
||||||
|
var orders = await context.Orders.AsNoTracking()
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.Where(o => o.CustomerId == customerId)
|
||||||
|
.ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return orders?.Length > 0
|
||||||
|
? Result.Ok(orders.Select(o => o.ToModel()).ToArray())
|
||||||
|
: Result.Fail<Order[]>(new Error($"No orders found for customer with Id {customerId}."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Order[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<OrderRefund>> GetOrderRefundAsync(Guid orderId, Guid orderRefundId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var refund = await context.OrderRefunds.AsNoTracking()
|
||||||
|
.FirstOrDefaultAsync(r => r.OrderId == orderId && r.Id == orderRefundId, cancellationToken);
|
||||||
|
|
||||||
|
return refund is not null
|
||||||
|
? Result.Ok(refund.ToModel())
|
||||||
|
: Result.Fail<OrderRefund>(new Error($"Refund {orderRefundId} not found for the given OrderId: {orderId}"));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<OrderRefund>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<OrderRefund>> GetOrderRefundAsync(Guid orderRefundId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var refund = await context.OrderRefunds.AsNoTracking().FirstOrDefaultAsync(r => r.Id == orderRefundId, cancellationToken);
|
||||||
|
|
||||||
|
return refund is not null
|
||||||
|
? Result.Ok(refund.ToModel())
|
||||||
|
: Result.Fail<OrderRefund>($"Order refund could not be found with id {orderRefundId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<OrderRefund>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<OrderRefund[]>> GetOrderRefundsAsync(Guid orderId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var refunds = await context.OrderRefunds.AsNoTracking()
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.Where(r => r.OrderId == orderId)
|
||||||
|
.ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return refunds?.Length > 0
|
||||||
|
? Result.Ok(refunds.Select(r => r.ToModel()).ToArray())
|
||||||
|
: Result.Fail<OrderRefund[]>($"Order refunds could not be found with order id {orderId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<OrderRefund[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Order[]>> GetOrdersAsync(DateRange range, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var fromDate = range.From.ToDateTime(TimeOnly.MinValue);
|
||||||
|
var toDate = range.To.ToDateTime(TimeOnly.MaxValue);
|
||||||
|
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var orders = await context.Orders
|
||||||
|
.AsNoTracking()
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.Where(o => o.CreatedAt >= fromDate && o.CreatedAt <= toDate)
|
||||||
|
.Take(range.MaxRecords)
|
||||||
|
.ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return orders?.Length > 0
|
||||||
|
? Result.Ok(orders.Select(o => o.ToModel()).ToArray())
|
||||||
|
: Result.Fail<Order[]>(new Error($"No orders found for the specified date range {range.From} - {range.To}."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Order[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Guid>> RefundCustomerAsync(RefundCustomer request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Orders.AnyAsync(o => o.Id == request.OrderId, cancellationToken))
|
||||||
|
return Result.Fail<Guid>(new Error($"Order with Id: {request.OrderId} does not exist"));
|
||||||
|
|
||||||
|
if (!await context.Customers.AnyAsync(c => c.Id == request.CustomerId, cancellationToken))
|
||||||
|
return Result.Fail<Guid>(new Error($"Customer with Id: {request.CustomerId} does not exist"));
|
||||||
|
|
||||||
|
if (!await context.Orders.AnyAsync(o => o.Id == request.OrderId && o.CustomerId == request.CustomerId, cancellationToken))
|
||||||
|
return Result.Fail<Guid>(new Error($"Order with Id: {request.OrderId} does not belong to Customer with Id: {request.CustomerId}"));
|
||||||
|
|
||||||
|
var refund = context.OrderRefunds.Add(new Entities.OrderRefund
|
||||||
|
{
|
||||||
|
OrderId = request.OrderId,
|
||||||
|
Reason = request.Reason,
|
||||||
|
Amount = request.Amount
|
||||||
|
});
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok(refund.Entity.Id)
|
||||||
|
: Result.Fail<Guid>(new Error($"Failed to create refund for OrderId: {request.OrderId}"));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Guid>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateOrderRefundAsync(Guid orderRefundId, string reason, decimal amount, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var refund = await context.OrderRefunds.FirstOrDefaultAsync(r => r.Id == orderRefundId, cancellationToken);
|
||||||
|
|
||||||
|
if (refund is null)
|
||||||
|
return Result.Fail($"Order refund not found with id {orderRefundId}");
|
||||||
|
|
||||||
|
refund.Reason = reason;
|
||||||
|
refund.Amount = amount;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail($"Failed to update order refund {orderRefundId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateOrderStatusAsync(UpdateOrder request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var order = await context.Orders.FirstOrDefaultAsync(o => o.Id == request.OrderId, cancellationToken);
|
||||||
|
|
||||||
|
if (order is null)
|
||||||
|
return Result.Fail(new Error($"Order {request.OrderId} not found"));
|
||||||
|
|
||||||
|
order.Status = request.Status;
|
||||||
|
order.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
if(!string.IsNullOrWhiteSpace(request.InvoiceUrl)) order.InvoiceUrl = request.InvoiceUrl;
|
||||||
|
|
||||||
|
if(request.Requirements?.Length > 0) order.Requirements = request.Requirements;
|
||||||
|
if(request.Notes?.Length > 0) order.Notes = request.Notes;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail(new Error($"Failed to update order {request.OrderId}"));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+106
-112
@@ -1,6 +1,6 @@
|
|||||||
// <auto-generated />
|
// <auto-generated />
|
||||||
using System;
|
using System;
|
||||||
using LiteCharms.Infrastructure.Database;
|
using LiteCharms.Features.TechShop.Postgres;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
@@ -9,10 +9,10 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
namespace LiteCharms.Infrastructure.Database.Migrations
|
namespace LiteCharms.Features.TechShop.Postgres.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(ShopDbContext))]
|
[DbContext(typeof(ShopDbContext))]
|
||||||
[Migration("20260510132008_Init")]
|
[Migration("20260512065421_Init")]
|
||||||
partial class Init
|
partial class Init
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -50,7 +50,8 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTimeOffset>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<string>("Discord")
|
b.Property<string>("Discord")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
@@ -86,7 +87,6 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
b.Property<DateTimeOffset?>("UpdatedAt")
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("Website")
|
b.Property<string>("Website")
|
||||||
@@ -130,7 +130,8 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTimeOffset>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<Guid?>("CustomerId")
|
b.Property<Guid?>("CustomerId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
@@ -148,7 +149,6 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
.HasColumnType("bigint");
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
b.Property<DateTimeOffset?>("UpdatedAt")
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("WebClickId")
|
b.Property<string>("WebClickId")
|
||||||
@@ -176,7 +176,8 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTimeOffset>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<int>("Direction")
|
b.Property<int>("Direction")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
@@ -234,7 +235,6 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
b.Property<DateTimeOffset?>("UpdatedAt")
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
@@ -250,29 +250,22 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTimeOffset>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<Guid>("CustomerId")
|
b.Property<Guid>("CustomerId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<bool>("DepositRequired")
|
b.Property<string>("InvoiceUrl")
|
||||||
.HasColumnType("boolean");
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
b.PrimitiveCollection<string>("Notes")
|
b.PrimitiveCollection<string>("Notes")
|
||||||
.HasColumnType("jsonb");
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
b.Property<Guid?>("QuoteId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<Guid?>("RefundId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.PrimitiveCollection<string>("Requirements")
|
b.PrimitiveCollection<string>("Requirements")
|
||||||
.HasColumnType("jsonb");
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
b.Property<Guid>("ShoppingCartId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<int>("Status")
|
b.Property<int>("Status")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
@@ -280,19 +273,12 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
.HasColumnType("jsonb");
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
b.Property<DateTimeOffset?>("UpdatedAt")
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("CustomerId");
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
b.HasIndex("QuoteId")
|
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.HasIndex("ShoppingCartId")
|
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.ToTable("Order", (string)null);
|
b.ToTable("Order", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -308,7 +294,8 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTimeOffset>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<Guid>("OrderId")
|
b.Property<Guid>("OrderId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
@@ -319,8 +306,7 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("OrderId")
|
b.HasIndex("OrderId");
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.ToTable("OrderRefund", (string)null);
|
b.ToTable("OrderRefund", (string)null);
|
||||||
});
|
});
|
||||||
@@ -336,27 +322,32 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTimeOffset>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<string>("Description")
|
b.Property<string>("Description")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
b.Property<string>("Name")
|
b.Property<string>("Name")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<Guid?>("ShoppingCartId")
|
b.Property<string>("Summary")
|
||||||
.HasColumnType("uuid");
|
.IsRequired()
|
||||||
|
.HasMaxLength(512)
|
||||||
|
.HasColumnType("character varying(512)");
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
b.Property<DateTimeOffset?>("UpdatedAt")
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("ShoppingCartId");
|
|
||||||
|
|
||||||
b.ToTable("Package", (string)null);
|
b.ToTable("Package", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -371,14 +362,12 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTimeOffset>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<Guid>("PackageId")
|
b.Property<Guid>("PackageId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<Guid?>("PackageId1")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<Guid>("ProductPriceId")
|
b.Property<Guid>("ProductPriceId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
@@ -386,7 +375,7 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.HasIndex("PackageId");
|
b.HasIndex("PackageId");
|
||||||
|
|
||||||
b.HasIndex("PackageId1");
|
b.HasIndex("ProductPriceId");
|
||||||
|
|
||||||
b.ToTable("PackageItem", (string)null);
|
b.ToTable("PackageItem", (string)null);
|
||||||
});
|
});
|
||||||
@@ -404,12 +393,25 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.Property<string>("Description")
|
b.Property<string>("Description")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
b.Property<string>("Name")
|
b.Property<string>("Name")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Summary")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(512)
|
||||||
|
.HasColumnType("character varying(512)");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Thumbnails")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("Product", (string)null);
|
b.ToTable("Product", (string)null);
|
||||||
@@ -426,7 +428,8 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTimeOffset>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<decimal>("Discount")
|
b.Property<decimal>("Discount")
|
||||||
.HasPrecision(18, 2)
|
.HasPrecision(18, 2)
|
||||||
@@ -440,7 +443,6 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
b.Property<DateTimeOffset?>("UpdatedAt")
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
@@ -458,35 +460,40 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTimeOffset>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<Guid>("CustomerId")
|
b.Property<Guid>("CustomerId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<Guid?>("CustomerId1")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("ExpiredAt")
|
b.Property<DateTimeOffset?>("ExpiredAt")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("InvoiceUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("OrderId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<string>("Reason")
|
b.Property<string>("Reason")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<Guid>("ShoppingCartId")
|
b.Property<Guid?>("ShoppingCartId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<int>("Status")
|
b.Property<int>("Status")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
b.Property<DateTimeOffset?>("UpdatedAt")
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("CustomerId");
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
b.HasIndex("CustomerId1");
|
b.HasIndex("OrderId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
b.HasIndex("ShoppingCartId")
|
b.HasIndex("ShoppingCartId")
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
@@ -502,25 +509,25 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTimeOffset>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<Guid?>("CustomerId")
|
b.Property<Guid>("CustomerId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<Guid?>("OrderId")
|
b.Property<Guid?>("OrderId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<Guid?>("QuoteId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
b.Property<DateTimeOffset?>("UpdatedAt")
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("CustomerId");
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
|
b.HasIndex("OrderId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
b.ToTable("ShoppingCart", (string)null);
|
b.ToTable("ShoppingCart", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -562,7 +569,8 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTimeOffset>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<Guid>("PackageId")
|
b.Property<Guid>("PackageId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
@@ -583,8 +591,7 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
{
|
{
|
||||||
b.HasOne("LiteCharms.Entities.Customer", "Customer")
|
b.HasOne("LiteCharms.Entities.Customer", "Customer")
|
||||||
.WithMany("Leads")
|
.WithMany("Leads")
|
||||||
.HasForeignKey("CustomerId")
|
.HasForeignKey("CustomerId");
|
||||||
.OnDelete(DeleteBehavior.NoAction);
|
|
||||||
|
|
||||||
b.Navigation("Customer");
|
b.Navigation("Customer");
|
||||||
});
|
});
|
||||||
@@ -597,55 +604,37 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
.OnDelete(DeleteBehavior.Restrict)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("LiteCharms.Entities.Quote", "Quote")
|
|
||||||
.WithOne("Order")
|
|
||||||
.HasForeignKey("LiteCharms.Entities.Order", "QuoteId")
|
|
||||||
.OnDelete(DeleteBehavior.Restrict);
|
|
||||||
|
|
||||||
b.HasOne("LiteCharms.Entities.ShoppingCart", "ShoppingCart")
|
|
||||||
.WithOne("Order")
|
|
||||||
.HasForeignKey("LiteCharms.Entities.Order", "ShoppingCartId")
|
|
||||||
.OnDelete(DeleteBehavior.NoAction)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("Customer");
|
b.Navigation("Customer");
|
||||||
|
|
||||||
b.Navigation("Quote");
|
|
||||||
|
|
||||||
b.Navigation("ShoppingCart");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.OrderRefund", b =>
|
modelBuilder.Entity("LiteCharms.Entities.OrderRefund", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("LiteCharms.Entities.Order", "Order")
|
b.HasOne("LiteCharms.Entities.Order", "Order")
|
||||||
.WithOne("Refund")
|
.WithMany("Refunds")
|
||||||
.HasForeignKey("LiteCharms.Entities.OrderRefund", "OrderId")
|
.HasForeignKey("OrderId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.Navigation("Order");
|
b.Navigation("Order");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Package", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("LiteCharms.Entities.ShoppingCart", null)
|
|
||||||
.WithMany("Packages")
|
|
||||||
.HasForeignKey("ShoppingCartId");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.PackageItem", b =>
|
modelBuilder.Entity("LiteCharms.Entities.PackageItem", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("LiteCharms.Entities.Package", "Package")
|
b.HasOne("LiteCharms.Entities.Package", "Package")
|
||||||
.WithMany()
|
.WithMany("PackageItems")
|
||||||
.HasForeignKey("PackageId")
|
.HasForeignKey("PackageId")
|
||||||
.OnDelete(DeleteBehavior.NoAction)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("LiteCharms.Entities.Package", null)
|
b.HasOne("LiteCharms.Entities.ProductPrice", "ProductPrice")
|
||||||
.WithMany("PackageItems")
|
.WithMany()
|
||||||
.HasForeignKey("PackageId1");
|
.HasForeignKey("ProductPriceId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
b.Navigation("Package");
|
b.Navigation("Package");
|
||||||
|
|
||||||
|
b.Navigation("ProductPrice");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.ProductPrice", b =>
|
modelBuilder.Entity("LiteCharms.Entities.ProductPrice", b =>
|
||||||
@@ -662,23 +651,23 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
modelBuilder.Entity("LiteCharms.Entities.Quote", b =>
|
modelBuilder.Entity("LiteCharms.Entities.Quote", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("LiteCharms.Entities.Customer", "Customer")
|
b.HasOne("LiteCharms.Entities.Customer", "Customer")
|
||||||
.WithMany()
|
.WithMany("Quotes")
|
||||||
.HasForeignKey("CustomerId")
|
.HasForeignKey("CustomerId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("LiteCharms.Entities.Customer", null)
|
b.HasOne("LiteCharms.Entities.Order", "Order")
|
||||||
.WithMany("Quotes")
|
.WithOne("Quote")
|
||||||
.HasForeignKey("CustomerId1");
|
.HasForeignKey("LiteCharms.Entities.Quote", "OrderId");
|
||||||
|
|
||||||
b.HasOne("LiteCharms.Entities.ShoppingCart", "ShoppingCart")
|
b.HasOne("LiteCharms.Entities.ShoppingCart", "ShoppingCart")
|
||||||
.WithOne("Quote")
|
.WithOne("Quote")
|
||||||
.HasForeignKey("LiteCharms.Entities.Quote", "ShoppingCartId")
|
.HasForeignKey("LiteCharms.Entities.Quote", "ShoppingCartId");
|
||||||
.OnDelete(DeleteBehavior.NoAction)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("Customer");
|
b.Navigation("Customer");
|
||||||
|
|
||||||
|
b.Navigation("Order");
|
||||||
|
|
||||||
b.Navigation("ShoppingCart");
|
b.Navigation("ShoppingCart");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -687,9 +676,17 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
b.HasOne("LiteCharms.Entities.Customer", "Customer")
|
b.HasOne("LiteCharms.Entities.Customer", "Customer")
|
||||||
.WithMany("ShoppingCarts")
|
.WithMany("ShoppingCarts")
|
||||||
.HasForeignKey("CustomerId")
|
.HasForeignKey("CustomerId")
|
||||||
.OnDelete(DeleteBehavior.NoAction);
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Entities.Order", "Order")
|
||||||
|
.WithOne("ShoppingCart")
|
||||||
|
.HasForeignKey("LiteCharms.Entities.ShoppingCart", "OrderId")
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
b.Navigation("Customer");
|
b.Navigation("Customer");
|
||||||
|
|
||||||
|
b.Navigation("Order");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.ShoppingCartItem", b =>
|
modelBuilder.Entity("LiteCharms.Entities.ShoppingCartItem", b =>
|
||||||
@@ -716,13 +713,13 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
b.HasOne("LiteCharms.Entities.Package", "Package")
|
b.HasOne("LiteCharms.Entities.Package", "Package")
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("PackageId")
|
.HasForeignKey("PackageId")
|
||||||
.OnDelete(DeleteBehavior.NoAction)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("LiteCharms.Entities.ShoppingCart", "ShoppingCart")
|
b.HasOne("LiteCharms.Entities.ShoppingCart", "ShoppingCart")
|
||||||
.WithMany()
|
.WithMany("ShoppingCartPackages")
|
||||||
.HasForeignKey("ShoppingCartId")
|
.HasForeignKey("ShoppingCartId")
|
||||||
.OnDelete(DeleteBehavior.NoAction)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.Navigation("Package");
|
b.Navigation("Package");
|
||||||
@@ -743,7 +740,11 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
|
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("Refund");
|
b.Navigation("Quote");
|
||||||
|
|
||||||
|
b.Navigation("Refunds");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCart");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Package", b =>
|
modelBuilder.Entity("LiteCharms.Entities.Package", b =>
|
||||||
@@ -756,20 +757,13 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
b.Navigation("ProductPrices");
|
b.Navigation("ProductPrices");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Quote", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Order");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.ShoppingCart", b =>
|
modelBuilder.Entity("LiteCharms.Entities.ShoppingCart", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("Order");
|
|
||||||
|
|
||||||
b.Navigation("Packages");
|
|
||||||
|
|
||||||
b.Navigation("Quote");
|
b.Navigation("Quote");
|
||||||
|
|
||||||
b.Navigation("ShoppingCartItems");
|
b.Navigation("ShoppingCartItems");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCartPackages");
|
||||||
});
|
});
|
||||||
#pragma warning restore 612, 618
|
#pragma warning restore 612, 618
|
||||||
}
|
}
|
||||||
+129
-145
@@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore.Migrations;
|
|||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
namespace LiteCharms.Infrastructure.Database.Migrations
|
namespace LiteCharms.Features.TechShop.Postgres.Migrations
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public partial class Init : Migration
|
public partial class Init : Migration
|
||||||
@@ -16,7 +16,7 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||||
Company = table.Column<string>(type: "text", nullable: true),
|
Company = table.Column<string>(type: "text", nullable: true),
|
||||||
Name = table.Column<string>(type: "text", nullable: false),
|
Name = table.Column<string>(type: "text", nullable: false),
|
||||||
@@ -46,7 +46,7 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||||
Direction = table.Column<int>(type: "integer", nullable: false),
|
Direction = table.Column<int>(type: "integer", nullable: false),
|
||||||
Platform = table.Column<int>(type: "integer", nullable: false),
|
Platform = table.Column<int>(type: "integer", nullable: false),
|
||||||
@@ -70,13 +70,34 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
table.PrimaryKey("PK_Notification", x => x.Id);
|
table.PrimaryKey("PK_Notification", x => x.Id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Package",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
|
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||||
|
Name = table.Column<string>(type: "text", nullable: false),
|
||||||
|
Summary = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: false),
|
||||||
|
Description = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: false),
|
||||||
|
ImageUrl = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||||
|
Active = table.Column<bool>(type: "boolean", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Package", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "Product",
|
name: "Product",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
Name = table.Column<string>(type: "text", nullable: false),
|
Name = table.Column<string>(type: "text", nullable: false),
|
||||||
Description = table.Column<string>(type: "text", nullable: false),
|
Summary = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: false),
|
||||||
|
Description = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: false),
|
||||||
|
ImageUrl = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||||
|
Thumbnails = table.Column<string>(type: "jsonb", nullable: true),
|
||||||
Active = table.Column<bool>(type: "boolean", nullable: false, defaultValue: true)
|
Active = table.Column<bool>(type: "boolean", nullable: false, defaultValue: true)
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
@@ -89,7 +110,7 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||||
CustomerId = table.Column<Guid>(type: "uuid", nullable: true),
|
CustomerId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||||
Source = table.Column<string>(type: "text", nullable: true),
|
Source = table.Column<string>(type: "text", nullable: true),
|
||||||
@@ -116,24 +137,28 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "ShoppingCart",
|
name: "Order",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||||
CustomerId = table.Column<Guid>(type: "uuid", nullable: true),
|
CustomerId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
OrderId = table.Column<Guid>(type: "uuid", nullable: true),
|
Status = table.Column<int>(type: "integer", nullable: false),
|
||||||
QuoteId = table.Column<Guid>(type: "uuid", nullable: true)
|
Requirements = table.Column<string>(type: "jsonb", nullable: true),
|
||||||
|
Notes = table.Column<string>(type: "jsonb", nullable: true),
|
||||||
|
Terms = table.Column<string>(type: "jsonb", nullable: true),
|
||||||
|
InvoiceUrl = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true)
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_ShoppingCart", x => x.Id);
|
table.PrimaryKey("PK_Order", x => x.Id);
|
||||||
table.ForeignKey(
|
table.ForeignKey(
|
||||||
name: "FK_ShoppingCart_Customer_CustomerId",
|
name: "FK_Order_Customer_CustomerId",
|
||||||
column: x => x.CustomerId,
|
column: x => x.CustomerId,
|
||||||
principalTable: "Customer",
|
principalTable: "Customer",
|
||||||
principalColumn: "Id");
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
@@ -141,7 +166,7 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||||
ProductId = table.Column<Guid>(type: "uuid", nullable: false),
|
ProductId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
Price = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
|
Price = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
|
||||||
@@ -160,25 +185,78 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "Package",
|
name: "OrderRefund",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
ShoppingCartId = table.Column<Guid>(type: "uuid", nullable: true),
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
OrderId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
Reason = table.Column<string>(type: "text", nullable: false),
|
||||||
|
Amount = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_OrderRefund", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_OrderRefund_Order_OrderId",
|
||||||
|
column: x => x.OrderId,
|
||||||
|
principalTable: "Order",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ShoppingCart",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||||
Name = table.Column<string>(type: "text", nullable: false),
|
CustomerId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
Description = table.Column<string>(type: "text", nullable: false),
|
OrderId = table.Column<Guid>(type: "uuid", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ShoppingCart", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ShoppingCart_Customer_CustomerId",
|
||||||
|
column: x => x.CustomerId,
|
||||||
|
principalTable: "Customer",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ShoppingCart_Order_OrderId",
|
||||||
|
column: x => x.OrderId,
|
||||||
|
principalTable: "Order",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.SetNull);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "PackageItem",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
PackageId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
ProductPriceId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
Active = table.Column<bool>(type: "boolean", nullable: false)
|
Active = table.Column<bool>(type: "boolean", nullable: false)
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_Package", x => x.Id);
|
table.PrimaryKey("PK_PackageItem", x => x.Id);
|
||||||
table.ForeignKey(
|
table.ForeignKey(
|
||||||
name: "FK_Package_ShoppingCart_ShoppingCartId",
|
name: "FK_PackageItem_Package_PackageId",
|
||||||
column: x => x.ShoppingCartId,
|
column: x => x.PackageId,
|
||||||
principalTable: "ShoppingCart",
|
principalTable: "Package",
|
||||||
principalColumn: "Id");
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_PackageItem_ProductPrice_ProductPriceId",
|
||||||
|
column: x => x.ProductPriceId,
|
||||||
|
principalTable: "ProductPrice",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
@@ -186,13 +264,14 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
CustomerId1 = table.Column<Guid>(type: "uuid", nullable: true),
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
|
||||||
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||||
ExpiredAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
ExpiredAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||||
CustomerId = table.Column<Guid>(type: "uuid", nullable: false),
|
CustomerId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
ShoppingCartId = table.Column<Guid>(type: "uuid", nullable: false),
|
OrderId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||||
|
ShoppingCartId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||||
Status = table.Column<int>(type: "integer", nullable: false),
|
Status = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
InvoiceUrl = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||||
Reason = table.Column<string>(type: "text", nullable: true)
|
Reason = table.Column<string>(type: "text", nullable: true)
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
@@ -205,9 +284,9 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Cascade);
|
||||||
table.ForeignKey(
|
table.ForeignKey(
|
||||||
name: "FK_Quote_Customer_CustomerId1",
|
name: "FK_Quote_Order_OrderId",
|
||||||
column: x => x.CustomerId1,
|
column: x => x.OrderId,
|
||||||
principalTable: "Customer",
|
principalTable: "Order",
|
||||||
principalColumn: "Id");
|
principalColumn: "Id");
|
||||||
table.ForeignKey(
|
table.ForeignKey(
|
||||||
name: "FK_Quote_ShoppingCart_ShoppingCartId",
|
name: "FK_Quote_ShoppingCart_ShoppingCartId",
|
||||||
@@ -244,38 +323,12 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Cascade);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "PackageItem",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
PackageId1 = table.Column<Guid>(type: "uuid", nullable: true),
|
|
||||||
PackageId = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
ProductPriceId = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
|
||||||
Active = table.Column<bool>(type: "boolean", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_PackageItem", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_PackageItem_Package_PackageId",
|
|
||||||
column: x => x.PackageId,
|
|
||||||
principalTable: "Package",
|
|
||||||
principalColumn: "Id");
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_PackageItem_Package_PackageId1",
|
|
||||||
column: x => x.PackageId1,
|
|
||||||
principalTable: "Package",
|
|
||||||
principalColumn: "Id");
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "ShoppingCartPackage",
|
name: "ShoppingCartPackage",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
ShoppingCartId = table.Column<Guid>(type: "uuid", nullable: false),
|
ShoppingCartId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
PackageId = table.Column<Guid>(type: "uuid", nullable: false)
|
PackageId = table.Column<Guid>(type: "uuid", nullable: false)
|
||||||
},
|
},
|
||||||
@@ -286,70 +339,12 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
name: "FK_ShoppingCartPackage_Package_PackageId",
|
name: "FK_ShoppingCartPackage_Package_PackageId",
|
||||||
column: x => x.PackageId,
|
column: x => x.PackageId,
|
||||||
principalTable: "Package",
|
principalTable: "Package",
|
||||||
principalColumn: "Id");
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
table.ForeignKey(
|
table.ForeignKey(
|
||||||
name: "FK_ShoppingCartPackage_ShoppingCart_ShoppingCartId",
|
name: "FK_ShoppingCartPackage_ShoppingCart_ShoppingCartId",
|
||||||
column: x => x.ShoppingCartId,
|
column: x => x.ShoppingCartId,
|
||||||
principalTable: "ShoppingCart",
|
principalTable: "ShoppingCart",
|
||||||
principalColumn: "Id");
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "Order",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
|
||||||
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
|
||||||
CustomerId = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
QuoteId = table.Column<Guid>(type: "uuid", nullable: true),
|
|
||||||
ShoppingCartId = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
RefundId = table.Column<Guid>(type: "uuid", nullable: true),
|
|
||||||
Status = table.Column<int>(type: "integer", nullable: false),
|
|
||||||
Requirements = table.Column<string>(type: "jsonb", nullable: true),
|
|
||||||
Notes = table.Column<string>(type: "jsonb", nullable: true),
|
|
||||||
Terms = table.Column<string>(type: "jsonb", nullable: true),
|
|
||||||
DepositRequired = table.Column<bool>(type: "boolean", nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_Order", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Order_Customer_CustomerId",
|
|
||||||
column: x => x.CustomerId,
|
|
||||||
principalTable: "Customer",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Order_Quote_QuoteId",
|
|
||||||
column: x => x.QuoteId,
|
|
||||||
principalTable: "Quote",
|
|
||||||
principalColumn: "Id",
|
|
||||||
onDelete: ReferentialAction.Restrict);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_Order_ShoppingCart_ShoppingCartId",
|
|
||||||
column: x => x.ShoppingCartId,
|
|
||||||
principalTable: "ShoppingCart",
|
|
||||||
principalColumn: "Id");
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "OrderRefund",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
|
|
||||||
OrderId = table.Column<Guid>(type: "uuid", nullable: false),
|
|
||||||
Reason = table.Column<string>(type: "text", nullable: false),
|
|
||||||
Amount = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false)
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_OrderRefund", x => x.Id);
|
|
||||||
table.ForeignKey(
|
|
||||||
name: "FK_OrderRefund_Order_OrderId",
|
|
||||||
column: x => x.OrderId,
|
|
||||||
principalTable: "Order",
|
|
||||||
principalColumn: "Id",
|
principalColumn: "Id",
|
||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Cascade);
|
||||||
});
|
});
|
||||||
@@ -364,28 +359,10 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
table: "Order",
|
table: "Order",
|
||||||
column: "CustomerId");
|
column: "CustomerId");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Order_QuoteId",
|
|
||||||
table: "Order",
|
|
||||||
column: "QuoteId",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Order_ShoppingCartId",
|
|
||||||
table: "Order",
|
|
||||||
column: "ShoppingCartId",
|
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_OrderRefund_OrderId",
|
name: "IX_OrderRefund_OrderId",
|
||||||
table: "OrderRefund",
|
table: "OrderRefund",
|
||||||
column: "OrderId",
|
column: "OrderId");
|
||||||
unique: true);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
|
||||||
name: "IX_Package_ShoppingCartId",
|
|
||||||
table: "Package",
|
|
||||||
column: "ShoppingCartId");
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_PackageItem_PackageId",
|
name: "IX_PackageItem_PackageId",
|
||||||
@@ -393,9 +370,9 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
column: "PackageId");
|
column: "PackageId");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_PackageItem_PackageId1",
|
name: "IX_PackageItem_ProductPriceId",
|
||||||
table: "PackageItem",
|
table: "PackageItem",
|
||||||
column: "PackageId1");
|
column: "ProductPriceId");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_ProductPrice_ProductId",
|
name: "IX_ProductPrice_ProductId",
|
||||||
@@ -408,9 +385,10 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
column: "CustomerId");
|
column: "CustomerId");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_Quote_CustomerId1",
|
name: "IX_Quote_OrderId",
|
||||||
table: "Quote",
|
table: "Quote",
|
||||||
column: "CustomerId1");
|
column: "OrderId",
|
||||||
|
unique: true);
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_Quote_ShoppingCartId",
|
name: "IX_Quote_ShoppingCartId",
|
||||||
@@ -423,6 +401,12 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
table: "ShoppingCart",
|
table: "ShoppingCart",
|
||||||
column: "CustomerId");
|
column: "CustomerId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ShoppingCart_OrderId",
|
||||||
|
table: "ShoppingCart",
|
||||||
|
column: "OrderId",
|
||||||
|
unique: true);
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_ShoppingCartItems_ProductPriceId",
|
name: "IX_ShoppingCartItems_ProductPriceId",
|
||||||
table: "ShoppingCartItems",
|
table: "ShoppingCartItems",
|
||||||
@@ -459,15 +443,15 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "PackageItem");
|
name: "PackageItem");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Quote");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "ShoppingCartItems");
|
name: "ShoppingCartItems");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "ShoppingCartPackage");
|
name: "ShoppingCartPackage");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "Order");
|
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "ProductPrice");
|
name: "ProductPrice");
|
||||||
|
|
||||||
@@ -475,13 +459,13 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
name: "Package");
|
name: "Package");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Quote");
|
name: "ShoppingCart");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Product");
|
name: "Product");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "ShoppingCart");
|
name: "Order");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "Customer");
|
name: "Customer");
|
||||||
Generated
+871
@@ -0,0 +1,871 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using LiteCharms.Features.TechShop.Postgres;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Postgres.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(ShopDbContext))]
|
||||||
|
[Migration("20260514004002_UsedStringTableNames")]
|
||||||
|
partial class UsedStringTableNames
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.Package", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Summary")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(512)
|
||||||
|
.HasColumnType("character varying(512)");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Package", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.PackageItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("PackageId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid>("ProductPriceId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PackageId");
|
||||||
|
|
||||||
|
b.HasIndex("ProductPriceId");
|
||||||
|
|
||||||
|
b.ToTable("PackageItem", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Customers.Entities.Customer", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(true);
|
||||||
|
|
||||||
|
b.Property<string>("Address")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("City")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Company")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Country")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<string>("Discord")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("LinkedIn")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Phone")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("PostalCode")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Region")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Slack")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Tax")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Website")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Whatsapp")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Customers", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Customers.Models.Customer", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<string>("Address")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("City")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Company")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Country")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Discord")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("LinkedIn")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Phone")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("PostalCode")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Region")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Slack")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Tax")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Website")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Whatsapp")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Customer");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Leads.Entities.Lead", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<long?>("AdGroupId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<long?>("AdName")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("AppClickId")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("AttributionHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<long?>("CampaignId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("ClickId")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("ClickLocation")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CustomerId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CustomerId1")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<long?>("FeedItemId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("Source")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<long?>("TargetId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("WebClickId")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
|
b.HasIndex("CustomerId1");
|
||||||
|
|
||||||
|
b.ToTable("Leads", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Notifications.Entities.Notification", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("CorrelationId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("CorrelationIdType")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<int>("Direction")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Errors")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.Property<bool>("HasError")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
|
b.Property<bool>("IsHtml")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
|
b.Property<bool>("IsInternal")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(true);
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("Platform")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("Priority")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<bool>("Processed")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
|
b.Property<string>("RecipientAddress")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("RecipientName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("SenderAddress")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("SenderName")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Subject")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Notification", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.Order", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("CustomerId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("InvoiceUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Notes")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Requirements")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Terms")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
|
b.ToTable("Orders", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.OrderRefund", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<decimal>("Amount")
|
||||||
|
.HasPrecision(18, 2)
|
||||||
|
.HasColumnType("numeric(18,2)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("OrderId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("OrderId");
|
||||||
|
|
||||||
|
b.ToTable("OrderRefunds", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.Product", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(true);
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Summary")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(512)
|
||||||
|
.HasColumnType("character varying(512)");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Thumbnails")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Products", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.ProductPrice", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<decimal>("Discount")
|
||||||
|
.HasPrecision(18, 2)
|
||||||
|
.HasColumnType("numeric(18,2)");
|
||||||
|
|
||||||
|
b.Property<decimal>("Price")
|
||||||
|
.HasPrecision(18, 2)
|
||||||
|
.HasColumnType("numeric(18,2)");
|
||||||
|
|
||||||
|
b.Property<Guid>("ProductId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ProductId");
|
||||||
|
|
||||||
|
b.ToTable("ProductPrices", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Quotes.Entities.Quote", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("CustomerId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("ExpiredAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("InvoiceUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("OrderId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<Guid?>("ShoppingCartId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
|
b.HasIndex("OrderId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.HasIndex("ShoppingCartId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Quotes", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("CustomerId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid?>("OrderId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
|
b.HasIndex("OrderId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ShoppingCarts", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("ProductPriceId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid?>("ProductPriceId1")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<int>("Quantity")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasDefaultValue(1);
|
||||||
|
|
||||||
|
b.Property<Guid>("ShoppingCartId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid?>("ShoppingCartId1")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ProductPriceId");
|
||||||
|
|
||||||
|
b.HasIndex("ProductPriceId1");
|
||||||
|
|
||||||
|
b.HasIndex("ShoppingCartId");
|
||||||
|
|
||||||
|
b.HasIndex("ShoppingCartId1");
|
||||||
|
|
||||||
|
b.ToTable("ShoppingCartItems", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartPackage", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("PackageId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid>("ShoppingCartId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PackageId");
|
||||||
|
|
||||||
|
b.HasIndex("ShoppingCartId");
|
||||||
|
|
||||||
|
b.ToTable("ShoppingCartPackages", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.PackageItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.CartPackages.Entities.Package", "Package")
|
||||||
|
.WithMany("PackageItems")
|
||||||
|
.HasForeignKey("PackageId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Products.Entities.ProductPrice", "ProductPrice")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ProductPriceId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Package");
|
||||||
|
|
||||||
|
b.Navigation("ProductPrice");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Leads.Entities.Lead", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Customers.Models.Customer", "Customer")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CustomerId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", null)
|
||||||
|
.WithMany("Leads")
|
||||||
|
.HasForeignKey("CustomerId1");
|
||||||
|
|
||||||
|
b.Navigation("Customer");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.Order", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||||
|
.WithMany("Orders")
|
||||||
|
.HasForeignKey("CustomerId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Customer");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.OrderRefund", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Orders.Entities.Order", "Order")
|
||||||
|
.WithMany("Refunds")
|
||||||
|
.HasForeignKey("OrderId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Order");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.ProductPrice", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Products.Entities.Product", "Product")
|
||||||
|
.WithMany("ProductPrices")
|
||||||
|
.HasForeignKey("ProductId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Product");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Quotes.Entities.Quote", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||||
|
.WithMany("Quotes")
|
||||||
|
.HasForeignKey("CustomerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Orders.Entities.Order", "Order")
|
||||||
|
.WithOne("Quote")
|
||||||
|
.HasForeignKey("LiteCharms.Features.Shop.Quotes.Entities.Quote", "OrderId");
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||||
|
.WithOne("Quote")
|
||||||
|
.HasForeignKey("LiteCharms.Features.Shop.Quotes.Entities.Quote", "ShoppingCartId");
|
||||||
|
|
||||||
|
b.Navigation("Customer");
|
||||||
|
|
||||||
|
b.Navigation("Order");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCart");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||||
|
.WithMany("ShoppingCarts")
|
||||||
|
.HasForeignKey("CustomerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Orders.Entities.Order", "Order")
|
||||||
|
.WithOne("ShoppingCart")
|
||||||
|
.HasForeignKey("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "OrderId")
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
|
b.Navigation("Customer");
|
||||||
|
|
||||||
|
b.Navigation("Order");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Products.Entities.ProductPrice", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ProductPriceId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Products.Entities.ProductPrice", "ProductPrice")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ProductPriceId1");
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", null)
|
||||||
|
.WithMany("ShoppingCartItems")
|
||||||
|
.HasForeignKey("ShoppingCartId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ShoppingCartId1");
|
||||||
|
|
||||||
|
b.Navigation("ProductPrice");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCart");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartPackage", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.CartPackages.Entities.Package", "Package")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("PackageId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||||
|
.WithMany("ShoppingCartPackages")
|
||||||
|
.HasForeignKey("ShoppingCartId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Package");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCart");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.Package", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("PackageItems");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Customers.Entities.Customer", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Leads");
|
||||||
|
|
||||||
|
b.Navigation("Orders");
|
||||||
|
|
||||||
|
b.Navigation("Quotes");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCarts");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.Order", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Quote");
|
||||||
|
|
||||||
|
b.Navigation("Refunds");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCart");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.Product", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("ProductPrices");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Quote");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCartItems");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCartPackages");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+936
@@ -0,0 +1,936 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Postgres.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class UsedStringTableNames : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_PackageItem_ProductPrice_ProductPriceId",
|
||||||
|
table: "PackageItem");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ProductPrice_ProductPriceId",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ShoppingCart_ShoppingCartId",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Lead");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "OrderRefund");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ProductPrice");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Quote");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ShoppingCartPackage");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Product");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ShoppingCart");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Order");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "Sender",
|
||||||
|
table: "Notification",
|
||||||
|
newName: "SenderAddress");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "Recipient",
|
||||||
|
table: "Notification",
|
||||||
|
newName: "RecipientName");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<DateTime>(
|
||||||
|
name: "UpdatedAt",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(DateTimeOffset),
|
||||||
|
oldType: "timestamp with time zone");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<int>(
|
||||||
|
name: "Quantity",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 1,
|
||||||
|
oldClrType: typeof(int),
|
||||||
|
oldType: "integer");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<DateTime>(
|
||||||
|
name: "CreatedAt",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValueSql: "now()",
|
||||||
|
oldClrType: typeof(DateTimeOffset),
|
||||||
|
oldType: "timestamp with time zone");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<Guid>(
|
||||||
|
name: "ProductPriceId1",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
type: "uuid",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<Guid>(
|
||||||
|
name: "ShoppingCartId1",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
type: "uuid",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "Name",
|
||||||
|
table: "Customer",
|
||||||
|
type: "text",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "text");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "LastName",
|
||||||
|
table: "Customer",
|
||||||
|
type: "text",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "text");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "Email",
|
||||||
|
table: "Customer",
|
||||||
|
type: "text",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "text");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<DateTime>(
|
||||||
|
name: "CreatedAt",
|
||||||
|
table: "Customer",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(DateTimeOffset),
|
||||||
|
oldType: "timestamp with time zone",
|
||||||
|
oldDefaultValueSql: "now()");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<bool>(
|
||||||
|
name: "Active",
|
||||||
|
table: "Customer",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(bool),
|
||||||
|
oldType: "boolean",
|
||||||
|
oldDefaultValue: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Customers",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
|
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||||
|
Company = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Name = table.Column<string>(type: "text", nullable: false),
|
||||||
|
LastName = table.Column<string>(type: "text", nullable: false),
|
||||||
|
Tax = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Email = table.Column<string>(type: "text", nullable: false),
|
||||||
|
Discord = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Slack = table.Column<string>(type: "text", nullable: true),
|
||||||
|
LinkedIn = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Whatsapp = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Website = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Phone = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Address = table.Column<string>(type: "text", nullable: true),
|
||||||
|
City = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Region = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Country = table.Column<string>(type: "text", nullable: true),
|
||||||
|
PostalCode = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Active = table.Column<bool>(type: "boolean", nullable: false, defaultValue: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Customers", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Products",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
Name = table.Column<string>(type: "text", nullable: false),
|
||||||
|
Summary = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: false),
|
||||||
|
Description = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: false),
|
||||||
|
ImageUrl = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||||
|
Thumbnails = table.Column<string>(type: "jsonb", nullable: true),
|
||||||
|
Active = table.Column<bool>(type: "boolean", nullable: false, defaultValue: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Products", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Leads",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CustomerId1 = table.Column<Guid>(type: "uuid", nullable: true),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
|
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||||
|
CustomerId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||||
|
Source = table.Column<string>(type: "text", nullable: true),
|
||||||
|
ClickId = table.Column<string>(type: "text", nullable: true),
|
||||||
|
WebClickId = table.Column<string>(type: "text", nullable: true),
|
||||||
|
AppClickId = table.Column<string>(type: "text", nullable: true),
|
||||||
|
CampaignId = table.Column<long>(type: "bigint", nullable: true),
|
||||||
|
AdGroupId = table.Column<long>(type: "bigint", nullable: true),
|
||||||
|
AdName = table.Column<long>(type: "bigint", nullable: true),
|
||||||
|
TargetId = table.Column<long>(type: "bigint", nullable: true),
|
||||||
|
FeedItemId = table.Column<long>(type: "bigint", nullable: true),
|
||||||
|
ClickLocation = table.Column<string>(type: "text", nullable: true),
|
||||||
|
AttributionHash = table.Column<string>(type: "text", nullable: false),
|
||||||
|
Status = table.Column<int>(type: "integer", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Leads", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Leads_Customer_CustomerId",
|
||||||
|
column: x => x.CustomerId,
|
||||||
|
principalTable: "Customer",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Leads_Customers_CustomerId1",
|
||||||
|
column: x => x.CustomerId1,
|
||||||
|
principalTable: "Customers",
|
||||||
|
principalColumn: "Id");
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Orders",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
|
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||||
|
CustomerId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
Status = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
Requirements = table.Column<string>(type: "jsonb", nullable: true),
|
||||||
|
Notes = table.Column<string>(type: "jsonb", nullable: true),
|
||||||
|
Terms = table.Column<string>(type: "jsonb", nullable: true),
|
||||||
|
InvoiceUrl = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Orders", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Orders_Customers_CustomerId",
|
||||||
|
column: x => x.CustomerId,
|
||||||
|
principalTable: "Customers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ProductPrices",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
|
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||||
|
ProductId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
Price = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
|
||||||
|
Discount = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
|
||||||
|
Active = table.Column<bool>(type: "boolean", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ProductPrices", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ProductPrices_Products_ProductId",
|
||||||
|
column: x => x.ProductId,
|
||||||
|
principalTable: "Products",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "OrderRefunds",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
|
OrderId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
Reason = table.Column<string>(type: "text", nullable: false),
|
||||||
|
Amount = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_OrderRefunds", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_OrderRefunds_Orders_OrderId",
|
||||||
|
column: x => x.OrderId,
|
||||||
|
principalTable: "Orders",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ShoppingCarts",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
|
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||||
|
CustomerId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
OrderId = table.Column<Guid>(type: "uuid", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ShoppingCarts", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ShoppingCarts_Customers_CustomerId",
|
||||||
|
column: x => x.CustomerId,
|
||||||
|
principalTable: "Customers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ShoppingCarts_Orders_OrderId",
|
||||||
|
column: x => x.OrderId,
|
||||||
|
principalTable: "Orders",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.SetNull);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Quotes",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
|
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||||
|
ExpiredAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||||
|
CustomerId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
OrderId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||||
|
ShoppingCartId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||||
|
Status = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
InvoiceUrl = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||||
|
Reason = table.Column<string>(type: "text", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Quotes", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Quotes_Customers_CustomerId",
|
||||||
|
column: x => x.CustomerId,
|
||||||
|
principalTable: "Customers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Quotes_Orders_OrderId",
|
||||||
|
column: x => x.OrderId,
|
||||||
|
principalTable: "Orders",
|
||||||
|
principalColumn: "Id");
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Quotes_ShoppingCarts_ShoppingCartId",
|
||||||
|
column: x => x.ShoppingCartId,
|
||||||
|
principalTable: "ShoppingCarts",
|
||||||
|
principalColumn: "Id");
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ShoppingCartPackages",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
|
ShoppingCartId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
PackageId = table.Column<Guid>(type: "uuid", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ShoppingCartPackages", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ShoppingCartPackages_Package_PackageId",
|
||||||
|
column: x => x.PackageId,
|
||||||
|
principalTable: "Package",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ShoppingCartPackages_ShoppingCarts_ShoppingCartId",
|
||||||
|
column: x => x.ShoppingCartId,
|
||||||
|
principalTable: "ShoppingCarts",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ShoppingCartItems_ProductPriceId1",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
column: "ProductPriceId1");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ShoppingCartItems_ShoppingCartId1",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
column: "ShoppingCartId1");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Leads_CustomerId",
|
||||||
|
table: "Leads",
|
||||||
|
column: "CustomerId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Leads_CustomerId1",
|
||||||
|
table: "Leads",
|
||||||
|
column: "CustomerId1");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_OrderRefunds_OrderId",
|
||||||
|
table: "OrderRefunds",
|
||||||
|
column: "OrderId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Orders_CustomerId",
|
||||||
|
table: "Orders",
|
||||||
|
column: "CustomerId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ProductPrices_ProductId",
|
||||||
|
table: "ProductPrices",
|
||||||
|
column: "ProductId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Quotes_CustomerId",
|
||||||
|
table: "Quotes",
|
||||||
|
column: "CustomerId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Quotes_OrderId",
|
||||||
|
table: "Quotes",
|
||||||
|
column: "OrderId",
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Quotes_ShoppingCartId",
|
||||||
|
table: "Quotes",
|
||||||
|
column: "ShoppingCartId",
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ShoppingCartPackages_PackageId",
|
||||||
|
table: "ShoppingCartPackages",
|
||||||
|
column: "PackageId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ShoppingCartPackages_ShoppingCartId",
|
||||||
|
table: "ShoppingCartPackages",
|
||||||
|
column: "ShoppingCartId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ShoppingCarts_CustomerId",
|
||||||
|
table: "ShoppingCarts",
|
||||||
|
column: "CustomerId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ShoppingCarts_OrderId",
|
||||||
|
table: "ShoppingCarts",
|
||||||
|
column: "OrderId",
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_PackageItem_ProductPrices_ProductPriceId",
|
||||||
|
table: "PackageItem",
|
||||||
|
column: "ProductPriceId",
|
||||||
|
principalTable: "ProductPrices",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ProductPrices_ProductPriceId",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
column: "ProductPriceId",
|
||||||
|
principalTable: "ProductPrices",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ProductPrices_ProductPriceId1",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
column: "ProductPriceId1",
|
||||||
|
principalTable: "ProductPrices",
|
||||||
|
principalColumn: "Id");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ShoppingCarts_ShoppingCartId",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
column: "ShoppingCartId",
|
||||||
|
principalTable: "ShoppingCarts",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ShoppingCarts_ShoppingCartId1",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
column: "ShoppingCartId1",
|
||||||
|
principalTable: "ShoppingCarts",
|
||||||
|
principalColumn: "Id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_PackageItem_ProductPrices_ProductPriceId",
|
||||||
|
table: "PackageItem");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ProductPrices_ProductPriceId",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ProductPrices_ProductPriceId1",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ShoppingCarts_ShoppingCartId",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ShoppingCarts_ShoppingCartId1",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Leads");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "OrderRefunds");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ProductPrices");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Quotes");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ShoppingCartPackages");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Products");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ShoppingCarts");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Orders");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Customers");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_ShoppingCartItems_ProductPriceId1",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_ShoppingCartItems_ShoppingCartId1",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ProductPriceId1",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ShoppingCartId1",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "SenderAddress",
|
||||||
|
table: "Notification",
|
||||||
|
newName: "Sender");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "RecipientName",
|
||||||
|
table: "Notification",
|
||||||
|
newName: "Recipient");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<DateTimeOffset>(
|
||||||
|
name: "UpdatedAt",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
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)),
|
||||||
|
oldClrType: typeof(DateTime),
|
||||||
|
oldType: "timestamp with time zone",
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<int>(
|
||||||
|
name: "Quantity",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(int),
|
||||||
|
oldType: "integer",
|
||||||
|
oldDefaultValue: 1);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<DateTimeOffset>(
|
||||||
|
name: "CreatedAt",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(DateTime),
|
||||||
|
oldType: "timestamp with time zone",
|
||||||
|
oldDefaultValueSql: "now()");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "Name",
|
||||||
|
table: "Customer",
|
||||||
|
type: "text",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "",
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "text",
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "LastName",
|
||||||
|
table: "Customer",
|
||||||
|
type: "text",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "",
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "text",
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "Email",
|
||||||
|
table: "Customer",
|
||||||
|
type: "text",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "",
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "text",
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<DateTimeOffset>(
|
||||||
|
name: "CreatedAt",
|
||||||
|
table: "Customer",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValueSql: "now()",
|
||||||
|
oldClrType: typeof(DateTime),
|
||||||
|
oldType: "timestamp with time zone");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<bool>(
|
||||||
|
name: "Active",
|
||||||
|
table: "Customer",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: true,
|
||||||
|
oldClrType: typeof(bool),
|
||||||
|
oldType: "boolean");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Lead",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CustomerId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||||
|
AdGroupId = table.Column<long>(type: "bigint", nullable: true),
|
||||||
|
AdName = table.Column<long>(type: "bigint", nullable: true),
|
||||||
|
AppClickId = table.Column<string>(type: "text", nullable: true),
|
||||||
|
AttributionHash = table.Column<string>(type: "text", nullable: false),
|
||||||
|
CampaignId = table.Column<long>(type: "bigint", nullable: true),
|
||||||
|
ClickId = table.Column<string>(type: "text", nullable: true),
|
||||||
|
ClickLocation = table.Column<string>(type: "text", nullable: true),
|
||||||
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
|
FeedItemId = table.Column<long>(type: "bigint", nullable: true),
|
||||||
|
Source = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Status = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
TargetId = table.Column<long>(type: "bigint", nullable: true),
|
||||||
|
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||||
|
WebClickId = table.Column<string>(type: "text", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Lead", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Lead_Customer_CustomerId",
|
||||||
|
column: x => x.CustomerId,
|
||||||
|
principalTable: "Customer",
|
||||||
|
principalColumn: "Id");
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Order",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CustomerId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
|
InvoiceUrl = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||||
|
Notes = table.Column<string>(type: "jsonb", nullable: true),
|
||||||
|
Requirements = table.Column<string>(type: "jsonb", nullable: true),
|
||||||
|
Status = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
Terms = table.Column<string>(type: "jsonb", nullable: true),
|
||||||
|
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Order", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Order_Customer_CustomerId",
|
||||||
|
column: x => x.CustomerId,
|
||||||
|
principalTable: "Customer",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Product",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
Active = table.Column<bool>(type: "boolean", nullable: false, defaultValue: true),
|
||||||
|
Description = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: false),
|
||||||
|
ImageUrl = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||||
|
Name = table.Column<string>(type: "text", nullable: false),
|
||||||
|
Summary = table.Column<string>(type: "character varying(512)", maxLength: 512, nullable: false),
|
||||||
|
Thumbnails = table.Column<string>(type: "jsonb", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Product", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "OrderRefund",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
OrderId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
Amount = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
|
Reason = table.Column<string>(type: "text", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_OrderRefund", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_OrderRefund_Order_OrderId",
|
||||||
|
column: x => x.OrderId,
|
||||||
|
principalTable: "Order",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ShoppingCart",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CustomerId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
OrderId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||||
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
|
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ShoppingCart", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ShoppingCart_Customer_CustomerId",
|
||||||
|
column: x => x.CustomerId,
|
||||||
|
principalTable: "Customer",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ShoppingCart_Order_OrderId",
|
||||||
|
column: x => x.OrderId,
|
||||||
|
principalTable: "Order",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.SetNull);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ProductPrice",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
ProductId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
Active = table.Column<bool>(type: "boolean", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
|
Discount = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
|
||||||
|
Price = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
|
||||||
|
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ProductPrice", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ProductPrice_Product_ProductId",
|
||||||
|
column: x => x.ProductId,
|
||||||
|
principalTable: "Product",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Quote",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CustomerId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
OrderId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||||
|
ShoppingCartId = table.Column<Guid>(type: "uuid", nullable: true),
|
||||||
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||||
|
ExpiredAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
|
||||||
|
InvoiceUrl = table.Column<string>(type: "character varying(2048)", maxLength: 2048, nullable: true),
|
||||||
|
Reason = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Status = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Quote", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Quote_Customer_CustomerId",
|
||||||
|
column: x => x.CustomerId,
|
||||||
|
principalTable: "Customer",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Quote_Order_OrderId",
|
||||||
|
column: x => x.OrderId,
|
||||||
|
principalTable: "Order",
|
||||||
|
principalColumn: "Id");
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Quote_ShoppingCart_ShoppingCartId",
|
||||||
|
column: x => x.ShoppingCartId,
|
||||||
|
principalTable: "ShoppingCart",
|
||||||
|
principalColumn: "Id");
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ShoppingCartPackage",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
PackageId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
ShoppingCartId = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ShoppingCartPackage", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ShoppingCartPackage_Package_PackageId",
|
||||||
|
column: x => x.PackageId,
|
||||||
|
principalTable: "Package",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ShoppingCartPackage_ShoppingCart_ShoppingCartId",
|
||||||
|
column: x => x.ShoppingCartId,
|
||||||
|
principalTable: "ShoppingCart",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Lead_CustomerId",
|
||||||
|
table: "Lead",
|
||||||
|
column: "CustomerId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Order_CustomerId",
|
||||||
|
table: "Order",
|
||||||
|
column: "CustomerId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_OrderRefund_OrderId",
|
||||||
|
table: "OrderRefund",
|
||||||
|
column: "OrderId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ProductPrice_ProductId",
|
||||||
|
table: "ProductPrice",
|
||||||
|
column: "ProductId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Quote_CustomerId",
|
||||||
|
table: "Quote",
|
||||||
|
column: "CustomerId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Quote_OrderId",
|
||||||
|
table: "Quote",
|
||||||
|
column: "OrderId",
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Quote_ShoppingCartId",
|
||||||
|
table: "Quote",
|
||||||
|
column: "ShoppingCartId",
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ShoppingCart_CustomerId",
|
||||||
|
table: "ShoppingCart",
|
||||||
|
column: "CustomerId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ShoppingCart_OrderId",
|
||||||
|
table: "ShoppingCart",
|
||||||
|
column: "OrderId",
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ShoppingCartPackage_PackageId",
|
||||||
|
table: "ShoppingCartPackage",
|
||||||
|
column: "PackageId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ShoppingCartPackage_ShoppingCartId",
|
||||||
|
table: "ShoppingCartPackage",
|
||||||
|
column: "ShoppingCartId");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_PackageItem_ProductPrice_ProductPriceId",
|
||||||
|
table: "PackageItem",
|
||||||
|
column: "ProductPriceId",
|
||||||
|
principalTable: "ProductPrice",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ProductPrice_ProductPriceId",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
column: "ProductPriceId",
|
||||||
|
principalTable: "ProductPrice",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ShoppingCart_ShoppingCartId",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
column: "ShoppingCartId",
|
||||||
|
principalTable: "ShoppingCart",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+262
-260
@@ -1,28 +1,100 @@
|
|||||||
// <auto-generated />
|
// <auto-generated />
|
||||||
using System;
|
using System;
|
||||||
using LiteCharms.Infrastructure.Database;
|
using LiteCharms.Features.TechShop.Postgres;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
namespace LiteCharms.Infrastructure.Database.Migrations
|
namespace LiteCharms.Features.TechShop.Postgres.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(ShopDbContext))]
|
[DbContext(typeof(ShopDbContext))]
|
||||||
partial class ShopDbContextModelSnapshot : ModelSnapshot
|
[Migration("20260515055221_FixedLeadCustomerRelationship")]
|
||||||
|
partial class FixedLeadCustomerRelationship
|
||||||
{
|
{
|
||||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "10.0.7")
|
.HasAnnotation("ProductVersion", "10.0.8")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Customer", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.Package", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Summary")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(512)
|
||||||
|
.HasColumnType("character varying(512)");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Package", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.PackageItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("PackageId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid>("ProductPriceId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PackageId");
|
||||||
|
|
||||||
|
b.HasIndex("ProductPriceId");
|
||||||
|
|
||||||
|
b.ToTable("PackageItem", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Customers.Entities.Customer", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
@@ -45,9 +117,10 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
b.Property<string>("Country")
|
b.Property<string>("Country")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTime>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<string>("Discord")
|
b.Property<string>("Discord")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
@@ -82,8 +155,7 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
b.Property<string>("Tax")
|
b.Property<string>("Tax")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("Website")
|
b.Property<string>("Website")
|
||||||
@@ -94,10 +166,10 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("Customer", (string)null);
|
b.ToTable("Customers", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Lead", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.Leads.Entities.Lead", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
@@ -125,9 +197,10 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
b.Property<string>("ClickLocation")
|
b.Property<string>("ClickLocation")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTime>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<Guid?>("CustomerId")
|
b.Property<Guid?>("CustomerId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
@@ -144,8 +217,7 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
b.Property<long?>("TargetId")
|
b.Property<long?>("TargetId")
|
||||||
.HasColumnType("bigint");
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("WebClickId")
|
b.Property<string>("WebClickId")
|
||||||
@@ -155,10 +227,10 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.HasIndex("CustomerId");
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
b.ToTable("Lead", (string)null);
|
b.ToTable("Leads", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Notification", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.Notifications.Entities.Notification", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
@@ -171,9 +243,10 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
b.Property<int>("CorrelationIdType")
|
b.Property<int>("CorrelationIdType")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTime>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<int>("Direction")
|
b.Property<int>("Direction")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
@@ -211,15 +284,15 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
.HasColumnType("boolean")
|
.HasColumnType("boolean")
|
||||||
.HasDefaultValue(false);
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
b.Property<string>("Recipient")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("RecipientAddress")
|
b.Property<string>("RecipientAddress")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<string>("Sender")
|
b.Property<string>("RecipientName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("SenderAddress")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
@@ -230,8 +303,7 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
@@ -239,61 +311,47 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
b.ToTable("Notification", (string)null);
|
b.ToTable("Notification", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.Order", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTime>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<Guid>("CustomerId")
|
b.Property<Guid>("CustomerId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<bool>("DepositRequired")
|
b.Property<string>("InvoiceUrl")
|
||||||
.HasColumnType("boolean");
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
b.PrimitiveCollection<string>("Notes")
|
b.PrimitiveCollection<string>("Notes")
|
||||||
.HasColumnType("jsonb");
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
b.Property<Guid?>("QuoteId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<Guid?>("RefundId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.PrimitiveCollection<string>("Requirements")
|
b.PrimitiveCollection<string>("Requirements")
|
||||||
.HasColumnType("jsonb");
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
b.Property<Guid>("ShoppingCartId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<int>("Status")
|
b.Property<int>("Status")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.PrimitiveCollection<string>("Terms")
|
b.PrimitiveCollection<string>("Terms")
|
||||||
.HasColumnType("jsonb");
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("CustomerId");
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
b.HasIndex("QuoteId")
|
b.ToTable("Orders", (string)null);
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.HasIndex("ShoppingCartId")
|
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.ToTable("Order", (string)null);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.OrderRefund", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.OrderRefund", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
@@ -303,9 +361,10 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
.HasPrecision(18, 2)
|
.HasPrecision(18, 2)
|
||||||
.HasColumnType("numeric(18,2)");
|
.HasColumnType("numeric(18,2)");
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTime>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<Guid>("OrderId")
|
b.Property<Guid>("OrderId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
@@ -316,79 +375,12 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("OrderId")
|
b.HasIndex("OrderId");
|
||||||
.IsUnique();
|
|
||||||
|
|
||||||
b.ToTable("OrderRefund", (string)null);
|
b.ToTable("OrderRefunds", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Package", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.Product", b =>
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<bool>("Active")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.Property<string>("Description")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<string>("Name")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("text");
|
|
||||||
|
|
||||||
b.Property<Guid?>("ShoppingCartId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("ShoppingCartId");
|
|
||||||
|
|
||||||
b.ToTable("Package", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.PackageItem", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("Id")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<bool>("Active")
|
|
||||||
.HasColumnType("boolean");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
|
||||||
|
|
||||||
b.Property<Guid>("PackageId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<Guid?>("PackageId1")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<Guid>("ProductPriceId")
|
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
|
||||||
|
|
||||||
b.HasIndex("PackageId");
|
|
||||||
|
|
||||||
b.HasIndex("PackageId1");
|
|
||||||
|
|
||||||
b.ToTable("PackageItem", (string)null);
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Product", b =>
|
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
@@ -401,18 +393,31 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.Property<string>("Description")
|
b.Property<string>("Description")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
b.Property<string>("Name")
|
b.Property<string>("Name")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Summary")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(512)
|
||||||
|
.HasColumnType("character varying(512)");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Thumbnails")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("Product", (string)null);
|
b.ToTable("Products", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.ProductPrice", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.ProductPrice", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
@@ -421,9 +426,10 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
b.Property<bool>("Active")
|
b.Property<bool>("Active")
|
||||||
.HasColumnType("boolean");
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTime>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<decimal>("Discount")
|
b.Property<decimal>("Discount")
|
||||||
.HasPrecision(18, 2)
|
.HasPrecision(18, 2)
|
||||||
@@ -436,110 +442,118 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
b.Property<Guid>("ProductId")
|
b.Property<Guid>("ProductId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("ProductId");
|
b.HasIndex("ProductId");
|
||||||
|
|
||||||
b.ToTable("ProductPrice", (string)null);
|
b.ToTable("ProductPrices", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Quote", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.Quotes.Entities.Quote", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTime>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<Guid>("CustomerId")
|
b.Property<Guid>("CustomerId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<Guid?>("CustomerId1")
|
b.Property<DateTime?>("ExpiredAt")
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("ExpiredAt")
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("InvoiceUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("OrderId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<string>("Reason")
|
b.Property<string>("Reason")
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<Guid>("ShoppingCartId")
|
b.Property<Guid?>("ShoppingCartId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<int>("Status")
|
b.Property<int>("Status")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("CustomerId");
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
b.HasIndex("CustomerId1");
|
b.HasIndex("OrderId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
b.HasIndex("ShoppingCartId")
|
b.HasIndex("ShoppingCartId")
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
b.ToTable("Quote", (string)null);
|
b.ToTable("Quotes", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.ShoppingCart", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTime>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<Guid?>("CustomerId")
|
b.Property<Guid>("CustomerId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<Guid?>("OrderId")
|
b.Property<Guid?>("OrderId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<Guid?>("QuoteId")
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
.HasColumnType("uuid");
|
|
||||||
|
|
||||||
b.Property<DateTimeOffset?>("UpdatedAt")
|
|
||||||
.ValueGeneratedOnUpdate()
|
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("CustomerId");
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
b.ToTable("ShoppingCart", (string)null);
|
b.HasIndex("OrderId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ShoppingCarts", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.ShoppingCartItem", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartItem", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTime>("CreatedAt")
|
||||||
.HasColumnType("timestamp with time zone");
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<Guid>("ProductPriceId")
|
b.Property<Guid>("ProductPriceId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<int>("Quantity")
|
b.Property<int>("Quantity")
|
||||||
.HasColumnType("integer");
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasDefaultValue(1);
|
||||||
|
|
||||||
b.Property<Guid>("ShoppingCartId")
|
b.Property<Guid>("ShoppingCartId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("UpdatedAt")
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
@@ -548,18 +562,19 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.HasIndex("ShoppingCartId");
|
b.HasIndex("ShoppingCartId");
|
||||||
|
|
||||||
b.ToTable("ShoppingCartItems");
|
b.ToTable("ShoppingCartItems", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.ShoppingCartPackage", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartPackage", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
b.Property<DateTimeOffset>("CreatedAt")
|
b.Property<DateTime>("CreatedAt")
|
||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
b.Property<Guid>("PackageId")
|
b.Property<Guid>("PackageId")
|
||||||
.HasColumnType("uuid");
|
.HasColumnType("uuid");
|
||||||
@@ -573,81 +588,63 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
|
|
||||||
b.HasIndex("ShoppingCartId");
|
b.HasIndex("ShoppingCartId");
|
||||||
|
|
||||||
b.ToTable("ShoppingCartPackage", (string)null);
|
b.ToTable("ShoppingCartPackages", (string)null);
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Lead", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.PackageItem", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("LiteCharms.Entities.Customer", "Customer")
|
b.HasOne("LiteCharms.Features.Shop.CartPackages.Entities.Package", "Package")
|
||||||
|
.WithMany("PackageItems")
|
||||||
|
.HasForeignKey("PackageId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Products.Entities.ProductPrice", "ProductPrice")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ProductPriceId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Package");
|
||||||
|
|
||||||
|
b.Navigation("ProductPrice");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Leads.Entities.Lead", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||||
.WithMany("Leads")
|
.WithMany("Leads")
|
||||||
.HasForeignKey("CustomerId")
|
.HasForeignKey("CustomerId")
|
||||||
.OnDelete(DeleteBehavior.NoAction);
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
b.Navigation("Customer");
|
b.Navigation("Customer");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.Order", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("LiteCharms.Entities.Customer", "Customer")
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||||
.WithMany("Orders")
|
.WithMany("Orders")
|
||||||
.HasForeignKey("CustomerId")
|
.HasForeignKey("CustomerId")
|
||||||
.OnDelete(DeleteBehavior.Restrict)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("LiteCharms.Entities.Quote", "Quote")
|
|
||||||
.WithOne("Order")
|
|
||||||
.HasForeignKey("LiteCharms.Entities.Order", "QuoteId")
|
|
||||||
.OnDelete(DeleteBehavior.Restrict);
|
|
||||||
|
|
||||||
b.HasOne("LiteCharms.Entities.ShoppingCart", "ShoppingCart")
|
|
||||||
.WithOne("Order")
|
|
||||||
.HasForeignKey("LiteCharms.Entities.Order", "ShoppingCartId")
|
|
||||||
.OnDelete(DeleteBehavior.NoAction)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.Navigation("Customer");
|
b.Navigation("Customer");
|
||||||
|
|
||||||
b.Navigation("Quote");
|
|
||||||
|
|
||||||
b.Navigation("ShoppingCart");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.OrderRefund", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.OrderRefund", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("LiteCharms.Entities.Order", "Order")
|
b.HasOne("LiteCharms.Features.Shop.Orders.Entities.Order", "Order")
|
||||||
.WithOne("Refund")
|
.WithMany("Refunds")
|
||||||
.HasForeignKey("LiteCharms.Entities.OrderRefund", "OrderId")
|
.HasForeignKey("OrderId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.Navigation("Order");
|
b.Navigation("Order");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Package", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.ProductPrice", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("LiteCharms.Entities.ShoppingCart", null)
|
b.HasOne("LiteCharms.Features.Shop.Products.Entities.Product", "Product")
|
||||||
.WithMany("Packages")
|
|
||||||
.HasForeignKey("ShoppingCartId");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.PackageItem", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("LiteCharms.Entities.Package", "Package")
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("PackageId")
|
|
||||||
.OnDelete(DeleteBehavior.NoAction)
|
|
||||||
.IsRequired();
|
|
||||||
|
|
||||||
b.HasOne("LiteCharms.Entities.Package", null)
|
|
||||||
.WithMany("PackageItems")
|
|
||||||
.HasForeignKey("PackageId1");
|
|
||||||
|
|
||||||
b.Navigation("Package");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.ProductPrice", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("LiteCharms.Entities.Product", "Product")
|
|
||||||
.WithMany("ProductPrices")
|
.WithMany("ProductPrices")
|
||||||
.HasForeignKey("ProductId")
|
.HasForeignKey("ProductId")
|
||||||
.OnDelete(DeleteBehavior.Restrict)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
@@ -656,48 +653,56 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
b.Navigation("Product");
|
b.Navigation("Product");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Quote", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.Quotes.Entities.Quote", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("LiteCharms.Entities.Customer", "Customer")
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||||
.WithMany()
|
.WithMany("Quotes")
|
||||||
.HasForeignKey("CustomerId")
|
.HasForeignKey("CustomerId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("LiteCharms.Entities.Customer", null)
|
b.HasOne("LiteCharms.Features.Shop.Orders.Entities.Order", "Order")
|
||||||
.WithMany("Quotes")
|
|
||||||
.HasForeignKey("CustomerId1");
|
|
||||||
|
|
||||||
b.HasOne("LiteCharms.Entities.ShoppingCart", "ShoppingCart")
|
|
||||||
.WithOne("Quote")
|
.WithOne("Quote")
|
||||||
.HasForeignKey("LiteCharms.Entities.Quote", "ShoppingCartId")
|
.HasForeignKey("LiteCharms.Features.Shop.Quotes.Entities.Quote", "OrderId");
|
||||||
.OnDelete(DeleteBehavior.NoAction)
|
|
||||||
.IsRequired();
|
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||||
|
.WithOne("Quote")
|
||||||
|
.HasForeignKey("LiteCharms.Features.Shop.Quotes.Entities.Quote", "ShoppingCartId");
|
||||||
|
|
||||||
b.Navigation("Customer");
|
b.Navigation("Customer");
|
||||||
|
|
||||||
|
b.Navigation("Order");
|
||||||
|
|
||||||
b.Navigation("ShoppingCart");
|
b.Navigation("ShoppingCart");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.ShoppingCart", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("LiteCharms.Entities.Customer", "Customer")
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||||
.WithMany("ShoppingCarts")
|
.WithMany("ShoppingCarts")
|
||||||
.HasForeignKey("CustomerId")
|
.HasForeignKey("CustomerId")
|
||||||
.OnDelete(DeleteBehavior.NoAction);
|
|
||||||
|
|
||||||
b.Navigation("Customer");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.ShoppingCartItem", b =>
|
|
||||||
{
|
|
||||||
b.HasOne("LiteCharms.Entities.ProductPrice", "ProductPrice")
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey("ProductPriceId")
|
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("LiteCharms.Entities.ShoppingCart", "ShoppingCart")
|
b.HasOne("LiteCharms.Features.Shop.Orders.Entities.Order", "Order")
|
||||||
|
.WithOne("ShoppingCart")
|
||||||
|
.HasForeignKey("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "OrderId")
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
|
b.Navigation("Customer");
|
||||||
|
|
||||||
|
b.Navigation("Order");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Products.Entities.ProductPrice", "ProductPrice")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ProductPriceId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||||
.WithMany("ShoppingCartItems")
|
.WithMany("ShoppingCartItems")
|
||||||
.HasForeignKey("ShoppingCartId")
|
.HasForeignKey("ShoppingCartId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
@@ -708,18 +713,18 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
b.Navigation("ShoppingCart");
|
b.Navigation("ShoppingCart");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.ShoppingCartPackage", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartPackage", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("LiteCharms.Entities.Package", "Package")
|
b.HasOne("LiteCharms.Features.Shop.CartPackages.Entities.Package", "Package")
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("PackageId")
|
.HasForeignKey("PackageId")
|
||||||
.OnDelete(DeleteBehavior.NoAction)
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.HasOne("LiteCharms.Entities.ShoppingCart", "ShoppingCart")
|
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||||
.WithMany()
|
.WithMany("ShoppingCartPackages")
|
||||||
.HasForeignKey("ShoppingCartId")
|
.HasForeignKey("ShoppingCartId")
|
||||||
.OnDelete(DeleteBehavior.NoAction)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.Navigation("Package");
|
b.Navigation("Package");
|
||||||
@@ -727,7 +732,12 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
b.Navigation("ShoppingCart");
|
b.Navigation("ShoppingCart");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Customer", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.Package", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("PackageItems");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Customers.Entities.Customer", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("Leads");
|
b.Navigation("Leads");
|
||||||
|
|
||||||
@@ -738,35 +748,27 @@ namespace LiteCharms.Infrastructure.Database.Migrations
|
|||||||
b.Navigation("ShoppingCarts");
|
b.Navigation("ShoppingCarts");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.Order", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("Refund");
|
b.Navigation("Quote");
|
||||||
|
|
||||||
|
b.Navigation("Refunds");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCart");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Package", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.Product", b =>
|
||||||
{
|
|
||||||
b.Navigation("PackageItems");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Product", b =>
|
|
||||||
{
|
{
|
||||||
b.Navigation("ProductPrices");
|
b.Navigation("ProductPrices");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.Quote", b =>
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("Order");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("LiteCharms.Entities.ShoppingCart", b =>
|
|
||||||
{
|
|
||||||
b.Navigation("Order");
|
|
||||||
|
|
||||||
b.Navigation("Packages");
|
|
||||||
|
|
||||||
b.Navigation("Quote");
|
b.Navigation("Quote");
|
||||||
|
|
||||||
b.Navigation("ShoppingCartItems");
|
b.Navigation("ShoppingCartItems");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCartPackages");
|
||||||
});
|
});
|
||||||
#pragma warning restore 612, 618
|
#pragma warning restore 612, 618
|
||||||
}
|
}
|
||||||
+166
@@ -0,0 +1,166 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Postgres.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class FixedLeadCustomerRelationship : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_Leads_Customer_CustomerId",
|
||||||
|
table: "Leads");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_Leads_Customers_CustomerId1",
|
||||||
|
table: "Leads");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ProductPrices_ProductPriceId1",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ShoppingCarts_ShoppingCartId1",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Customer");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_ShoppingCartItems_ProductPriceId1",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_ShoppingCartItems_ShoppingCartId1",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Leads_CustomerId1",
|
||||||
|
table: "Leads");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ProductPriceId1",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "ShoppingCartId1",
|
||||||
|
table: "ShoppingCartItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "CustomerId1",
|
||||||
|
table: "Leads");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_Leads_Customers_CustomerId",
|
||||||
|
table: "Leads",
|
||||||
|
column: "CustomerId",
|
||||||
|
principalTable: "Customers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_Leads_Customers_CustomerId",
|
||||||
|
table: "Leads");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<Guid>(
|
||||||
|
name: "ProductPriceId1",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
type: "uuid",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<Guid>(
|
||||||
|
name: "ShoppingCartId1",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
type: "uuid",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<Guid>(
|
||||||
|
name: "CustomerId1",
|
||||||
|
table: "Leads",
|
||||||
|
type: "uuid",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Customer",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
Active = table.Column<bool>(type: "boolean", nullable: false),
|
||||||
|
Address = table.Column<string>(type: "text", nullable: true),
|
||||||
|
City = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Company = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Country = table.Column<string>(type: "text", nullable: true),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||||
|
Discord = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Email = table.Column<string>(type: "text", nullable: true),
|
||||||
|
LastName = table.Column<string>(type: "text", nullable: true),
|
||||||
|
LinkedIn = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Name = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Phone = table.Column<string>(type: "text", nullable: true),
|
||||||
|
PostalCode = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Region = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Slack = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Tax = table.Column<string>(type: "text", nullable: true),
|
||||||
|
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||||
|
Website = table.Column<string>(type: "text", nullable: true),
|
||||||
|
Whatsapp = table.Column<string>(type: "text", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Customer", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ShoppingCartItems_ProductPriceId1",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
column: "ProductPriceId1");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ShoppingCartItems_ShoppingCartId1",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
column: "ShoppingCartId1");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Leads_CustomerId1",
|
||||||
|
table: "Leads",
|
||||||
|
column: "CustomerId1");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_Leads_Customer_CustomerId",
|
||||||
|
table: "Leads",
|
||||||
|
column: "CustomerId",
|
||||||
|
principalTable: "Customer",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_Leads_Customers_CustomerId1",
|
||||||
|
table: "Leads",
|
||||||
|
column: "CustomerId1",
|
||||||
|
principalTable: "Customers",
|
||||||
|
principalColumn: "Id");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ProductPrices_ProductPriceId1",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
column: "ProductPriceId1",
|
||||||
|
principalTable: "ProductPrices",
|
||||||
|
principalColumn: "Id");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_ShoppingCartItems_ShoppingCarts_ShoppingCartId1",
|
||||||
|
table: "ShoppingCartItems",
|
||||||
|
column: "ShoppingCartId1",
|
||||||
|
principalTable: "ShoppingCarts",
|
||||||
|
principalColumn: "Id");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+788
@@ -0,0 +1,788 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using LiteCharms.Features.TechShop.Postgres;
|
||||||
|
using LiteCharms.Features.TechShop.Products.Models;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Postgres.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(ShopDbContext))]
|
||||||
|
[Migration("20260520191059_AddedProductMetadata")]
|
||||||
|
partial class AddedProductMetadata
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.Package", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Summary")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(512)
|
||||||
|
.HasColumnType("character varying(512)");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Package", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.PackageItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("PackageId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid>("ProductPriceId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PackageId");
|
||||||
|
|
||||||
|
b.HasIndex("ProductPriceId");
|
||||||
|
|
||||||
|
b.ToTable("PackageItem", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Customers.Entities.Customer", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(true);
|
||||||
|
|
||||||
|
b.Property<string>("Address")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("City")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Company")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Country")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<string>("Discord")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("LinkedIn")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Phone")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("PostalCode")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Region")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Slack")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Tax")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Website")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Whatsapp")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Customers", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Leads.Entities.Lead", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<long?>("AdGroupId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<long?>("AdName")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("AppClickId")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("AttributionHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<long?>("CampaignId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("ClickId")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("ClickLocation")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CustomerId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<long?>("FeedItemId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("Source")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<long?>("TargetId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("WebClickId")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
|
b.ToTable("Leads", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Notifications.Entities.Notification", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("CorrelationId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("CorrelationIdType")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<int>("Direction")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Errors")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.Property<bool>("HasError")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
|
b.Property<bool>("IsHtml")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
|
b.Property<bool>("IsInternal")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(true);
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("Platform")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("Priority")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<bool>("Processed")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
|
b.Property<string>("RecipientAddress")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("RecipientName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("SenderAddress")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("SenderName")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Subject")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Notification", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.Order", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("CustomerId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("InvoiceUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Notes")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Requirements")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Terms")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
|
b.ToTable("Orders", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.OrderRefund", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<decimal>("Amount")
|
||||||
|
.HasPrecision(18, 2)
|
||||||
|
.HasColumnType("numeric(18,2)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("OrderId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("OrderId");
|
||||||
|
|
||||||
|
b.ToTable("OrderRefunds", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.Product", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<ProductMetadata>("Metadata")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Summary")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(512)
|
||||||
|
.HasColumnType("character varying(512)");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Thumbnails")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Products", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.ProductPrice", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<decimal>("Discount")
|
||||||
|
.HasPrecision(18, 2)
|
||||||
|
.HasColumnType("numeric(18,2)");
|
||||||
|
|
||||||
|
b.Property<decimal>("Price")
|
||||||
|
.HasPrecision(18, 2)
|
||||||
|
.HasColumnType("numeric(18,2)");
|
||||||
|
|
||||||
|
b.Property<Guid>("ProductId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ProductId");
|
||||||
|
|
||||||
|
b.ToTable("ProductPrices", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Quotes.Entities.Quote", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("CustomerId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("ExpiredAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("InvoiceUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("OrderId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<Guid?>("ShoppingCartId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
|
b.HasIndex("OrderId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.HasIndex("ShoppingCartId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Quotes", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("CustomerId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid?>("OrderId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
|
b.HasIndex("OrderId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ShoppingCarts", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("ProductPriceId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<int>("Quantity")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasDefaultValue(1);
|
||||||
|
|
||||||
|
b.Property<Guid>("ShoppingCartId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ProductPriceId");
|
||||||
|
|
||||||
|
b.HasIndex("ShoppingCartId");
|
||||||
|
|
||||||
|
b.ToTable("ShoppingCartItems", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartPackage", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("PackageId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid>("ShoppingCartId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PackageId");
|
||||||
|
|
||||||
|
b.HasIndex("ShoppingCartId");
|
||||||
|
|
||||||
|
b.ToTable("ShoppingCartPackages", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.PackageItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.CartPackages.Entities.Package", "Package")
|
||||||
|
.WithMany("PackageItems")
|
||||||
|
.HasForeignKey("PackageId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Products.Entities.ProductPrice", "ProductPrice")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ProductPriceId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Package");
|
||||||
|
|
||||||
|
b.Navigation("ProductPrice");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Leads.Entities.Lead", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||||
|
.WithMany("Leads")
|
||||||
|
.HasForeignKey("CustomerId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
b.Navigation("Customer");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.Order", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||||
|
.WithMany("Orders")
|
||||||
|
.HasForeignKey("CustomerId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Customer");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.OrderRefund", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Orders.Entities.Order", "Order")
|
||||||
|
.WithMany("Refunds")
|
||||||
|
.HasForeignKey("OrderId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Order");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.ProductPrice", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Products.Entities.Product", "Product")
|
||||||
|
.WithMany("ProductPrices")
|
||||||
|
.HasForeignKey("ProductId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Product");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Quotes.Entities.Quote", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||||
|
.WithMany("Quotes")
|
||||||
|
.HasForeignKey("CustomerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Orders.Entities.Order", "Order")
|
||||||
|
.WithOne("Quote")
|
||||||
|
.HasForeignKey("LiteCharms.Features.Shop.Quotes.Entities.Quote", "OrderId");
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||||
|
.WithOne("Quote")
|
||||||
|
.HasForeignKey("LiteCharms.Features.Shop.Quotes.Entities.Quote", "ShoppingCartId");
|
||||||
|
|
||||||
|
b.Navigation("Customer");
|
||||||
|
|
||||||
|
b.Navigation("Order");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCart");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||||
|
.WithMany("ShoppingCarts")
|
||||||
|
.HasForeignKey("CustomerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Orders.Entities.Order", "Order")
|
||||||
|
.WithOne("ShoppingCart")
|
||||||
|
.HasForeignKey("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "OrderId")
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
|
b.Navigation("Customer");
|
||||||
|
|
||||||
|
b.Navigation("Order");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Products.Entities.ProductPrice", "ProductPrice")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ProductPriceId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||||
|
.WithMany("ShoppingCartItems")
|
||||||
|
.HasForeignKey("ShoppingCartId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("ProductPrice");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCart");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartPackage", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.CartPackages.Entities.Package", "Package")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("PackageId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||||
|
.WithMany("ShoppingCartPackages")
|
||||||
|
.HasForeignKey("ShoppingCartId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Package");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCart");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.Package", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("PackageItems");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Customers.Entities.Customer", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Leads");
|
||||||
|
|
||||||
|
b.Navigation("Orders");
|
||||||
|
|
||||||
|
b.Navigation("Quotes");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCarts");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.Order", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Quote");
|
||||||
|
|
||||||
|
b.Navigation("Refunds");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCart");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.Product", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("ProductPrices");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Quote");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCartItems");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCartPackages");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+71
@@ -0,0 +1,71 @@
|
|||||||
|
using System;
|
||||||
|
using LiteCharms.Features.TechShop.Products.Models;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Postgres.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddedProductMetadata : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<bool>(
|
||||||
|
name: "Active",
|
||||||
|
table: "Products",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: false,
|
||||||
|
oldClrType: typeof(bool),
|
||||||
|
oldType: "boolean",
|
||||||
|
oldDefaultValue: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "CreatedAt",
|
||||||
|
table: "Products",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: false,
|
||||||
|
defaultValueSql: "now()");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<ProductMetadata>(
|
||||||
|
name: "Metadata",
|
||||||
|
table: "Products",
|
||||||
|
type: "jsonb",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<DateTime>(
|
||||||
|
name: "UpdatedAt",
|
||||||
|
table: "Products",
|
||||||
|
type: "timestamp with time zone",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "CreatedAt",
|
||||||
|
table: "Products");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Metadata",
|
||||||
|
table: "Products");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UpdatedAt",
|
||||||
|
table: "Products");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<bool>(
|
||||||
|
name: "Active",
|
||||||
|
table: "Products",
|
||||||
|
type: "boolean",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: true,
|
||||||
|
oldClrType: typeof(bool),
|
||||||
|
oldType: "boolean",
|
||||||
|
oldDefaultValue: false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,785 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using LiteCharms.Features.TechShop.Postgres;
|
||||||
|
using LiteCharms.Features.TechShop.Products.Models;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Postgres.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(ShopDbContext))]
|
||||||
|
partial class ShopDbContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.Package", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Summary")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(512)
|
||||||
|
.HasColumnType("character varying(512)");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Package", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.PackageItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("PackageId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid>("ProductPriceId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PackageId");
|
||||||
|
|
||||||
|
b.HasIndex("ProductPriceId");
|
||||||
|
|
||||||
|
b.ToTable("PackageItem", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Customers.Entities.Customer", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(true);
|
||||||
|
|
||||||
|
b.Property<string>("Address")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("City")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Company")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Country")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<string>("Discord")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("LinkedIn")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Phone")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("PostalCode")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Region")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Slack")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Tax")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Website")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Whatsapp")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Customers", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Leads.Entities.Lead", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<long?>("AdGroupId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<long?>("AdName")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("AppClickId")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("AttributionHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<long?>("CampaignId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("ClickId")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("ClickLocation")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CustomerId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<long?>("FeedItemId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("Source")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<long?>("TargetId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("WebClickId")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
|
b.ToTable("Leads", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Notifications.Entities.Notification", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("CorrelationId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("CorrelationIdType")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<int>("Direction")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Errors")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.Property<bool>("HasError")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
|
b.Property<bool>("IsHtml")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
|
b.Property<bool>("IsInternal")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(true);
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("Platform")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<int>("Priority")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<bool>("Processed")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
|
b.Property<string>("RecipientAddress")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("RecipientName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("SenderAddress")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("SenderName")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Subject")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Notification", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.Order", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("CustomerId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("InvoiceUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Notes")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Requirements")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Terms")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
|
b.ToTable("Orders", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.OrderRefund", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<decimal>("Amount")
|
||||||
|
.HasPrecision(18, 2)
|
||||||
|
.HasColumnType("numeric(18,2)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("OrderId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("OrderId");
|
||||||
|
|
||||||
|
b.ToTable("OrderRefunds", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.Product", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(false);
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<string>("ImageUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<ProductMetadata>("Metadata")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Summary")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(512)
|
||||||
|
.HasColumnType("character varying(512)");
|
||||||
|
|
||||||
|
b.PrimitiveCollection<string>("Thumbnails")
|
||||||
|
.HasColumnType("jsonb");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Products", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.ProductPrice", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<bool>("Active")
|
||||||
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<decimal>("Discount")
|
||||||
|
.HasPrecision(18, 2)
|
||||||
|
.HasColumnType("numeric(18,2)");
|
||||||
|
|
||||||
|
b.Property<decimal>("Price")
|
||||||
|
.HasPrecision(18, 2)
|
||||||
|
.HasColumnType("numeric(18,2)");
|
||||||
|
|
||||||
|
b.Property<Guid>("ProductId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ProductId");
|
||||||
|
|
||||||
|
b.ToTable("ProductPrices", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Quotes.Entities.Quote", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("CustomerId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("ExpiredAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("InvoiceUrl")
|
||||||
|
.HasMaxLength(2048)
|
||||||
|
.HasColumnType("character varying(2048)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("OrderId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Reason")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<Guid?>("ShoppingCartId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
|
b.HasIndex("OrderId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.HasIndex("ShoppingCartId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Quotes", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("CustomerId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid?>("OrderId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CustomerId");
|
||||||
|
|
||||||
|
b.HasIndex("OrderId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ShoppingCarts", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("ProductPriceId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<int>("Quantity")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasDefaultValue(1);
|
||||||
|
|
||||||
|
b.Property<Guid>("ShoppingCartId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ProductPriceId");
|
||||||
|
|
||||||
|
b.HasIndex("ShoppingCartId");
|
||||||
|
|
||||||
|
b.ToTable("ShoppingCartItems", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartPackage", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("timestamp with time zone")
|
||||||
|
.HasDefaultValueSql("now()");
|
||||||
|
|
||||||
|
b.Property<Guid>("PackageId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<Guid>("ShoppingCartId")
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PackageId");
|
||||||
|
|
||||||
|
b.HasIndex("ShoppingCartId");
|
||||||
|
|
||||||
|
b.ToTable("ShoppingCartPackages", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.PackageItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.CartPackages.Entities.Package", "Package")
|
||||||
|
.WithMany("PackageItems")
|
||||||
|
.HasForeignKey("PackageId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Products.Entities.ProductPrice", "ProductPrice")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ProductPriceId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Package");
|
||||||
|
|
||||||
|
b.Navigation("ProductPrice");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Leads.Entities.Lead", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||||
|
.WithMany("Leads")
|
||||||
|
.HasForeignKey("CustomerId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
|
||||||
|
b.Navigation("Customer");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.Order", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||||
|
.WithMany("Orders")
|
||||||
|
.HasForeignKey("CustomerId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Customer");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.OrderRefund", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Orders.Entities.Order", "Order")
|
||||||
|
.WithMany("Refunds")
|
||||||
|
.HasForeignKey("OrderId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Order");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.ProductPrice", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Products.Entities.Product", "Product")
|
||||||
|
.WithMany("ProductPrices")
|
||||||
|
.HasForeignKey("ProductId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Product");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Quotes.Entities.Quote", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||||
|
.WithMany("Quotes")
|
||||||
|
.HasForeignKey("CustomerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Orders.Entities.Order", "Order")
|
||||||
|
.WithOne("Quote")
|
||||||
|
.HasForeignKey("LiteCharms.Features.Shop.Quotes.Entities.Quote", "OrderId");
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||||
|
.WithOne("Quote")
|
||||||
|
.HasForeignKey("LiteCharms.Features.Shop.Quotes.Entities.Quote", "ShoppingCartId");
|
||||||
|
|
||||||
|
b.Navigation("Customer");
|
||||||
|
|
||||||
|
b.Navigation("Order");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCart");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||||
|
.WithMany("ShoppingCarts")
|
||||||
|
.HasForeignKey("CustomerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Orders.Entities.Order", "Order")
|
||||||
|
.WithOne("ShoppingCart")
|
||||||
|
.HasForeignKey("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "OrderId")
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
|
b.Navigation("Customer");
|
||||||
|
|
||||||
|
b.Navigation("Order");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.Products.Entities.ProductPrice", "ProductPrice")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ProductPriceId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||||
|
.WithMany("ShoppingCartItems")
|
||||||
|
.HasForeignKey("ShoppingCartId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("ProductPrice");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCart");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartPackage", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.CartPackages.Entities.Package", "Package")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("PackageId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||||
|
.WithMany("ShoppingCartPackages")
|
||||||
|
.HasForeignKey("ShoppingCartId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Package");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCart");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.Package", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("PackageItems");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Customers.Entities.Customer", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Leads");
|
||||||
|
|
||||||
|
b.Navigation("Orders");
|
||||||
|
|
||||||
|
b.Navigation("Quotes");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCarts");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.Order", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Quote");
|
||||||
|
|
||||||
|
b.Navigation("Refunds");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCart");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.Product", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("ProductPrices");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Quote");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCartItems");
|
||||||
|
|
||||||
|
b.Navigation("ShoppingCartPackages");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-2
@@ -1,6 +1,13 @@
|
|||||||
using LiteCharms.Entities;
|
using LiteCharms.Features.TechShop.CartPackages.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.Customers.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.Leads.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.Notifications.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.Orders.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.Products.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.Quotes.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.ShoppingCarts.Entities;
|
||||||
|
|
||||||
namespace LiteCharms.Infrastructure.Database;
|
namespace LiteCharms.Features.TechShop.Postgres;
|
||||||
|
|
||||||
public class ShopDbContext(DbContextOptions<ShopDbContext> options) : DbContext(options)
|
public class ShopDbContext(DbContextOptions<ShopDbContext> options) : DbContext(options)
|
||||||
{
|
{
|
||||||
+4
-2
@@ -1,4 +1,6 @@
|
|||||||
namespace LiteCharms.Infrastructure.Database;
|
using static LiteCharms.Features.TechShop.Extensions.Postgres;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Postgres;
|
||||||
|
|
||||||
public class ShopDbContextFactory : IDesignTimeDbContextFactory<ShopDbContext>
|
public class ShopDbContextFactory : IDesignTimeDbContextFactory<ShopDbContext>
|
||||||
{
|
{
|
||||||
@@ -12,7 +14,7 @@ public class ShopDbContextFactory : IDesignTimeDbContextFactory<ShopDbContext>
|
|||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var optionsBuilder = new DbContextOptionsBuilder<ShopDbContext>();
|
var optionsBuilder = new DbContextOptionsBuilder<ShopDbContext>();
|
||||||
optionsBuilder.UseNpgsql(configuration.GetConnectionString("PostgresShop"));
|
optionsBuilder.UseNpgsql(configuration.GetConnectionString(ShopDbConfigName));
|
||||||
|
|
||||||
return new ShopDbContext(optionsBuilder.Options);
|
return new ShopDbContext(optionsBuilder.Options);
|
||||||
}
|
}
|
||||||
+2
-3
@@ -1,9 +1,8 @@
|
|||||||
using LiteCharms.Entities.Configuration;
|
namespace LiteCharms.Features.TechShop.Products.Entities;
|
||||||
|
|
||||||
namespace LiteCharms.Entities;
|
|
||||||
|
|
||||||
[EntityTypeConfiguration<ProductConfiguration, Product>]
|
[EntityTypeConfiguration<ProductConfiguration, Product>]
|
||||||
public class Product : Models.Product
|
public class Product : Models.Product
|
||||||
{
|
{
|
||||||
|
|
||||||
public virtual ICollection<ProductPrice>? ProductPrices { get; set; }
|
public virtual ICollection<ProductPrice>? ProductPrices { get; set; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.Products.Entities;
|
||||||
|
|
||||||
|
public class ProductConfiguration : IEntityTypeConfiguration<Product>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<Product> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("Products");
|
||||||
|
|
||||||
|
builder.HasKey(f => f.Id);
|
||||||
|
builder.Property(f => f.Name).IsRequired();
|
||||||
|
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
|
builder.Property(f => f.UpdatedAt).IsRequired(false);
|
||||||
|
builder.Property(f => f.Summary).IsRequired().HasMaxLength(512);
|
||||||
|
builder.Property(f => f.Description).IsRequired().HasMaxLength(2048);
|
||||||
|
builder.Property(f => f.ImageUrl).IsRequired(false).HasMaxLength(2048);
|
||||||
|
builder.Property(f => f.Thumbnails).HasColumnType("jsonb").IsRequired(false);
|
||||||
|
builder.Property(f => f.Active).HasDefaultValue(false);
|
||||||
|
builder.Property(f => f.Metadata).HasColumnType("jsonb").IsRequired(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-3
@@ -1,6 +1,4 @@
|
|||||||
using LiteCharms.Entities.Configuration;
|
namespace LiteCharms.Features.TechShop.Products.Entities;
|
||||||
|
|
||||||
namespace LiteCharms.Entities;
|
|
||||||
|
|
||||||
[EntityTypeConfiguration<ProductPriceConfiguration, ProductPrice>]
|
[EntityTypeConfiguration<ProductPriceConfiguration, ProductPrice>]
|
||||||
public class ProductPrice : Models.ProductPrice
|
public class ProductPrice : Models.ProductPrice
|
||||||
+7
-6
@@ -1,22 +1,23 @@
|
|||||||
namespace LiteCharms.Entities.Configuration;
|
namespace LiteCharms.Features.TechShop.Products.Entities;
|
||||||
|
|
||||||
public class ProductPriceConfiguration : IEntityTypeConfiguration<ProductPrice>
|
public class ProductPriceConfiguration : IEntityTypeConfiguration<ProductPrice>
|
||||||
{
|
{
|
||||||
public void Configure(EntityTypeBuilder<ProductPrice> builder)
|
public void Configure(EntityTypeBuilder<ProductPrice> builder)
|
||||||
{
|
{
|
||||||
builder.ToTable(nameof(ProductPrice));
|
builder.ToTable("ProductPrices");
|
||||||
|
|
||||||
builder.HasKey(f => f.Id);
|
builder.HasKey(f => f.Id);
|
||||||
builder.Property(f => f.CreatedAt).ValueGeneratedOnAdd();
|
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
builder.Property(f => f.UpdatedAt).IsRequired(false).ValueGeneratedOnUpdate();
|
builder.Property(f => f.UpdatedAt).IsRequired(false);
|
||||||
builder.Property(f => f.ProductId).IsRequired();
|
builder.Property(f => f.ProductId).IsRequired();
|
||||||
builder.Property(f => f.Price).IsRequired().HasPrecision(18, 2);
|
builder.Property(f => f.Price).IsRequired().HasPrecision(18, 2);
|
||||||
builder.Property(f => f.Discount).HasPrecision(18, 2);
|
builder.Property(f => f.Discount).HasPrecision(18, 2);
|
||||||
builder.Property(f => f.Active);
|
builder.Property(f => f.Active);
|
||||||
|
|
||||||
builder.HasOne(f => f.Product)
|
builder.HasOne(f => f.Product)
|
||||||
.WithMany(p => p.ProductPrices)
|
.WithMany(f => f.ProductPrices)
|
||||||
.HasForeignKey(f => f.ProductId)
|
.HasForeignKey(pp => pp.ProductId)
|
||||||
|
.IsRequired()
|
||||||
.OnDelete(DeleteBehavior.Restrict);
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Products.Models;
|
||||||
|
|
||||||
|
public class CreateProductModel
|
||||||
|
{
|
||||||
|
[MaxLength(128)]
|
||||||
|
[Required(ErrorMessage = "Product name is required.")]
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(512)]
|
||||||
|
[Required(ErrorMessage = "Summary is required.")]
|
||||||
|
public string? Summary { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(2048)]
|
||||||
|
[Required(ErrorMessage = "Description is required.")]
|
||||||
|
public string? Description { get; set; }
|
||||||
|
|
||||||
|
[Range(0.01, double.MaxValue, ErrorMessage = "Price must be greater than zero.")]
|
||||||
|
public decimal Price { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(128)]
|
||||||
|
[Required(ErrorMessage = "Author metadata is required.")]
|
||||||
|
public string? Author { get; set; }
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "Publication Date is required.")]
|
||||||
|
public DateTime PublishDate { get; set; } = DateTime.Today;
|
||||||
|
|
||||||
|
[MaxLength(255)]
|
||||||
|
[Required(ErrorMessage = "Copyright Information field is required.")]
|
||||||
|
public string? CopyrightInfo { get; set; }
|
||||||
|
|
||||||
|
[MaxLength(128)]
|
||||||
|
[Required(ErrorMessage = "ISBN code is required.")]
|
||||||
|
[RegularExpression(@"^(?=(?:\D*\d){10}(?:(?:\D*\d){3})?$)[\d-]+$", ErrorMessage = "Please enter a valid ISBN-10 or ISBN-13 string.")]
|
||||||
|
public string? Isbn { get; set; }
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "Primary image is required.")]
|
||||||
|
public string? ImageUrl { get; set; }
|
||||||
|
|
||||||
|
public List<string> Thumbnails { get; set; } = [];
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.Products.Models;
|
||||||
|
|
||||||
|
public class Product
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
public string? Summary { get; set; }
|
||||||
|
|
||||||
|
public string? Description { get; set; }
|
||||||
|
|
||||||
|
public string? ImageUrl { get; set; }
|
||||||
|
|
||||||
|
public string[]? Thumbnails { get; set; }
|
||||||
|
|
||||||
|
public bool Active { get; set; }
|
||||||
|
|
||||||
|
public ProductMetadata? Metadata { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.Products.Models;
|
||||||
|
|
||||||
|
public class ProductMetadata
|
||||||
|
{
|
||||||
|
public string? Manufacturer { get; set; }
|
||||||
|
|
||||||
|
public string? ManufactureDate { get; set; }
|
||||||
|
|
||||||
|
public string? CopyrightInfo { get; set; }
|
||||||
|
|
||||||
|
public string? SerialNumber { get; set; }
|
||||||
|
}
|
||||||
+3
-3
@@ -1,12 +1,12 @@
|
|||||||
namespace LiteCharms.Models;
|
namespace LiteCharms.Features.TechShop.Products.Models;
|
||||||
|
|
||||||
public class ProductPrice
|
public class ProductPrice
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
public DateTimeOffset CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
public DateTimeOffset? UpdatedAt { get; set; }
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
public Guid ProductId { get; set; }
|
public Guid ProductId { get; set; }
|
||||||
|
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.Products.Models;
|
||||||
|
|
||||||
|
public record CreateProduct
|
||||||
|
{
|
||||||
|
public required string Name { get; set; }
|
||||||
|
|
||||||
|
public required string Summary { get; set; }
|
||||||
|
|
||||||
|
public required string Description { get; set; }
|
||||||
|
|
||||||
|
public required string ImageUrl { get; set; }
|
||||||
|
|
||||||
|
public string[]? Thumbnails { get; set; }
|
||||||
|
|
||||||
|
public ProductMetadata? Metadata { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,277 @@
|
|||||||
|
using LiteCharms.Features.TechShop.Extensions;
|
||||||
|
using LiteCharms.Features.TechShop.Postgres;
|
||||||
|
using LiteCharms.Features.TechShop.Products.Models;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Products;
|
||||||
|
|
||||||
|
public class ProductService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||||
|
{
|
||||||
|
public async ValueTask<Result> ChangeProductPriceStatusAsync(Guid productPriceId, bool active, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var price = await context.ProductPrices.FirstOrDefaultAsync(p => p.Id == productPriceId, cancellationToken);
|
||||||
|
|
||||||
|
if (price is null)
|
||||||
|
return Result.Fail($"Could not find product price with ID {productPriceId}");
|
||||||
|
|
||||||
|
price.Active = active;
|
||||||
|
price.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail($"Failed to change product price by ID {productPriceId}");
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> ChangeProductStatusAsync(Guid productId, bool active, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var product = await context.Products.FirstOrDefaultAsync(p => p.Id == productId, cancellationToken);
|
||||||
|
|
||||||
|
if (product is null)
|
||||||
|
return Result.Fail($"Could not find product with ID {productId}");
|
||||||
|
|
||||||
|
product.Active = active;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail($"Failed to change product status by ID {productId}");
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Guid>> CreateProductAsync(CreateProduct request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Products.AnyAsync(p => p.Name == request.Name, cancellationToken))
|
||||||
|
return Result.Fail<Guid>($"A product by the same name '{request.Name}' already exists");
|
||||||
|
|
||||||
|
var newProduct = context.Products.Add(new Entities.Product
|
||||||
|
{
|
||||||
|
Name = request.Name,
|
||||||
|
Summary = request.Summary,
|
||||||
|
Description = request.Description,
|
||||||
|
ImageUrl = request.ImageUrl,
|
||||||
|
Thumbnails = request.Thumbnails,
|
||||||
|
Metadata = request.Metadata
|
||||||
|
});
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok(newProduct.Entity.Id)
|
||||||
|
: Result.Fail($"Failed to create new product '{request.Name}'");
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Guid>> CreateProductPriceAsync(Guid productId, decimal price, decimal discount = 0, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var newProductPrice = context.ProductPrices.Add(new Entities.ProductPrice
|
||||||
|
{
|
||||||
|
Price = price,
|
||||||
|
Discount = discount,
|
||||||
|
ProductId = productId
|
||||||
|
});
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok(newProductPrice.Entity.Id)
|
||||||
|
: Result.Fail($"Failed to create new product price for product id {productId}");
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Product>> GetProductAsync(Guid productId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var product = await context.Products.FirstOrDefaultAsync(p => p.Id == productId, cancellationToken);
|
||||||
|
|
||||||
|
return product is not null
|
||||||
|
? Result.Ok(product.ToModel())
|
||||||
|
: Result.Fail<Product>(new Error($"Product with ID {productId} not found."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Product>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<ProductPrice>> GetProductPriceAsync(Guid productPriceId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Products.AnyAsync(p => p.Id == productPriceId, cancellationToken))
|
||||||
|
return Result.Fail<ProductPrice>(new Error($"Product {productPriceId} not found."));
|
||||||
|
|
||||||
|
var productPrice = await context.ProductPrices.AsNoTracking()
|
||||||
|
.OrderByDescending(pp => pp.CreatedAt)
|
||||||
|
.FirstOrDefaultAsync(pp => pp.Id == productPriceId, cancellationToken);
|
||||||
|
|
||||||
|
return productPrice is not null
|
||||||
|
? Result.Ok(productPrice.ToModel())
|
||||||
|
: Result.Fail<ProductPrice>(new Error($"Product price {productPriceId} not found."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<ProductPrice>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<ProductPrice[]>> GetProductPricesAsync(int maxRecords = 1000, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var products = await context.ProductPrices.AsNoTracking()
|
||||||
|
.OrderByDescending(o => o.Id)
|
||||||
|
.Take(maxRecords)
|
||||||
|
.ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return Result.Ok(products.Select(p => p.ToModel()).ToArray());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<ProductPrice[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Product[]>> GetProductsAsync(int maxRecords = 1000, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var products = await context.Products.AsNoTracking()
|
||||||
|
.OrderByDescending(o => o.Id)
|
||||||
|
.Take(maxRecords)
|
||||||
|
.ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return Result.Ok(products.Select(p => p.ToModel()).ToArray());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Product[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Guid>> ReplaceProductPriceAsync(Guid productPriceId, decimal price, decimal discount = 0, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var existingPrice = await context.ProductPrices.FirstOrDefaultAsync(p => p.Id == productPriceId, cancellationToken);
|
||||||
|
|
||||||
|
if (existingPrice is null)
|
||||||
|
return Result.Fail($"Could not find product price with ID {productPriceId}");
|
||||||
|
|
||||||
|
existingPrice.Active = false;
|
||||||
|
existingPrice.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
if (!(await context.SaveChangesAsync(cancellationToken) > 0))
|
||||||
|
return Result.Fail<Guid>($"Failed to deactivate existing price of ID {productPriceId}, try again later");
|
||||||
|
|
||||||
|
var result = await CreateProductPriceAsync(existingPrice.ProductId, price, discount, cancellationToken);
|
||||||
|
|
||||||
|
if (result.IsFailed)
|
||||||
|
{
|
||||||
|
var deactivatedPrice = await context.ProductPrices.FirstOrDefaultAsync(p => p.Id == productPriceId, cancellationToken);
|
||||||
|
|
||||||
|
existingPrice.Active = true;
|
||||||
|
existingPrice.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Fail<Guid>("Reverted to old price, creation of new price failed")
|
||||||
|
: Result.Fail<Guid>($"Failed to reactivate price of ID {productPriceId} after new price creation failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Ok(result.Value);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> SetProductPriceStatusAsync(Guid productPriceId, bool active, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var productPrice = await context.ProductPrices.FirstOrDefaultAsync(p => p.Id == productPriceId, cancellationToken);
|
||||||
|
|
||||||
|
if (productPrice is null)
|
||||||
|
return Result.Fail($"Could not find product price with ID {productPriceId}");
|
||||||
|
|
||||||
|
productPrice.Active = active;
|
||||||
|
productPrice.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail($"Failed to change product price status by ID {productPriceId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateProductMetadataAsync(Guid productId, ProductMetadata metadata, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var product = await context.Products.FirstOrDefaultAsync(p => p.Id == productId, cancellationToken);
|
||||||
|
|
||||||
|
if (product is null)
|
||||||
|
return Result.Fail($"Could not find product with ID {productId}");
|
||||||
|
|
||||||
|
product.Metadata = metadata;
|
||||||
|
product.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail($"Failed to update product metadata by ID {productId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-4
@@ -1,13 +1,15 @@
|
|||||||
using LiteCharms.Entities.Configuration;
|
using LiteCharms.Features.TechShop.Customers.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.Orders.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.ShoppingCarts.Entities;
|
||||||
|
|
||||||
namespace LiteCharms.Entities;
|
namespace LiteCharms.Features.TechShop.Quotes.Entities;
|
||||||
|
|
||||||
[EntityTypeConfiguration<QuoteConfiguration, Quote>]
|
[EntityTypeConfiguration<QuoteConfiguration, Quote>]
|
||||||
public class Quote : Models.Quote
|
public class Quote : Models.Quote
|
||||||
{
|
{
|
||||||
public virtual Customer? Customer { get; set; }
|
public virtual Customer? Customer { get; set; }
|
||||||
|
|
||||||
public virtual ShoppingCart? ShoppingCart { get; set; }
|
|
||||||
|
|
||||||
public virtual Order? Order { get; set; }
|
public virtual Order? Order { get; set; }
|
||||||
|
|
||||||
|
public virtual ShoppingCart? ShoppingCart { get; set; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.Quotes.Entities;
|
||||||
|
|
||||||
|
public class QuoteConfiguration : IEntityTypeConfiguration<Quote>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<Quote> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("Quotes");
|
||||||
|
|
||||||
|
builder.HasKey(f => f.Id);
|
||||||
|
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
|
builder.Property(f => f.UpdatedAt).IsRequired(false).HasDefaultValueSql(null);
|
||||||
|
builder.Property(f => f.ExpiredAt).IsRequired(false).HasDefaultValueSql(null);
|
||||||
|
builder.Property(f => f.CustomerId).IsRequired();
|
||||||
|
builder.Property(f => f.OrderId);
|
||||||
|
builder.Property(f => f.ShoppingCartId);
|
||||||
|
builder.Property(f => f.Status).IsRequired().HasConversion<int>();
|
||||||
|
builder.Property(f => f.InvoiceUrl).IsRequired(false).HasMaxLength(2048);
|
||||||
|
builder.Property(f => f.Reason).IsRequired(false);
|
||||||
|
|
||||||
|
builder.HasOne(q => q.Customer)
|
||||||
|
.WithMany(c => c.Quotes)
|
||||||
|
.HasForeignKey(q => q.CustomerId)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
builder.HasOne(q => q.Order)
|
||||||
|
.WithOne(o => o.Quote)
|
||||||
|
.HasForeignKey<Quote>(q => q.OrderId);
|
||||||
|
|
||||||
|
builder.HasOne(q => q.ShoppingCart)
|
||||||
|
.WithOne(o => o.Quote)
|
||||||
|
.HasForeignKey<Quote>(q => q.ShoppingCartId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.Quotes.Models;
|
||||||
|
|
||||||
|
public class Quote
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
|
public DateTime? ExpiredAt { get; set; }
|
||||||
|
|
||||||
|
public Guid CustomerId { get; set; }
|
||||||
|
|
||||||
|
public Guid? OrderId { get; set; }
|
||||||
|
|
||||||
|
public Guid? ShoppingCartId { get; set; }
|
||||||
|
|
||||||
|
public QuoteStatus Status { get; set; }
|
||||||
|
|
||||||
|
public string? InvoiceUrl { get; set; }
|
||||||
|
|
||||||
|
public string? Reason { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
using LiteCharms.Features.Extensions;
|
||||||
|
using LiteCharms.Features.Models;
|
||||||
|
using LiteCharms.Features.TechShop.Extensions;
|
||||||
|
using LiteCharms.Features.TechShop.Postgres;
|
||||||
|
using LiteCharms.Features.TechShop.Quotes.Models;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.Quotes;
|
||||||
|
|
||||||
|
public class QuoteService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||||
|
{
|
||||||
|
public async ValueTask<Result> AssignQuoteToOrderAsync(Guid quoteId, Guid orderId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var quote = await context.Quotes.FirstOrDefaultAsync(o => o.Id == quoteId, cancellationToken);
|
||||||
|
|
||||||
|
if (quote is null)
|
||||||
|
return Result.Fail(new Error($"Quote with id {orderId} not found"));
|
||||||
|
|
||||||
|
if (!await context.Orders.AnyAsync(q => q.Id == orderId, cancellationToken))
|
||||||
|
return Result.Fail(new Error($"Order with id {quoteId} not found"));
|
||||||
|
|
||||||
|
if (quote.OrderId == orderId)
|
||||||
|
return Result.Fail(new Error($"Quote with id {quoteId} is already assigned to order with id {orderId}"));
|
||||||
|
|
||||||
|
quote.OrderId = orderId;
|
||||||
|
quote.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail(new Error($"Failed to assign quote with id {quoteId} to order with id {orderId}"));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> AssignQuoteToShoppingCartAsync(Guid quoteId, Guid shoppingCartId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var quote = await context.Quotes.FirstOrDefaultAsync(o => o.Id == quoteId, cancellationToken);
|
||||||
|
|
||||||
|
if (quote is null)
|
||||||
|
return Result.Fail(new Error($"Quote with id {quoteId} not found"));
|
||||||
|
|
||||||
|
if (!await context.ShoppingCarts.AnyAsync(q => q.Id == shoppingCartId, cancellationToken))
|
||||||
|
return Result.Fail(new Error($"Shopping Cart with id {shoppingCartId} not found"));
|
||||||
|
|
||||||
|
quote.ShoppingCartId = shoppingCartId;
|
||||||
|
quote.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail(new Error("Failed to assign quote to shopping cart"));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Quote[]>> GetCustomerQuotesAsync(Guid customerId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Customers.AnyAsync(c => c.Id == customerId, cancellationToken))
|
||||||
|
return Result.Fail<Quote[]>(new Error($"Customer with Id {customerId} does not exist."));
|
||||||
|
|
||||||
|
var quotes = await context.Quotes.AsNoTracking()
|
||||||
|
.Where(q => q.CustomerId == customerId).ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return quotes?.Length > 0
|
||||||
|
? Result.Ok(quotes.Select(q => q.ToModel()).ToArray())
|
||||||
|
: Result.Fail<Quote[]>(new Error($"No quotes found for customer with Id {customerId}."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Quote[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Quote>> GetQuoteAsync(Guid quoteId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var quote = await context.Quotes.AsNoTracking().FirstOrDefaultAsync(q => q.Id == quoteId, cancellationToken);
|
||||||
|
|
||||||
|
return quote is not null
|
||||||
|
? Result.Ok(quote.ToModel())
|
||||||
|
: Result.Fail<Quote>(new Error($"Quote with ID {quoteId} not found."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Quote>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Quote[]>> GetQuotesAsync(DateRange range, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var fromDate = range.From.ToDateTime(TimeOnly.MinValue);
|
||||||
|
var toDate = range.To.ToDateTime(TimeOnly.MaxValue);
|
||||||
|
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var quotes = await context.Quotes.AsNoTracking()
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.Where(o => o.CreatedAt >= fromDate && o.CreatedAt <= toDate)
|
||||||
|
.Take(range.MaxRecords)
|
||||||
|
.ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return quotes?.Length > 0
|
||||||
|
? Result.Ok(quotes.Select(o => o.ToModel()).ToArray())
|
||||||
|
: Result.Fail<Quote[]>(new Error($"No quotes found for the specified date range {range.From} - {range.To}."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Quote[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateQuoteStatusAsync(Guid quoteId, QuoteStatus status, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var quote = await context.Quotes.FirstOrDefaultAsync(q => q.Id == quoteId, cancellationToken);
|
||||||
|
|
||||||
|
if (quote is null)
|
||||||
|
return Result.Fail(new Error("Quote not found."));
|
||||||
|
|
||||||
|
quote.Status = status;
|
||||||
|
quote.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail(new Error("Failed to update quote status."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-3
@@ -1,6 +1,8 @@
|
|||||||
using LiteCharms.Entities.Configuration;
|
using LiteCharms.Features.TechShop.Customers.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.Orders.Entities;
|
||||||
|
using LiteCharms.Features.TechShop.Quotes.Entities;
|
||||||
|
|
||||||
namespace LiteCharms.Entities;
|
namespace LiteCharms.Features.TechShop.ShoppingCarts.Entities;
|
||||||
|
|
||||||
[EntityTypeConfiguration<ShoppingCartConfiguration, ShoppingCart>]
|
[EntityTypeConfiguration<ShoppingCartConfiguration, ShoppingCart>]
|
||||||
public class ShoppingCart : Models.ShoppingCart
|
public class ShoppingCart : Models.ShoppingCart
|
||||||
@@ -13,5 +15,5 @@ public class ShoppingCart : Models.ShoppingCart
|
|||||||
|
|
||||||
public virtual ICollection<ShoppingCartItem>? ShoppingCartItems { get; set; }
|
public virtual ICollection<ShoppingCartItem>? ShoppingCartItems { get; set; }
|
||||||
|
|
||||||
public virtual ICollection<Package>? Packages { get; set; }
|
public virtual ICollection<ShoppingCartPackage>? ShoppingCartPackages { get; set; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.ShoppingCarts.Entities;
|
||||||
|
|
||||||
|
public class ShoppingCartConfiguration : IEntityTypeConfiguration<ShoppingCart>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<ShoppingCart> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("ShoppingCarts");
|
||||||
|
|
||||||
|
builder.HasKey(f => f.Id);
|
||||||
|
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
|
builder.Property(f => f.UpdatedAt).IsRequired(false).HasDefaultValueSql(null);
|
||||||
|
builder.Property(f => f.CustomerId).IsRequired();
|
||||||
|
builder.Property(f => f.OrderId);
|
||||||
|
|
||||||
|
builder.HasOne(s => s.Customer)
|
||||||
|
.WithMany(c => c.ShoppingCarts)
|
||||||
|
.HasForeignKey(s => s.CustomerId)
|
||||||
|
.IsRequired()
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
builder.HasOne(s => s.Order)
|
||||||
|
.WithOne(o => o.ShoppingCart)
|
||||||
|
.HasForeignKey<ShoppingCart>(s => s.OrderId)
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using LiteCharms.Features.TechShop.Products.Entities;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.ShoppingCarts.Entities;
|
||||||
|
|
||||||
|
[EntityTypeConfiguration<ShoppingCartItemConfiguration, ShoppingCartItem>]
|
||||||
|
public class ShoppingCartItem : Models.ShoppingCartItem
|
||||||
|
{
|
||||||
|
public virtual ShoppingCart? ShoppingCart { get; set; }
|
||||||
|
|
||||||
|
public virtual ProductPrice? ProductPrice { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.ShoppingCarts.Entities;
|
||||||
|
|
||||||
|
public class ShoppingCartItemConfiguration : IEntityTypeConfiguration<ShoppingCartItem>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<ShoppingCartItem> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("ShoppingCartItems");
|
||||||
|
|
||||||
|
builder.HasKey(f => f.Id);
|
||||||
|
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
|
builder.Property(f => f.UpdatedAt).IsRequired(false).HasDefaultValueSql(null);
|
||||||
|
builder.Property(f => f.Quantity).IsRequired().HasDefaultValue(1);
|
||||||
|
builder.Property(f => f.ShoppingCartId).IsRequired();
|
||||||
|
builder.Property(f => f.ProductPriceId).IsRequired();
|
||||||
|
|
||||||
|
builder.HasOne(f => f.ShoppingCart)
|
||||||
|
.WithMany(s => s.ShoppingCartItems)
|
||||||
|
.HasForeignKey(f => f.ShoppingCartId)
|
||||||
|
.IsRequired()
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
builder.HasOne(f => f.ProductPrice)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(f => f.ProductPriceId)
|
||||||
|
.IsRequired()
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
using LiteCharms.Entities.Configuration;
|
using LiteCharms.Features.TechShop.CartPackages.Entities;
|
||||||
|
|
||||||
namespace LiteCharms.Entities;
|
namespace LiteCharms.Features.TechShop.ShoppingCarts.Entities;
|
||||||
|
|
||||||
[EntityTypeConfiguration<ShoppingCartPackageConfiguration, ShoppingCartPackage>]
|
[EntityTypeConfiguration<ShoppingCartPackageConfiguration, ShoppingCartPackage>]
|
||||||
public class ShoppingCartPackage : Models.ShoppingCartPackage
|
public class ShoppingCartPackage : Models.ShoppingCartPackage
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.ShoppingCarts.Entities;
|
||||||
|
|
||||||
|
public class ShoppingCartPackageConfiguration : IEntityTypeConfiguration<ShoppingCartPackage>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<ShoppingCartPackage> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("ShoppingCartPackages");
|
||||||
|
|
||||||
|
builder.HasKey(f => f.Id);
|
||||||
|
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
|
builder.Property(f => f.ShoppingCartId).IsRequired();
|
||||||
|
builder.Property(f => f.PackageId).IsRequired();
|
||||||
|
|
||||||
|
builder.HasOne(f => f.ShoppingCart)
|
||||||
|
.WithMany(s => s.ShoppingCartPackages)
|
||||||
|
.HasForeignKey(scp => scp.ShoppingCartId)
|
||||||
|
.IsRequired()
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
builder.HasOne(f => f.Package)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(scp => scp.PackageId)
|
||||||
|
.IsRequired()
|
||||||
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace LiteCharms.Features.TechShop.ShoppingCarts.Models;
|
||||||
|
|
||||||
|
public class ShoppingCart
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
|
public Guid CustomerId { get; set; }
|
||||||
|
|
||||||
|
public Guid? OrderId { get; set; }
|
||||||
|
}
|
||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
namespace LiteCharms.Models;
|
namespace LiteCharms.Features.TechShop.ShoppingCarts.Models;
|
||||||
|
|
||||||
public class ShoppingCartItem
|
public class ShoppingCartItem
|
||||||
{
|
{
|
||||||
@@ -8,9 +8,9 @@ public class ShoppingCartItem
|
|||||||
|
|
||||||
public Guid ProductPriceId { get; set; }
|
public Guid ProductPriceId { get; set; }
|
||||||
|
|
||||||
public DateTimeOffset CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
public DateTimeOffset UpdatedAt { get; set; }
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
public int Quantity { get; set; }
|
public int Quantity { get; set; }
|
||||||
}
|
}
|
||||||
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
namespace LiteCharms.Models;
|
namespace LiteCharms.Features.TechShop.ShoppingCarts.Models;
|
||||||
|
|
||||||
public class ShoppingCartPackage
|
public class ShoppingCartPackage
|
||||||
{
|
{
|
||||||
public Guid Id { get; set; }
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
public DateTimeOffset CreatedAt { get; set; }
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
public Guid ShoppingCartId { get; set; }
|
public Guid ShoppingCartId { get; set; }
|
||||||
|
|
||||||
@@ -0,0 +1,297 @@
|
|||||||
|
using LiteCharms.Features.TechShop.Extensions;
|
||||||
|
using LiteCharms.Features.TechShop.Postgres;
|
||||||
|
using LiteCharms.Features.TechShop.ShoppingCarts.Models;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.TechShop.ShoppingCarts;
|
||||||
|
|
||||||
|
public class ShoppingCartService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||||
|
{
|
||||||
|
public async ValueTask<Result> AddItemToShoppingCartAsync(Guid shoppingCartId, Guid productPriceId, int quantity, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.ProductPrices.AnyAsync(c => c.Id == productPriceId, cancellationToken))
|
||||||
|
return Result.Fail($"Product item could not be found with id {productPriceId}");
|
||||||
|
|
||||||
|
var cart = await context.ShoppingCarts.FirstOrDefaultAsync(c => c.Id == shoppingCartId, cancellationToken);
|
||||||
|
|
||||||
|
if (cart is null)
|
||||||
|
return Result.Fail($"Shopping cart could not be found with id {shoppingCartId}");
|
||||||
|
|
||||||
|
if (cart.ShoppingCartItems?.Any(i => i.ProductPriceId == productPriceId) == true)
|
||||||
|
return Result.Fail($"Item already in shopping cart with id {shoppingCartId}");
|
||||||
|
|
||||||
|
context.ShoppingCartItems.Add(new Entities.ShoppingCartItem
|
||||||
|
{
|
||||||
|
ShoppingCartId = shoppingCartId,
|
||||||
|
ProductPriceId = productPriceId,
|
||||||
|
Quantity = quantity
|
||||||
|
});
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail($"Failed to add cart item with id {productPriceId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> AddPackageToShoppingCartAsync(Guid shoppingCartId, Guid packageId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Packages.AnyAsync(p => p.Id == packageId, cancellationToken))
|
||||||
|
return Result.Fail($"Package cold not be found by ID {packageId}");
|
||||||
|
|
||||||
|
var shoppingCart = await context.ShoppingCarts.FirstOrDefaultAsync(c => c.Id == shoppingCartId, cancellationToken);
|
||||||
|
|
||||||
|
if (shoppingCart is null)
|
||||||
|
return Result.Fail($"Shopping cart could not be found by ID {shoppingCartId}");
|
||||||
|
|
||||||
|
if (!await context.ShoppingCartPackages.AnyAsync(cp => cp.ShoppingCartId == shoppingCartId, cancellationToken))
|
||||||
|
return Result.Fail($"Package {packageId} is already in the cart");
|
||||||
|
|
||||||
|
var newShoppingCartPackage = context.ShoppingCartPackages.Add(new Entities.ShoppingCartPackage
|
||||||
|
{
|
||||||
|
ShoppingCartId = shoppingCartId,
|
||||||
|
PackageId = packageId
|
||||||
|
});
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail($"Could not add package of id {packageId} to shopping cart {shoppingCartId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Guid>> CreateShoppingCartAsync(Guid customerId, Guid orderId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Customers.AnyAsync(c => c.Id == customerId, cancellationToken))
|
||||||
|
return Result.Fail<Guid>($"Customer could not be found with id {customerId}");
|
||||||
|
|
||||||
|
var cart = context.ShoppingCarts.Add(new Entities.ShoppingCart
|
||||||
|
{
|
||||||
|
CustomerId = customerId,
|
||||||
|
OrderId = orderId
|
||||||
|
});
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok(cart.Entity.Id)
|
||||||
|
: Result.Fail<Guid>($"Failed to create shopping cart for customer id {customerId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Guid>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> EmptyShoppingCartAsync(Guid shoppingCartId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.ShoppingCarts.AnyAsync(c => c.Id == shoppingCartId, cancellationToken))
|
||||||
|
return Result.Fail($"Shopping could not be found with id {shoppingCartId}");
|
||||||
|
|
||||||
|
if (await context.ShoppingCartItems.CountAsync(i => i.ShoppingCartId == shoppingCartId, cancellationToken) == 0)
|
||||||
|
return Result.Ok();
|
||||||
|
|
||||||
|
var cartItems = await context.ShoppingCartItems.Where(i => i.ShoppingCartId == shoppingCartId).ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
context.RemoveRange(cartItems);
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail($"Could not empty cart with id {shoppingCartId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<ShoppingCart[]>> GetCustomerShoppingCartsAsync(Guid customerId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Customers.AnyAsync(c => c.Id == customerId, cancellationToken))
|
||||||
|
return Result.Fail<ShoppingCart[]>(new Error($"Customer with Id {customerId} does not exist."));
|
||||||
|
|
||||||
|
var shoppingCarts = await context.ShoppingCarts.Where(sc => sc.CustomerId == customerId).ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return shoppingCarts?.Length > 0
|
||||||
|
? Result.Ok(shoppingCarts.Select(c => c.ToModel()).ToArray())
|
||||||
|
: Result.Fail<ShoppingCart[]>(new Error($"No shopping carts found for customer with Id {customerId}."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<ShoppingCart[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<ShoppingCart>> GetShoppingCartAsync(Guid shoppingCartId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var cart = await context.ShoppingCarts.AsNoTracking().FirstOrDefaultAsync(c => c.Id == shoppingCartId, cancellationToken);
|
||||||
|
|
||||||
|
return cart is not null
|
||||||
|
? Result.Ok(cart.ToModel())
|
||||||
|
: Result.Fail<ShoppingCart>($"Failed to find shopping cart with id {shoppingCartId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<ShoppingCart>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<ShoppingCartItem[]>> GetShoppingCartItemsAsync(Guid shoppingCartId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.ShoppingCarts.AnyAsync(i => i.Id == shoppingCartId, cancellationToken))
|
||||||
|
return Result.Fail($"Shopping cart could not be found with id {shoppingCartId}");
|
||||||
|
|
||||||
|
var items = await context.ShoppingCartItems.AsNoTracking()
|
||||||
|
.Where(i => i.ShoppingCartId == shoppingCartId).ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return items?.Length > 0
|
||||||
|
? Result.Ok(items.Select(i => i.ToModel()).ToArray())
|
||||||
|
: Result.Fail<ShoppingCartItem[]>($"Failed to retrieve shopping cart items with id {shoppingCartId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<ShoppingCartItem[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<ShoppingCartPackage[]>> GetShoppingCartPackagesAsync(Guid shoppingCartId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.ShoppingCarts.AnyAsync(c => c.Id == shoppingCartId, cancellationToken))
|
||||||
|
return Result.Fail($"Shopping cart could not be found by ID {shoppingCartId}");
|
||||||
|
|
||||||
|
var packages = await context.ShoppingCartPackages.AsNoTracking()
|
||||||
|
.OrderByDescending(o => o.CreatedAt)
|
||||||
|
.Where(cp => cp.ShoppingCartId == shoppingCartId)
|
||||||
|
.ToArrayAsync(cancellationToken);
|
||||||
|
|
||||||
|
return packages?.Length > 0
|
||||||
|
? Result.Ok(packages.Select(p => p.ToModel()).ToArray())
|
||||||
|
: Result.Fail($"Could not find packaged in shopping cart by ID {shoppingCartId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<ShoppingCartPackage[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> RemovePackageFromShoppingCartAsync(Guid shoppingCartId, Guid shoppingCartPackageId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.ShoppingCarts.AnyAsync(c => c.Id == shoppingCartId, cancellationToken))
|
||||||
|
return Result.Fail($"Shopping cart could not be found by ID {shoppingCartId}");
|
||||||
|
|
||||||
|
if (!await context.ShoppingCartPackages.AnyAsync(p => p.Id == shoppingCartPackageId, cancellationToken))
|
||||||
|
return Result.Fail($"Shopping cart package {shoppingCartPackageId} is not in the shopping cart {shoppingCartId}");
|
||||||
|
|
||||||
|
var shoppingCartPackage = await context.ShoppingCartPackages.FirstOrDefaultAsync(cp => cp.Id == shoppingCartPackageId, cancellationToken);
|
||||||
|
|
||||||
|
if (shoppingCartPackage is null)
|
||||||
|
return Result.Ok();
|
||||||
|
|
||||||
|
context.ShoppingCartPackages.Remove(shoppingCartPackage!);
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail($"Could remove package of id {shoppingCartPackageId} from shopping cart {shoppingCartId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> RemoveShoppingCartItemAsync(Guid shoppingCartId, Guid shoppingCartItemId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.ProductPrices.AnyAsync(c => c.Id == shoppingCartItemId, cancellationToken))
|
||||||
|
return Result.Fail($"Product item could not be found with id {shoppingCartItemId}");
|
||||||
|
|
||||||
|
var cart = await context.ShoppingCarts.FirstOrDefaultAsync(c => c.Id == shoppingCartId, cancellationToken);
|
||||||
|
|
||||||
|
if (cart is null)
|
||||||
|
return Result.Fail($"Shopping cart item could not be found with id {shoppingCartId}");
|
||||||
|
|
||||||
|
var item = await context.ShoppingCartItems.FirstOrDefaultAsync(i => i.Id == shoppingCartItemId, cancellationToken);
|
||||||
|
|
||||||
|
if (item is null) return Result.Ok();
|
||||||
|
|
||||||
|
context.ShoppingCartItems.Remove(item);
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail($"Failed to remove shopping cart item with id {shoppingCartItemId}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateShoppingCartItemAsync(Guid shoppingCartId, Guid shoppingCartItemId, int quantity, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.ShoppingCarts.AnyAsync(c => c.Id == shoppingCartId, cancellationToken))
|
||||||
|
return Result.Fail($"Shopping could not be found with id {shoppingCartId}");
|
||||||
|
|
||||||
|
var item = await context.ShoppingCartItems.FirstOrDefaultAsync(i => i.ShoppingCartId == shoppingCartId, cancellationToken);
|
||||||
|
|
||||||
|
if (item is null)
|
||||||
|
return Result.Fail($"Shopping cart item could not be found with id {shoppingCartItemId}");
|
||||||
|
|
||||||
|
item.Quantity = quantity;
|
||||||
|
item.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail($"Failed to update cart item quntity");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"Email": {
|
||||||
|
"Credentials": {
|
||||||
|
"Username": "shop@litecharms.co.za"
|
||||||
|
},
|
||||||
|
"Port": 465,
|
||||||
|
"Host": "mail.litecharms.co.za",
|
||||||
|
"UseSsl": true
|
||||||
|
},
|
||||||
|
"Monitoring": {
|
||||||
|
"ApiKey": "",
|
||||||
|
"Address": "http://aspire-dashboard-service.aspire.svc.cluster.local:18889",
|
||||||
|
"ServiceName": "LiteCharms.LeadGenerator"
|
||||||
|
},
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using LiteCharms.Features.Extensions;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.Tests;
|
||||||
|
|
||||||
|
public class Fixture : IDisposable
|
||||||
|
{
|
||||||
|
public IConfiguration Configuration { get; set; }
|
||||||
|
|
||||||
|
public IServiceProvider Services { get; set; }
|
||||||
|
|
||||||
|
public IMediator Mediator { get; set; }
|
||||||
|
|
||||||
|
public Fixture()
|
||||||
|
{
|
||||||
|
Configuration = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(Directory.GetCurrentDirectory())
|
||||||
|
.AddUserSecrets<Fixture>()
|
||||||
|
.AddJsonFile(Path.Combine(Directory.GetCurrentDirectory(), "appsettings.json"), optional: true, reloadOnChange: true)
|
||||||
|
.AddEnvironmentVariables()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
Services = new ServiceCollection()
|
||||||
|
.AddMediator()
|
||||||
|
.AddLogging()
|
||||||
|
.AddEmailServiceBus()
|
||||||
|
.AddGarageS3(Configuration)
|
||||||
|
.AddEmailServices(Configuration)
|
||||||
|
.AddSingleton(Configuration)
|
||||||
|
.BuildServiceProvider();
|
||||||
|
|
||||||
|
Mediator = Services.GetRequiredService<IMediator>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose() { }
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<UserSecretsId>62fa604a-1340-4edb-9ddd-3305fcf46fca</UserSecretsId>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="10.0.1">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Mediator.SourceGenerator" Version="3.0.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.5.1" />
|
||||||
|
<PackageReference Include="xunit" Version="2.9.3" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<!-- Global Usings -->
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Mediator" />
|
||||||
|
<Using Include="Xunit.Abstractions" />
|
||||||
|
<Using Include="Microsoft.Extensions.DependencyInjection" />
|
||||||
|
<Using Include="Microsoft.Extensions.Configuration" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\LiteCharms.Features\LiteCharms.Features.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Using Include="Xunit" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="appsettings.json">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user