Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7743c3178e | |||
| da141311ff | |||
| ab3d8e6e9a | |||
| 97bde73777 | |||
| db4c348288 | |||
| a65e926a53 | |||
| 6683234642 | |||
| 1471d9e597 | |||
| 6ddbb9479a | |||
| e978aa17f8 | |||
| 6c7349a0f8 | |||
| a31f75c5ef | |||
| e97fd6cd3f | |||
| 7f4246ac63 | |||
| 184c7c252a | |||
| dfc62c8fe1 | |||
| bfe8c458d6 | |||
| 0f91f102e5 | |||
| e6e0475db1 | |||
| be9c83c8a3 | |||
| 65687d231e | |||
| 5090c60797 | |||
| 4523ef6151 |
+1
-1
@@ -41,7 +41,7 @@ steps:
|
||||
\"tag_name\": \"$VERSION\",
|
||||
\"target_commitish\": \"${DRONE_COMMIT_SHA}\",
|
||||
\"name\": \"Library Suite $VERSION\",
|
||||
\"body\": \"### Published NuGet Packages\nAll packages versioned as **$VERSION**:\n* LiteCharms.Abstractions\n* LiteCharms.Features\n\n[View in Nexus](https://nexus.khongisa.co.za/repository/nuget-group/)\",
|
||||
\"body\": \"### Published NuGet Packages\nAll packages versioned as **$VERSION**:\n* LiteCharms.Features\n\n[View in Nexus](https://nexus.khongisa.co.za/repository/nuget-group/)\",
|
||||
\"draft\": false,
|
||||
\"prerelease\": false
|
||||
}"
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using LiteCharms.Features.Shop.Notifications;
|
||||
using LiteCharms.Features.Models;
|
||||
using LiteCharms.Features.Shop.Notifications;
|
||||
using LiteCharms.Features.Shop.Notifications.Events;
|
||||
|
||||
namespace LiteCharms.Features.Tests;
|
||||
|
||||
@@ -32,4 +34,31 @@ public class NotificationsFeatureTests(CommonFixture fixture, ITestOutputHelper
|
||||
|
||||
foreach (var error in createResult.Errors) output.WriteLine(error.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetNotifications_ShouldReturn_AllNotifications()
|
||||
{
|
||||
DateRange range = new()
|
||||
{
|
||||
From = DateOnly.FromDateTime(new DateTime(2026, 04, 01, 0, 0, 0, DateTimeKind.Utc)),
|
||||
To = DateOnly.FromDateTime(DateTime.UtcNow),
|
||||
MaxRecords = 10
|
||||
};
|
||||
|
||||
var getResult = await notificationService.GetNotificationsAsync(range);
|
||||
|
||||
Assert.True(getResult.IsSuccess);
|
||||
|
||||
foreach (var error in getResult.Errors) output.WriteLine(error.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ProcessEmailNotificationsEvent_ShouldSucceed()
|
||||
{
|
||||
var notification = ProcessEmailNotificationsEvent.Create();
|
||||
|
||||
await fixture.Mediator.Publish(notification);
|
||||
|
||||
Assert.True(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,8 +35,9 @@ public class EmailService(IOptions<SmtpSettings> options) : IDisposable
|
||||
|
||||
var bodyBuilder = new BodyBuilder();
|
||||
|
||||
foreach (var attachment in message.Body?.Attachments!)
|
||||
bodyBuilder.Attachments.Add(attachment.Name!, attachment.FileStream!, cancellationToken);
|
||||
if (message.Body!.Properties.HasAttachments)
|
||||
foreach (var attachment in message.Body?.Attachments!)
|
||||
bodyBuilder.Attachments.Add(attachment.Name!, attachment.FileStream!, cancellationToken);
|
||||
|
||||
if (!message.Body.Properties.IsHtml) bodyBuilder.TextBody = message.Body.Message;
|
||||
if (message.Body.Properties.IsHtml) bodyBuilder.HtmlBody = message.Body.Message;
|
||||
|
||||
@@ -34,7 +34,7 @@ public static class Quartz
|
||||
storage.UseClustering(cluster =>
|
||||
{
|
||||
cluster.CheckinInterval = TimeSpan.FromSeconds(30);
|
||||
cluster.CheckinMisfireThreshold = TimeSpan.FromSeconds(2);
|
||||
cluster.CheckinMisfireThreshold = TimeSpan.FromSeconds(90);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -48,6 +48,8 @@ public static class Quartz
|
||||
|
||||
services.ConfigureCommon();
|
||||
|
||||
services.AddQuartzHostedService(options => options.WaitForJobsToComplete = true);
|
||||
|
||||
services.AddQuartz(config =>
|
||||
{
|
||||
config.SchedulerName = schedulerName;
|
||||
@@ -60,6 +62,8 @@ public static class Quartz
|
||||
config.UseDefaultThreadPool(options => options.MaxConcurrency = 1);
|
||||
config.UseTimeZoneConverter();
|
||||
|
||||
config.SetProperty("quartz.jobStore.misfireThreshold", TimeSpan.FromMinutes(2).TotalMilliseconds.ToString());
|
||||
|
||||
config.UsePersistentStore(storage =>
|
||||
{
|
||||
storage.PerformSchemaValidation = false;
|
||||
@@ -72,7 +76,7 @@ public static class Quartz
|
||||
storage.UseClustering(cluster =>
|
||||
{
|
||||
cluster.CheckinInterval = TimeSpan.FromSeconds(30);
|
||||
cluster.CheckinMisfireThreshold = TimeSpan.FromSeconds(2);
|
||||
cluster.CheckinMisfireThreshold = TimeSpan.FromSeconds(90);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -86,14 +90,14 @@ public static class Quartz
|
||||
{
|
||||
options.Scheduling.IgnoreDuplicates = true;
|
||||
options.Scheduling.OverWriteExistingData = true;
|
||||
|
||||
options["quartz.plugin.jobHistory.type"] = "Quartz.Plugin.History.LoggingJobHistoryPlugin, Quartz.Plugins";
|
||||
options["quartz.plugin.triggerHistory.type"] = "Quartz.Plugin.History.LoggingTriggerHistoryPlugin, Quartz.Plugins";
|
||||
});
|
||||
|
||||
services.AddTransient<RetryJobListener>();
|
||||
services.AddTransient<IJobOrchestrator, JobOrchestrator>();
|
||||
services.AddQuartzHostedService(options => options.WaitForJobsToComplete = true);
|
||||
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using LiteCharms.Features.Abstractions;
|
||||
using LiteCharms.Features.Quartz.Abstractions;
|
||||
using static LiteCharms.Features.Extensions.Timezones;
|
||||
|
||||
namespace LiteCharms.Features.Quartz;
|
||||
|
||||
@@ -47,13 +46,13 @@ public class JobOrchestrator(ISchedulerFactory schedulerFactory) : IJobOrchestra
|
||||
.StoreDurably()
|
||||
.Build();
|
||||
|
||||
var now = SouthAfricanTimeZone.UtcNow();
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
var trigger = global::Quartz.TriggerBuilder.Create()
|
||||
.WithIdentity(triggerKey)
|
||||
.WithDescription($"Scheduled via Main Job at {now:g}")
|
||||
.WithCronSchedule(cronExpression, cron => cron.InTimeZone(SouthAfricanTimeZone)
|
||||
.WithMisfireHandlingInstructionFireAndProceed())
|
||||
.WithCronSchedule(cronExpression, cron => cron
|
||||
.WithMisfireHandlingInstructionIgnoreMisfires())
|
||||
.StartAt(now)
|
||||
.Build();
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using LiteCharms.Features.Abstractions;
|
||||
using LiteCharms.Features.Mediator;
|
||||
|
||||
namespace LiteCharms.Features.Quartz;
|
||||
|
||||
@@ -9,13 +10,28 @@ public class MediatorJob<TNotification>(IMediator mediator) : IJob where TNotifi
|
||||
{
|
||||
var data = context.MergedJobDataMap["Payload"] as string;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(data)) return;
|
||||
if (string.IsNullOrWhiteSpace(data))
|
||||
{
|
||||
Trace.WriteLine("Job Payload missing, job ended");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var notification = JsonSerializer.Deserialize<TNotification>(data);
|
||||
|
||||
if(notification is null) return;
|
||||
if (notification is null)
|
||||
{
|
||||
Trace.WriteLine("Notification could not be JSon converted from data string, job ended");
|
||||
|
||||
if(notification is TNotification)
|
||||
await mediator.Publish(notification, context.CancellationToken);
|
||||
return;
|
||||
}
|
||||
|
||||
using var activity = MediatorTelemetry.Source.StartActivity($"Quartz: {typeof(TNotification).Name}");
|
||||
|
||||
activity?.SetTag("event.correlation_id", notification.CorrelationId);
|
||||
|
||||
await mediator.Publish(notification, context.CancellationToken);
|
||||
|
||||
Trace.WriteLine("Job published");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@ public class PackageService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||
|
||||
var newPackage = context.Packages.Add(new Entities.Package
|
||||
{
|
||||
UpdatedAt = null,
|
||||
Name = name,
|
||||
Summary = summary,
|
||||
Description = description,
|
||||
@@ -206,7 +205,7 @@ public class PackageService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||
package.Summary = summary;
|
||||
package.Description = description;
|
||||
package.ImageUrl = ImageUrl;
|
||||
package.UpdatedAt = SouthAfricanTimeZone.UtcNow();
|
||||
package.UpdatedAt = DateTime.UtcNow;
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
? Result.Ok()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using LiteCharms.Features.Shop.Customers.Models;
|
||||
using LiteCharms.Features.Shop.Customers.Entities;
|
||||
|
||||
namespace LiteCharms.Features.Shop.Leads.Entities;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ public class LeadConfiguration : IEntityTypeConfiguration<Lead>
|
||||
builder.Property(f => f.AttributionHash).IsRequired(true);
|
||||
|
||||
builder.HasOne(f => f.Customer)
|
||||
.WithMany()
|
||||
.WithMany(f => f.Leads)
|
||||
.HasForeignKey(f => f.CustomerId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ public class LeadService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||
return Result.Fail(new Error($"Lead with ID {leadId} not found."));
|
||||
|
||||
lead.Status = status;
|
||||
lead.UpdatedAt = DateTime.UtcNow;
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
? Result.Ok()
|
||||
|
||||
+17
-10
@@ -1,7 +1,7 @@
|
||||
using LiteCharms.Features.Email;
|
||||
using LiteCharms.Features.Shop.Notifications.Entities;
|
||||
using k8s.KubeConfigModels;
|
||||
using LiteCharms.Features.Email;
|
||||
using LiteCharms.Features.Shop.Notifications.Models;
|
||||
using LiteCharms.Features.Shop.Postgres;
|
||||
using static LiteCharms.Features.Extensions.Timezones;
|
||||
|
||||
namespace LiteCharms.Features.Shop.Notifications.Events.Handlers;
|
||||
|
||||
@@ -16,17 +16,20 @@ public class ProcessEmailNotificationsEventHandler(IDbContextFactory<ShopDbConte
|
||||
{
|
||||
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
if (emailService.Status != EmailStatuses.Connected)
|
||||
await emailService.ConnectAsync(cancellationToken);
|
||||
|
||||
var notifications = await context.Notifications
|
||||
.OrderByDescending(o => o.Priority)
|
||||
.ThenBy(o => o.CreatedAt)
|
||||
.Where(n => n.CorrelationIdType == CorrelationIdTypes.Email)
|
||||
.Where(n => n.Direction == NotificationDirection.Outgoing)
|
||||
.OrderByDescending(o => o.CreatedAt)
|
||||
.ThenBy(o => o.Priority)
|
||||
.Where(n => n.Platform == NotificationPlatforms.Email &&
|
||||
n.Direction == NotificationDirection.Outgoing && n.Processed == false)
|
||||
.Take(message.MaxRecords)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
foreach (var notification in notifications)
|
||||
{
|
||||
if (dropBatch || cancellationToken.IsCancellationRequested) break;
|
||||
if (dropBatch) break;
|
||||
|
||||
var sendResult = await SendEmailAsync(notification,emailService, cancellationToken);
|
||||
|
||||
@@ -44,15 +47,19 @@ public class ProcessEmailNotificationsEventHandler(IDbContextFactory<ShopDbConte
|
||||
}
|
||||
|
||||
notification.Processed = true;
|
||||
notification.UpdatedAt = SouthAfricanTimeZone.UtcNow();
|
||||
notification.UpdatedAt = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
await context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await emailService.DisconnectAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<Result> SendEmailAsync(Notification notification, EmailService service, CancellationToken cancellationToken = default)
|
||||
|
||||
@@ -8,6 +8,8 @@ public class ProcessEmailNotificationsEvent : EventBase, IEvent
|
||||
|
||||
public int MaxRecords { get; set; }
|
||||
|
||||
public ProcessEmailNotificationsEvent() { MaxRecords = 1000; }
|
||||
|
||||
private ProcessEmailNotificationsEvent(int maxRecords = 1000) => MaxRecords = maxRecords;
|
||||
|
||||
public static ProcessEmailNotificationsEvent Create(int maxRecords = 1000) => new(maxRecords);
|
||||
|
||||
@@ -63,8 +63,8 @@ public class NotificationService(IDbContextFactory<ShopDbContext> contextFactory
|
||||
{
|
||||
try
|
||||
{
|
||||
var fromDate = range.From.ToDateTime(TimeOnly.MinValue);
|
||||
var toDate = range.To.ToDateTime(TimeOnly.MaxValue);
|
||||
var fromDate = range.From.ToDateTime(TimeOnly.MinValue, DateTimeKind.Utc);
|
||||
var toDate = range.To.ToDateTime(TimeOnly.MaxValue, DateTimeKind.Utc);
|
||||
|
||||
using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
@@ -96,12 +96,9 @@ public class NotificationService(IDbContextFactory<ShopDbContext> contextFactory
|
||||
return Result.Fail(new Error($"Notification with id {request.NotificationId} not found."));
|
||||
|
||||
notification.Processed = request.Processed;
|
||||
|
||||
if (request.HasError)
|
||||
{
|
||||
notification.HasError = request.HasError;
|
||||
notification.Errors = request.Errors;
|
||||
}
|
||||
notification.UpdatedAt = DateTime.UtcNow;
|
||||
notification.HasError = request.HasError;
|
||||
notification.Errors = request.Errors;
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
? Result.Ok()
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using LiteCharms.Features.Models;
|
||||
using LiteCharms.Features.Shop.Orders.Models;
|
||||
using LiteCharms.Features.Shop.Postgres;
|
||||
using static LiteCharms.Features.Extensions.Timezones;
|
||||
|
||||
namespace LiteCharms.Features.Shop.Orders;
|
||||
|
||||
@@ -241,7 +240,7 @@ public class OrderService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||
return Result.Fail(new Error($"Order {request.OrderId} not found"));
|
||||
|
||||
order.Status = request.Status;
|
||||
order.UpdatedAt = SouthAfricanTimeZone.UtcNow();
|
||||
order.UpdatedAt = DateTime.UtcNow;
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(request.InvoiceUrl)) order.InvoiceUrl = request.InvoiceUrl;
|
||||
|
||||
|
||||
+776
@@ -0,0 +1,776 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using LiteCharms.Features.Shop.Postgres;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace LiteCharms.Features.Shop.Postgres.Migrations
|
||||
{
|
||||
[DbContext(typeof(ShopDbContext))]
|
||||
[Migration("20260515055221_FixedLeadCustomerRelationship")]
|
||||
partial class FixedLeadCustomerRelationship
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "10.0.8")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.Package", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("Active")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<string>("ImageUrl")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.IsRequired()
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Package", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.PackageItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("Active")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<DateTimeOffset>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<Guid>("PackageId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("ProductPriceId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PackageId");
|
||||
|
||||
b.HasIndex("ProductPriceId");
|
||||
|
||||
b.ToTable("PackageItem", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Customers.Entities.Customer", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("Active")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(true);
|
||||
|
||||
b.Property<string>("Address")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("City")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Company")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Country")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<string>("Discord")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("LinkedIn")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Phone")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("PostalCode")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Region")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Slack")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Tax")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Website")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Whatsapp")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Customers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Leads.Entities.Lead", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long?>("AdGroupId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<long?>("AdName")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("AppClickId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("AttributionHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<long?>("CampaignId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("ClickId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ClickLocation")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<Guid?>("CustomerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long?>("FeedItemId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("Source")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<long?>("TargetId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("WebClickId")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CustomerId");
|
||||
|
||||
b.ToTable("Leads", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Notifications.Entities.Notification", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("CorrelationId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("CorrelationIdType")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<int>("Direction")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.PrimitiveCollection<string>("Errors")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<bool>("HasError")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false);
|
||||
|
||||
b.Property<bool>("IsHtml")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false);
|
||||
|
||||
b.Property<bool>("IsInternal")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(true);
|
||||
|
||||
b.Property<string>("Message")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Platform")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("Priority")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<bool>("Processed")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(false);
|
||||
|
||||
b.Property<string>("RecipientAddress")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("RecipientName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("SenderAddress")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("SenderName")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Subject")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Notification", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.Order", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<Guid>("CustomerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("InvoiceUrl")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.PrimitiveCollection<string>("Notes")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.PrimitiveCollection<string>("Requirements")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.PrimitiveCollection<string>("Terms")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CustomerId");
|
||||
|
||||
b.ToTable("Orders", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.OrderRefund", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<decimal>("Amount")
|
||||
.HasPrecision(18, 2)
|
||||
.HasColumnType("numeric(18,2)");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<Guid>("OrderId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Reason")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OrderId");
|
||||
|
||||
b.ToTable("OrderRefunds", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.Product", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("Active")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("boolean")
|
||||
.HasDefaultValue(true);
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<string>("ImageUrl")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.IsRequired()
|
||||
.HasMaxLength(512)
|
||||
.HasColumnType("character varying(512)");
|
||||
|
||||
b.PrimitiveCollection<string>("Thumbnails")
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Products", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.ProductPrice", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("Active")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<decimal>("Discount")
|
||||
.HasPrecision(18, 2)
|
||||
.HasColumnType("numeric(18,2)");
|
||||
|
||||
b.Property<decimal>("Price")
|
||||
.HasPrecision(18, 2)
|
||||
.HasColumnType("numeric(18,2)");
|
||||
|
||||
b.Property<Guid>("ProductId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ProductId");
|
||||
|
||||
b.ToTable("ProductPrices", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Quotes.Entities.Quote", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<Guid>("CustomerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime?>("ExpiredAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("InvoiceUrl")
|
||||
.HasMaxLength(2048)
|
||||
.HasColumnType("character varying(2048)");
|
||||
|
||||
b.Property<Guid?>("OrderId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Reason")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("ShoppingCartId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CustomerId");
|
||||
|
||||
b.HasIndex("OrderId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("ShoppingCartId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("Quotes", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<Guid>("CustomerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("OrderId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CustomerId");
|
||||
|
||||
b.HasIndex("OrderId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("ShoppingCarts", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartItem", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<Guid>("ProductPriceId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Quantity")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasDefaultValue(1);
|
||||
|
||||
b.Property<Guid>("ShoppingCartId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ProductPriceId");
|
||||
|
||||
b.HasIndex("ShoppingCartId");
|
||||
|
||||
b.ToTable("ShoppingCartItems", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartPackage", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<Guid>("PackageId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("ShoppingCartId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("PackageId");
|
||||
|
||||
b.HasIndex("ShoppingCartId");
|
||||
|
||||
b.ToTable("ShoppingCartPackages", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.PackageItem", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.Shop.CartPackages.Entities.Package", "Package")
|
||||
.WithMany("PackageItems")
|
||||
.HasForeignKey("PackageId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LiteCharms.Features.Shop.Products.Entities.ProductPrice", "ProductPrice")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProductPriceId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Package");
|
||||
|
||||
b.Navigation("ProductPrice");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Leads.Entities.Lead", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||
.WithMany("Leads")
|
||||
.HasForeignKey("CustomerId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.Navigation("Customer");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.Order", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||
.WithMany("Orders")
|
||||
.HasForeignKey("CustomerId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Customer");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.OrderRefund", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.Shop.Orders.Entities.Order", "Order")
|
||||
.WithMany("Refunds")
|
||||
.HasForeignKey("OrderId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Order");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.ProductPrice", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.Shop.Products.Entities.Product", "Product")
|
||||
.WithMany("ProductPrices")
|
||||
.HasForeignKey("ProductId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Quotes.Entities.Quote", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||
.WithMany("Quotes")
|
||||
.HasForeignKey("CustomerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LiteCharms.Features.Shop.Orders.Entities.Order", "Order")
|
||||
.WithOne("Quote")
|
||||
.HasForeignKey("LiteCharms.Features.Shop.Quotes.Entities.Quote", "OrderId");
|
||||
|
||||
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||
.WithOne("Quote")
|
||||
.HasForeignKey("LiteCharms.Features.Shop.Quotes.Entities.Quote", "ShoppingCartId");
|
||||
|
||||
b.Navigation("Customer");
|
||||
|
||||
b.Navigation("Order");
|
||||
|
||||
b.Navigation("ShoppingCart");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||
.WithMany("ShoppingCarts")
|
||||
.HasForeignKey("CustomerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LiteCharms.Features.Shop.Orders.Entities.Order", "Order")
|
||||
.WithOne("ShoppingCart")
|
||||
.HasForeignKey("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "OrderId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.Navigation("Customer");
|
||||
|
||||
b.Navigation("Order");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartItem", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.Shop.Products.Entities.ProductPrice", "ProductPrice")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProductPriceId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||
.WithMany("ShoppingCartItems")
|
||||
.HasForeignKey("ShoppingCartId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("ProductPrice");
|
||||
|
||||
b.Navigation("ShoppingCart");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartPackage", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.Shop.CartPackages.Entities.Package", "Package")
|
||||
.WithMany()
|
||||
.HasForeignKey("PackageId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||
.WithMany("ShoppingCartPackages")
|
||||
.HasForeignKey("ShoppingCartId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Package");
|
||||
|
||||
b.Navigation("ShoppingCart");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.CartPackages.Entities.Package", b =>
|
||||
{
|
||||
b.Navigation("PackageItems");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Customers.Entities.Customer", b =>
|
||||
{
|
||||
b.Navigation("Leads");
|
||||
|
||||
b.Navigation("Orders");
|
||||
|
||||
b.Navigation("Quotes");
|
||||
|
||||
b.Navigation("ShoppingCarts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Orders.Entities.Order", b =>
|
||||
{
|
||||
b.Navigation("Quote");
|
||||
|
||||
b.Navigation("Refunds");
|
||||
|
||||
b.Navigation("ShoppingCart");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Products.Entities.Product", b =>
|
||||
{
|
||||
b.Navigation("ProductPrices");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", b =>
|
||||
{
|
||||
b.Navigation("Quote");
|
||||
|
||||
b.Navigation("ShoppingCartItems");
|
||||
|
||||
b.Navigation("ShoppingCartPackages");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace LiteCharms.Features.Shop.Postgres.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class FixedLeadCustomerRelationship : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Leads_Customer_CustomerId",
|
||||
table: "Leads");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Leads_Customers_CustomerId1",
|
||||
table: "Leads");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_ShoppingCartItems_ProductPrices_ProductPriceId1",
|
||||
table: "ShoppingCartItems");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_ShoppingCartItems_ShoppingCarts_ShoppingCartId1",
|
||||
table: "ShoppingCartItems");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Customer");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_ShoppingCartItems_ProductPriceId1",
|
||||
table: "ShoppingCartItems");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_ShoppingCartItems_ShoppingCartId1",
|
||||
table: "ShoppingCartItems");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Leads_CustomerId1",
|
||||
table: "Leads");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ProductPriceId1",
|
||||
table: "ShoppingCartItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ShoppingCartId1",
|
||||
table: "ShoppingCartItems");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "CustomerId1",
|
||||
table: "Leads");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Leads_Customers_CustomerId",
|
||||
table: "Leads",
|
||||
column: "CustomerId",
|
||||
principalTable: "Customers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Leads_Customers_CustomerId",
|
||||
table: "Leads");
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "ProductPriceId1",
|
||||
table: "ShoppingCartItems",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "ShoppingCartId1",
|
||||
table: "ShoppingCartItems",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "CustomerId1",
|
||||
table: "Leads",
|
||||
type: "uuid",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Customer",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||
Active = table.Column<bool>(type: "boolean", nullable: false),
|
||||
Address = table.Column<string>(type: "text", nullable: true),
|
||||
City = table.Column<string>(type: "text", nullable: true),
|
||||
Company = table.Column<string>(type: "text", nullable: true),
|
||||
Country = table.Column<string>(type: "text", nullable: true),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
Discord = table.Column<string>(type: "text", nullable: true),
|
||||
Email = table.Column<string>(type: "text", nullable: true),
|
||||
LastName = table.Column<string>(type: "text", nullable: true),
|
||||
LinkedIn = table.Column<string>(type: "text", nullable: true),
|
||||
Name = table.Column<string>(type: "text", nullable: true),
|
||||
Phone = table.Column<string>(type: "text", nullable: true),
|
||||
PostalCode = table.Column<string>(type: "text", nullable: true),
|
||||
Region = table.Column<string>(type: "text", nullable: true),
|
||||
Slack = table.Column<string>(type: "text", nullable: true),
|
||||
Tax = table.Column<string>(type: "text", nullable: true),
|
||||
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||
Website = table.Column<string>(type: "text", nullable: true),
|
||||
Whatsapp = table.Column<string>(type: "text", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Customer", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ShoppingCartItems_ProductPriceId1",
|
||||
table: "ShoppingCartItems",
|
||||
column: "ProductPriceId1");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_ShoppingCartItems_ShoppingCartId1",
|
||||
table: "ShoppingCartItems",
|
||||
column: "ShoppingCartId1");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Leads_CustomerId1",
|
||||
table: "Leads",
|
||||
column: "CustomerId1");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Leads_Customer_CustomerId",
|
||||
table: "Leads",
|
||||
column: "CustomerId",
|
||||
principalTable: "Customer",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Leads_Customers_CustomerId1",
|
||||
table: "Leads",
|
||||
column: "CustomerId1",
|
||||
principalTable: "Customers",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_ShoppingCartItems_ProductPrices_ProductPriceId1",
|
||||
table: "ShoppingCartItems",
|
||||
column: "ProductPriceId1",
|
||||
principalTable: "ProductPrices",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_ShoppingCartItems_ShoppingCarts_ShoppingCartId1",
|
||||
table: "ShoppingCartItems",
|
||||
column: "ShoppingCartId1",
|
||||
principalTable: "ShoppingCarts",
|
||||
principalColumn: "Id");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -166,74 +166,6 @@ namespace LiteCharms.Features.Shop.Postgres.Migrations
|
||||
b.ToTable("Customers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Customers.Models.Customer", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("Active")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Address")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("City")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Company")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Country")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Discord")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("LinkedIn")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Phone")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("PostalCode")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Region")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Slack")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Tax")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Website")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Whatsapp")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Customer");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Leads.Entities.Lead", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -270,9 +202,6 @@ namespace LiteCharms.Features.Shop.Postgres.Migrations
|
||||
b.Property<Guid?>("CustomerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("CustomerId1")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<long?>("FeedItemId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
@@ -295,8 +224,6 @@ namespace LiteCharms.Features.Shop.Postgres.Migrations
|
||||
|
||||
b.HasIndex("CustomerId");
|
||||
|
||||
b.HasIndex("CustomerId1");
|
||||
|
||||
b.ToTable("Leads", (string)null);
|
||||
});
|
||||
|
||||
@@ -615,9 +542,6 @@ namespace LiteCharms.Features.Shop.Postgres.Migrations
|
||||
b.Property<Guid>("ProductPriceId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("ProductPriceId1")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<int>("Quantity")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
@@ -626,9 +550,6 @@ namespace LiteCharms.Features.Shop.Postgres.Migrations
|
||||
b.Property<Guid>("ShoppingCartId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid?>("ShoppingCartId1")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
@@ -636,12 +557,8 @@ namespace LiteCharms.Features.Shop.Postgres.Migrations
|
||||
|
||||
b.HasIndex("ProductPriceId");
|
||||
|
||||
b.HasIndex("ProductPriceId1");
|
||||
|
||||
b.HasIndex("ShoppingCartId");
|
||||
|
||||
b.HasIndex("ShoppingCartId1");
|
||||
|
||||
b.ToTable("ShoppingCartItems", (string)null);
|
||||
});
|
||||
|
||||
@@ -692,15 +609,11 @@ namespace LiteCharms.Features.Shop.Postgres.Migrations
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.Leads.Entities.Lead", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.Shop.Customers.Models.Customer", "Customer")
|
||||
.WithMany()
|
||||
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", "Customer")
|
||||
.WithMany("Leads")
|
||||
.HasForeignKey("CustomerId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.HasOne("LiteCharms.Features.Shop.Customers.Entities.Customer", null)
|
||||
.WithMany("Leads")
|
||||
.HasForeignKey("CustomerId1");
|
||||
|
||||
b.Navigation("Customer");
|
||||
});
|
||||
|
||||
@@ -780,26 +693,18 @@ namespace LiteCharms.Features.Shop.Postgres.Migrations
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCartItem", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.Shop.Products.Entities.ProductPrice", null)
|
||||
b.HasOne("LiteCharms.Features.Shop.Products.Entities.ProductPrice", "ProductPrice")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProductPriceId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LiteCharms.Features.Shop.Products.Entities.ProductPrice", "ProductPrice")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProductPriceId1");
|
||||
|
||||
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", null)
|
||||
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||
.WithMany("ShoppingCartItems")
|
||||
.HasForeignKey("ShoppingCartId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LiteCharms.Features.Shop.ShoppingCarts.Entities.ShoppingCart", "ShoppingCart")
|
||||
.WithMany()
|
||||
.HasForeignKey("ShoppingCartId1");
|
||||
|
||||
b.Navigation("ProductPrice");
|
||||
|
||||
b.Navigation("ShoppingCart");
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using LiteCharms.Features.Extensions;
|
||||
using LiteCharms.Features.Shop.Postgres;
|
||||
using LiteCharms.Features.Shop.Products.Models;
|
||||
using static LiteCharms.Features.Extensions.Timezones;
|
||||
|
||||
namespace LiteCharms.Features.Shop.Products;
|
||||
|
||||
@@ -19,7 +18,7 @@ public class ProductService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||
return Result.Fail($"Could not find product price with ID {productPriceId}");
|
||||
|
||||
price.Active = active;
|
||||
price.UpdatedAt = SouthAfricanTimeZone.UtcNow();
|
||||
price.UpdatedAt = DateTime.UtcNow;
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
? Result.Ok()
|
||||
@@ -200,7 +199,7 @@ public class ProductService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||
return Result.Fail($"Could not find product price with ID {productPriceId}");
|
||||
|
||||
existingPrice.Active = false;
|
||||
existingPrice.UpdatedAt = SouthAfricanTimeZone.UtcNow();
|
||||
existingPrice.UpdatedAt = DateTime.UtcNow;
|
||||
|
||||
if (!(await context.SaveChangesAsync(cancellationToken) > 0))
|
||||
return Result.Fail<Guid>($"Failed to deactivate existing price of ID {productPriceId}, try again later");
|
||||
@@ -212,7 +211,7 @@ public class ProductService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||
var deactivatedPrice = await context.ProductPrices.FirstOrDefaultAsync(p => p.Id == productPriceId, cancellationToken);
|
||||
|
||||
existingPrice.Active = true;
|
||||
existingPrice.UpdatedAt = SouthAfricanTimeZone.UtcNow();
|
||||
existingPrice.UpdatedAt = DateTime.UtcNow;
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
? Result.Fail<Guid>("Reverted to old price, creation of new price failed")
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using LiteCharms.Features.Models;
|
||||
using LiteCharms.Features.Shop.Postgres;
|
||||
using LiteCharms.Features.Shop.Quotes.Models;
|
||||
using static LiteCharms.Features.Extensions.Timezones;
|
||||
|
||||
namespace LiteCharms.Features.Shop.Quotes;
|
||||
|
||||
@@ -26,6 +25,7 @@ public class QuoteService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||
return Result.Fail(new Error($"Quote with id {quoteId} is already assigned to order with id {orderId}"));
|
||||
|
||||
quote.OrderId = orderId;
|
||||
quote.UpdatedAt = DateTime.UtcNow;
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
? Result.Ok()
|
||||
@@ -52,6 +52,7 @@ public class QuoteService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||
return Result.Fail(new Error($"Shopping Cart with id {shoppingCartId} not found"));
|
||||
|
||||
quote.ShoppingCartId = shoppingCartId;
|
||||
quote.UpdatedAt = DateTime.UtcNow;
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
? Result.Ok()
|
||||
@@ -140,7 +141,7 @@ public class QuoteService(IDbContextFactory<ShopDbContext> contextFactory)
|
||||
return Result.Fail(new Error("Quote not found."));
|
||||
|
||||
quote.Status = status;
|
||||
quote.UpdatedAt = SouthAfricanTimeZone.UtcNow();
|
||||
quote.UpdatedAt = DateTime.UtcNow;
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
? Result.Ok()
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using LiteCharms.Features.Shop.Products.Entities;
|
||||
|
||||
namespace LiteCharms.Features.Shop.ShoppingCarts.Entities;
|
||||
namespace LiteCharms.Features.Shop.ShoppingCarts.Entities;
|
||||
|
||||
public class ShoppingCartItemConfiguration : IEntityTypeConfiguration<ShoppingCartItem>
|
||||
{
|
||||
@@ -15,13 +13,13 @@ public class ShoppingCartItemConfiguration : IEntityTypeConfiguration<ShoppingCa
|
||||
builder.Property(f => f.ShoppingCartId).IsRequired();
|
||||
builder.Property(f => f.ProductPriceId).IsRequired();
|
||||
|
||||
builder.HasOne<ShoppingCart>()
|
||||
builder.HasOne(f => f.ShoppingCart)
|
||||
.WithMany(s => s.ShoppingCartItems)
|
||||
.HasForeignKey(f => f.ShoppingCartId)
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.HasOne<ProductPrice>()
|
||||
builder.HasOne(f => f.ProductPrice)
|
||||
.WithMany()
|
||||
.HasForeignKey(f => f.ProductPriceId)
|
||||
.IsRequired()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using LiteCharms.Features.Extensions;
|
||||
using LiteCharms.Features.Shop.Postgres;
|
||||
using LiteCharms.Features.Shop.ShoppingCarts.Models;
|
||||
using static LiteCharms.Features.Extensions.Timezones;
|
||||
|
||||
namespace LiteCharms.Features.Shop.ShoppingCarts;
|
||||
|
||||
@@ -284,7 +283,7 @@ public class ShoppingCartService(IDbContextFactory<ShopDbContext> contextFactory
|
||||
return Result.Fail($"Shopping cart item could not be found with id {shoppingCartItemId}");
|
||||
|
||||
item.Quantity = quantity;
|
||||
item.UpdatedAt = SouthAfricanTimeZone.UtcNow();
|
||||
item.UpdatedAt = DateTime.UtcNow;
|
||||
|
||||
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||
? Result.Ok()
|
||||
|
||||
Reference in New Issue
Block a user