Compare commits

..

7 Commits

Author SHA1 Message Date
khwezi c3b079ab4b Merge commit 'cecd9f90e9812a2bd84b2bb8026dbc9cce79741f' 2026-05-10 14:51:22 +00:00
Khwezi Mngoma cecd9f90e9 Implemented service bus handling of emails and notification processing
continuous-integration/drone/pr Build is passing
2026-05-10 16:50:36 +02:00
Khwezi Mngoma 73ba41beaf Added outgoing email notification processing event 2026-05-10 16:07:53 +02:00
Khwezi Mngoma e8e9a85c57 Migrated database changes after refactoring the Notification model 2026-05-10 15:27:26 +02:00
Khwezi Mngoma 394429677e Added package management 2026-05-10 14:18:56 +02:00
khwezi 20d9387d0b Merge pull request 'Migrated database changes' (#15) from develop into master
Reviewed-on: #15
2026-05-10 11:17:54 +02:00
Khwezi Mngoma 32d1019eb5 Migrated database changes
continuous-integration/drone/pr Build is passing
2026-05-10 11:16:52 +02:00
87 changed files with 2106 additions and 3784 deletions
+2
View File
@@ -5,6 +5,8 @@ public static class Constants
public const int QueueBounds = 100000; public const int QueueBounds = 100000;
public const string ShopSchedulerName = "shop"; public const string ShopSchedulerName = "shop";
public const string ShopEmailFromName = "Khongisa Shop";
public const string ShopEmailFromAddress = "shop@litecharms.co.za";
public const string EmailServiceBus = nameof(EmailServiceBus); public const string EmailServiceBus = nameof(EmailServiceBus);
public const string GeneralServiceBus = nameof(GeneralServiceBus); public const string GeneralServiceBus = nameof(GeneralServiceBus);
+12
View File
@@ -0,0 +1,12 @@
using static LiteCharms.Abstractions.Timezones;
namespace LiteCharms.Abstractions;
public abstract class EventBase
{
public Guid Id { get; set; } = Guid.CreateVersion7();
public DateTimeOffset EnqueueAt { get; set; } = SouthAfricanTimeZone.UtcNow();
public string CorrelationId { get; set; } = Guid.CreateVersion7().ToString();
}
@@ -1,4 +1,6 @@
namespace LiteCharms.Entities.Configuration; using LiteCharms.Models;
namespace LiteCharms.Entities.Configuration;
public class NotificationConfiguration : IEntityTypeConfiguration<Notification> public class NotificationConfiguration : IEntityTypeConfiguration<Notification>
{ {
@@ -8,15 +10,21 @@ public class NotificationConfiguration : IEntityTypeConfiguration<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();
builder.Property(f => f.Direction).IsRequired(); builder.Property(f => f.UpdatedAt).IsRequired(false).ValueGeneratedOnUpdate();
builder.Property(f => f.Author).IsRequired(); builder.Property(f => f.Direction).IsRequired().HasConversion<int>();
builder.Property(f => f.Title).IsRequired(); builder.Property(f => f.Platform).IsRequired().HasConversion<int>();
builder.Property(f => f.Description).IsRequired(); builder.Property(f => f.Priority).IsRequired().HasConversion<int>();
builder.Property(f => f.Platform).IsRequired(); builder.Property(f => f.CorrelationIdType).IsRequired().HasConversion<int>();
builder.Property(f => f.PlatformAddress).IsRequired(); builder.Property(f => f.Sender).IsRequired();
builder.Property(f => f.Subject).IsRequired();
builder.Property(f => f.Message).IsRequired();
builder.Property(f => f.Recipient).IsRequired();
builder.Property(f => f.RecipientAddress).IsRequired();
builder.Property(f => f.CorrelationId).IsRequired(); builder.Property(f => f.CorrelationId).IsRequired();
builder.Property(f => f.CorrelationIdType).IsRequired(); builder.Property(f => f.IsHtml).HasDefaultValue(false);
builder.Property(f => f.IsInternal).HasDefaultValue(true); builder.Property(f => f.IsInternal).HasDefaultValue(true);
builder.Property(f => f.Processed).HasDefaultValue(false); builder.Property(f => f.Processed).HasDefaultValue(false);
builder.Property(f => f.HasError).HasDefaultValue(false);
builder.Property(f => f.Errors).HasColumnType("jsonb").IsRequired(false);
} }
} }
@@ -14,7 +14,10 @@ public class OrderConfiguration : IEntityTypeConfiguration<Order>
builder.Property(f => f.RefundId).IsRequired(false); builder.Property(f => f.RefundId).IsRequired(false);
builder.Property(f => f.ShoppingCartId).IsRequired(); builder.Property(f => f.ShoppingCartId).IsRequired();
builder.Property(f => f.Status).HasConversion<int>().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.Notes).HasColumnType("jsonb").IsRequired(false);
builder.Property(f => f.Terms).HasColumnType("jsonb").IsRequired(false);
builder.Property(f => f.DepositRequired);
builder.HasOne(f => f.Quote) builder.HasOne(f => f.Quote)
.WithOne(f => f.Order) .WithOne(f => f.Order)
@@ -0,0 +1,16 @@
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);
}
}
@@ -0,0 +1,20 @@
namespace LiteCharms.Entities.Configuration;
public class PackageItemConfiguration : IEntityTypeConfiguration<PackageItem>
{
public void Configure(EntityTypeBuilder<PackageItem> builder)
{
builder.ToTable(nameof(PackageItem));
builder.HasKey(f => f.Id);
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd();
builder.Property(f => f.PackageId).IsRequired();
builder.Property(f => f.ProductPriceId).IsRequired();
builder.Property(f => f.Active);
builder.HasOne(f => f.Package)
.WithMany()
.HasForeignKey(f => f.PackageId)
.OnDelete(DeleteBehavior.NoAction);
}
}
@@ -8,10 +8,10 @@ public class QuoteConfiguration : IEntityTypeConfiguration<Quote>
builder.HasKey(f => f.Id); builder.HasKey(f => f.Id);
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd(); builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd();
builder.Property(f => f.UpdatedAt).IsRequired().ValueGeneratedOnAddOrUpdate(); builder.Property(f => f.UpdatedAt).IsRequired(false).ValueGeneratedOnUpdate();
builder.Property(f => f.ExpiredAt).IsRequired(false); builder.Property(f => f.ExpiredAt).IsRequired(false);
builder.Property(f => f.CustomerId).IsRequired(); builder.Property(f => f.CustomerId).IsRequired();
builder.Property(f => f.Status).IsRequired(); builder.Property(f => f.Status).IsRequired().HasConversion<int>();
builder.Property(f => f.ShoppingCartId).IsRequired(); builder.Property(f => f.ShoppingCartId).IsRequired();
builder.Property(f => f.Reason).IsRequired(false); builder.Property(f => f.Reason).IsRequired(false);
@@ -8,7 +8,7 @@ public class ShoppingCartConfiguration : IEntityTypeConfiguration<ShoppingCart>
builder.HasKey(f => f.Id); builder.HasKey(f => f.Id);
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd(); builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd();
builder.Property(f => f.UpdatedAt).IsRequired().ValueGeneratedOnAddOrUpdate(); builder.Property(f => f.UpdatedAt).IsRequired(false).ValueGeneratedOnUpdate();
builder.Property(f => f.CustomerId).IsRequired(false); builder.Property(f => f.CustomerId).IsRequired(false);
builder.Property(f => f.OrderId).IsRequired(false); builder.Property(f => f.OrderId).IsRequired(false);
builder.Property(f => f.QuoteId).IsRequired(false); builder.Property(f => f.QuoteId).IsRequired(false);
@@ -8,7 +8,7 @@ public class ShoppingCartItemConfiguration : IEntityTypeConfiguration<ShoppingCa
builder.HasKey(f => f.Id); builder.HasKey(f => f.Id);
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd(); builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd();
builder.Property(f => f.UpdatedAt).IsRequired().ValueGeneratedOnAddOrUpdate(); builder.Property(f => f.UpdatedAt).IsRequired(false).ValueGeneratedOnUpdate();
builder.Property(f => f.Quantity).IsRequired().HasDefaultValue(1); builder.Property(f => f.Quantity).IsRequired().HasDefaultValue(1);
builder.Property(f => f.ProductPriceId).IsRequired(); builder.Property(f => f.ProductPriceId).IsRequired();
@@ -0,0 +1,24 @@
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);
}
}
+9
View File
@@ -0,0 +1,9 @@
using LiteCharms.Entities.Configuration;
namespace LiteCharms.Entities;
[EntityTypeConfiguration<PackageConfirguration, Package>]
public class Package : Models.Package
{
public virtual ICollection<PackageItem>? PackageItems { get; set; }
}
+9
View File
@@ -0,0 +1,9 @@
using LiteCharms.Entities.Configuration;
namespace LiteCharms.Entities;
[EntityTypeConfiguration<PackageItemConfiguration, PackageItem>]
public class PackageItem : Models.PackageItem
{
public virtual Package? Package { get; set; }
}
+2
View File
@@ -12,4 +12,6 @@ public class ShoppingCart : Models.ShoppingCart
public virtual Quote? Quote { get; set; } public virtual Quote? Quote { get; set; }
public virtual ICollection<ShoppingCartItem>? ShoppingCartItems { get; set; } public virtual ICollection<ShoppingCartItem>? ShoppingCartItems { get; set; }
public virtual ICollection<Package>? Packages { get; set; }
} }
@@ -0,0 +1,11 @@
using LiteCharms.Entities.Configuration;
namespace LiteCharms.Entities;
[EntityTypeConfiguration<ShoppingCartPackageConfiguration, ShoppingCartPackage>]
public class ShoppingCartPackage : Models.ShoppingCartPackage
{
public virtual ShoppingCart? ShoppingCart { get; set; }
public virtual Package? Package { get; set; }
}
+48 -8
View File
@@ -4,6 +4,36 @@ namespace LiteCharms.Extensions;
public static class EntityModeMappers public static class EntityModeMappers
{ {
public static ShoppingCartPackage ToModel(this Entities.ShoppingCartPackage entity) =>
new()
{
Id = entity.Id,
CreatedAt = entity.CreatedAt,
PackageId = entity.PackageId,
ShoppingCartId = entity.ShoppingCartId
};
public static PackageItem ToModel(this Entities.PackageItem entity) =>
new()
{
Id = entity.Id,
Active = entity.Active,
CreatedAt = entity.CreatedAt,
PackageId = entity.PackageId,
ProductPriceId = entity.ProductPriceId
};
public static Package ToModel(this Entities.Package entity) =>
new()
{
Id = entity.Id,
CreatedAt = entity.CreatedAt,
Active = entity.Active,
Description = entity.Description,
Name = entity.Name,
UpdatedAt = entity.UpdatedAt
};
public static ShoppingCartItem ToModel(this Entities.ShoppingCartItem entity) => public static ShoppingCartItem ToModel(this Entities.ShoppingCartItem entity) =>
new() new()
{ {
@@ -36,7 +66,7 @@ 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
}; };
public static Notification ToModel(this Entities.Notification entity) => public static Notification ToModel(this Entities.Notification entity) =>
@@ -44,16 +74,23 @@ public static class EntityModeMappers
{ {
Id = entity.Id, Id = entity.Id,
CreatedAt = entity.CreatedAt, CreatedAt = entity.CreatedAt,
Description = entity.Description, Message = entity.Message,
Direction = entity.Direction, Direction = entity.Direction,
CorrelationId = entity.CorrelationId, CorrelationId = entity.CorrelationId,
CorrelationIdType = entity.CorrelationIdType, CorrelationIdType = entity.CorrelationIdType,
IsInternal = entity.IsInternal, IsInternal = entity.IsInternal,
Author = entity.Author, Sender = entity.Sender,
Platform = entity.Platform, Platform = entity.Platform,
PlatformAddress = entity.PlatformAddress, Recipient = entity.Recipient,
Title = entity.Title, Subject = entity.Subject,
Processed = entity.Processed Processed = entity.Processed,
SenderName = entity.SenderName,
RecipientAddress = entity.RecipientAddress,
Priority = entity.Priority,
UpdatedAt = entity?.UpdatedAt,
IsHtml = entity!.IsHtml,
HasError = entity.HasError,
Errors = entity.Errors
}; };
public static Customer ToModel(this Entities.Customer entity) => public static Customer ToModel(this Entities.Customer entity) =>
@@ -78,7 +115,7 @@ public static class EntityModeMappers
Slack = entity.Slack, Slack = entity.Slack,
Tax = entity.Tax, Tax = entity.Tax,
Website = entity.Website, Website = entity.Website,
Whatsapp = entity.Whatsapp Whatsapp = entity.Whatsapp
}; };
public static Lead ToModel(this Entities.Lead entity) => public static Lead ToModel(this Entities.Lead entity) =>
@@ -113,7 +150,10 @@ public static class EntityModeMappers
RefundId = entity.RefundId, RefundId = entity.RefundId,
QuoteId = entity.QuoteId, QuoteId = entity.QuoteId,
Status = entity.Status, Status = entity.Status,
ShoppingCartId = entity.ShoppingCartId ShoppingCartId = entity.ShoppingCartId,
DepositRequired = entity.DepositRequired,
Requirements = entity.Requirements,
Terms = entity.Terms
}; };
public static OrderRefund ToModel(this Entities.OrderRefund entity) => public static OrderRefund ToModel(this Entities.OrderRefund entity) =>
@@ -0,0 +1,25 @@
namespace LiteCharms.Features.CartPackages.Commands;
public class AddPackageItemCommand : IRequest<Result<Guid>>
{
public Guid PackageId { get; set; }
public Guid ProductPriceId { get; set; }
private AddPackageItemCommand(Guid packageId, Guid productPriceId)
{
PackageId = packageId;
ProductPriceId = productPriceId;
}
public static AddPackageItemCommand Create(Guid packageId, Guid productPriceId)
{
if (packageId == Guid.Empty)
throw new ArgumentException("Package id is required", nameof(packageId));
if (productPriceId == Guid.Empty)
throw new ArgumentException("Product price id is required", nameof(productPriceId));
return new(packageId, productPriceId);
}
}
@@ -0,0 +1,23 @@
namespace LiteCharms.Features.CartPackages.Commands;
public class CreatePackageCommand : IRequest<Result<Guid>>
{
public string? Name { get; set; }
public string? Description { get; set; }
private CreatePackageCommand(string? name, string? description)
{
Name = name;
Description = description;
}
public static CreatePackageCommand Create(string? name, string? description)
{
ArgumentException.ThrowIfNullOrWhiteSpace(name, nameof(name));
ArgumentException.ThrowIfNullOrWhiteSpace(description, nameof(description));
return new(name, description);
}
}
@@ -0,0 +1,25 @@
namespace LiteCharms.Features.CartPackages.Commands;
public class DeletePackageItemCommand : IRequest<Result>
{
public Guid PackageId { get; set; }
public Guid PackageItemId { get; set; }
private DeletePackageItemCommand(Guid packageId, Guid packageItemId)
{
PackageId = packageId;
PackageItemId = packageItemId;
}
public static DeletePackageItemCommand Create(Guid packageId, Guid packageItemId)
{
if (packageId == Guid.Empty)
throw new ArgumentException("Package id is required", nameof(packageId));
if (packageItemId == Guid.Empty)
throw new ArgumentException("Product price id is required", nameof(packageItemId));
return new(packageId, packageItemId);
}
}
@@ -0,0 +1,16 @@
namespace LiteCharms.Features.CartPackages.Commands;
public class DeletePackageItemsCommand : IRequest<Result>
{
public Guid PackageId { get; set; }
private DeletePackageItemsCommand(Guid packageId) => PackageId = packageId;
public static DeletePackageItemsCommand Create(Guid packageId)
{
if (packageId == Guid.Empty)
throw new ArgumentException("Package ID is required", nameof(packageId));
return new(packageId);
}
}
@@ -0,0 +1,38 @@
using LiteCharms.Infrastructure.Database;
namespace LiteCharms.Features.CartPackages.Commands.Handlers;
public class AddPackageItemCommandHandler(IDbContextFactory<ShopDbContext> contextFactory) : IRequestHandler<AddPackageItemCommand, Result<Guid>>
{
public async ValueTask<Result<Guid>> Handle(AddPackageItemCommand request, CancellationToken cancellationToken)
{
try
{
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
if (!await context.Packages.AnyAsync(p => p.Id == request.PackageId, cancellationToken))
return Result.Fail($"Could not find package by ID {request.PackageId}");
if (!await context.ProductPrices.AnyAsync(p => p.Id == request.ProductPriceId && p.Active == true, cancellationToken))
return Result.Fail($"Could not find an active product price by ID {request.ProductPriceId}");
if (await context.PackageItems.AnyAsync(p => p.ProductPriceId == request.ProductPriceId && p.PackageId == request.PackageId, cancellationToken))
return Result.Fail<Guid>($"Product price {request.ProductPriceId} is already added to this package {request.PackageId}");
var newPackageItem = context.PackageItems.Add(new Entities.PackageItem
{
PackageId = request.PackageId,
ProductPriceId = request.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 {request.ProductPriceId}");
}
catch (Exception ex)
{
return Result.Fail<Guid>(new Error(ex.Message).CausedBy(ex));
}
}
}
@@ -0,0 +1,32 @@
using LiteCharms.Infrastructure.Database;
namespace LiteCharms.Features.CartPackages.Commands.Handlers;
public class CreatePackageCommandHandler(IDbContextFactory<ShopDbContext> contextFactory) : IRequestHandler<CreatePackageCommand, Result<Guid>>
{
public async ValueTask<Result<Guid>> Handle(CreatePackageCommand request, CancellationToken cancellationToken)
{
try
{
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
if (await context.Packages.AnyAsync(p => p.Name == request.Name, cancellationToken))
return Result.Fail($"A package by the same name already exists: {request.Name}");
var newPackage = context.Packages.Add(new Entities.Package
{
Name = request.Name,
Description = request.Description,
Active = true
});
return await context.SaveChangesAsync(cancellationToken) > 0
? Result.Ok(newPackage.Entity.Id)
: Result.Fail($"Failed to create a new package by the name: {request.Name}");
}
catch (Exception ex)
{
return Result.Fail<Guid>(new Error(ex.Message).CausedBy(ex));
}
}
}
@@ -0,0 +1,32 @@
using LiteCharms.Infrastructure.Database;
namespace LiteCharms.Features.CartPackages.Commands.Handlers;
public class DeletePackageItemCommandHandler(IDbContextFactory<ShopDbContext> contextFactory) : IRequestHandler<DeletePackageItemCommand, Result>
{
public async ValueTask<Result> Handle(DeletePackageItemCommand request, CancellationToken cancellationToken)
{
try
{
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
if (!await context.Packages.AnyAsync(p => p.Id == request.PackageId, cancellationToken))
return Result.Fail($"Could not find package by ID {request.PackageId}");
var item = await context.PackageItems.FirstOrDefaultAsync(p => p.Id == request.PackageItemId && p.PackageId == request.PackageId, cancellationToken);
if(item is null)
return Result.Fail($"Product item {request.PackageItemId} is already added to this package {request.PackageId}");
context.PackageItems.Remove(item);
return await context.SaveChangesAsync(cancellationToken) > 0
? Result.Ok()
: Result.Fail($"Failed to delete package item by id {request.PackageItemId}");
}
catch (Exception ex)
{
return Result.Fail(new Error(ex.Message).CausedBy(ex));
}
}
}
@@ -0,0 +1,29 @@
using LiteCharms.Infrastructure.Database;
namespace LiteCharms.Features.CartPackages.Commands.Handlers;
public class DeletePackageItemsCommandHandler(IDbContextFactory<ShopDbContext> contextFactory) : IRequestHandler<DeletePackageItemsCommand, Result>
{
public async ValueTask<Result> Handle(DeletePackageItemsCommand request, CancellationToken cancellationToken)
{
try
{
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
if (!await context.Packages.AnyAsync(p => p.Id == request.PackageId, cancellationToken))
return Result.Fail($"Could not find package by ID {request.PackageId}");
var items = await context.PackageItems.Where(i => i.PackageId == request.PackageId).ToArrayAsync(cancellationToken);
context.PackageItems.RemoveRange(items);
return await context.SaveChangesAsync(cancellationToken) > 0
? Result.Ok()
: Result.Fail($"Failed to delete package {request.PackageId} items");
}
catch (Exception ex)
{
return Result.Fail(new Error(ex.Message).CausedBy(ex));
}
}
}
@@ -0,0 +1,33 @@
using LiteCharms.Infrastructure.Database;
namespace LiteCharms.Features.CartPackages.Commands.Handlers;
public class UpdatePackageCommandHandler(IDbContextFactory<ShopDbContext> contextFactory) : IRequestHandler<UpdatePackageCommand, Result>
{
public async ValueTask<Result> Handle(UpdatePackageCommand request, CancellationToken cancellationToken)
{
try
{
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
if (await context.Packages.AnyAsync(p => p.Name == request.Name, cancellationToken))
return Result.Fail($"A package by the same name already exists: {request.Name}");
var package = await context.Packages.FirstOrDefaultAsync(p => p.Id == request.PackageId, cancellationToken);
if (package is null)
return Result.Fail($"Could not find package by id {request.PackageId}");
package.Name = request.Name;
package.Description = request.Description;
return await context.SaveChangesAsync(cancellationToken) > 0
? Result.Ok()
: Result.Fail($"Failed to update package with id {request.PackageId}");
}
catch (Exception ex)
{
return Result.Fail(new Error(ex.Message).CausedBy(ex));
}
}
}
@@ -0,0 +1,29 @@
using LiteCharms.Infrastructure.Database;
namespace LiteCharms.Features.CartPackages.Commands.Handlers;
public class UpdatePackageStatusCommandHandler(IDbContextFactory<ShopDbContext> contextFactory) : IRequestHandler<UpdatePackageStatusCommand, Result>
{
public async ValueTask<Result> Handle(UpdatePackageStatusCommand request, CancellationToken cancellationToken)
{
try
{
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
var package = await context.Packages.FirstOrDefaultAsync(p => p.Id == request.PackageId, cancellationToken);
if (package is null)
return Result.Fail($"Could not find package by id {request.PackageId}");
package.Active = request.Active;
return await context.SaveChangesAsync(cancellationToken) > 0
? Result.Ok()
: Result.Fail($"Failed to update package with id {request.PackageId}");
}
catch (Exception ex)
{
return Result.Fail(new Error(ex.Message).CausedBy(ex));
}
}
}
@@ -0,0 +1,28 @@
namespace LiteCharms.Features.CartPackages.Commands;
public class UpdatePackageCommand : IRequest<Result>
{
public Guid PackageId { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
private UpdatePackageCommand(Guid packageId, string? name, string? description)
{
PackageId = packageId;
Name = name;
Description = description;
}
public static UpdatePackageCommand Create(Guid packageId, string? name, string? description)
{
if (packageId == Guid.Empty)
throw new ArgumentException($"Package ID is required", nameof(packageId));
ArgumentNullException.ThrowIfNullOrWhiteSpace(name, nameof(name));
ArgumentNullException.ThrowIfNullOrWhiteSpace(description, nameof(description));
return new(packageId, name, description);
}
}
@@ -0,0 +1,22 @@
namespace LiteCharms.Features.CartPackages.Commands;
public class UpdatePackageStatusCommand : IRequest<Result>
{
public Guid PackageId { get; set; }
public bool Active { get; set; }
private UpdatePackageStatusCommand(Guid packageId, bool active)
{
PackageId = packageId;
Active = active;
}
public static UpdatePackageStatusCommand Create(Guid packageId, bool active)
{
if(packageId == Guid.Empty)
throw new ArgumentException($"Package id is required", nameof(packageId));
return new(packageId, active);
}
}
@@ -0,0 +1,18 @@
using LiteCharms.Models;
namespace LiteCharms.Features.CartPackages.Queries;
public class GetPackageItemsQuery : IRequest<Result<PackageItem[]>>
{
public Guid PackageId { get; set; }
private GetPackageItemsQuery(Guid packageId) => PackageId = packageId;
public static GetPackageItemsQuery Create(Guid packageId)
{
if (packageId == Guid.Empty)
throw new ArgumentException("Package ID is required", nameof(packageId));
return new(packageId);
}
}
@@ -0,0 +1,18 @@
using LiteCharms.Models;
namespace LiteCharms.Features.CartPackages.Queries;
public class GetPackageQuery : IRequest<Result<Package>>
{
public Guid PackageId { get; set; }
private GetPackageQuery(Guid packageId) => PackageId = packageId;
public static GetPackageQuery Create(Guid packageId)
{
if(packageId == Guid.Empty)
throw new ArgumentException("Package ID is required", nameof(packageId));
return new(packageId);
}
}
@@ -0,0 +1,33 @@
using LiteCharms.Models;
namespace LiteCharms.Features.CartPackages.Queries;
public class GetPackagesQuery : IRequest<Result<Package[]>>
{
public DateOnly From { get; set; }
public DateOnly To { get; set; }
public int MaxRecords { get; set; }
public bool Active { get; set; }
private GetPackagesQuery(DateOnly from, DateOnly to, int maxRecords = 1000, bool active = true)
{
From = from;
To = to;
MaxRecords = maxRecords;
Active = active;
}
public static GetPackagesQuery Create(DateOnly from, DateOnly to, int maxRecords = 1000, bool active = true)
{
if (from > to)
throw new ArgumentException("From date cannot be greater than To date.");
if (maxRecords <= 0)
throw new ArgumentException("MaxRecords must be a positive integer.");
return new(from, to, maxRecords, active);
}
}
@@ -0,0 +1,32 @@
using LiteCharms.Extensions;
using LiteCharms.Infrastructure.Database;
using LiteCharms.Models;
namespace LiteCharms.Features.CartPackages.Queries.Handlers;
public class GetPackageItemsQueryHandler(IDbContextFactory<ShopDbContext> contextFactory) : IRequestHandler<GetPackageItemsQuery, Result<PackageItem[]>>
{
public async ValueTask<Result<PackageItem[]>> Handle(GetPackageItemsQuery request, CancellationToken cancellationToken)
{
try
{
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
if (!await context.Packages.AnyAsync(p => p.Id == request.PackageId, cancellationToken))
return Result.Fail<PackageItem[]>($"Package could not be found with ID {request.PackageId}");
var items = await context.PackageItems.AsNoTracking()
.OrderByDescending(o => o.CreatedAt)
.Where(p => p.PackageId == request.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 {request.PackageId}");
}
catch (Exception ex)
{
return Result.Fail<PackageItem[]>(new Error(ex.Message).CausedBy(ex));
}
}
}
@@ -0,0 +1,27 @@
using LiteCharms.Extensions;
using LiteCharms.Infrastructure.Database;
using LiteCharms.Models;
namespace LiteCharms.Features.CartPackages.Queries.Handlers;
public class GetPackageQueryHandler(IDbContextFactory<ShopDbContext> contextFactory) : IRequestHandler<GetPackageQuery, Result<Package>>
{
public async ValueTask<Result<Package>> Handle(GetPackageQuery request, CancellationToken cancellationToken)
{
try
{
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
var package = await context.Packages.FirstOrDefaultAsync(p => p.Id == request.PackageId, cancellationToken);
return package is not null
? Result.Ok(package.ToModel())
: Result.Fail($"Failed to find package by ID {request.PackageId}");
}
catch (Exception ex)
{
return Result.Fail<Package>(new Error(ex.Message).CausedBy(ex));
}
}
}
@@ -0,0 +1,35 @@
using LiteCharms.Extensions;
using LiteCharms.Infrastructure.Database;
using LiteCharms.Models;
namespace LiteCharms.Features.CartPackages.Queries.Handlers;
public class GetPackagesQueryHandler(IDbContextFactory<ShopDbContext> contextFactory) : IRequestHandler<GetPackagesQuery, Result<Package[]>>
{
public async ValueTask<Result<Package[]>> Handle(GetPackagesQuery request, CancellationToken cancellationToken)
{
try
{
var fromDate = request.From.ToDateTime(TimeOnly.MinValue);
var toDate = request.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 == request.Active)
.Take(request.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 {request.From} - {request.To}."));
}
catch (Exception ex)
{
return Result.Fail<Package[]>(new Error(ex.Message).CausedBy(ex));
}
}
}
@@ -1,6 +1,7 @@
using LiteCharms.Models.Configuraton.Email; using LiteCharms.Features.Email.Commands;
using LiteCharms.Models.Configuraton.Email;
namespace LiteCharms.Features.Utilities.Commands.Handlers; namespace LiteCharms.Features.Email.Commands.Handlers;
public class SendEmailCommandHandler(IOptions<SmtpSettings> smtpOptions) : IRequestHandler<SendEmailCommand, Result> public class SendEmailCommandHandler(IOptions<SmtpSettings> smtpOptions) : IRequestHandler<SendEmailCommand, Result>
{ {
@@ -1,4 +1,4 @@
namespace LiteCharms.Features.Utilities.Commands; namespace LiteCharms.Features.Email.Commands;
public class SendEmailCommand : IRequest<Result> public class SendEmailCommand : IRequest<Result>
{ {
@@ -0,0 +1,18 @@
using LiteCharms.Features.Notifications.Commands;
using static LiteCharms.Abstractions.Constants;
namespace LiteCharms.Features.Email.Events.Handlers;
public class SendShopEmailEnquiryEventHandler(ISender mediator) :
INotificationHandler<SendShopEmailEnquiryEvent>
{
public async ValueTask Handle(SendShopEmailEnquiryEvent notification, CancellationToken cancellationToken)
{
var command = CreateNotificationCommand.Create(Models.NotificationDirection.Outgoing, notification.SenderName!,
notification.SenderAddress!, notification.Subject!, notification.Message!, Models.NotificationPlatforms.Email,
notification.Priority, ShopEmailFromName, ShopEmailFromAddress, Guid.CreateVersion7().ToString(),
Models.CorrelationIdTypes.None, isInternal: true, isHtml: false);
await mediator.Send(command, cancellationToken);
}
}
@@ -0,0 +1,40 @@
using LiteCharms.Abstractions;
using LiteCharms.Models;
namespace LiteCharms.Features.Email.Events;
public class SendShopEmailEnquiryEvent : EventBase, IEvent
{
public string Name { get; set; } = nameof(SendShopEmailEnquiryEvent);
public string? SenderName { get; set; }
public string? SenderAddress { get; set; }
public string? Subject { get; set; }
public string? Message { get; set; }
public Priorities Priority { get; set; }
public SendShopEmailEnquiryEvent() { }
private SendShopEmailEnquiryEvent(string senderName, string senderAddress, string subject, string message, Priorities priority = Priorities.Medium)
{
SenderName = senderName;
SenderAddress = senderAddress;
Subject = subject;
Message = message;
Priority = priority;
}
public static SendShopEmailEnquiryEvent Create(string senderName, string senderAddress, string subject, string message, Priorities priority = Priorities.Medium)
{
ArgumentNullException.ThrowIfNullOrWhiteSpace(senderName, nameof(senderName));
ArgumentNullException.ThrowIfNullOrWhiteSpace(senderAddress, nameof(senderAddress));
ArgumentNullException.ThrowIfNullOrWhiteSpace(subject, nameof(subject));
ArgumentNullException.ThrowIfNullOrWhiteSpace(message, nameof(message));
return new(senderName, senderAddress, subject, message, priority);
}
}
@@ -1,4 +1,4 @@
using LiteCharms.Features.Utilities.Commands; using LiteCharms.Features.Utilities.Hash.Commands;
using LiteCharms.Infrastructure.Database; using LiteCharms.Infrastructure.Database;
namespace LiteCharms.Features.Leads.Commands.Handlers; namespace LiteCharms.Features.Leads.Commands.Handlers;
@@ -54,6 +54,7 @@
<Using Include="System.Security.Cryptography" /> <Using Include="System.Security.Cryptography" />
<Using Include="Microsoft.EntityFrameworkCore" /> <Using Include="Microsoft.EntityFrameworkCore" />
<Using Include="Microsoft.Extensions.Options" /> <Using Include="Microsoft.Extensions.Options" />
<Using Include="Microsoft.Extensions.Logging" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -6,58 +6,67 @@ public class CreateNotificationCommand : IRequest<Result<Guid>>
{ {
public NotificationDirection Direction { get; set; } public NotificationDirection Direction { get; set; }
public string? Author { get; set; } public string? Sender { get; set; }
public string? Title { get; set; } public string? SenderAddress { get; set; }
public string? Description { get; set; } public string? Subject { get; set; }
public string? Platform { get; set; } public string? Message { get; set; }
public string? PlatformAddress { get; set; } public NotificationPlatforms Platform { get; set; }
public Priorities Priority { get; set; }
public string? Recipient { get; set; }
public string? RecipientAddress { get; set; }
public string? CorrelationId { get; set; } public string? CorrelationId { get; set; }
public string? CorrelationIdType { get; set; } public CorrelationIdTypes CorrelationIdType { get; set; }
public bool IsInternal { get; set; } public bool IsInternal { get; set; }
private CreateNotificationCommand(NotificationDirection direction, string author, string title, string description, string platform, string platformAddress, string correlationId, string correlationIdType, bool isInternal) public bool IsHtml { get; set; }
private CreateNotificationCommand(NotificationDirection direction, string sender, string senderAddress, string subject, string message, NotificationPlatforms platform, Priorities priority, string recipient, string recipientAddress, string correlationId, CorrelationIdTypes correlationIdType, bool isInternal, bool isHtml = false)
{ {
Direction = direction; Direction = direction;
Author = author; Sender = sender;
Title = title; SenderAddress = senderAddress;
Description = description; Subject = subject;
Message = message;
Platform = platform; Platform = platform;
PlatformAddress = platformAddress; Priority = priority;
Recipient = recipient;
RecipientAddress = recipientAddress;
CorrelationId = correlationId; CorrelationId = correlationId;
CorrelationIdType = correlationIdType; CorrelationIdType = correlationIdType;
IsInternal = isInternal; IsInternal = isInternal;
IsHtml = isHtml;
} }
public static CreateNotificationCommand Create(NotificationDirection direction, string author, string title, string description, string platform, string platformAddress, string correlationId, string correlationIdType, bool isInternal) public static CreateNotificationCommand Create(NotificationDirection direction, string sender, string senderAddress, string subject, string message, NotificationPlatforms platform, Priorities priority, string recipient, string recipientAddress, string correlationId, CorrelationIdTypes correlationIdType, bool isInternal, bool isHtml = false)
{ {
if (string.IsNullOrWhiteSpace(author)) if (string.IsNullOrWhiteSpace(sender))
throw new ArgumentException("Author cannot be null or whitespace.", nameof(author)); throw new ArgumentException("Sender name is required.", nameof(sender));
if (string.IsNullOrWhiteSpace(title)) if (string.IsNullOrWhiteSpace(subject))
throw new ArgumentException("Title cannot be null or whitespace.", nameof(title)); throw new ArgumentException("Subject is required.", nameof(subject));
if (string.IsNullOrWhiteSpace(description)) if (string.IsNullOrWhiteSpace(message))
throw new ArgumentException("Description cannot be null or whitespace.", nameof(description)); throw new ArgumentException("Message is required.", nameof(message));
if (string.IsNullOrWhiteSpace(platform)) if (string.IsNullOrWhiteSpace(recipient))
throw new ArgumentException("Platform cannot be null or whitespace.", nameof(platform)); throw new ArgumentException("Recipient name is required.", nameof(recipient));
if (string.IsNullOrWhiteSpace(platformAddress)) if (string.IsNullOrWhiteSpace(recipientAddress))
throw new ArgumentException("PlatformAddress cannot be null or whitespace.", nameof(platformAddress)); throw new ArgumentException("Recipient address is required.", nameof(recipientAddress));
if (string.IsNullOrWhiteSpace(correlationId)) if (string.IsNullOrWhiteSpace(correlationId))
throw new ArgumentException("CorrelationId cannot be null or whitespace.", nameof(correlationId)); throw new ArgumentException("CorrelationId is required.", nameof(correlationId));
if (string.IsNullOrWhiteSpace(correlationIdType)) return new(direction, sender, senderAddress, subject, message, platform, priority, recipient, recipientAddress, correlationId, correlationIdType, isInternal, isHtml);
throw new ArgumentException("CorrelationIdType cannot be null or whitespace.", nameof(correlationIdType));
return new(direction, author, title, description, platform, platformAddress, correlationId, correlationIdType, isInternal);
} }
} }
@@ -6,29 +6,34 @@ public class CreateNotificationCommandHandler(IDbContextFactory<ShopDbContext> c
{ {
public async ValueTask<Result<Guid>> Handle(CreateNotificationCommand request, CancellationToken cancellationToken) public async ValueTask<Result<Guid>> Handle(CreateNotificationCommand request, CancellationToken cancellationToken)
{ {
try try
{ {
using var context = await contextFactory.CreateDbContextAsync(cancellationToken); using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
var newNotification = context.Notifications.Add(new Entities.Notification var newNotification = context.Notifications.Add(new Entities.Notification
{ {
Direction = request.Direction, Direction = request.Direction,
Author = request.Author, SenderName = request.Sender,
Title = request.Title, Sender = request.SenderAddress,
Description = request.Description, Recipient = request.Recipient,
RecipientAddress = request.RecipientAddress,
Subject = request.Subject,
Message = request.Message,
Platform = request.Platform, Platform = request.Platform,
PlatformAddress = request.PlatformAddress, Priority = request.Priority,
CorrelationId = request.CorrelationId, CorrelationId = request.CorrelationId,
CorrelationIdType = request.CorrelationIdType, CorrelationIdType = request.CorrelationIdType,
IsInternal = request.IsInternal, IsInternal = request.IsInternal,
IsHtml = request.IsHtml,
Processed = false
}); });
return newNotification is not null return newNotification is not null
? Result.Ok(newNotification.Entity.Id) ? Result.Ok(newNotification.Entity.Id)
: Result.Fail(new Error("Failed to create notification")); : Result.Fail(new Error("Failed to create notification"));
} }
catch (Exception ex) catch (Exception ex)
{ {
return Result.Fail(new Error(ex.Message).CausedBy(ex)); return Result.Fail(new Error(ex.Message).CausedBy(ex));
} }
} }
@@ -17,6 +17,12 @@ public class UpdateNotificationCommandHandler(IDbContextFactory<ShopDbContext> c
notification.Processed = request.Processed; notification.Processed = request.Processed;
if (request.HasError)
{
notification.HasError = request.HasError;
notification.Errors = request.Errors;
}
return await context.SaveChangesAsync(cancellationToken) > 0 return await context.SaveChangesAsync(cancellationToken) > 0
? Result.Ok() ? Result.Ok()
: Result.Fail(new Error($"Failed to update notification with id {request.NotificationId}.")); : Result.Fail(new Error($"Failed to update notification with id {request.NotificationId}."));
@@ -6,13 +6,19 @@ public class UpdateNotificationCommand : IRequest<Result>
public bool Processed { get; set; } public bool Processed { get; set; }
private UpdateNotificationCommand(Guid notificationId, bool processed) public bool HasError { get; set; }
public string[]? Errors { get; set; }
private UpdateNotificationCommand(Guid notificationId, bool processed, bool hasError = false, string[]? errors = null)
{ {
NotificationId = notificationId; NotificationId = notificationId;
Processed = processed; Processed = processed;
HasError = hasError;
Errors = errors;
} }
public static UpdateNotificationCommand Create(Guid notificationId, bool processed) public static UpdateNotificationCommand Create(Guid notificationId, bool processed, bool hasError = false, string[]? errors = null)
{ {
if(notificationId == Guid.Empty) if(notificationId == Guid.Empty)
throw new ArgumentException("Notification ID cannot be empty.", nameof(notificationId)); throw new ArgumentException("Notification ID cannot be empty.", nameof(notificationId));
@@ -0,0 +1,70 @@
using LiteCharms.Features.Email.Commands;
using LiteCharms.Infrastructure.Database;
using static LiteCharms.Abstractions.Constants;
namespace LiteCharms.Features.Notifications.Events.Handlers;
public class ProcessEmailNotificationsEventHandler(IDbContextFactory<ShopDbContext> contextFactory, ILogger<ProcessEmailNotificationsEvent> logger, ISender mediator) :
INotificationHandler<ProcessEmailNotificationsEvent>
{
public async ValueTask Handle(ProcessEmailNotificationsEvent message, CancellationToken cancellationToken)
{
try
{
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
var notifications = await context.Notifications
.OrderByDescending(o => o.Priority)
.ThenBy(o => o.CreatedAt)
.Where(n => n.CorrelationIdType == Models.CorrelationIdTypes.Email)
.Where(n => n.Direction == Models.NotificationDirection.Outgoing)
.Take(message.MaxRecords)
.ToListAsync(cancellationToken);
foreach (var notification in notifications)
{
var sendResult = await SendEmailAsync(notification, 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;
}
await context.SaveChangesAsync(cancellationToken);
}
catch (Exception ex)
{
logger.LogError(ex, ex.Message);
}
}
private async Task<Result> SendEmailAsync(Entities.Notification notification, CancellationToken cancellationToken = default)
{
try
{
var request = SendEmailCommand.Create(notification.Sender!, notification.SenderName!, ShopEmailFromAddress,
ShopEmailFromName, notification.Subject!, notification.Message!);
var result = await mediator.Send(request, cancellationToken);
return result.IsFailed
? Result.Fail(result.Errors)
: Result.Ok();
}
catch (Exception ex)
{
return Result.Fail(new Error(ex.Message).CausedBy(ex));
}
}
}
@@ -0,0 +1,14 @@
using LiteCharms.Abstractions;
namespace LiteCharms.Features.Notifications.Events;
public class ProcessEmailNotificationsEvent : EventBase, IEvent
{
public string Name { get; set; } = nameof(ProcessEmailNotificationsEvent);
public int MaxRecords { get; set; }
private ProcessEmailNotificationsEvent(int maxRecords = 1000) => MaxRecords = maxRecords;
public static ProcessEmailNotificationsEvent Create(int maxRecords = 1000) => new(maxRecords);
}
@@ -12,7 +12,7 @@ public class GetNotificationQueryHandler(IDbContextFactory<ShopDbContext> contex
{ {
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken); await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
var notification = await context.Notifications.FindAsync(new object[] { request.NotificationId }, cancellationToken); var notification = await context.Notifications.FirstOrDefaultAsync(n => n.Id == request.NotificationId, cancellationToken);
return notification is not null return notification is not null
? Result.Ok(notification.ToModel()) ? Result.Ok(notification.ToModel())
@@ -8,14 +8,26 @@ public class CreateOrderCommand : IRequest<Result<Guid>>
public Guid? QuoteId { get; set; } public Guid? QuoteId { get; set; }
private CreateOrderCommand(Guid customerId, Guid shoppingCartId, Guid? quoteId = null) public string[]? Requirements { get; set; }
public string[]? Notes { get; set; }
public string[]? Terms { get; set; }
public bool DepositRequired { get; set; }
private CreateOrderCommand(Guid customerId, Guid shoppingCartId, bool depositRequired, Guid? quoteId = null, string[]? requirements = null, string[]? notes = null, string[]? terms = null)
{ {
CustomerId = customerId; CustomerId = customerId;
ShoppingCartId = shoppingCartId; ShoppingCartId = shoppingCartId;
DepositRequired = depositRequired;
QuoteId = quoteId; QuoteId = quoteId;
Requirements = requirements;
Notes = notes;
Terms = terms;
} }
public static CreateOrderCommand Create(Guid customerId, Guid shoppingCartId, Guid? quoteId = null) public static CreateOrderCommand Create(Guid customerId, Guid shoppingCartId, bool depositRequired, Guid? quoteId = null, string[]? requirements = null, string[]? notes = null, string[]? terms = null)
{ {
if (customerId == Guid.Empty) if (customerId == Guid.Empty)
throw new ArgumentException("CustomerId is required.", nameof(customerId)); throw new ArgumentException("CustomerId is required.", nameof(customerId));
@@ -23,6 +35,6 @@ public class CreateOrderCommand : IRequest<Result<Guid>>
if (shoppingCartId == Guid.Empty) if (shoppingCartId == Guid.Empty)
throw new ArgumentException("ShoppingCartId is required.", nameof(shoppingCartId)); throw new ArgumentException("ShoppingCartId is required.", nameof(shoppingCartId));
return new(customerId, shoppingCartId, quoteId); return new(customerId, shoppingCartId, depositRequired, quoteId, requirements, notes, terms);
} }
} }
@@ -1,4 +1,5 @@
using LiteCharms.Infrastructure.Database; using LiteCharms.Infrastructure.Database;
using LiteCharms.Models;
namespace LiteCharms.Features.Orders.Commands.Handlers; namespace LiteCharms.Features.Orders.Commands.Handlers;
@@ -21,10 +22,15 @@ public class CreateOrderCommandHandler(IDbContextFactory<ShopDbContext> contextF
var newOrder = context.Orders.Add(new Entities.Order var newOrder = context.Orders.Add(new Entities.Order
{ {
CreatedAt = DateTime.UtcNow,
Status = OrderStatus.Pending,
CustomerId = request.CustomerId, CustomerId = request.CustomerId,
ShoppingCartId = request.ShoppingCartId,
QuoteId = request.QuoteId, QuoteId = request.QuoteId,
CreatedAt = DateTime.UtcNow ShoppingCartId = request.ShoppingCartId,
DepositRequired = request.DepositRequired,
Requirements = request.Requirements,
Notes = request.Notes,
Terms = request.Terms
}); });
return await context.SaveChangesAsync(cancellationToken) > 0 return await context.SaveChangesAsync(cancellationToken) > 0
@@ -16,6 +16,7 @@ public class GetOrdersQueryHandler(IDbContextFactory<ShopDbContext> contextFacto
using var context = await contextFactory.CreateDbContextAsync(cancellationToken); using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
var orders = await context.Orders var orders = await context.Orders
.AsNoTracking()
.OrderByDescending(o => o.CreatedAt) .OrderByDescending(o => o.CreatedAt)
.Where(o => o.CreatedAt >= fromDate && o.CreatedAt <= toDate) .Where(o => o.CreatedAt >= fromDate && o.CreatedAt <= toDate)
.Take(request.MaxRecords) .Take(request.MaxRecords)
@@ -0,0 +1,25 @@
namespace LiteCharms.Features.ShoppingCarts.Commands;
public class AddPackageToShoppingCartCommand : IRequest<Result>
{
public Guid ShoppingCartId { get; set; }
public Guid PackageId { get; set; }
private AddPackageToShoppingCartCommand(Guid shoppingCartId, Guid packageId)
{
ShoppingCartId = shoppingCartId;
PackageId = packageId;
}
public static AddPackageToShoppingCartCommand Create(Guid shoppingCartId, Guid packageId)
{
if (shoppingCartId == Guid.Empty)
throw new ArgumentException($"Shopping cart ID is required", nameof(shoppingCartId));
if (packageId == Guid.Empty)
throw new ArgumentException($"Package ID is required", nameof(packageId));
return new(shoppingCartId, packageId);
}
}
@@ -0,0 +1,39 @@
using LiteCharms.Infrastructure.Database;
namespace LiteCharms.Features.ShoppingCarts.Commands.Handlers;
public class AddPackageToShoppingCartCommandHandler(IDbContextFactory<ShopDbContext> contextFactory) : IRequestHandler<AddPackageToShoppingCartCommand, Result>
{
public async ValueTask<Result> Handle(AddPackageToShoppingCartCommand request, CancellationToken cancellationToken)
{
try
{
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
if (!await context.Packages.AnyAsync(p => p.Id == request.PackageId, cancellationToken))
return Result.Fail($"Package cold not be found by ID {request.PackageId}");
var shoppingCart = await context.ShoppingCarts.FirstOrDefaultAsync(c => c.Id == request.ShoppingCartId, cancellationToken);
if (shoppingCart is null)
return Result.Fail($"Shopping cart could not be found by ID {request.ShoppingCartId}");
if (!await context.ShoppingCartPackages.AnyAsync(cp => cp.ShoppingCartId == request.ShoppingCartId, cancellationToken))
return Result.Fail($"Package {request.PackageId} is already in the cart");
var newShoppingCartPackage = context.ShoppingCartPackages.Add(new Entities.ShoppingCartPackage
{
ShoppingCartId = request.ShoppingCartId,
PackageId = request.PackageId
});
return await context.SaveChangesAsync(cancellationToken) > 0
? Result.Ok()
: Result.Fail($"Could not add package of id {request.PackageId} to shopping cart {request.ShoppingCartId}");
}
catch (Exception ex)
{
return Result.Fail(new Error(ex.Message).CausedBy(ex));
}
}
}
@@ -0,0 +1,35 @@
using LiteCharms.Infrastructure.Database;
namespace LiteCharms.Features.ShoppingCarts.Commands.Handlers;
public class RemovePackageFromShoppingCartCommandHandler(IDbContextFactory<ShopDbContext> contextFactory) : IRequestHandler<RemovePackageFromShoppingCartCommand, Result>
{
public async ValueTask<Result> Handle(RemovePackageFromShoppingCartCommand request, CancellationToken cancellationToken)
{
try
{
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
if (!await context.ShoppingCarts.AnyAsync(c => c.Id == request.ShoppingCartId, cancellationToken))
return Result.Fail($"Shopping cart could not be found by ID {request.ShoppingCartId}");
if (!await context.ShoppingCartPackages.AnyAsync(p => p.Id == request.ShoppingCartPackageId, cancellationToken))
return Result.Fail($"Shopping cart package {request.ShoppingCartPackageId} is not in the shopping cart {request.ShoppingCartId}");
var shoppingCartPackage = await context.ShoppingCartPackages.FirstOrDefaultAsync(cp => cp.Id == request.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 {request.ShoppingCartPackageId} from shopping cart {request.ShoppingCartId}");
}
catch (Exception ex)
{
return Result.Fail(new Error(ex.Message).CausedBy(ex));
}
}
}
@@ -0,0 +1,25 @@
namespace LiteCharms.Features.ShoppingCarts.Commands;
public class RemovePackageFromShoppingCartCommand : IRequest<Result>
{
public Guid ShoppingCartId { get; set; }
public Guid ShoppingCartPackageId { get; set; }
private RemovePackageFromShoppingCartCommand(Guid shoppingCartId, Guid shoppingCartPackageId)
{
ShoppingCartId = shoppingCartId;
ShoppingCartPackageId = shoppingCartPackageId;
}
public static RemovePackageFromShoppingCartCommand Create(Guid shoppingCartId, Guid shoppingCartPackageId)
{
if (shoppingCartId == Guid.Empty)
throw new ArgumentException($"Shopping cart ID is required", nameof(shoppingCartId));
if (shoppingCartPackageId == Guid.Empty)
throw new ArgumentException($"Shopping cart Package ID is required", nameof(shoppingCartPackageId));
return new(shoppingCartId, shoppingCartPackageId);
}
}
@@ -0,0 +1,18 @@
using LiteCharms.Models;
namespace LiteCharms.Features.ShoppingCarts.Queries;
public class GetShoppingCartPackagesQuery : IRequest<Result<ShoppingCartPackage[]>>
{
public Guid ShoppingCartId { get; set; }
private GetShoppingCartPackagesQuery(Guid shoppingCartId) => ShoppingCartId = shoppingCartId;
public static GetShoppingCartPackagesQuery Create(Guid shoppingCartId)
{
if (shoppingCartId == Guid.Empty)
throw new ArgumentException("Shopping cart id is required", nameof(shoppingCartId));
return new(shoppingCartId);
}
}
@@ -0,0 +1,32 @@
using LiteCharms.Extensions;
using LiteCharms.Infrastructure.Database;
using LiteCharms.Models;
namespace LiteCharms.Features.ShoppingCarts.Queries.Handlers;
public class GetShoppingCartPackagesQueryHandler(IDbContextFactory<ShopDbContext> contextFactory) : IRequestHandler<GetShoppingCartPackagesQuery, Result<ShoppingCartPackage[]>>
{
public async ValueTask<Result<ShoppingCartPackage[]>> Handle(GetShoppingCartPackagesQuery request, CancellationToken cancellationToken)
{
try
{
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
if (!await context.ShoppingCarts.AnyAsync(c => c.Id == request.ShoppingCartId, cancellationToken))
return Result.Fail($"Shopping cart could not be found by ID {request.ShoppingCartId}");
var packages = await context.ShoppingCartPackages.AsNoTracking()
.OrderByDescending(o => o.CreatedAt)
.Where(cp => cp.ShoppingCartId == request.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 {request.ShoppingCartId}");
}
catch (Exception ex)
{
return Result.Fail<ShoppingCartPackage[]>(new Error(ex.Message).CausedBy(ex));
}
}
}
@@ -1,4 +1,4 @@
namespace LiteCharms.Features.Utilities.Commands; namespace LiteCharms.Features.Utilities.Hash.Commands;
public class ComputeHashCommand : IRequest<Result<string>> public class ComputeHashCommand : IRequest<Result<string>>
{ {
@@ -1,4 +1,6 @@
namespace LiteCharms.Features.Utilities.Commands.Handlers; using LiteCharms.Features.Utilities.Hash.Commands;
namespace LiteCharms.Features.Utilities.Hash.Commands.Handlers;
public class ComputeHashCommandHandler : IRequestHandler<ComputeHashCommand, Result<string>> public class ComputeHashCommandHandler : IRequestHandler<ComputeHashCommand, Result<string>>
{ {
@@ -1,272 +0,0 @@
// <auto-generated />
using System;
using LiteCharms.Infrastructure.Database;
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.Infrastructure.Database.Migrations
{
[DbContext(typeof(ShopDbContext))]
[Migration("20260502231708_Init")]
partial class Init
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("LeadGenerator.Database.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<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("Website")
.HasColumnType("text");
b.Property<string>("Whatsapp")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Customer", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.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>("AttribusionHash")
.IsRequired()
.HasColumnType("text");
b.Property<long?>("CampaignId")
.HasColumnType("bigint");
b.Property<string>("ClickLocation")
.HasColumnType("text");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<long?>("FeedItemId")
.HasColumnType("bigint");
b.Property<string>("GoogleClickId")
.HasColumnType("text");
b.Property<long?>("TargetId")
.HasColumnType("bigint");
b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("WebClickId")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Lead", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Order", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("LeadId")
.HasColumnType("uuid");
b.PrimitiveCollection<string>("Notes")
.HasColumnType("jsonb");
b.Property<Guid>("ProductId")
.HasColumnType("uuid");
b.Property<Guid>("ProductPriceId")
.HasColumnType("uuid");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.ToTable("Order", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.OrderRefund", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<decimal>("Amount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("OrderId")
.HasColumnType("uuid");
b.Property<string>("Reason")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("OrderRefund", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Product", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("Active")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true);
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Product", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.ProductPrice", 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<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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.ToTable("ProductPrice", (string)null);
});
#pragma warning restore 612, 618
}
}
}
@@ -1,154 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LiteCharms.Infrastructure.Database.Migrations
{
/// <inheritdoc />
public partial class Init : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Customer",
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),
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_Customer", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Lead",
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),
GoogleClickId = 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),
AttribusionHash = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Lead", x => x.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),
LeadId = table.Column<Guid>(type: "uuid", nullable: false),
ProductId = table.Column<Guid>(type: "uuid", nullable: false),
ProductPriceId = table.Column<Guid>(type: "uuid", nullable: false),
Status = table.Column<int>(type: "integer", nullable: false),
Notes = table.Column<string>(type: "jsonb", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Order", x => x.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);
});
migrationBuilder.CreateTable(
name: "Product",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
Description = table.Column<string>(type: "text", nullable: false),
Active = table.Column<bool>(type: "boolean", nullable: false, defaultValue: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Product", x => x.Id);
});
migrationBuilder.CreateTable(
name: "ProductPrice",
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),
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_ProductPrice", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Customer");
migrationBuilder.DropTable(
name: "Lead");
migrationBuilder.DropTable(
name: "Order");
migrationBuilder.DropTable(
name: "OrderRefund");
migrationBuilder.DropTable(
name: "Product");
migrationBuilder.DropTable(
name: "ProductPrice");
}
}
}
@@ -1,357 +0,0 @@
// <auto-generated />
using System;
using LiteCharms.Infrastructure.Database;
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.Infrastructure.Database.Migrations
{
[DbContext(typeof(ShopDbContext))]
[Migration("20260503002123_DefinedEntityRelationships")]
partial class DefinedEntityRelationships
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("LeadGenerator.Database.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<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("Website")
.HasColumnType("text");
b.Property<string>("Whatsapp")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Customer", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.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>("AttribusionHash")
.IsRequired()
.HasColumnType("text");
b.Property<long?>("CampaignId")
.HasColumnType("bigint");
b.Property<string>("ClickLocation")
.HasColumnType("text");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CustomerId")
.HasColumnType("uuid");
b.Property<long?>("FeedItemId")
.HasColumnType("bigint");
b.Property<string>("GoogleClickId")
.HasColumnType("text");
b.Property<Guid?>("LeadId")
.HasColumnType("uuid");
b.Property<long?>("TargetId")
.HasColumnType("bigint");
b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("WebClickId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CustomerId");
b.ToTable("Lead", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Order", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("CustomerId")
.HasColumnType("uuid");
b.PrimitiveCollection<string>("Notes")
.HasColumnType("jsonb");
b.Property<Guid>("ProductPriceId")
.HasColumnType("uuid");
b.Property<Guid?>("RefundId")
.HasColumnType("uuid");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("CustomerId");
b.HasIndex("ProductPriceId");
b.ToTable("Order", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.OrderRefund", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<decimal>("Amount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("OrderId")
.HasColumnType("uuid");
b.Property<string>("Reason")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("OrderId")
.IsUnique();
b.ToTable("OrderRefund", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Product", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("Active")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true);
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Product", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.ProductPrice", 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<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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("ProductPrice", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Lead", b =>
{
b.HasOne("LeadGenerator.Database.Entities.Customer", "Customer")
.WithMany("Leads")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.NoAction);
b.Navigation("Customer");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Order", b =>
{
b.HasOne("LeadGenerator.Database.Entities.Customer", "Customer")
.WithMany("Orders")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("LeadGenerator.Database.Entities.ProductPrice", "ProductPrice")
.WithMany()
.HasForeignKey("ProductPriceId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Customer");
b.Navigation("ProductPrice");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.OrderRefund", b =>
{
b.HasOne("LeadGenerator.Database.Entities.Order", "Order")
.WithOne("Refund")
.HasForeignKey("LeadGenerator.Database.Entities.OrderRefund", "OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Order");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.ProductPrice", b =>
{
b.HasOne("LeadGenerator.Database.Entities.Product", "Product")
.WithMany("ProductPrices")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Customer", b =>
{
b.Navigation("Leads");
b.Navigation("Orders");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Order", b =>
{
b.Navigation("Refund");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Product", b =>
{
b.Navigation("ProductPrices");
});
#pragma warning restore 612, 618
}
}
}
@@ -1,175 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LiteCharms.Infrastructure.Database.Migrations
{
/// <inheritdoc />
public partial class DefinedEntityRelationships : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "LeadId",
table: "Order");
migrationBuilder.RenameColumn(
name: "ProductId",
table: "Order",
newName: "CustomerId");
migrationBuilder.AddColumn<Guid>(
name: "RefundId",
table: "Order",
type: "uuid",
nullable: true);
migrationBuilder.AddColumn<Guid>(
name: "CustomerId",
table: "Lead",
type: "uuid",
nullable: true);
migrationBuilder.AddColumn<Guid>(
name: "LeadId",
table: "Lead",
type: "uuid",
nullable: true);
migrationBuilder.CreateIndex(
name: "IX_ProductPrice_ProductId",
table: "ProductPrice",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_OrderRefund_OrderId",
table: "OrderRefund",
column: "OrderId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Order_CustomerId",
table: "Order",
column: "CustomerId");
migrationBuilder.CreateIndex(
name: "IX_Order_ProductPriceId",
table: "Order",
column: "ProductPriceId");
migrationBuilder.CreateIndex(
name: "IX_Lead_CustomerId",
table: "Lead",
column: "CustomerId");
migrationBuilder.AddForeignKey(
name: "FK_Lead_Customer_CustomerId",
table: "Lead",
column: "CustomerId",
principalTable: "Customer",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_Order_Customer_CustomerId",
table: "Order",
column: "CustomerId",
principalTable: "Customer",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
migrationBuilder.AddForeignKey(
name: "FK_Order_ProductPrice_ProductPriceId",
table: "Order",
column: "ProductPriceId",
principalTable: "ProductPrice",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
migrationBuilder.AddForeignKey(
name: "FK_OrderRefund_Order_OrderId",
table: "OrderRefund",
column: "OrderId",
principalTable: "Order",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_ProductPrice_Product_ProductId",
table: "ProductPrice",
column: "ProductId",
principalTable: "Product",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Lead_Customer_CustomerId",
table: "Lead");
migrationBuilder.DropForeignKey(
name: "FK_Order_Customer_CustomerId",
table: "Order");
migrationBuilder.DropForeignKey(
name: "FK_Order_ProductPrice_ProductPriceId",
table: "Order");
migrationBuilder.DropForeignKey(
name: "FK_OrderRefund_Order_OrderId",
table: "OrderRefund");
migrationBuilder.DropForeignKey(
name: "FK_ProductPrice_Product_ProductId",
table: "ProductPrice");
migrationBuilder.DropIndex(
name: "IX_ProductPrice_ProductId",
table: "ProductPrice");
migrationBuilder.DropIndex(
name: "IX_OrderRefund_OrderId",
table: "OrderRefund");
migrationBuilder.DropIndex(
name: "IX_Order_CustomerId",
table: "Order");
migrationBuilder.DropIndex(
name: "IX_Order_ProductPriceId",
table: "Order");
migrationBuilder.DropIndex(
name: "IX_Lead_CustomerId",
table: "Lead");
migrationBuilder.DropColumn(
name: "RefundId",
table: "Order");
migrationBuilder.DropColumn(
name: "CustomerId",
table: "Lead");
migrationBuilder.DropColumn(
name: "LeadId",
table: "Lead");
migrationBuilder.RenameColumn(
name: "CustomerId",
table: "Order",
newName: "ProductId");
migrationBuilder.AddColumn<Guid>(
name: "LeadId",
table: "Order",
type: "uuid",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
}
}
}
@@ -1,354 +0,0 @@
// <auto-generated />
using System;
using LiteCharms.Infrastructure.Database;
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.Infrastructure.Database.Migrations
{
[DbContext(typeof(ShopDbContext))]
[Migration("20260503003624_RemovedLeadIdFromLead")]
partial class RemovedLeadIdFromLead
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("LeadGenerator.Database.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<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("Website")
.HasColumnType("text");
b.Property<string>("Whatsapp")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Customer", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.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>("AttribusionHash")
.IsRequired()
.HasColumnType("text");
b.Property<long?>("CampaignId")
.HasColumnType("bigint");
b.Property<string>("ClickLocation")
.HasColumnType("text");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CustomerId")
.HasColumnType("uuid");
b.Property<long?>("FeedItemId")
.HasColumnType("bigint");
b.Property<string>("GoogleClickId")
.HasColumnType("text");
b.Property<long?>("TargetId")
.HasColumnType("bigint");
b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("WebClickId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CustomerId");
b.ToTable("Lead", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Order", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("CustomerId")
.HasColumnType("uuid");
b.PrimitiveCollection<string>("Notes")
.HasColumnType("jsonb");
b.Property<Guid>("ProductPriceId")
.HasColumnType("uuid");
b.Property<Guid?>("RefundId")
.HasColumnType("uuid");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("CustomerId");
b.HasIndex("ProductPriceId");
b.ToTable("Order", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.OrderRefund", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<decimal>("Amount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("OrderId")
.HasColumnType("uuid");
b.Property<string>("Reason")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("OrderId")
.IsUnique();
b.ToTable("OrderRefund", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Product", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("Active")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true);
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Product", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.ProductPrice", 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<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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("ProductPrice", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Lead", b =>
{
b.HasOne("LeadGenerator.Database.Entities.Customer", "Customer")
.WithMany("Leads")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.NoAction);
b.Navigation("Customer");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Order", b =>
{
b.HasOne("LeadGenerator.Database.Entities.Customer", "Customer")
.WithMany("Orders")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("LeadGenerator.Database.Entities.ProductPrice", "ProductPrice")
.WithMany()
.HasForeignKey("ProductPriceId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Customer");
b.Navigation("ProductPrice");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.OrderRefund", b =>
{
b.HasOne("LeadGenerator.Database.Entities.Order", "Order")
.WithOne("Refund")
.HasForeignKey("LeadGenerator.Database.Entities.OrderRefund", "OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Order");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.ProductPrice", b =>
{
b.HasOne("LeadGenerator.Database.Entities.Product", "Product")
.WithMany("ProductPrices")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Customer", b =>
{
b.Navigation("Leads");
b.Navigation("Orders");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Order", b =>
{
b.Navigation("Refund");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Product", b =>
{
b.Navigation("ProductPrices");
});
#pragma warning restore 612, 618
}
}
}
@@ -1,29 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LiteCharms.Infrastructure.Database.Migrations
{
/// <inheritdoc />
public partial class RemovedLeadIdFromLead : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "LeadId",
table: "Lead");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<Guid>(
name: "LeadId",
table: "Lead",
type: "uuid",
nullable: true);
}
}
}
@@ -1,357 +0,0 @@
// <auto-generated />
using System;
using LiteCharms.Infrastructure.Database;
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.Infrastructure.Database.Migrations
{
[DbContext(typeof(ShopDbContext))]
[Migration("20260503012708_AddedStatusToLead")]
partial class AddedStatusToLead
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("LeadGenerator.Database.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<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("Website")
.HasColumnType("text");
b.Property<string>("Whatsapp")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Customer", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.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>("AttribusionHash")
.IsRequired()
.HasColumnType("text");
b.Property<long?>("CampaignId")
.HasColumnType("bigint");
b.Property<string>("ClickLocation")
.HasColumnType("text");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CustomerId")
.HasColumnType("uuid");
b.Property<long?>("FeedItemId")
.HasColumnType("bigint");
b.Property<string>("GoogleClickId")
.HasColumnType("text");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<long?>("TargetId")
.HasColumnType("bigint");
b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("WebClickId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CustomerId");
b.ToTable("Lead", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Order", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("CustomerId")
.HasColumnType("uuid");
b.PrimitiveCollection<string>("Notes")
.HasColumnType("jsonb");
b.Property<Guid>("ProductPriceId")
.HasColumnType("uuid");
b.Property<Guid?>("RefundId")
.HasColumnType("uuid");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("CustomerId");
b.HasIndex("ProductPriceId");
b.ToTable("Order", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.OrderRefund", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<decimal>("Amount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("OrderId")
.HasColumnType("uuid");
b.Property<string>("Reason")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("OrderId")
.IsUnique();
b.ToTable("OrderRefund", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Product", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("Active")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true);
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Product", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.ProductPrice", 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<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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("ProductPrice", (string)null);
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Lead", b =>
{
b.HasOne("LeadGenerator.Database.Entities.Customer", "Customer")
.WithMany("Leads")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.NoAction);
b.Navigation("Customer");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Order", b =>
{
b.HasOne("LeadGenerator.Database.Entities.Customer", "Customer")
.WithMany("Orders")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("LeadGenerator.Database.Entities.ProductPrice", "ProductPrice")
.WithMany()
.HasForeignKey("ProductPriceId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Customer");
b.Navigation("ProductPrice");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.OrderRefund", b =>
{
b.HasOne("LeadGenerator.Database.Entities.Order", "Order")
.WithOne("Refund")
.HasForeignKey("LeadGenerator.Database.Entities.OrderRefund", "OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Order");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.ProductPrice", b =>
{
b.HasOne("LeadGenerator.Database.Entities.Product", "Product")
.WithMany("ProductPrices")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Customer", b =>
{
b.Navigation("Leads");
b.Navigation("Orders");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Order", b =>
{
b.Navigation("Refund");
});
modelBuilder.Entity("LeadGenerator.Database.Entities.Product", b =>
{
b.Navigation("ProductPrices");
});
#pragma warning restore 612, 618
}
}
}
@@ -1,29 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LiteCharms.Infrastructure.Database.Migrations
{
/// <inheritdoc />
public partial class AddedStatusToLead : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "Status",
table: "Lead",
type: "integer",
nullable: false,
defaultValue: 0);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Status",
table: "Lead");
}
}
}
@@ -1,357 +0,0 @@
// <auto-generated />
using System;
using LiteCharms.Infrastructure.Database;
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.Infrastructure.Database.Migrations
{
[DbContext(typeof(ShopDbContext))]
[Migration("20260503133855_CorrectedAttributionHashColumnOnLead")]
partial class CorrectedAttributionHashColumnOnLead
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("LiteCharms.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<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("Website")
.HasColumnType("text");
b.Property<string>("Whatsapp")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Customer", (string)null);
});
modelBuilder.Entity("LiteCharms.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>("ClickLocation")
.HasColumnType("text");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid?>("CustomerId")
.HasColumnType("uuid");
b.Property<long?>("FeedItemId")
.HasColumnType("bigint");
b.Property<string>("GoogleClickId")
.HasColumnType("text");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<long?>("TargetId")
.HasColumnType("bigint");
b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("WebClickId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CustomerId");
b.ToTable("Lead", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("CustomerId")
.HasColumnType("uuid");
b.PrimitiveCollection<string>("Notes")
.HasColumnType("jsonb");
b.Property<Guid>("ProductPriceId")
.HasColumnType("uuid");
b.Property<Guid?>("RefundId")
.HasColumnType("uuid");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("CustomerId");
b.HasIndex("ProductPriceId");
b.ToTable("Order", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.OrderRefund", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<decimal>("Amount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("OrderId")
.HasColumnType("uuid");
b.Property<string>("Reason")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("OrderId")
.IsUnique();
b.ToTable("OrderRefund", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Product", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("Active")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true);
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Product", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.ProductPrice", 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<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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("ProductPrice", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Lead", b =>
{
b.HasOne("LiteCharms.Entities.Customer", "Customer")
.WithMany("Leads")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.NoAction);
b.Navigation("Customer");
});
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
{
b.HasOne("LiteCharms.Entities.Customer", "Customer")
.WithMany("Orders")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("LiteCharms.Entities.ProductPrice", "ProductPrice")
.WithMany()
.HasForeignKey("ProductPriceId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Customer");
b.Navigation("ProductPrice");
});
modelBuilder.Entity("LiteCharms.Entities.OrderRefund", b =>
{
b.HasOne("LiteCharms.Entities.Order", "Order")
.WithOne("Refund")
.HasForeignKey("LiteCharms.Entities.OrderRefund", "OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Order");
});
modelBuilder.Entity("LiteCharms.Entities.ProductPrice", b =>
{
b.HasOne("LiteCharms.Entities.Product", "Product")
.WithMany("ProductPrices")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("LiteCharms.Entities.Customer", b =>
{
b.Navigation("Leads");
b.Navigation("Orders");
});
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
{
b.Navigation("Refund");
});
modelBuilder.Entity("LiteCharms.Entities.Product", b =>
{
b.Navigation("ProductPrices");
});
#pragma warning restore 612, 618
}
}
}
@@ -1,28 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LiteCharms.Infrastructure.Database.Migrations
{
/// <inheritdoc />
public partial class CorrectedAttributionHashColumnOnLead : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "AttribusionHash",
table: "Lead",
newName: "AttributionHash");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "AttributionHash",
table: "Lead",
newName: "AttribusionHash");
}
}
}
@@ -1,360 +0,0 @@
// <auto-generated />
using System;
using LiteCharms.Infrastructure.Database;
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.Infrastructure.Database.Migrations
{
[DbContext(typeof(ShopDbContext))]
[Migration("20260505120450_GeneralisedLead")]
partial class GeneralisedLead
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("LiteCharms.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<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("Website")
.HasColumnType("text");
b.Property<string>("Whatsapp")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Customer", (string)null);
});
modelBuilder.Entity("LiteCharms.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<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("WebClickId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CustomerId");
b.ToTable("Lead", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("CustomerId")
.HasColumnType("uuid");
b.PrimitiveCollection<string>("Notes")
.HasColumnType("jsonb");
b.Property<Guid>("ProductPriceId")
.HasColumnType("uuid");
b.Property<Guid?>("RefundId")
.HasColumnType("uuid");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("CustomerId");
b.HasIndex("ProductPriceId");
b.ToTable("Order", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.OrderRefund", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<decimal>("Amount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("OrderId")
.HasColumnType("uuid");
b.Property<string>("Reason")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("OrderId")
.IsUnique();
b.ToTable("OrderRefund", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Product", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("Active")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true);
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Product", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.ProductPrice", 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<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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("ProductPrice", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Lead", b =>
{
b.HasOne("LiteCharms.Entities.Customer", "Customer")
.WithMany("Leads")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.NoAction);
b.Navigation("Customer");
});
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
{
b.HasOne("LiteCharms.Entities.Customer", "Customer")
.WithMany("Orders")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("LiteCharms.Entities.ProductPrice", "ProductPrice")
.WithMany()
.HasForeignKey("ProductPriceId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Customer");
b.Navigation("ProductPrice");
});
modelBuilder.Entity("LiteCharms.Entities.OrderRefund", b =>
{
b.HasOne("LiteCharms.Entities.Order", "Order")
.WithOne("Refund")
.HasForeignKey("LiteCharms.Entities.OrderRefund", "OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Order");
});
modelBuilder.Entity("LiteCharms.Entities.ProductPrice", b =>
{
b.HasOne("LiteCharms.Entities.Product", "Product")
.WithMany("ProductPrices")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("LiteCharms.Entities.Customer", b =>
{
b.Navigation("Leads");
b.Navigation("Orders");
});
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
{
b.Navigation("Refund");
});
modelBuilder.Entity("LiteCharms.Entities.Product", b =>
{
b.Navigation("ProductPrices");
});
#pragma warning restore 612, 618
}
}
}
@@ -1,38 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LiteCharms.Infrastructure.Database.Migrations
{
/// <inheritdoc />
public partial class GeneralisedLead : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.RenameColumn(
name: "GoogleClickId",
table: "Lead",
newName: "Source");
migrationBuilder.AddColumn<string>(
name: "ClickId",
table: "Lead",
type: "text",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "ClickId",
table: "Lead");
migrationBuilder.RenameColumn(
name: "Source",
table: "Lead",
newName: "GoogleClickId");
}
}
}
@@ -1,409 +0,0 @@
// <auto-generated />
using System;
using LiteCharms.Infrastructure.Database;
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.Infrastructure.Database.Migrations
{
[DbContext(typeof(ShopDbContext))]
[Migration("20260505123745_AddedNotifications")]
partial class AddedNotifications
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("LiteCharms.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<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("Website")
.HasColumnType("text");
b.Property<string>("Whatsapp")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Customer", (string)null);
});
modelBuilder.Entity("LiteCharms.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<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("WebClickId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CustomerId");
b.ToTable("Lead", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Notification", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Author")
.IsRequired()
.HasColumnType("text");
b.Property<string>("CorrelationId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("CorrelationIdType")
.IsRequired()
.HasColumnType("text");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Direction")
.HasColumnType("integer");
b.Property<bool>("IsInternal")
.HasColumnType("boolean");
b.Property<string>("Platform")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PlatformAddress")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Title")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Notification", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("CustomerId")
.HasColumnType("uuid");
b.PrimitiveCollection<string>("Notes")
.HasColumnType("jsonb");
b.Property<Guid>("ProductPriceId")
.HasColumnType("uuid");
b.Property<Guid?>("RefundId")
.HasColumnType("uuid");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("CustomerId");
b.HasIndex("ProductPriceId");
b.ToTable("Order", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.OrderRefund", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<decimal>("Amount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("OrderId")
.HasColumnType("uuid");
b.Property<string>("Reason")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("OrderId")
.IsUnique();
b.ToTable("OrderRefund", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Product", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("Active")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true);
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Product", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.ProductPrice", 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<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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("ProductPrice", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Lead", b =>
{
b.HasOne("LiteCharms.Entities.Customer", "Customer")
.WithMany("Leads")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.NoAction);
b.Navigation("Customer");
});
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
{
b.HasOne("LiteCharms.Entities.Customer", "Customer")
.WithMany("Orders")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("LiteCharms.Entities.ProductPrice", "ProductPrice")
.WithMany()
.HasForeignKey("ProductPriceId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Customer");
b.Navigation("ProductPrice");
});
modelBuilder.Entity("LiteCharms.Entities.OrderRefund", b =>
{
b.HasOne("LiteCharms.Entities.Order", "Order")
.WithOne("Refund")
.HasForeignKey("LiteCharms.Entities.OrderRefund", "OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Order");
});
modelBuilder.Entity("LiteCharms.Entities.ProductPrice", b =>
{
b.HasOne("LiteCharms.Entities.Product", "Product")
.WithMany("ProductPrices")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("LiteCharms.Entities.Customer", b =>
{
b.Navigation("Leads");
b.Navigation("Orders");
});
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
{
b.Navigation("Refund");
});
modelBuilder.Entity("LiteCharms.Entities.Product", b =>
{
b.Navigation("ProductPrices");
});
#pragma warning restore 612, 618
}
}
}
@@ -1,43 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LiteCharms.Infrastructure.Database.Migrations
{
/// <inheritdoc />
public partial class AddedNotifications : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Notification",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
Direction = table.Column<int>(type: "integer", nullable: false),
Author = table.Column<string>(type: "text", nullable: false),
Title = table.Column<string>(type: "text", nullable: false),
Description = table.Column<string>(type: "text", nullable: false),
Platform = table.Column<string>(type: "text", nullable: false),
PlatformAddress = table.Column<string>(type: "text", nullable: false),
CorrelationId = table.Column<string>(type: "text", nullable: false),
CorrelationIdType = table.Column<string>(type: "text", nullable: false),
IsInternal = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Notification", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Notification");
}
}
}
@@ -1,416 +0,0 @@
// <auto-generated />
using System;
using LiteCharms.Infrastructure.Database;
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.Infrastructure.Database.Migrations
{
[DbContext(typeof(ShopDbContext))]
[Migration("20260505124135_AddedProcessedColumnToNotifications")]
partial class AddedProcessedColumnToNotifications
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("LiteCharms.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<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("Website")
.HasColumnType("text");
b.Property<string>("Whatsapp")
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Customer", (string)null);
});
modelBuilder.Entity("LiteCharms.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<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.Property<string>("WebClickId")
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("CustomerId");
b.ToTable("Lead", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Notification", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("Author")
.IsRequired()
.HasColumnType("text");
b.Property<string>("CorrelationId")
.IsRequired()
.HasColumnType("text");
b.Property<string>("CorrelationIdType")
.IsRequired()
.HasColumnType("text");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Direction")
.HasColumnType("integer");
b.Property<bool>("IsInternal")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true);
b.Property<string>("Platform")
.IsRequired()
.HasColumnType("text");
b.Property<string>("PlatformAddress")
.IsRequired()
.HasColumnType("text");
b.Property<bool>("Processed")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(false);
b.Property<string>("Title")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Notification", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("CustomerId")
.HasColumnType("uuid");
b.PrimitiveCollection<string>("Notes")
.HasColumnType("jsonb");
b.Property<Guid>("ProductPriceId")
.HasColumnType("uuid");
b.Property<Guid?>("RefundId")
.HasColumnType("uuid");
b.Property<int>("Status")
.HasColumnType("integer");
b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("CustomerId");
b.HasIndex("ProductPriceId");
b.ToTable("Order", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.OrderRefund", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<decimal>("Amount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("OrderId")
.HasColumnType("uuid");
b.Property<string>("Reason")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.HasIndex("OrderId")
.IsUnique();
b.ToTable("OrderRefund", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Product", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("Active")
.ValueGeneratedOnAdd()
.HasColumnType("boolean")
.HasDefaultValue(true);
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Product", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.ProductPrice", 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<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<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("ProductPrice", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Lead", b =>
{
b.HasOne("LiteCharms.Entities.Customer", "Customer")
.WithMany("Leads")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.NoAction);
b.Navigation("Customer");
});
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
{
b.HasOne("LiteCharms.Entities.Customer", "Customer")
.WithMany("Orders")
.HasForeignKey("CustomerId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("LiteCharms.Entities.ProductPrice", "ProductPrice")
.WithMany()
.HasForeignKey("ProductPriceId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Customer");
b.Navigation("ProductPrice");
});
modelBuilder.Entity("LiteCharms.Entities.OrderRefund", b =>
{
b.HasOne("LiteCharms.Entities.Order", "Order")
.WithOne("Refund")
.HasForeignKey("LiteCharms.Entities.OrderRefund", "OrderId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Order");
});
modelBuilder.Entity("LiteCharms.Entities.ProductPrice", b =>
{
b.HasOne("LiteCharms.Entities.Product", "Product")
.WithMany("ProductPrices")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("LiteCharms.Entities.Customer", b =>
{
b.Navigation("Leads");
b.Navigation("Orders");
});
modelBuilder.Entity("LiteCharms.Entities.Order", b =>
{
b.Navigation("Refund");
});
modelBuilder.Entity("LiteCharms.Entities.Product", b =>
{
b.Navigation("ProductPrices");
});
#pragma warning restore 612, 618
}
}
}
@@ -1,47 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LiteCharms.Infrastructure.Database.Migrations
{
/// <inheritdoc />
public partial class AddedProcessedColumnToNotifications : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<bool>(
name: "IsInternal",
table: "Notification",
type: "boolean",
nullable: false,
defaultValue: true,
oldClrType: typeof(bool),
oldType: "boolean");
migrationBuilder.AddColumn<bool>(
name: "Processed",
table: "Notification",
type: "boolean",
nullable: false,
defaultValue: false);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Processed",
table: "Notification");
migrationBuilder.AlterColumn<bool>(
name: "IsInternal",
table: "Notification",
type: "boolean",
nullable: false,
oldClrType: typeof(bool),
oldType: "boolean",
oldDefaultValue: true);
}
}
}
@@ -1,227 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LiteCharms.Infrastructure.Database.Migrations
{
/// <inheritdoc />
public partial class AddedQuoteShoppingCartalteredOrderCustomer : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Order_ProductPrice_ProductPriceId",
table: "Order");
migrationBuilder.DropIndex(
name: "IX_Order_ProductPriceId",
table: "Order");
migrationBuilder.RenameColumn(
name: "ProductPriceId",
table: "Order",
newName: "ShoppingCartId");
migrationBuilder.AddColumn<Guid>(
name: "QuoteId",
table: "Order",
type: "uuid",
nullable: true);
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),
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
CustomerId = table.Column<Guid>(type: "uuid", nullable: true),
OrderId = table.Column<Guid>(type: "uuid", nullable: true),
QuoteId = 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");
});
migrationBuilder.CreateTable(
name: "Quote",
columns: table => new
{
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),
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
ExpiredAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
CustomerId = table.Column<Guid>(type: "uuid", nullable: false),
ShoppingCartId = table.Column<Guid>(type: "uuid", nullable: false),
Status = table.Column<int>(type: "integer", nullable: false),
Reason = table.Column<string>(type: "text", 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_Customer_CustomerId1",
column: x => x.CustomerId1,
principalTable: "Customer",
principalColumn: "Id");
table.ForeignKey(
name: "FK_Quote_ShoppingCart_ShoppingCartId",
column: x => x.ShoppingCartId,
principalTable: "ShoppingCart",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "ShoppingCartItems",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
ShoppingCartId = 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),
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
Quantity = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ShoppingCartItems", x => x.Id);
table.ForeignKey(
name: "FK_ShoppingCartItems_ProductPrice_ProductPriceId",
column: x => x.ProductPriceId,
principalTable: "ProductPrice",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ShoppingCartItems_ShoppingCart_ShoppingCartId",
column: x => x.ShoppingCartId,
principalTable: "ShoppingCart",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
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(
name: "IX_Quote_CustomerId",
table: "Quote",
column: "CustomerId");
migrationBuilder.CreateIndex(
name: "IX_Quote_CustomerId1",
table: "Quote",
column: "CustomerId1");
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_ShoppingCartItems_ProductPriceId",
table: "ShoppingCartItems",
column: "ProductPriceId");
migrationBuilder.CreateIndex(
name: "IX_ShoppingCartItems_ShoppingCartId",
table: "ShoppingCartItems",
column: "ShoppingCartId");
migrationBuilder.AddForeignKey(
name: "FK_Order_Quote_QuoteId",
table: "Order",
column: "QuoteId",
principalTable: "Quote",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
migrationBuilder.AddForeignKey(
name: "FK_Order_ShoppingCart_ShoppingCartId",
table: "Order",
column: "ShoppingCartId",
principalTable: "ShoppingCart",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_Order_Quote_QuoteId",
table: "Order");
migrationBuilder.DropForeignKey(
name: "FK_Order_ShoppingCart_ShoppingCartId",
table: "Order");
migrationBuilder.DropTable(
name: "Quote");
migrationBuilder.DropTable(
name: "ShoppingCartItems");
migrationBuilder.DropTable(
name: "ShoppingCart");
migrationBuilder.DropIndex(
name: "IX_Order_QuoteId",
table: "Order");
migrationBuilder.DropIndex(
name: "IX_Order_ShoppingCartId",
table: "Order");
migrationBuilder.DropColumn(
name: "QuoteId",
table: "Order");
migrationBuilder.RenameColumn(
name: "ShoppingCartId",
table: "Order",
newName: "ProductPriceId");
migrationBuilder.CreateIndex(
name: "IX_Order_ProductPriceId",
table: "Order",
column: "ProductPriceId");
migrationBuilder.AddForeignKey(
name: "FK_Order_ProductPrice_ProductPriceId",
table: "Order",
column: "ProductPriceId",
principalTable: "ProductPrice",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
}
}
}
@@ -12,8 +12,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace LiteCharms.Infrastructure.Database.Migrations namespace LiteCharms.Infrastructure.Database.Migrations
{ {
[DbContext(typeof(ShopDbContext))] [DbContext(typeof(ShopDbContext))]
[Migration("20260505202859_AddedQuoteShoppingCartalteredOrderCustomer")] [Migration("20260510132008_Init")]
partial class AddedQuoteShoppingCartalteredOrderCustomer partial class Init
{ {
/// <inheritdoc /> /// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder)
@@ -167,51 +167,76 @@ namespace LiteCharms.Infrastructure.Database.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<string>("Author")
.IsRequired()
.HasColumnType("text");
b.Property<string>("CorrelationId") b.Property<string>("CorrelationId")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("CorrelationIdType") b.Property<int>("CorrelationIdType")
.IsRequired() .HasColumnType("integer");
.HasColumnType("text");
b.Property<DateTimeOffset>("CreatedAt") b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Direction") b.Property<int>("Direction")
.HasColumnType("integer"); .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") b.Property<bool>("IsInternal")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("boolean") .HasColumnType("boolean")
.HasDefaultValue(true); .HasDefaultValue(true);
b.Property<string>("Platform") b.Property<string>("Message")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("PlatformAddress") b.Property<int>("Platform")
.IsRequired() .HasColumnType("integer");
.HasColumnType("text");
b.Property<int>("Priority")
.HasColumnType("integer");
b.Property<bool>("Processed") b.Property<bool>("Processed")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("boolean") .HasColumnType("boolean")
.HasDefaultValue(false); .HasDefaultValue(false);
b.Property<string>("Title") b.Property<string>("Recipient")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("RecipientAddress")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Sender")
.IsRequired()
.HasColumnType("text");
b.Property<string>("SenderName")
.HasColumnType("text");
b.Property<string>("Subject")
.IsRequired()
.HasColumnType("text");
b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Notification", (string)null); b.ToTable("Notification", (string)null);
@@ -230,6 +255,9 @@ namespace LiteCharms.Infrastructure.Database.Migrations
b.Property<Guid>("CustomerId") b.Property<Guid>("CustomerId")
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<bool>("DepositRequired")
.HasColumnType("boolean");
b.PrimitiveCollection<string>("Notes") b.PrimitiveCollection<string>("Notes")
.HasColumnType("jsonb"); .HasColumnType("jsonb");
@@ -239,12 +267,18 @@ namespace LiteCharms.Infrastructure.Database.Migrations
b.Property<Guid?>("RefundId") b.Property<Guid?>("RefundId")
.HasColumnType("uuid"); .HasColumnType("uuid");
b.PrimitiveCollection<string>("Requirements")
.HasColumnType("jsonb");
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.PrimitiveCollection<string>("Terms")
.HasColumnType("jsonb");
b.Property<DateTimeOffset?>("UpdatedAt") b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate() .ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
@@ -291,6 +325,72 @@ namespace LiteCharms.Infrastructure.Database.Migrations
b.ToTable("OrderRefund", (string)null); b.ToTable("OrderRefund", (string)null);
}); });
modelBuilder.Entity("LiteCharms.Entities.Package", 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 => modelBuilder.Entity("LiteCharms.Entities.Product", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
@@ -378,8 +478,8 @@ namespace LiteCharms.Infrastructure.Database.Migrations
b.Property<int>("Status") b.Property<int>("Status")
.HasColumnType("integer"); .HasColumnType("integer");
b.Property<DateTimeOffset>("UpdatedAt") b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnAddOrUpdate() .ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.HasKey("Id"); b.HasKey("Id");
@@ -413,8 +513,8 @@ namespace LiteCharms.Infrastructure.Database.Migrations
b.Property<Guid?>("QuoteId") b.Property<Guid?>("QuoteId")
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<DateTimeOffset>("UpdatedAt") b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnAddOrUpdate() .ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.HasKey("Id"); b.HasKey("Id");
@@ -454,6 +554,31 @@ namespace LiteCharms.Infrastructure.Database.Migrations
b.ToTable("ShoppingCartItems"); b.ToTable("ShoppingCartItems");
}); });
modelBuilder.Entity("LiteCharms.Entities.ShoppingCartPackage", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("PackageId")
.HasColumnType("uuid");
b.Property<Guid>("ShoppingCartId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("PackageId");
b.HasIndex("ShoppingCartId");
b.ToTable("ShoppingCartPackage", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Lead", b => modelBuilder.Entity("LiteCharms.Entities.Lead", b =>
{ {
b.HasOne("LiteCharms.Entities.Customer", "Customer") b.HasOne("LiteCharms.Entities.Customer", "Customer")
@@ -501,6 +626,28 @@ namespace LiteCharms.Infrastructure.Database.Migrations
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 =>
{
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 => modelBuilder.Entity("LiteCharms.Entities.ProductPrice", b =>
{ {
b.HasOne("LiteCharms.Entities.Product", "Product") b.HasOne("LiteCharms.Entities.Product", "Product")
@@ -564,6 +711,25 @@ namespace LiteCharms.Infrastructure.Database.Migrations
b.Navigation("ShoppingCart"); b.Navigation("ShoppingCart");
}); });
modelBuilder.Entity("LiteCharms.Entities.ShoppingCartPackage", b =>
{
b.HasOne("LiteCharms.Entities.Package", "Package")
.WithMany()
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.NoAction)
.IsRequired();
b.HasOne("LiteCharms.Entities.ShoppingCart", "ShoppingCart")
.WithMany()
.HasForeignKey("ShoppingCartId")
.OnDelete(DeleteBehavior.NoAction)
.IsRequired();
b.Navigation("Package");
b.Navigation("ShoppingCart");
});
modelBuilder.Entity("LiteCharms.Entities.Customer", b => modelBuilder.Entity("LiteCharms.Entities.Customer", b =>
{ {
b.Navigation("Leads"); b.Navigation("Leads");
@@ -580,6 +746,11 @@ namespace LiteCharms.Infrastructure.Database.Migrations
b.Navigation("Refund"); b.Navigation("Refund");
}); });
modelBuilder.Entity("LiteCharms.Entities.Package", b =>
{
b.Navigation("PackageItems");
});
modelBuilder.Entity("LiteCharms.Entities.Product", b => modelBuilder.Entity("LiteCharms.Entities.Product", b =>
{ {
b.Navigation("ProductPrices"); b.Navigation("ProductPrices");
@@ -594,6 +765,8 @@ namespace LiteCharms.Infrastructure.Database.Migrations
{ {
b.Navigation("Order"); b.Navigation("Order");
b.Navigation("Packages");
b.Navigation("Quote"); b.Navigation("Quote");
b.Navigation("ShoppingCartItems"); b.Navigation("ShoppingCartItems");
@@ -0,0 +1,490 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LiteCharms.Infrastructure.Database.Migrations
{
/// <inheritdoc />
public partial class Init : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Customer",
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),
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_Customer", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Notification",
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),
Direction = table.Column<int>(type: "integer", nullable: false),
Platform = table.Column<int>(type: "integer", nullable: false),
Priority = table.Column<int>(type: "integer", nullable: false),
CorrelationIdType = table.Column<int>(type: "integer", nullable: false),
Sender = table.Column<string>(type: "text", nullable: false),
SenderName = table.Column<string>(type: "text", nullable: true),
Subject = table.Column<string>(type: "text", nullable: false),
Message = table.Column<string>(type: "text", nullable: false),
Recipient = table.Column<string>(type: "text", nullable: false),
RecipientAddress = table.Column<string>(type: "text", nullable: false),
CorrelationId = table.Column<string>(type: "text", nullable: false),
IsHtml = table.Column<bool>(type: "boolean", nullable: false, defaultValue: false),
IsInternal = table.Column<bool>(type: "boolean", nullable: false, defaultValue: true),
Processed = table.Column<bool>(type: "boolean", nullable: false, defaultValue: false),
HasError = table.Column<bool>(type: "boolean", nullable: false, defaultValue: false),
Errors = table.Column<string>(type: "jsonb", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Notification", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Product",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
Name = table.Column<string>(type: "text", nullable: false),
Description = table.Column<string>(type: "text", nullable: false),
Active = table.Column<bool>(type: "boolean", nullable: false, defaultValue: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Product", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Lead",
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: 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_Lead", x => x.Id);
table.ForeignKey(
name: "FK_Lead_Customer_CustomerId",
column: x => x.CustomerId,
principalTable: "Customer",
principalColumn: "Id");
});
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),
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
CustomerId = table.Column<Guid>(type: "uuid", nullable: true),
OrderId = table.Column<Guid>(type: "uuid", nullable: true),
QuoteId = 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");
});
migrationBuilder.CreateTable(
name: "ProductPrice",
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),
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_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: "Package",
columns: table => new
{
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),
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: true),
Name = table.Column<string>(type: "text", nullable: false),
Description = table.Column<string>(type: "text", nullable: false),
Active = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Package", x => x.Id);
table.ForeignKey(
name: "FK_Package_ShoppingCart_ShoppingCartId",
column: x => x.ShoppingCartId,
principalTable: "ShoppingCart",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "Quote",
columns: table => new
{
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),
UpdatedAt = 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),
ShoppingCartId = table.Column<Guid>(type: "uuid", nullable: false),
Status = table.Column<int>(type: "integer", nullable: false),
Reason = table.Column<string>(type: "text", 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_Customer_CustomerId1",
column: x => x.CustomerId1,
principalTable: "Customer",
principalColumn: "Id");
table.ForeignKey(
name: "FK_Quote_ShoppingCart_ShoppingCartId",
column: x => x.ShoppingCartId,
principalTable: "ShoppingCart",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "ShoppingCartItems",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
ShoppingCartId = 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),
UpdatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
Quantity = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ShoppingCartItems", x => x.Id);
table.ForeignKey(
name: "FK_ShoppingCartItems_ProductPrice_ProductPriceId",
column: x => x.ProductPriceId,
principalTable: "ProductPrice",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ShoppingCartItems_ShoppingCart_ShoppingCartId",
column: x => x.ShoppingCartId,
principalTable: "ShoppingCart",
principalColumn: "Id",
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(
name: "ShoppingCartPackage",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
CreatedAt = table.Column<DateTimeOffset>(type: "timestamp with time zone", nullable: false),
ShoppingCartId = table.Column<Guid>(type: "uuid", nullable: false),
PackageId = table.Column<Guid>(type: "uuid", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ShoppingCartPackage", x => x.Id);
table.ForeignKey(
name: "FK_ShoppingCartPackage_Package_PackageId",
column: x => x.PackageId,
principalTable: "Package",
principalColumn: "Id");
table.ForeignKey(
name: "FK_ShoppingCartPackage_ShoppingCart_ShoppingCartId",
column: x => x.ShoppingCartId,
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",
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_Order_QuoteId",
table: "Order",
column: "QuoteId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Order_ShoppingCartId",
table: "Order",
column: "ShoppingCartId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_OrderRefund_OrderId",
table: "OrderRefund",
column: "OrderId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_Package_ShoppingCartId",
table: "Package",
column: "ShoppingCartId");
migrationBuilder.CreateIndex(
name: "IX_PackageItem_PackageId",
table: "PackageItem",
column: "PackageId");
migrationBuilder.CreateIndex(
name: "IX_PackageItem_PackageId1",
table: "PackageItem",
column: "PackageId1");
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_CustomerId1",
table: "Quote",
column: "CustomerId1");
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_ShoppingCartItems_ProductPriceId",
table: "ShoppingCartItems",
column: "ProductPriceId");
migrationBuilder.CreateIndex(
name: "IX_ShoppingCartItems_ShoppingCartId",
table: "ShoppingCartItems",
column: "ShoppingCartId");
migrationBuilder.CreateIndex(
name: "IX_ShoppingCartPackage_PackageId",
table: "ShoppingCartPackage",
column: "PackageId");
migrationBuilder.CreateIndex(
name: "IX_ShoppingCartPackage_ShoppingCartId",
table: "ShoppingCartPackage",
column: "ShoppingCartId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Lead");
migrationBuilder.DropTable(
name: "Notification");
migrationBuilder.DropTable(
name: "OrderRefund");
migrationBuilder.DropTable(
name: "PackageItem");
migrationBuilder.DropTable(
name: "ShoppingCartItems");
migrationBuilder.DropTable(
name: "ShoppingCartPackage");
migrationBuilder.DropTable(
name: "Order");
migrationBuilder.DropTable(
name: "ProductPrice");
migrationBuilder.DropTable(
name: "Package");
migrationBuilder.DropTable(
name: "Quote");
migrationBuilder.DropTable(
name: "Product");
migrationBuilder.DropTable(
name: "ShoppingCart");
migrationBuilder.DropTable(
name: "Customer");
}
}
}
@@ -8,10 +8,10 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable #nullable disable
namespace LiteCharms.Infrastructure.Migrations namespace LiteCharms.Infrastructure.Database.Migrations
{ {
[DbContext(typeof(ShopDbContext))] [DbContext(typeof(ShopDbContext))]
partial class LeadGeneratorDbContextModelSnapshot : ModelSnapshot partial class ShopDbContextModelSnapshot : ModelSnapshot
{ {
protected override void BuildModel(ModelBuilder modelBuilder) protected override void BuildModel(ModelBuilder modelBuilder)
{ {
@@ -164,51 +164,76 @@ namespace LiteCharms.Infrastructure.Migrations
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<string>("Author")
.IsRequired()
.HasColumnType("text");
b.Property<string>("CorrelationId") b.Property<string>("CorrelationId")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("CorrelationIdType") b.Property<int>("CorrelationIdType")
.IsRequired() .HasColumnType("integer");
.HasColumnType("text");
b.Property<DateTimeOffset>("CreatedAt") b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("text");
b.Property<int>("Direction") b.Property<int>("Direction")
.HasColumnType("integer"); .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") b.Property<bool>("IsInternal")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("boolean") .HasColumnType("boolean")
.HasDefaultValue(true); .HasDefaultValue(true);
b.Property<string>("Platform") b.Property<string>("Message")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("PlatformAddress") b.Property<int>("Platform")
.IsRequired() .HasColumnType("integer");
.HasColumnType("text");
b.Property<int>("Priority")
.HasColumnType("integer");
b.Property<bool>("Processed") b.Property<bool>("Processed")
.ValueGeneratedOnAdd() .ValueGeneratedOnAdd()
.HasColumnType("boolean") .HasColumnType("boolean")
.HasDefaultValue(false); .HasDefaultValue(false);
b.Property<string>("Title") b.Property<string>("Recipient")
.IsRequired() .IsRequired()
.HasColumnType("text"); .HasColumnType("text");
b.Property<string>("RecipientAddress")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Sender")
.IsRequired()
.HasColumnType("text");
b.Property<string>("SenderName")
.HasColumnType("text");
b.Property<string>("Subject")
.IsRequired()
.HasColumnType("text");
b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone");
b.HasKey("Id"); b.HasKey("Id");
b.ToTable("Notification", (string)null); b.ToTable("Notification", (string)null);
@@ -227,6 +252,9 @@ namespace LiteCharms.Infrastructure.Migrations
b.Property<Guid>("CustomerId") b.Property<Guid>("CustomerId")
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<bool>("DepositRequired")
.HasColumnType("boolean");
b.PrimitiveCollection<string>("Notes") b.PrimitiveCollection<string>("Notes")
.HasColumnType("jsonb"); .HasColumnType("jsonb");
@@ -236,12 +264,18 @@ namespace LiteCharms.Infrastructure.Migrations
b.Property<Guid?>("RefundId") b.Property<Guid?>("RefundId")
.HasColumnType("uuid"); .HasColumnType("uuid");
b.PrimitiveCollection<string>("Requirements")
.HasColumnType("jsonb");
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.PrimitiveCollection<string>("Terms")
.HasColumnType("jsonb");
b.Property<DateTimeOffset?>("UpdatedAt") b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnUpdate() .ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
@@ -288,6 +322,72 @@ namespace LiteCharms.Infrastructure.Migrations
b.ToTable("OrderRefund", (string)null); b.ToTable("OrderRefund", (string)null);
}); });
modelBuilder.Entity("LiteCharms.Entities.Package", 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 => modelBuilder.Entity("LiteCharms.Entities.Product", b =>
{ {
b.Property<Guid>("Id") b.Property<Guid>("Id")
@@ -375,8 +475,8 @@ namespace LiteCharms.Infrastructure.Migrations
b.Property<int>("Status") b.Property<int>("Status")
.HasColumnType("integer"); .HasColumnType("integer");
b.Property<DateTimeOffset>("UpdatedAt") b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnAddOrUpdate() .ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.HasKey("Id"); b.HasKey("Id");
@@ -410,8 +510,8 @@ namespace LiteCharms.Infrastructure.Migrations
b.Property<Guid?>("QuoteId") b.Property<Guid?>("QuoteId")
.HasColumnType("uuid"); .HasColumnType("uuid");
b.Property<DateTimeOffset>("UpdatedAt") b.Property<DateTimeOffset?>("UpdatedAt")
.ValueGeneratedOnAddOrUpdate() .ValueGeneratedOnUpdate()
.HasColumnType("timestamp with time zone"); .HasColumnType("timestamp with time zone");
b.HasKey("Id"); b.HasKey("Id");
@@ -451,6 +551,31 @@ namespace LiteCharms.Infrastructure.Migrations
b.ToTable("ShoppingCartItems"); b.ToTable("ShoppingCartItems");
}); });
modelBuilder.Entity("LiteCharms.Entities.ShoppingCartPackage", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<DateTimeOffset>("CreatedAt")
.ValueGeneratedOnAdd()
.HasColumnType("timestamp with time zone");
b.Property<Guid>("PackageId")
.HasColumnType("uuid");
b.Property<Guid>("ShoppingCartId")
.HasColumnType("uuid");
b.HasKey("Id");
b.HasIndex("PackageId");
b.HasIndex("ShoppingCartId");
b.ToTable("ShoppingCartPackage", (string)null);
});
modelBuilder.Entity("LiteCharms.Entities.Lead", b => modelBuilder.Entity("LiteCharms.Entities.Lead", b =>
{ {
b.HasOne("LiteCharms.Entities.Customer", "Customer") b.HasOne("LiteCharms.Entities.Customer", "Customer")
@@ -498,6 +623,28 @@ namespace LiteCharms.Infrastructure.Migrations
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 =>
{
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 => modelBuilder.Entity("LiteCharms.Entities.ProductPrice", b =>
{ {
b.HasOne("LiteCharms.Entities.Product", "Product") b.HasOne("LiteCharms.Entities.Product", "Product")
@@ -561,6 +708,25 @@ namespace LiteCharms.Infrastructure.Migrations
b.Navigation("ShoppingCart"); b.Navigation("ShoppingCart");
}); });
modelBuilder.Entity("LiteCharms.Entities.ShoppingCartPackage", b =>
{
b.HasOne("LiteCharms.Entities.Package", "Package")
.WithMany()
.HasForeignKey("PackageId")
.OnDelete(DeleteBehavior.NoAction)
.IsRequired();
b.HasOne("LiteCharms.Entities.ShoppingCart", "ShoppingCart")
.WithMany()
.HasForeignKey("ShoppingCartId")
.OnDelete(DeleteBehavior.NoAction)
.IsRequired();
b.Navigation("Package");
b.Navigation("ShoppingCart");
});
modelBuilder.Entity("LiteCharms.Entities.Customer", b => modelBuilder.Entity("LiteCharms.Entities.Customer", b =>
{ {
b.Navigation("Leads"); b.Navigation("Leads");
@@ -577,6 +743,11 @@ namespace LiteCharms.Infrastructure.Migrations
b.Navigation("Refund"); b.Navigation("Refund");
}); });
modelBuilder.Entity("LiteCharms.Entities.Package", b =>
{
b.Navigation("PackageItems");
});
modelBuilder.Entity("LiteCharms.Entities.Product", b => modelBuilder.Entity("LiteCharms.Entities.Product", b =>
{ {
b.Navigation("ProductPrices"); b.Navigation("ProductPrices");
@@ -591,6 +762,8 @@ namespace LiteCharms.Infrastructure.Migrations
{ {
b.Navigation("Order"); b.Navigation("Order");
b.Navigation("Packages");
b.Navigation("Quote"); b.Navigation("Quote");
b.Navigation("ShoppingCartItems"); b.Navigation("ShoppingCartItems");
@@ -23,4 +23,10 @@ public class ShopDbContext(DbContextOptions<ShopDbContext> options) : DbContext(
public DbSet<ShoppingCart> ShoppingCarts { get; set; } public DbSet<ShoppingCart> ShoppingCarts { get; set; }
public DbSet<ShoppingCartItem> ShoppingCartItems { get; set; } public DbSet<ShoppingCartItem> ShoppingCartItems { get; set; }
public DbSet<Package> Packages { get; set; }
public DbSet<PackageItem> PackageItems { get; set; }
public DbSet<ShoppingCartPackage> ShoppingCartPackages { get; set; }
} }
@@ -89,10 +89,11 @@
<ProjectReference Include="..\LiteCharms.Models\LiteCharms.Models.csproj" /> <ProjectReference Include="..\LiteCharms.Models\LiteCharms.Models.csproj" />
</ItemGroup> </ItemGroup>
<!-- Global Usings --> <!-- Global Shared Usings -->
<ItemGroup> <ItemGroup>
<Using Include="System.Text.Json" /> <Using Include="System.Text.Json" />
<Using Include="Microsoft.Extensions.Hosting" /> <Using Include="Microsoft.Extensions.Hosting" />
<Using Include="Microsoft.Extensions.Logging" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -100,5 +101,9 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None> </None>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Database\Migrations\" />
</ItemGroup>
</Project> </Project>
@@ -2,11 +2,36 @@
namespace LiteCharms.Infrastructure.ServiceBus.Exchanges; namespace LiteCharms.Infrastructure.ServiceBus.Exchanges;
public class EmailExchange(EmailQueue messages) : BackgroundService public class EmailExchange(EmailQueue messages, ILogger<EmailExchange> logger, IPublisher mediator) : BackgroundService
{ {
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
if(messages.Incoming.CanCount) while (!stoppingToken.IsCancellationRequested)
{
while (messages.Incoming.TryRead(out var message))
{
try
{
switch (message.Name)
{
case "SendShopEmailEnquiryEvent":
await mediator.Publish(message, stoppingToken);
break;
case "ProcessEmailNotificationsEvent":
await mediator.Publish(message, stoppingToken);
break;
default:
logger.LogWarning("Unsupported email event {Event}", message.Name);
break;
}
}
catch (Exception ex)
{
logger.LogError(ex, ex.Message);
}
}
await Task.Delay(1000, stoppingToken); await Task.Delay(1000, stoppingToken);
}
} }
} }
+31
View File
@@ -1,5 +1,36 @@
namespace LiteCharms.Models; namespace LiteCharms.Models;
public enum CorrelationIdTypes : int
{
None = 0,
Email = 1,
Discord = 2,
Slack = 3,
Whatsapp = 4,
Customer = 5,
Order = 6,
Refund = 7,
Lead = 8,
Quote = 9,
LinkedIn = 10
}
public enum Priorities : int
{
Low = 0,
Medium = 1,
High = 2,
}
public enum NotificationPlatforms : int
{
Email = 1,
Discord = 2,
Slack = 3,
WhatsApp = 4,
System = 5
}
public enum QuoteStatus : int public enum QuoteStatus : int
{ {
Draft = 0, Draft = 0,
+20 -6
View File
@@ -6,23 +6,37 @@ public class Notification
public DateTimeOffset CreatedAt { get; set; } public DateTimeOffset CreatedAt { get; set; }
public DateTimeOffset? UpdatedAt { get; set; }
public NotificationDirection Direction { get; set; } public NotificationDirection Direction { get; set; }
public string? Author { get; set; } public NotificationPlatforms Platform { get; set; }
public string? Title { get; set; } public Priorities Priority { get; set; }
public string? Description { get; set; } public CorrelationIdTypes CorrelationIdType { get; set; }
public string? Platform { get; set; } public string? Sender { get; set; }
public string? PlatformAddress { get; set; } public string? SenderName { get; set; }
public string? Subject { get; set; }
public string? Message { get; set; }
public string? Recipient { get; set; }
public string? RecipientAddress { get; set; }
public string? CorrelationId { get; set; } public string? CorrelationId { get; set; }
public string? CorrelationIdType { get; set; } public bool IsHtml { get; set; }
public bool IsInternal { get; set; } public bool IsInternal { get; set; }
public bool Processed { get; set; } public bool Processed { get; set; }
public bool HasError { get; set; }
public string[]? Errors { get; set; }
} }
+7 -1
View File
@@ -12,11 +12,17 @@ public class Order
public Guid? QuoteId { get; set; } public Guid? QuoteId { get; set; }
public Guid ShoppingCartId { get; set; } public Guid ShoppingCartId { get; set; }
public Guid? RefundId { get; set; } public Guid? RefundId { get; set; }
public OrderStatus Status { get; set; } public OrderStatus Status { get; set; }
public string[]? Requirements { get; set; }
public string[]? Notes { get; set; } public string[]? Notes { get; set; }
public string[]? Terms { get; set; }
public bool DepositRequired { get; set; }
} }
+16
View File
@@ -0,0 +1,16 @@
namespace LiteCharms.Models;
public class Package
{
public Guid Id { get; set; }
public DateTimeOffset CreatedAt { get; set; }
public DateTimeOffset? UpdatedAt { get; set; }
public string? Name { get; set; }
public string? Description { get; set; }
public bool Active { get; set; }
}
+14
View File
@@ -0,0 +1,14 @@
namespace LiteCharms.Models;
public class PackageItem
{
public Guid Id { get; set; }
public Guid PackageId { get; set; }
public Guid ProductPriceId { get; set; }
public DateTimeOffset CreatedAt { get; set; }
public bool Active { get; set; }
}
+12
View File
@@ -0,0 +1,12 @@
namespace LiteCharms.Models;
public class ShoppingCartPackage
{
public Guid Id { get; set; }
public DateTimeOffset CreatedAt { get; set; }
public Guid ShoppingCartId { get; set; }
public Guid PackageId { get; set; }
}
-7
View File
@@ -1,13 +1,6 @@
<Solution> <Solution>
<Folder Name="/Solution Items/"> <Folder Name="/Solution Items/">
<File Path=".drone.yml" /> <File Path=".drone.yml" />
<File Path=".editorconfig" />
<File Path=".gitattributes" />
<File Path=".gitignore" />
<File Path="icon.png" />
<File Path="LICENSE" />
<File Path="LiteCharms.snk" />
<File Path="README.md" />
</Folder> </Folder>
<Project Path="LiteCharms.Abstractions/LiteCharms.Abstractions.csproj" Id="e080e621-5394-4260-a793-d54178401942" /> <Project Path="LiteCharms.Abstractions/LiteCharms.Abstractions.csproj" Id="e080e621-5394-4260-a793-d54178401942" />
<Project Path="LiteCharms.Entities/LiteCharms.Entities.csproj" /> <Project Path="LiteCharms.Entities/LiteCharms.Entities.csproj" />