Added Customer, Contact and Address with Service
Labeled all service to enable assembly scanning
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
namespace LiteCharms.Features.MidrandBooks.Abstractions;
|
||||||
|
|
||||||
|
public interface IService;
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
using LiteCharms.Features.MidrandBooks.AuthorBooks.Models;
|
using LiteCharms.Features.MidrandBooks.Abstractions;
|
||||||
|
using LiteCharms.Features.MidrandBooks.AuthorBooks.Models;
|
||||||
using LiteCharms.Features.MidrandBooks.Extensions;
|
using LiteCharms.Features.MidrandBooks.Extensions;
|
||||||
using LiteCharms.Features.MidrandBooks.Postgres;
|
using LiteCharms.Features.MidrandBooks.Postgres;
|
||||||
|
|
||||||
namespace LiteCharms.Features.MidrandBooks.AuthorBooks;
|
namespace LiteCharms.Features.MidrandBooks.AuthorBooks;
|
||||||
|
|
||||||
public class BooksService(IDbContextFactory<MidrandBooksDbContext> contextFactory)
|
public class BooksService(IDbContextFactory<MidrandBooksDbContext> contextFactory) : IService
|
||||||
{
|
{
|
||||||
public async ValueTask<Result> UpdateBookStatusAsync(long bookId, bool isEnabled, CancellationToken cancellationToken)
|
public async ValueTask<Result> UpdateBookStatusAsync(long bookId, bool isEnabled, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
using LiteCharms.Features.MidrandBooks.AuthorBooks.Models;
|
using LiteCharms.Features.MidrandBooks.Abstractions;
|
||||||
|
using LiteCharms.Features.MidrandBooks.AuthorBooks.Models;
|
||||||
using LiteCharms.Features.MidrandBooks.Authors.Models;
|
using LiteCharms.Features.MidrandBooks.Authors.Models;
|
||||||
using LiteCharms.Features.MidrandBooks.Extensions;
|
using LiteCharms.Features.MidrandBooks.Extensions;
|
||||||
using LiteCharms.Features.MidrandBooks.Postgres;
|
using LiteCharms.Features.MidrandBooks.Postgres;
|
||||||
using LiteCharms.Features.MidrandBooks.Products.Models;
|
|
||||||
using LiteCharms.Features.Models;
|
using LiteCharms.Features.Models;
|
||||||
|
|
||||||
namespace LiteCharms.Features.MidrandBooks.Authors;
|
namespace LiteCharms.Features.MidrandBooks.Authors;
|
||||||
|
|
||||||
public class AuthorService(IDbContextFactory<MidrandBooksDbContext> contextFactory)
|
public class AuthorService(IDbContextFactory<MidrandBooksDbContext> contextFactory) : IService
|
||||||
{
|
{
|
||||||
public async ValueTask<Result<AuthorBook[]>> GetAuthorBooksAsync(long authorId, CancellationToken cancellationToken)
|
public async ValueTask<Result<AuthorBook[]>> GetAuthorBooksAsync(long authorId, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,408 @@
|
|||||||
|
using LiteCharms.Features.MidrandBooks.Abstractions;
|
||||||
|
using LiteCharms.Features.MidrandBooks.Customers.Models;
|
||||||
|
using LiteCharms.Features.MidrandBooks.Extensions;
|
||||||
|
using LiteCharms.Features.MidrandBooks.Postgres;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.MidrandBooks.Customers;
|
||||||
|
|
||||||
|
public class CustomerService(IDbContextFactory<MidrandBooksDbContext> contextFactory) : IService
|
||||||
|
{
|
||||||
|
public async ValueTask<Result<long>> CreateCustomerAsync(CreateCustomer request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (await context.Customers.AnyAsync(c => c.Email!.Equals(request.Email, StringComparison.OrdinalIgnoreCase), cancellationToken))
|
||||||
|
return Result.Fail<long>(new Error($"Customer with email '{request.Email}' already exists."));
|
||||||
|
|
||||||
|
var customer = context.Customers.Add(new Entities.Customer
|
||||||
|
{
|
||||||
|
Company = request.Company,
|
||||||
|
VatNumber = request.VatNumber,
|
||||||
|
Email = request.Email,
|
||||||
|
Website = request.Website,
|
||||||
|
Phone = request.Phone,
|
||||||
|
SocialMedia = request.SocialMedia,
|
||||||
|
Enabled = true
|
||||||
|
});
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok(customer.Entity.Id)
|
||||||
|
: Result.Fail<long>(new Error("Failed to create customer."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<long>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<long>> CreateCustomerContactAsync(long customerId, CreateCustomerContact request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Customers.AnyAsync(c => c.Id == customerId, cancellationToken))
|
||||||
|
return Result.Fail<long>(new Error($"Customer with ID '{customerId}' does not exist."));
|
||||||
|
|
||||||
|
if (await context.Contacts.AnyAsync(cc => cc.CustomerId == customerId && cc.Email!.Equals(request.Email, StringComparison.OrdinalIgnoreCase), cancellationToken))
|
||||||
|
return Result.Fail<long>(new Error($"Contact with email '{request.Email}' already exists for this customer."));
|
||||||
|
|
||||||
|
var contact = context.Contacts.Add(new Entities.Contact
|
||||||
|
{
|
||||||
|
CustomerId = customerId,
|
||||||
|
Name = request.Name,
|
||||||
|
Email = request.Email,
|
||||||
|
Phone = request.Phone,
|
||||||
|
LastName = request.LastName,
|
||||||
|
Type = request.Type,
|
||||||
|
Enabled = true
|
||||||
|
});
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok(contact.Entity.Id)
|
||||||
|
: Result.Fail<long>(new Error("Failed to create customer contact."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<long>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<long>> CreateCustomerAddressAsync(long customerId, CreateCustomerAddress request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Customers.AnyAsync(c => c.Id == customerId, cancellationToken))
|
||||||
|
return Result.Fail<long>(new Error($"Customer with ID '{customerId}' does not exist."));
|
||||||
|
|
||||||
|
var address = context.Addresses.Add(new Entities.Address
|
||||||
|
{
|
||||||
|
CustomerId = customerId,
|
||||||
|
Street = request.Street,
|
||||||
|
City = request.City,
|
||||||
|
State = request.State,
|
||||||
|
PostalCode = request.PostalCode,
|
||||||
|
Country = request.Country,
|
||||||
|
Type = request.Type,
|
||||||
|
Enabled = true,
|
||||||
|
BuildingType = request.BuildingType,
|
||||||
|
IsPrimary = request.IsPrimary,
|
||||||
|
Name = request.Name
|
||||||
|
});
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok(address.Entity.Id)
|
||||||
|
: Result.Fail<long>(new Error("Failed to create customer address."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<long>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateCustomerAsync(long customerId, UpdateCustomer request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var customer = await context.Customers.FirstOrDefaultAsync(c => c.Id == customerId, cancellationToken);
|
||||||
|
|
||||||
|
if (customer is null)
|
||||||
|
return Result.Fail(new Error($"Customer with ID '{customerId}' does not exist."));
|
||||||
|
|
||||||
|
customer.UpdatedAt = DateTime.UtcNow;
|
||||||
|
customer.Company = request.Company;
|
||||||
|
customer.VatNumber = request.VatNumber;
|
||||||
|
customer.Email = request.Email;
|
||||||
|
customer.Website = request.Website;
|
||||||
|
customer.Phone = request.Phone;
|
||||||
|
customer.SocialMedia = request.SocialMedia;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail(new Error("Failed to update customer."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateCustomerContactAsync(long contactId, UpdateCustomerContact request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var contact = await context.Contacts.FirstOrDefaultAsync(cc => cc.Id == contactId, cancellationToken);
|
||||||
|
|
||||||
|
if (contact is null)
|
||||||
|
return Result.Fail(new Error($"Contact with ID '{contactId}' does not exist."));
|
||||||
|
|
||||||
|
contact.UpdatedAt = DateTime.UtcNow;
|
||||||
|
contact.Name = request.Name;
|
||||||
|
contact.LastName = request.LastName;
|
||||||
|
contact.Email = request.Email;
|
||||||
|
contact.Phone = request.Phone;
|
||||||
|
contact.Type = request.Type;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail(new Error("Failed to update customer contact."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateCustomerAddressAsync(long addressId, UpdateCustomerAddress request, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var address = await context.Addresses.FirstOrDefaultAsync(a => a.Id == addressId, cancellationToken);
|
||||||
|
|
||||||
|
if (address is null)
|
||||||
|
return Result.Fail(new Error($"Address with ID '{addressId}' does not exist."));
|
||||||
|
|
||||||
|
address.UpdatedAt = DateTime.UtcNow;
|
||||||
|
address.Street = request.Street;
|
||||||
|
address.City = request.City;
|
||||||
|
address.State = request.State;
|
||||||
|
address.PostalCode = request.PostalCode;
|
||||||
|
address.Country = request.Country;
|
||||||
|
address.Type = request.Type;
|
||||||
|
address.BuildingType = request.BuildingType;
|
||||||
|
address.IsPrimary = request.IsPrimary;
|
||||||
|
address.Name = request.Name;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail(new Error("Failed to update customer address."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateCustomerStatusAsync(long customerId, bool enabled, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var customer = await context.Customers.FirstOrDefaultAsync(c => c.Id == customerId, cancellationToken);
|
||||||
|
|
||||||
|
if (customer is null)
|
||||||
|
return Result.Fail(new Error($"Customer with ID '{customerId}' does not exist."));
|
||||||
|
|
||||||
|
customer.Enabled = enabled;
|
||||||
|
customer.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail(new Error("Failed to update customer status."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateCustomerContactStatusAsync(long contactId, bool enabled, bool isPrimary, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var contact = await context.Contacts.FirstOrDefaultAsync(cc => cc.Id == contactId, cancellationToken);
|
||||||
|
|
||||||
|
if (contact is null)
|
||||||
|
return Result.Fail(new Error($"Contact with ID '{contactId}' does not exist."));
|
||||||
|
|
||||||
|
contact.Enabled = enabled;
|
||||||
|
contact.IsPrimary = isPrimary;
|
||||||
|
contact.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail(new Error("Failed to update customer contact status."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result> UpdateCustomerAddressStatusAsync(long addressId, bool enabled, bool isPrimary, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var address = await context.Addresses.FirstOrDefaultAsync(a => a.Id == addressId, cancellationToken);
|
||||||
|
|
||||||
|
if (address is null)
|
||||||
|
return Result.Fail(new Error($"Address with ID '{addressId}' does not exist."));
|
||||||
|
|
||||||
|
address.Enabled = enabled;
|
||||||
|
address.IsPrimary = isPrimary;
|
||||||
|
address.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
return await context.SaveChangesAsync(cancellationToken) > 0
|
||||||
|
? Result.Ok()
|
||||||
|
: Result.Fail(new Error("Failed to update customer address status."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Customer[]>> GetCustomersAsync(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var customers = await context.Customers
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(c => c.Contacts)
|
||||||
|
.Include(c => c.Addresses)
|
||||||
|
.OrderByDescending(c => c.CreatedAt)
|
||||||
|
.ThenByDescending(c => c.UpdatedAt)
|
||||||
|
.AsSplitQuery()
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
return customers?.Count > 0
|
||||||
|
? Result.Ok(customers.Select(c => c.ToModel()).ToArray())
|
||||||
|
: Result.Fail<Customer[]>(new Error("No customers found."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Customer[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Contact[]>> GetCustomerContactsAsync(long customerId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Customers.AnyAsync(c => c.Id == customerId, cancellationToken))
|
||||||
|
return Result.Fail<Contact[]>(new Error($"Customer with ID '{customerId}' does not exist."));
|
||||||
|
|
||||||
|
var contacts = await context.Contacts
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(cc => cc.CustomerId == customerId)
|
||||||
|
.OrderByDescending(cc => cc.CreatedAt)
|
||||||
|
.ThenByDescending(cc => cc.UpdatedAt)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
return contacts?.Count > 0
|
||||||
|
? Result.Ok(contacts.Select(cc => cc.ToModel()).ToArray())
|
||||||
|
: Result.Fail<Contact[]>(new Error("No contacts found for the specified customer."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Contact[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Address[]>> GetCustomerAddressesAsync(long customerId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (!await context.Customers.AnyAsync(c => c.Id == customerId, cancellationToken))
|
||||||
|
return Result.Fail<Address[]>(new Error($"Customer with ID '{customerId}' does not exist."));
|
||||||
|
|
||||||
|
var addresses = await context.Addresses
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(a => a.CustomerId == customerId)
|
||||||
|
.OrderByDescending(a => a.CreatedAt)
|
||||||
|
.ThenByDescending(a => a.UpdatedAt)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
return addresses?.Count > 0
|
||||||
|
? Result.Ok(addresses.Select(a => a.ToModel()).ToArray())
|
||||||
|
: Result.Fail<Address[]>(new Error($"No addresses found for customer with ID '{customerId}'."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Address[]>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Customer>> GetCustomerAsync(long customerId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var customer = await context.Customers
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(c => c.Contacts)
|
||||||
|
.Include(c => c.Addresses)
|
||||||
|
.FirstOrDefaultAsync(c => c.Id == customerId, cancellationToken);
|
||||||
|
|
||||||
|
return customer is not null
|
||||||
|
? Result.Ok(customer.ToModel())
|
||||||
|
: Result.Fail<Customer>(new Error($"Customer with ID '{customerId}' does not exist."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Customer>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Contact>> GetCustomerContactAsync(long contactId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var contact = await context.Contacts
|
||||||
|
.AsNoTracking()
|
||||||
|
.FirstOrDefaultAsync(cc => cc.Id == contactId, cancellationToken);
|
||||||
|
|
||||||
|
return contact is not null
|
||||||
|
? Result.Ok(contact.ToModel())
|
||||||
|
: Result.Fail<Contact>(new Error($"Contact with ID '{contactId}' does not exist."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Contact>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask<Result<Address>> GetCustomerAddressAsync(long addressId, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
|
||||||
|
|
||||||
|
var address = await context.Addresses
|
||||||
|
.AsNoTracking()
|
||||||
|
.FirstOrDefaultAsync(a => a.Id == addressId, cancellationToken);
|
||||||
|
|
||||||
|
return address is not null
|
||||||
|
? Result.Ok(address.ToModel())
|
||||||
|
: Result.Fail<Address>(new Error($"Address with ID '{addressId}' does not exist."));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result.Fail<Address>(new Error(ex.Message).CausedBy(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace LiteCharms.Features.MidrandBooks.Customers.Entities;
|
||||||
|
|
||||||
|
[EntityTypeConfiguration<AddressConfiguration, Address>]
|
||||||
|
public class Address : Models.Address
|
||||||
|
{
|
||||||
|
public virtual Customer? Customer { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
namespace LiteCharms.Features.MidrandBooks.Customers.Entities;
|
||||||
|
|
||||||
|
public class AddressConfiguration : IEntityTypeConfiguration<Address>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<Address> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("Addresses");
|
||||||
|
|
||||||
|
builder.HasKey(a => a.Id);
|
||||||
|
builder.Property(a => a.CustomerId).IsRequired();
|
||||||
|
builder.Property(a => a.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
|
builder.Property(a => a.UpdatedAt).HasDefaultValueSql("now()");
|
||||||
|
builder.Property(a => a.Name).IsRequired();
|
||||||
|
builder.Property(a => a.Type).IsRequired();
|
||||||
|
builder.Property(a => a.BuildingType).IsRequired();
|
||||||
|
builder.Property(a => a.Street).IsRequired();
|
||||||
|
builder.Property(a => a.City).IsRequired();
|
||||||
|
builder.Property(a => a.State).IsRequired();
|
||||||
|
builder.Property(a => a.PostalCode).IsRequired();
|
||||||
|
builder.Property(a => a.Country).IsRequired();
|
||||||
|
builder.Property(a => a.IsPrimary).HasDefaultValue(false);
|
||||||
|
builder.Property(a => a.Enabled).HasDefaultValue(true);
|
||||||
|
|
||||||
|
builder.HasOne(a => a.Customer)
|
||||||
|
.WithMany(c => c.Addresses)
|
||||||
|
.HasForeignKey(a => a.CustomerId)
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace LiteCharms.Features.MidrandBooks.Customers.Entities;
|
||||||
|
|
||||||
|
[EntityTypeConfiguration<ContactConfiguration, Contact>]
|
||||||
|
public class Contact : Models.Contact
|
||||||
|
{
|
||||||
|
public virtual Customer? Customer { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
namespace LiteCharms.Features.MidrandBooks.Customers.Entities;
|
||||||
|
|
||||||
|
public class ContactConfiguration : IEntityTypeConfiguration<Contact>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<Contact> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("Contacts");
|
||||||
|
|
||||||
|
builder.HasKey(c => c.Id);
|
||||||
|
builder.Property(c => c.CustomerId).IsRequired();
|
||||||
|
builder.Property(c => c.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
|
builder.Property(c => c.UpdatedAt).HasDefaultValueSql("now()");
|
||||||
|
builder.Property(c => c.Name).IsRequired();
|
||||||
|
builder.Property(c => c.LastName).IsRequired();
|
||||||
|
builder.Property(c => c.Type).IsRequired();
|
||||||
|
builder.Property(c => c.Phone).IsRequired();
|
||||||
|
builder.Property(c => c.Email).IsRequired();
|
||||||
|
builder.Property(c => c.IsPrimary).HasDefaultValue(false);
|
||||||
|
builder.Property(c => c.Enabled).HasDefaultValue(true);
|
||||||
|
|
||||||
|
builder.HasOne(c => c.Customer)
|
||||||
|
.WithMany(c => c.Contacts)
|
||||||
|
.HasForeignKey(c => c.CustomerId)
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace LiteCharms.Features.MidrandBooks.Customers.Entities;
|
||||||
|
|
||||||
|
[EntityTypeConfiguration<CustomerConfiguration, Customer>]
|
||||||
|
public class Customer : Models.Customer
|
||||||
|
{
|
||||||
|
public virtual ICollection<Contact> Contacts { get; set; } = [];
|
||||||
|
|
||||||
|
public virtual ICollection<Address> Addresses { get; set; } = [];
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
namespace LiteCharms.Features.MidrandBooks.Customers.Entities;
|
||||||
|
|
||||||
|
public class CustomerConfiguration : IEntityTypeConfiguration<Customer>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<Customer> builder)
|
||||||
|
{
|
||||||
|
builder.ToTable("Customers");
|
||||||
|
|
||||||
|
builder.HasKey(c => c.Id);
|
||||||
|
builder.Property(c => c.CreatedAt).IsRequired().ValueGeneratedOnAdd().HasDefaultValueSql("now()");
|
||||||
|
builder.Property(c => c.UpdatedAt).HasDefaultValueSql("now()");
|
||||||
|
builder.Property(c => c.Company).IsRequired(false);
|
||||||
|
builder.Property(c => c.VatNumber).IsRequired(false);
|
||||||
|
builder.Property(c => c.Email).IsRequired();
|
||||||
|
builder.Property(c => c.Phone).IsRequired();
|
||||||
|
builder.Property(c => c.Website).IsRequired();
|
||||||
|
builder.Property(c => c.SocialMedia).IsRequired(false).HasColumnType("jsonb");
|
||||||
|
builder.Property(c => c.Enabled).HasDefaultValue(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
namespace LiteCharms.Features.MidrandBooks.Customers.Models;
|
||||||
|
|
||||||
|
public class Address
|
||||||
|
{
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
public long CustomerId { get; set; }
|
||||||
|
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
|
public AddressType Type { get; set; }
|
||||||
|
|
||||||
|
public AddressBuildingTypes BuildingType { get; set; }
|
||||||
|
|
||||||
|
public string? Street { get; set; }
|
||||||
|
|
||||||
|
public string? City { get; set; }
|
||||||
|
|
||||||
|
public string? State { get; set; }
|
||||||
|
|
||||||
|
public string? PostalCode { get; set; }
|
||||||
|
|
||||||
|
public string? Country { get; set; }
|
||||||
|
|
||||||
|
public bool IsPrimary { get; set; }
|
||||||
|
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
namespace LiteCharms.Features.MidrandBooks.Customers.Models;
|
||||||
|
|
||||||
|
public class Contact
|
||||||
|
{
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
public long CustomerId { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
|
public ContactTypes Type { get; set; }
|
||||||
|
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
public string? LastName { get; set; }
|
||||||
|
|
||||||
|
public string? Email { get; set; }
|
||||||
|
|
||||||
|
public string? Phone { get; set; }
|
||||||
|
|
||||||
|
public bool IsPrimary { get; set; }
|
||||||
|
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using LiteCharms.Features.Models;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.MidrandBooks.Customers.Models;
|
||||||
|
|
||||||
|
public class Customer
|
||||||
|
{
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
|
public string? Company { get; set; }
|
||||||
|
|
||||||
|
public string? VatNumber { get; set; }
|
||||||
|
|
||||||
|
public string? Email { get; set; }
|
||||||
|
|
||||||
|
public string? Website { get; set; }
|
||||||
|
|
||||||
|
public string? Phone { get; set; }
|
||||||
|
|
||||||
|
public SocialMedia[]? SocialMedia { get; set; }
|
||||||
|
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
using LiteCharms.Features.Models;
|
||||||
|
|
||||||
|
namespace LiteCharms.Features.MidrandBooks.Customers.Models;
|
||||||
|
|
||||||
|
public record CreateCustomer
|
||||||
|
{
|
||||||
|
public string? Company { get; set; }
|
||||||
|
|
||||||
|
public string? VatNumber { get; set; }
|
||||||
|
|
||||||
|
public string? Email { get; set; }
|
||||||
|
|
||||||
|
public string? Website { get; set; }
|
||||||
|
|
||||||
|
public string? Phone { get; set; }
|
||||||
|
|
||||||
|
public SocialMedia[]? SocialMedia { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public record UpdateCustomer : CreateCustomer;
|
||||||
|
|
||||||
|
public record CreateCustomerContact
|
||||||
|
{
|
||||||
|
public ContactTypes Type { get; set; }
|
||||||
|
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
public string? LastName { get; set; }
|
||||||
|
|
||||||
|
public string? Email { get; set; }
|
||||||
|
|
||||||
|
public string? Phone { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public record UpdateCustomerContact : CreateCustomerContact;
|
||||||
|
|
||||||
|
public record CreateCustomerAddress
|
||||||
|
{
|
||||||
|
public string? Name { get; set; }
|
||||||
|
|
||||||
|
public AddressType Type { get; set; }
|
||||||
|
|
||||||
|
public AddressBuildingTypes BuildingType { get; set; }
|
||||||
|
|
||||||
|
public string? Street { get; set; }
|
||||||
|
|
||||||
|
public string? City { get; set; }
|
||||||
|
|
||||||
|
public string? State { get; set; }
|
||||||
|
|
||||||
|
public string? PostalCode { get; set; }
|
||||||
|
|
||||||
|
public string? Country { get; set; }
|
||||||
|
|
||||||
|
public bool IsPrimary { get; set; }
|
||||||
|
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public record UpdateCustomerAddress : CreateCustomerAddress;
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using LiteCharms.Features.MidrandBooks.AuthorBooks.Models;
|
using LiteCharms.Features.MidrandBooks.AuthorBooks.Models;
|
||||||
using LiteCharms.Features.MidrandBooks.Authors.Models;
|
using LiteCharms.Features.MidrandBooks.Authors.Models;
|
||||||
|
using LiteCharms.Features.MidrandBooks.Customers.Models;
|
||||||
using LiteCharms.Features.MidrandBooks.Pages.Models;
|
using LiteCharms.Features.MidrandBooks.Pages.Models;
|
||||||
using LiteCharms.Features.MidrandBooks.Products.Models;
|
using LiteCharms.Features.MidrandBooks.Products.Models;
|
||||||
|
|
||||||
@@ -7,6 +8,52 @@ namespace LiteCharms.Features.MidrandBooks.Extensions;
|
|||||||
|
|
||||||
public static class Mappers
|
public static class Mappers
|
||||||
{
|
{
|
||||||
|
public static Customer ToModel(this Customers.Entities.Customer entiry) => new()
|
||||||
|
{
|
||||||
|
Id = entiry.Id,
|
||||||
|
Company = entiry.Company,
|
||||||
|
CreatedAt = entiry.CreatedAt,
|
||||||
|
Email = entiry.Email,
|
||||||
|
Enabled = entiry.Enabled,
|
||||||
|
Phone = entiry.Phone,
|
||||||
|
SocialMedia = entiry.SocialMedia,
|
||||||
|
UpdatedAt = entiry.UpdatedAt,
|
||||||
|
VatNumber = entiry.VatNumber,
|
||||||
|
Website = entiry.Website
|
||||||
|
};
|
||||||
|
|
||||||
|
public static Address ToModel(this Customers.Entities.Address entity) => new()
|
||||||
|
{
|
||||||
|
Id = entity.Id,
|
||||||
|
BuildingType = entity.BuildingType,
|
||||||
|
CreatedAt = entity.CreatedAt,
|
||||||
|
CustomerId = entity.CustomerId,
|
||||||
|
Enabled = entity.Enabled,
|
||||||
|
IsPrimary = entity.IsPrimary,
|
||||||
|
Name = entity.Name,
|
||||||
|
PostalCode = entity.PostalCode,
|
||||||
|
Type = entity.Type,
|
||||||
|
UpdatedAt = entity.UpdatedAt,
|
||||||
|
Street = entity.Street,
|
||||||
|
City = entity.City,
|
||||||
|
State = entity.State,
|
||||||
|
Country = entity.Country
|
||||||
|
};
|
||||||
|
|
||||||
|
public static Contact ToModel(this Customers.Entities.Contact entity) => new()
|
||||||
|
{
|
||||||
|
Id = entity.Id,
|
||||||
|
Type = entity.Type,
|
||||||
|
CreatedAt = entity.CreatedAt,
|
||||||
|
UpdatedAt = entity.UpdatedAt,
|
||||||
|
CustomerId = entity.CustomerId,
|
||||||
|
Email = entity.Email,
|
||||||
|
Enabled = entity.Enabled,
|
||||||
|
LastName = entity.LastName,
|
||||||
|
Name = entity.Name,
|
||||||
|
Phone = entity.Phone
|
||||||
|
};
|
||||||
|
|
||||||
public static BookPage ToModel(this Pages.Entities.BookPage entity) => new()
|
public static BookPage ToModel(this Pages.Entities.BookPage entity) => new()
|
||||||
{
|
{
|
||||||
Id = entity.Id,
|
Id = entity.Id,
|
||||||
|
|||||||
+3
-2
@@ -1,10 +1,11 @@
|
|||||||
using LiteCharms.Features.MidrandBooks.Extensions;
|
using LiteCharms.Features.MidrandBooks.Abstractions;
|
||||||
|
using LiteCharms.Features.MidrandBooks.Extensions;
|
||||||
using LiteCharms.Features.MidrandBooks.Pages.Models;
|
using LiteCharms.Features.MidrandBooks.Pages.Models;
|
||||||
using LiteCharms.Features.MidrandBooks.Postgres;
|
using LiteCharms.Features.MidrandBooks.Postgres;
|
||||||
|
|
||||||
namespace LiteCharms.Features.MidrandBooks.Pages;
|
namespace LiteCharms.Features.MidrandBooks.Pages;
|
||||||
|
|
||||||
public class PagesService(IDbContextFactory<MidrandBooksDbContext> contextFactory)
|
public class PageService(IDbContextFactory<MidrandBooksDbContext> contextFactory) : IService
|
||||||
{
|
{
|
||||||
public async ValueTask<Result> DeleteAllAsync(long authorBookId, CancellationToken cancellationToken = default)
|
public async ValueTask<Result> DeleteAllAsync(long authorBookId, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using LiteCharms.Features.MidrandBooks.AuthorBooks.Entities;
|
using LiteCharms.Features.MidrandBooks.AuthorBooks.Entities;
|
||||||
using LiteCharms.Features.MidrandBooks.Authors.Entities;
|
using LiteCharms.Features.MidrandBooks.Authors.Entities;
|
||||||
|
using LiteCharms.Features.MidrandBooks.Customers.Entities;
|
||||||
using LiteCharms.Features.MidrandBooks.Pages.Entities;
|
using LiteCharms.Features.MidrandBooks.Pages.Entities;
|
||||||
using LiteCharms.Features.MidrandBooks.Products.Entities;
|
using LiteCharms.Features.MidrandBooks.Products.Entities;
|
||||||
|
|
||||||
@@ -16,4 +17,10 @@ public class MidrandBooksDbContext(DbContextOptions<MidrandBooksDbContext> optio
|
|||||||
public DbSet<AuthorBook> Books => Set<AuthorBook>();
|
public DbSet<AuthorBook> Books => Set<AuthorBook>();
|
||||||
|
|
||||||
public DbSet<BookPage> Pages => Set<BookPage>();
|
public DbSet<BookPage> Pages => Set<BookPage>();
|
||||||
|
|
||||||
|
public DbSet<Contact> Contacts => Set<Contact>();
|
||||||
|
|
||||||
|
public DbSet<Address> Addresses => Set<Address>();
|
||||||
|
|
||||||
|
public DbSet<Customer> Customers => Set<Customer>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
using LiteCharms.Features.MidrandBooks.Extensions;
|
using LiteCharms.Features.MidrandBooks.Abstractions;
|
||||||
|
using LiteCharms.Features.MidrandBooks.Extensions;
|
||||||
using LiteCharms.Features.MidrandBooks.Postgres;
|
using LiteCharms.Features.MidrandBooks.Postgres;
|
||||||
using LiteCharms.Features.MidrandBooks.Products.Models;
|
using LiteCharms.Features.MidrandBooks.Products.Models;
|
||||||
using LiteCharms.Features.Models;
|
using LiteCharms.Features.Models;
|
||||||
|
|
||||||
namespace LiteCharms.Features.MidrandBooks.Products;
|
namespace LiteCharms.Features.MidrandBooks.Products;
|
||||||
|
|
||||||
public class ProductService(IDbContextFactory<MidrandBooksDbContext> contextFactory)
|
public class ProductService(IDbContextFactory<MidrandBooksDbContext> contextFactory) : IService
|
||||||
{
|
{
|
||||||
public async ValueTask<Result> UpdateProductPriceStatusAsync(long productPriceId, bool isEnabled, CancellationToken cancellationToken = default)
|
public async ValueTask<Result> UpdateProductPriceStatusAsync(long productPriceId, bool isEnabled, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,6 +23,11 @@
|
|||||||
<PackageTags>utility;dotnet</PackageTags>
|
<PackageTags>utility;dotnet</PackageTags>
|
||||||
<PackageIcon>icon.png</PackageIcon>
|
<PackageIcon>icon.png</PackageIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Addresses\**" />
|
||||||
|
<EmbeddedResource Remove="Addresses\**" />
|
||||||
|
<None Remove="Addresses\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\LICENSE" Pack="true" PackagePath="\" />
|
<None Include="..\LICENSE" Pack="true" PackagePath="\" />
|
||||||
|
|||||||
@@ -1,5 +1,30 @@
|
|||||||
namespace LiteCharms.Features;
|
namespace LiteCharms.Features;
|
||||||
|
|
||||||
|
public enum ContactTypes : int
|
||||||
|
{
|
||||||
|
Personal = 0,
|
||||||
|
Business = 1,
|
||||||
|
Other = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AddressType
|
||||||
|
{
|
||||||
|
Billing = 1,
|
||||||
|
Shipping = 2,
|
||||||
|
Other = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AddressBuildingTypes : int
|
||||||
|
{
|
||||||
|
Residential = 0,
|
||||||
|
Commercial = 1,
|
||||||
|
Industrial = 2,
|
||||||
|
MixedUse = 3,
|
||||||
|
Agricultural = 4,
|
||||||
|
Institutional = 5,
|
||||||
|
Recreational = 6,
|
||||||
|
}
|
||||||
|
|
||||||
public enum SocialMediaTypes : int
|
public enum SocialMediaTypes : int
|
||||||
{
|
{
|
||||||
Twitter = 0,
|
Twitter = 0,
|
||||||
|
|||||||
Reference in New Issue
Block a user