Compare commits
47
Commits
0e21ec283d
..
1.52.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1977b6b301 | ||
|
|
0ab14d8b63 | ||
|
|
466458e230 | ||
|
|
141d32f591 | ||
|
|
d9e7f225ae | ||
|
|
6ae63e2ad1 | ||
|
|
f5efdde37c | ||
|
|
1592d5dc8f | ||
|
|
50a8a59d92 | ||
|
|
b70d9559b0 | ||
|
|
81d5e8f07c | ||
|
|
20a53942b5 | ||
|
|
9edb2aa4aa | ||
|
|
6ed023f2cf | ||
|
|
2c9f5a846c | ||
|
|
41f7c05be3 | ||
|
|
1a03355e84 | ||
|
|
7743c3178e | ||
|
|
ab3d8e6e9a | ||
|
|
db4c348288 | ||
|
|
6683234642 | ||
|
|
6ddbb9479a | ||
|
|
6c7349a0f8 | ||
|
|
e97fd6cd3f | ||
|
|
184c7c252a | ||
|
|
bfe8c458d6 | ||
|
|
e6e0475db1 | ||
|
|
5090c60797 | ||
|
|
9432252e15 | ||
|
|
47111a1a3a | ||
|
|
6eb3d50375 | ||
|
|
4deb732804 | ||
|
|
20d9387d0b | ||
|
|
9f6d0ccaa0 | ||
|
|
1acbc4d213 | ||
|
|
8c99668fac | ||
|
|
ad44f46204 | ||
|
|
49d999c1e3 | ||
|
|
9ed4777a18 | ||
|
|
0cf44f68cc | ||
|
|
41ed5a4288 | ||
|
|
bbcba5e06c | ||
|
|
502cc326dd | ||
|
|
4675d4c5fc | ||
|
|
f80bb2fff9 | ||
|
|
6767906b0d | ||
|
|
a344af4498 |
@@ -1,133 +0,0 @@
|
||||
using LiteCharms.Features.MidrandBooks.Categories;
|
||||
using LiteCharms.Features.MidrandBooks.Products;
|
||||
|
||||
namespace LiteCharms.Features.MidrandBooks.Seed;
|
||||
|
||||
public class CategorySeederService(CategoryService categoryService, ProductService productService, IFeatureManager features,
|
||||
ILogger<CategorySeederService> logger) : BackgroundService
|
||||
{
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
if (!await features.IsEnabledAsync("CategorySeederService")) return;
|
||||
|
||||
logger.LogInformation("Category and Product-Tag Mapping Seeding started (15-char limit applied)");
|
||||
|
||||
// Initialize Bogus to ensure repeatable distribution matrix pathing
|
||||
var faker = new Faker();
|
||||
Randomizer.Seed = new Random(101);
|
||||
|
||||
// 1. Curate Broad Book Categories (IsMain = true, Max 20, Max 15 chars)
|
||||
var broadMainCategories = new[]
|
||||
{
|
||||
"Fiction", "Non-Fiction", "Youth & Kids", "Academic",
|
||||
"Biographies", "Business", "Sci-Fi & Fantasy",
|
||||
"Thrillers", "Self-Help", "History",
|
||||
"Spirituality", "Arts & Photo", "Technology",
|
||||
"Cookbooks", "Travel & Maps", "Poetry & Drama", "Graphic Novels"
|
||||
};
|
||||
|
||||
// 2. Curate Niche Subcategories/Tags (IsMain = false, Max 15 chars)
|
||||
var specializedSubCategories = new[]
|
||||
{
|
||||
"Cyberpunk", "Space Opera", "Historical Fix", "Cozy Mystery", "True Crime",
|
||||
"Agile Project", "Software Eng", "AI & ML", "Cloud Comput",
|
||||
"SA History", "African Lit", "Apartheid Era", "Mandela Legacy",
|
||||
"Finance", "Investments", "Startup", "Leadership",
|
||||
"CBT Therapy", "Mindfulness", "Yoga & Health",
|
||||
"Baking Basics", "African Food", "Vegan Recipes",
|
||||
"Ancient World", "WWII History", "Geopolitics",
|
||||
"Writing Guides", "Criticism", "Classic Poetry",
|
||||
"Early Learning", "Teen Romance", "Survival",
|
||||
"Urban Fantasy", "Dark Fantasy", "Psych Thriller", "Hard Sci-Fi",
|
||||
"Data Science", "DevOps", "Cybersecurity",
|
||||
"Economics", "Real Estate", "Governance",
|
||||
"Essays", "Memoirs", "Art History",
|
||||
"Architecture", "Photography", "Travel Writing",
|
||||
"Gaming Culture", "Philosophy", "Ethics",
|
||||
"DIY Home", "SA Gardening", "Parenting"
|
||||
};
|
||||
|
||||
// 3. Seed Main Categories into the System
|
||||
logger.LogInformation("Seeding broad main categories...");
|
||||
foreach (var mainCat in broadMainCategories)
|
||||
{
|
||||
if (stoppingToken.IsCancellationRequested) return;
|
||||
|
||||
// Defensive truncation fallback just in case strings get modified later
|
||||
string safeName = mainCat.Length > 15 ? mainCat.Substring(0, 15) : mainCat;
|
||||
|
||||
var result = await categoryService.CreateCategoryAsync(safeName, isMain: true, stoppingToken);
|
||||
if (result.IsFailed && !result.Errors[0].Message.Contains("already exists", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
logger.LogWarning("Notice while adding main category '{Name}': {Msg}", safeName, result.Errors[0].Message);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Seed Subcategories into the System
|
||||
logger.LogInformation("Seeding boundless specialized niche tags...");
|
||||
foreach (var subCat in specializedSubCategories)
|
||||
{
|
||||
if (stoppingToken.IsCancellationRequested) return;
|
||||
|
||||
string safeName = subCat.Length > 15 ? subCat.Substring(0, 15) : subCat;
|
||||
|
||||
var result = await categoryService.CreateCategoryAsync(safeName, isMain: false, stoppingToken);
|
||||
if (result.IsFailed && !result.Errors[0].Message.Contains("already exists", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
logger.LogWarning("Notice while adding subcategory '{Name}': {Msg}", safeName, result.Errors[0].Message);
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Query back all enabled categories to extract active IDs for junction mapping
|
||||
var fetchMainResult = await categoryService.GetCategoriesAsync(isMain: true, stoppingToken);
|
||||
var fetchSubResult = await categoryService.GetCategoriesAsync(isMain: false, stoppingToken);
|
||||
|
||||
if (fetchMainResult.IsFailed || fetchSubResult.IsFailed)
|
||||
{
|
||||
logger.LogError("Aborting junction seeding: Could not retrieve categories from data store.");
|
||||
return;
|
||||
}
|
||||
|
||||
var mainCategoryIds = fetchMainResult.Value.Select(c => c.Id).ToArray();
|
||||
var subCategoryIds = fetchSubResult.Value.Select(c => c.Id).ToArray();
|
||||
|
||||
// 6. Map Categories to your Product Collection (Product IDs 0 - 21)
|
||||
logger.LogInformation("Beginning Product-Category mapping assignments for Product IDs 0 through 21...");
|
||||
|
||||
for (long productId = 0; productId <= 21; productId++)
|
||||
{
|
||||
if (stoppingToken.IsCancellationRequested) break;
|
||||
|
||||
// Every book belongs to 1 or 2 main categories
|
||||
int mainCategoriesToAssign = faker.Random.Number(1, 2);
|
||||
var chosenMainIds = faker.PickRandom(mainCategoryIds, mainCategoriesToAssign).Distinct();
|
||||
|
||||
foreach (var mainId in chosenMainIds)
|
||||
{
|
||||
var linkResult = await productService.AddProductCategoryAsync(productId, mainId, stoppingToken);
|
||||
if (linkResult.IsFailed)
|
||||
{
|
||||
if (!linkResult.Errors[0].Message.Contains("exist", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
logger.LogDebug("Junction note for Product {PId} and Main Category {CId}: {Msg}", productId, mainId, linkResult.Errors[0].Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Every book gets 1 to 4 granular subgenre tags
|
||||
int subCategoriesToAssign = faker.Random.Number(1, 4);
|
||||
var chosenSubIds = faker.PickRandom(subCategoryIds, subCategoriesToAssign).Distinct();
|
||||
|
||||
foreach (var subId in chosenSubIds)
|
||||
{
|
||||
var linkResult = await productService.AddProductCategoryAsync(productId, subId, stoppingToken);
|
||||
if (linkResult.IsFailed && !linkResult.Errors[0].Message.Contains("exist", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
logger.LogDebug("Junction note for Product {PId} and Sub Category {CId}: {Msg}", productId, subId, linkResult.Errors[0].Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.LogInformation("Category and Product-Tag Mapping Seeding completed successfully.");
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@ builder.Services
|
||||
.AddLogging()
|
||||
.AddShopServices()
|
||||
.AddHostedService<ProductsSeederService>()
|
||||
.AddHostedService<CategorySeederService>()
|
||||
.AddHostedService<CustomerSeederService>()
|
||||
.AddMidrandShopDatabase(builder.Configuration);
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"FeatureManagement": {
|
||||
"CategorySeederService": true,
|
||||
"CustomerSeederService": false,
|
||||
"ProductsSeederService": false
|
||||
},
|
||||
|
||||
@@ -95,7 +95,7 @@ public sealed class BooksService(IDbContextFactory<MidrandBooksDbContext> contex
|
||||
.AsNoTracking()
|
||||
.Include(b => b.Author)
|
||||
.Include(b => b.Product)
|
||||
.ThenInclude(b => b!.Prices)
|
||||
.ThenInclude(b => b.Prices)
|
||||
.OrderByDescending(b => b.CreatedAt)
|
||||
.Where(b => b.AuthorId == authorId)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
@@ -8,29 +8,6 @@ namespace LiteCharms.Features.MidrandBooks.Authors;
|
||||
|
||||
public sealed class AuthorService(IDbContextFactory<MidrandBooksDbContext> contextFactory) : IService
|
||||
{
|
||||
public async ValueTask<Result<Author>> GetAuthorByProductIdAsync(long productId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var author = await context.Books
|
||||
.AsNoTracking()
|
||||
.Include(i => i.Author)
|
||||
.Where(b => b.ProductId == productId)
|
||||
.FirstOrDefaultAsync(cancellationToken);
|
||||
|
||||
if (author is null)
|
||||
return Result.Fail<Author>(new Error($"No author association discovered for Product ID {productId}"));
|
||||
|
||||
return Result.Ok(author.Author!.ToModel());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Result.Fail<Author>(new Error(ex.Message).CausedBy(ex));
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask<Result> UpdateAuthorStatusAsync(long authorId, bool isEnabled, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
namespace LiteCharms.Features.MidrandBooks;
|
||||
|
||||
public enum PublisherTypes : int
|
||||
{
|
||||
Individual = 0,
|
||||
Company = 1,
|
||||
Organization = 2,
|
||||
SelfPublished = 3,
|
||||
UniversityPress = 4,
|
||||
GovernmentAgency = 5,
|
||||
NonProfit = 6,
|
||||
Independent = 7
|
||||
}
|
||||
|
||||
public enum BookTypes : int
|
||||
{
|
||||
Fiction = 0,
|
||||
NonFiction = 1,
|
||||
Academic = 2,
|
||||
SelfHelp = 3,
|
||||
Biography = 4,
|
||||
Poetry = 5,
|
||||
Children = 6,
|
||||
YoungAdult = 7,
|
||||
ScienceFiction = 8,
|
||||
Fantasy = 9
|
||||
}
|
||||
|
||||
public enum BookContentTypes : int
|
||||
{
|
||||
Text = 0,
|
||||
Image = 1,
|
||||
Video = 2,
|
||||
Audio = 3,
|
||||
Interactive = 4,
|
||||
Markdown = 5,
|
||||
Html = 6,
|
||||
Json = 7,
|
||||
Yaml = 8
|
||||
}
|
||||
|
||||
public enum BookPageTypes : int
|
||||
{
|
||||
Cover = 0,
|
||||
Preface = 1,
|
||||
Introduction = 2,
|
||||
Content = 3,
|
||||
Closing = 4,
|
||||
Referencer = 5,
|
||||
Credits = 6,
|
||||
BackCover = 7
|
||||
}
|
||||
|
||||
public enum ProductTypes : int
|
||||
{
|
||||
Book = 1,
|
||||
Journal = 2,
|
||||
Magazine = 3,
|
||||
EBook = 4,
|
||||
Audiobook = 5,
|
||||
Accessory = 6
|
||||
}
|
||||
@@ -4,61 +4,12 @@ using LiteCharms.Features.MidrandBooks.Categories.Models;
|
||||
using LiteCharms.Features.MidrandBooks.Customers.Models;
|
||||
using LiteCharms.Features.MidrandBooks.Orders.Models;
|
||||
using LiteCharms.Features.MidrandBooks.Pages.Models;
|
||||
using LiteCharms.Features.MidrandBooks.Payments.Models;
|
||||
using LiteCharms.Features.MidrandBooks.Products.Models;
|
||||
|
||||
namespace LiteCharms.Features.MidrandBooks.Extensions;
|
||||
|
||||
public static class Mappers
|
||||
{
|
||||
public static PaymentLedger ToModel(this Payments.Entities.PaymentLedger entity) => new()
|
||||
{
|
||||
Id = entity.Id,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
CustomerId = entity.CustomerId,
|
||||
OrderId = entity.OrderId,
|
||||
PaymentGatewayId = entity.PaymentGatewayId,
|
||||
PaymentGatewayReference = entity.PaymentGatewayReference,
|
||||
PaymentId = entity.PaymentId,
|
||||
Status = entity.Status,
|
||||
};
|
||||
|
||||
public static PaymentGateway ToModel(this Payments.Entities.PaymentGateway entity) => new()
|
||||
{
|
||||
Id = entity.Id,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
UpdatedAt = entity.UpdatedAt,
|
||||
Enabled = entity.Enabled,
|
||||
IsSandbox = entity.IsSandbox,
|
||||
MerchantId = entity.MerchantId,
|
||||
MerchantKey = entity.MerchantKey,
|
||||
Name = entity.Name,
|
||||
Passphrase = entity.Passphrase,
|
||||
Website = entity.Website,
|
||||
};
|
||||
|
||||
public static Payment ToModel(this Payments.Entities.Payment entity) => new()
|
||||
{
|
||||
Id = entity.Id,
|
||||
Amount = entity.Amount,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
OrderId = entity.OrderId,
|
||||
Reference = entity.Reference,
|
||||
Status = entity.Status,
|
||||
UpdatedAt = entity.UpdatedAt,
|
||||
};
|
||||
|
||||
public static ProductInventory ToModel(this Products.Entities.ProductInventory entity) => new()
|
||||
{
|
||||
Id = entity.Id,
|
||||
CreatedAt = entity.CreatedAt,
|
||||
ProductId = entity.ProductId,
|
||||
ProductPriceId = entity.ProductPriceId,
|
||||
Status = entity.Status,
|
||||
TotalAllocated = entity.TotalAllocated,
|
||||
TotalReserved = entity.TotalReserved,
|
||||
};
|
||||
|
||||
public static Category ToModel(this Categories.Entities.Category entity) => new()
|
||||
{
|
||||
Id = entity.Id,
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
using LiteCharms.Features.MidrandBooks.Orders.Entities;
|
||||
|
||||
namespace LiteCharms.Features.MidrandBooks.Payments.Entities;
|
||||
|
||||
[EntityTypeConfiguration<PaymentConfiguration, Payment>]
|
||||
public class Payment : Models.Payment
|
||||
{
|
||||
public virtual Order? Order { get; set; }
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
namespace LiteCharms.Features.MidrandBooks.Payments.Entities;
|
||||
|
||||
public sealed class PaymentConfiguration : IEntityTypeConfiguration<Payment>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Payment> builder)
|
||||
{
|
||||
builder.ToTable("Payments");
|
||||
|
||||
builder.HasKey(f => f.Id);
|
||||
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||
builder.Property(f => f.UpdatedAt);
|
||||
builder.Property(f => f.Status).IsRequired();
|
||||
builder.Property(f => f.Reference).IsRequired();
|
||||
builder.Property(f => f.OrderId).IsRequired();
|
||||
builder.Property(f => f.Amount).IsRequired().HasPrecision(18, 2);
|
||||
|
||||
builder.HasOne(f => f.Order)
|
||||
.WithMany()
|
||||
.HasForeignKey(f => f.OrderId)
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
namespace LiteCharms.Features.MidrandBooks.Payments.Entities;
|
||||
|
||||
[EntityTypeConfiguration<PaymentGatewayConfiguration, PaymentGateway>]
|
||||
public class PaymentGateway : Models.PaymentGateway;
|
||||
@@ -1,20 +0,0 @@
|
||||
namespace LiteCharms.Features.MidrandBooks.Payments.Entities;
|
||||
|
||||
public sealed class PaymentGatewayConfiguration : IEntityTypeConfiguration<PaymentGateway>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<PaymentGateway> builder)
|
||||
{
|
||||
builder.ToTable("Gateways");
|
||||
|
||||
builder.HasKey(f => f.Id);
|
||||
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||
builder.Property(f => f.UpdatedAt);
|
||||
builder.Property(f => f.Website).IsRequired(false);
|
||||
builder.Property(f => f.IsSandbox);
|
||||
builder.Property(f => f.MerchantKey).IsRequired();
|
||||
builder.Property(f => f.MerchantId).IsRequired();
|
||||
builder.Property(f => f.Enabled);
|
||||
builder.Property(f => f.Name).IsRequired();
|
||||
builder.Property(f => f.Passphrase).IsRequired();
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
using LiteCharms.Features.MidrandBooks.Customers.Entities;
|
||||
using LiteCharms.Features.MidrandBooks.Orders.Entities;
|
||||
|
||||
namespace LiteCharms.Features.MidrandBooks.Payments.Entities;
|
||||
|
||||
[EntityTypeConfiguration<PaymentLedgerConfiguration, PaymentLedger>]
|
||||
public class PaymentLedger : Models.PaymentLedger
|
||||
{
|
||||
public virtual Payment? Payment { get; set; }
|
||||
|
||||
public virtual Order? Order { get; set; }
|
||||
|
||||
public virtual Customer? Customer { get; set; }
|
||||
|
||||
public virtual PaymentGateway? Gateway { get; set; }
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
namespace LiteCharms.Features.MidrandBooks.Payments.Entities;
|
||||
|
||||
public sealed class PaymentLedgerConfiguration : IEntityTypeConfiguration<PaymentLedger>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<PaymentLedger> builder)
|
||||
{
|
||||
builder.ToTable("Ledger");
|
||||
|
||||
builder.HasKey(f => f.Id);
|
||||
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||
builder.Property(f => f.Status).IsRequired();
|
||||
builder.Property(f => f.PaymentGatewayReference).IsRequired(false);
|
||||
builder.Property(f => f.PaymentGatewayId).IsRequired(false);
|
||||
builder.Property(f => f.OrderId).IsRequired();
|
||||
builder.Property(f => f.CustomerId).IsRequired();
|
||||
builder.Property(f => f.PaymentId).IsRequired();
|
||||
|
||||
builder.HasOne(f => f.Payment)
|
||||
.WithMany()
|
||||
.IsRequired()
|
||||
.HasForeignKey(f => f.PaymentId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.HasOne(f => f.Order)
|
||||
.WithMany()
|
||||
.IsRequired()
|
||||
.HasForeignKey(f => f.OrderId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.HasOne(f => f.Customer)
|
||||
.WithMany()
|
||||
.IsRequired()
|
||||
.HasForeignKey(f => f.CustomerId);
|
||||
|
||||
builder.HasOne(f => f.Gateway)
|
||||
.WithMany()
|
||||
.IsRequired(false)
|
||||
.HasForeignKey(f => f.PaymentGatewayId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace LiteCharms.Features.MidrandBooks.Payments.Models;
|
||||
|
||||
public class Payment
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
|
||||
public decimal Amount { get; set; }
|
||||
|
||||
public long OrderId { get; set; }
|
||||
|
||||
public string? Reference { get; set; }
|
||||
|
||||
public PaymentStatuses Status { get; set; }
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
namespace LiteCharms.Features.MidrandBooks.Payments.Models;
|
||||
|
||||
public class PaymentGateway
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
|
||||
public string? Name { get; set; }
|
||||
|
||||
public string? Website { get; set; }
|
||||
|
||||
public string? MerchantId { get; set; }
|
||||
|
||||
public string? MerchantKey { get; set; }
|
||||
|
||||
public string? Passphrase { get; set; }
|
||||
|
||||
public bool IsSandbox { get; set; }
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
namespace LiteCharms.Features.MidrandBooks.Payments.Models;
|
||||
|
||||
public class PaymentLedger
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
public LedgerStatuses Status { get; set; }
|
||||
|
||||
public long OrderId { get; set; }
|
||||
|
||||
public long PaymentId { get; set; }
|
||||
|
||||
public long CustomerId { get; set; }
|
||||
|
||||
public string? PaymentGatewayReference { get; set; }
|
||||
|
||||
public long? PaymentGatewayId { get; set; }
|
||||
}
|
||||
@@ -40,12 +40,4 @@ public sealed class MidrandBooksDbContext(DbContextOptions<MidrandBooksDbContext
|
||||
public DbSet<Category> Categories => Set<Category>();
|
||||
|
||||
public DbSet<ProductCategory> ProductCategories => Set<ProductCategory>();
|
||||
|
||||
public DbSet<ProductInventory> Inventories => Set<ProductInventory>();
|
||||
|
||||
public DbSet<Payment> Payments => Set<Payment>();
|
||||
|
||||
public DbSet<PaymentGateway> Gateways => Set<PaymentGateway>();
|
||||
|
||||
public DbSet<PaymentLedger> Ledger => Set<PaymentLedger>();
|
||||
}
|
||||
|
||||
Generated
-1235
File diff suppressed because it is too large
Load Diff
-185
@@ -1,185 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace LiteCharms.Features.MidrandBooks.Postgres.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedPaymentObjects : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Gateways",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||
Name = table.Column<string>(type: "text", nullable: false),
|
||||
Website = table.Column<string>(type: "text", nullable: true),
|
||||
MerchantId = table.Column<string>(type: "text", nullable: false),
|
||||
MerchantKey = table.Column<string>(type: "text", nullable: false),
|
||||
Passphrase = table.Column<string>(type: "text", nullable: false),
|
||||
IsSandbox = table.Column<bool>(type: "boolean", nullable: false),
|
||||
Enabled = table.Column<bool>(type: "boolean", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Gateways", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Inventories",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
Status = table.Column<int>(type: "integer", nullable: false),
|
||||
ProductId = table.Column<long>(type: "bigint", nullable: false),
|
||||
ProductPriceId = table.Column<long>(type: "bigint", nullable: false),
|
||||
TotalAllocated = table.Column<int>(type: "integer", nullable: false),
|
||||
TotalReserved = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Inventories", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Inventories_Prices_ProductPriceId",
|
||||
column: x => x.ProductPriceId,
|
||||
principalTable: "Prices",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_Inventories_Products_ProductId",
|
||||
column: x => x.ProductId,
|
||||
principalTable: "Products",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Payments",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||
Amount = table.Column<decimal>(type: "numeric(18,2)", precision: 18, scale: 2, nullable: false),
|
||||
OrderId = table.Column<long>(type: "bigint", nullable: false),
|
||||
Reference = table.Column<string>(type: "text", nullable: false),
|
||||
Status = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Payments", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Payments_Orders_OrderId",
|
||||
column: x => x.OrderId,
|
||||
principalTable: "Orders",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Ledger",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false, defaultValueSql: "now()"),
|
||||
Status = table.Column<int>(type: "integer", nullable: false),
|
||||
OrderId = table.Column<long>(type: "bigint", nullable: false),
|
||||
PaymentId = table.Column<long>(type: "bigint", nullable: false),
|
||||
CustomerId = table.Column<long>(type: "bigint", nullable: false),
|
||||
PaymentGatewayReference = table.Column<string>(type: "text", nullable: true),
|
||||
PaymentGatewayId = table.Column<long>(type: "bigint", nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Ledger", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Ledger_Customers_CustomerId",
|
||||
column: x => x.CustomerId,
|
||||
principalTable: "Customers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_Ledger_Gateways_PaymentGatewayId",
|
||||
column: x => x.PaymentGatewayId,
|
||||
principalTable: "Gateways",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_Ledger_Orders_OrderId",
|
||||
column: x => x.OrderId,
|
||||
principalTable: "Orders",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_Ledger_Payments_PaymentId",
|
||||
column: x => x.PaymentId,
|
||||
principalTable: "Payments",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Inventories_ProductId",
|
||||
table: "Inventories",
|
||||
column: "ProductId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Inventories_ProductPriceId",
|
||||
table: "Inventories",
|
||||
column: "ProductPriceId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Ledger_CustomerId",
|
||||
table: "Ledger",
|
||||
column: "CustomerId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Ledger_OrderId",
|
||||
table: "Ledger",
|
||||
column: "OrderId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Ledger_PaymentGatewayId",
|
||||
table: "Ledger",
|
||||
column: "PaymentGatewayId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Ledger_PaymentId",
|
||||
table: "Ledger",
|
||||
column: "PaymentId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Payments_OrderId",
|
||||
table: "Payments",
|
||||
column: "OrderId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "Inventories");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Ledger");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Gateways");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Payments");
|
||||
}
|
||||
}
|
||||
}
|
||||
-228
@@ -536,133 +536,6 @@ namespace LiteCharms.Features.MidrandBooks.Postgres.Migrations
|
||||
b.ToTable("BookPages", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.MidrandBooks.Payments.Entities.Payment", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
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<long>("OrderId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("Reference")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OrderId");
|
||||
|
||||
b.ToTable("Payments", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.MidrandBooks.Payments.Entities.PaymentGateway", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<bool>("Enabled")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsSandbox")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("MerchantId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("MerchantKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Passphrase")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<DateTime?>("UpdatedAt")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Website")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Gateways", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.MidrandBooks.Payments.Entities.PaymentLedger", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<long>("CustomerId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<long>("OrderId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<long?>("PaymentGatewayId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("PaymentGatewayReference")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<long>("PaymentId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CustomerId");
|
||||
|
||||
b.HasIndex("OrderId");
|
||||
|
||||
b.HasIndex("PaymentGatewayId");
|
||||
|
||||
b.HasIndex("PaymentId");
|
||||
|
||||
b.ToTable("Ledger", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.MidrandBooks.Payments.Entities.Refund", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
@@ -780,43 +653,6 @@ namespace LiteCharms.Features.MidrandBooks.Postgres.Migrations
|
||||
b.ToTable("ProductCategories", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.MidrandBooks.Products.Entities.ProductInventory", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreatedAt")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasDefaultValueSql("now()");
|
||||
|
||||
b.Property<long>("ProductId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<long>("ProductPriceId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("TotalAllocated")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("TotalReserved")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ProductId");
|
||||
|
||||
b.HasIndex("ProductPriceId");
|
||||
|
||||
b.ToTable("Inventories", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.MidrandBooks.Products.Entities.ProductPrice", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
@@ -1055,51 +891,6 @@ namespace LiteCharms.Features.MidrandBooks.Postgres.Migrations
|
||||
b.Navigation("References");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.MidrandBooks.Payments.Entities.Payment", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.MidrandBooks.Orders.Entities.Order", "Order")
|
||||
.WithMany()
|
||||
.HasForeignKey("OrderId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Order");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.MidrandBooks.Payments.Entities.PaymentLedger", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.MidrandBooks.Customers.Entities.Customer", "Customer")
|
||||
.WithMany()
|
||||
.HasForeignKey("CustomerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LiteCharms.Features.MidrandBooks.Orders.Entities.Order", "Order")
|
||||
.WithMany()
|
||||
.HasForeignKey("OrderId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LiteCharms.Features.MidrandBooks.Payments.Entities.PaymentGateway", "Gateway")
|
||||
.WithMany()
|
||||
.HasForeignKey("PaymentGatewayId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("LiteCharms.Features.MidrandBooks.Payments.Entities.Payment", "Payment")
|
||||
.WithMany()
|
||||
.HasForeignKey("PaymentId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Customer");
|
||||
|
||||
b.Navigation("Gateway");
|
||||
|
||||
b.Navigation("Order");
|
||||
|
||||
b.Navigation("Payment");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.MidrandBooks.Payments.Entities.Refund", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.MidrandBooks.Orders.Entities.Order", "Order")
|
||||
@@ -1159,25 +950,6 @@ namespace LiteCharms.Features.MidrandBooks.Postgres.Migrations
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.MidrandBooks.Products.Entities.ProductInventory", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.MidrandBooks.Products.Entities.Product", "Product")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProductId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("LiteCharms.Features.MidrandBooks.Products.Entities.ProductPrice", "Price")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProductPriceId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Price");
|
||||
|
||||
b.Navigation("Product");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("LiteCharms.Features.MidrandBooks.Products.Entities.ProductPrice", b =>
|
||||
{
|
||||
b.HasOne("LiteCharms.Features.MidrandBooks.Products.Entities.Product", "Product")
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace LiteCharms.Features.MidrandBooks.Products.Entities;
|
||||
|
||||
[EntityTypeConfiguration<ProductInventoryConfiguration, ProductInventory>]
|
||||
public class ProductInventory : Models.ProductInventory
|
||||
{
|
||||
public virtual Product? Product { get; set; }
|
||||
|
||||
public virtual ProductPrice? Price { get; set; }
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
namespace LiteCharms.Features.MidrandBooks.Products.Entities;
|
||||
|
||||
public sealed class ProductInventoryConfiguration : IEntityTypeConfiguration<ProductInventory>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ProductInventory> builder)
|
||||
{
|
||||
builder.ToTable("Inventories");
|
||||
|
||||
builder.HasKey(f => f.Id);
|
||||
builder.Property(f => f.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||
builder.Property(f => f.Status).IsRequired();
|
||||
builder.Property(f => f.TotalAllocated).IsRequired();
|
||||
builder.Property(f => f.TotalReserved).IsRequired();
|
||||
builder.Property(f => f.ProductId).IsRequired();
|
||||
builder.Property(f => f.ProductPriceId).IsRequired();
|
||||
|
||||
builder.HasOne(f => f.Product)
|
||||
.WithMany()
|
||||
.HasForeignKey(f => f.ProductId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.HasOne(f => f.Price)
|
||||
.WithMany()
|
||||
.HasForeignKey(f => f.ProductPriceId)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
namespace LiteCharms.Features.MidrandBooks.Products.Models;
|
||||
|
||||
public class ProductInventory
|
||||
{
|
||||
public long Id { get; set; }
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
public InventoryStatuses Status { get; set; }
|
||||
|
||||
public long ProductId { get; set; }
|
||||
|
||||
public long ProductPriceId { get; set; }
|
||||
|
||||
public int TotalAllocated { get; set; }
|
||||
|
||||
public int TotalReserved { get; set; }
|
||||
}
|
||||
@@ -304,8 +304,7 @@ public sealed class ProductService(IDbContextFactory<MidrandBooksDbContext> cont
|
||||
{
|
||||
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||
|
||||
var product = await context.Products
|
||||
.AsNoTracking().FirstOrDefaultAsync(p => p.Id == productId, cancellationToken);
|
||||
var product = await context.Products.AsNoTracking().FirstOrDefaultAsync(p => p.Id == productId, cancellationToken);
|
||||
|
||||
return product is null
|
||||
? Result.Fail<Product>(new Error($"Product with ID {productId} not found."))
|
||||
|
||||
@@ -1,35 +1,5 @@
|
||||
namespace LiteCharms.Features;
|
||||
|
||||
public enum InventoryStatuses : int
|
||||
{
|
||||
Adjustment = 0,
|
||||
Reserved = 1,
|
||||
Released = 2,
|
||||
Sold = 3,
|
||||
Replenished = 4,
|
||||
Correction = 5,
|
||||
}
|
||||
|
||||
public enum LedgerStatuses : int
|
||||
{
|
||||
Changed = 0,
|
||||
Sent = 1,
|
||||
Received = 2,
|
||||
Refunded = 3,
|
||||
Cancelled = 4,
|
||||
Failed = 5,
|
||||
Partial = 6,
|
||||
}
|
||||
|
||||
public enum PaymentStatuses : int
|
||||
{
|
||||
NotPaid = 0,
|
||||
Paid = 1,
|
||||
Cancelled = 2,
|
||||
Requested = 3,
|
||||
Failed = 4,
|
||||
}
|
||||
|
||||
public enum ShippingProviderTypes : int
|
||||
{
|
||||
Dsv = 0,
|
||||
@@ -144,65 +114,4 @@ public enum Priorities : int
|
||||
Low = 0,
|
||||
Medium = 1,
|
||||
High = 2,
|
||||
}
|
||||
|
||||
public enum PublisherTypes : int
|
||||
{
|
||||
Individual = 0,
|
||||
Company = 1,
|
||||
Organization = 2,
|
||||
SelfPublished = 3,
|
||||
UniversityPress = 4,
|
||||
GovernmentAgency = 5,
|
||||
NonProfit = 6,
|
||||
Independent = 7
|
||||
}
|
||||
|
||||
public enum BookTypes : int
|
||||
{
|
||||
Fiction = 0,
|
||||
NonFiction = 1,
|
||||
Academic = 2,
|
||||
SelfHelp = 3,
|
||||
Biography = 4,
|
||||
Poetry = 5,
|
||||
Children = 6,
|
||||
YoungAdult = 7,
|
||||
ScienceFiction = 8,
|
||||
Fantasy = 9
|
||||
}
|
||||
|
||||
public enum BookContentTypes : int
|
||||
{
|
||||
Text = 0,
|
||||
Image = 1,
|
||||
Video = 2,
|
||||
Audio = 3,
|
||||
Interactive = 4,
|
||||
Markdown = 5,
|
||||
Html = 6,
|
||||
Json = 7,
|
||||
Yaml = 8
|
||||
}
|
||||
|
||||
public enum BookPageTypes : int
|
||||
{
|
||||
Cover = 0,
|
||||
Preface = 1,
|
||||
Introduction = 2,
|
||||
Content = 3,
|
||||
Closing = 4,
|
||||
Referencer = 5,
|
||||
Credits = 6,
|
||||
BackCover = 7
|
||||
}
|
||||
|
||||
public enum ProductTypes : int
|
||||
{
|
||||
Book = 1,
|
||||
Journal = 2,
|
||||
Magazine = 3,
|
||||
EBook = 4,
|
||||
Audiobook = 5,
|
||||
Accessory = 6
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace LiteCharms.Features.Models;
|
||||
|
||||
public class SearchState
|
||||
{
|
||||
public string Query { get; private set; } = string.Empty;
|
||||
|
||||
public event Action? OnSearchSubmitted;
|
||||
|
||||
public void UpdateQuery(string newQuery) => Query = newQuery;
|
||||
|
||||
public void SubmitSearch() => OnSearchSubmitted?.Invoke();
|
||||
}
|
||||
Reference in New Issue
Block a user