diff --git a/VichVich.BuildingBlocks.Domain/DomainEventBase.cs b/VichVich.BuildingBlocks.Domain/DomainEventBase.cs index f4eda5a..57d9d14 100644 --- a/VichVich.BuildingBlocks.Domain/DomainEventBase.cs +++ b/VichVich.BuildingBlocks.Domain/DomainEventBase.cs @@ -1,6 +1,6 @@ namespace Vizhvizh.BuildingBlocks.Domain; -public class DomainEventBase : IDomainEvent +public abstract class DomainEventBase : IDomainEvent { public Guid Id { get; } diff --git a/Vichvich.Shop.Api/Controllers/ShopController.cs b/Vichvich.Shop.Api/Controllers/ShopController.cs index 22daf71..5595793 100644 --- a/Vichvich.Shop.Api/Controllers/ShopController.cs +++ b/Vichvich.Shop.Api/Controllers/ShopController.cs @@ -1,5 +1,6 @@ using Microsoft.AspNetCore.Mvc; using Vizhvizh.BuildingBlocks.Infrastructure; +using Vizhvizh.Shop.ApplicationContract.Commands; using Vizhvizh.Shop.ApplicationContract.DTOs; using Vizhvizh.Shop.ApplicationContract.Queries; @@ -13,6 +14,11 @@ namespace Vizhvizh.Shop.Api.Controllers public async Task> GetById([FromQuery] long shopId, CancellationToken cancellationToken) => Ok(await executor.Execute(new GetShopByIdQuery(shopId), cancellationToken)); - + [HttpPost] + public async Task Create([FromBody] CreateShopCommand request, CancellationToken cancellationToken) + { + await executor.Execute(request, cancellationToken); + return Ok(); + } } } diff --git a/Vichvich.Shop.Application/CommandHandlers/Shops/CreateShopCommandHandler.cs b/Vichvich.Shop.Application/CommandHandlers/Shops/CreateShopCommandHandler.cs index f8816d1..5c3407d 100644 --- a/Vichvich.Shop.Application/CommandHandlers/Shops/CreateShopCommandHandler.cs +++ b/Vichvich.Shop.Application/CommandHandlers/Shops/CreateShopCommandHandler.cs @@ -7,18 +7,18 @@ using Vizhvizh.Shop.Domain.Shops.ValuesObjects; namespace Vizhvizh.Shop.Application.CommandHandlers.Shops; -public class CreateShopCommandHandler(IShopRepository shopRepository) : ICommandHandler +public class CreateShopCommandHandler(IShopRepository shopRepository) : ICommandHandler { - public async Task Handle(CreateShopCommand request, CancellationToken cancellationToken) + public async Task Handle(CreateShopCommand request, CancellationToken cancellationToken) { var location = ShopLocation.CreateNew(request.ShopLocation.Latitude, request.ShopLocation.Longitude, request.ShopLocation.ProvinceId, request.ShopLocation.CityId, request.ShopLocation.Address, request.ShopLocation.PostalCode); + var businessLicense = ShopBusinessLicense.CreateNew(request.ShopBusinessLicenseImage, request.ShopBusinessLicenseCode); + var shop = Domain.Shops.Entities.Shop.CreateNew(request.OwnerId, request.Title, - location,TelephoneVO.CreateNew(request.Telephone), request.Description); + location, TelephoneVO.CreateNew(request.Telephone), businessLicense, request.Description); await shopRepository.AddAsync(shop, cancellationToken); - - return shop.Id; } } diff --git a/Vichvich.Shop.Application/Vizhvizh.Shop.Application.csproj b/Vichvich.Shop.Application/Vizhvizh.Shop.Application.csproj index a655872..73d19f1 100644 --- a/Vichvich.Shop.Application/Vizhvizh.Shop.Application.csproj +++ b/Vichvich.Shop.Application/Vizhvizh.Shop.Application.csproj @@ -14,4 +14,8 @@ + + + + diff --git a/Vichvich.Shop.ApplicationContract/Commands/ProductCommands.cs b/Vichvich.Shop.ApplicationContract/Commands/ProductCommands.cs new file mode 100644 index 0000000..9590822 --- /dev/null +++ b/Vichvich.Shop.ApplicationContract/Commands/ProductCommands.cs @@ -0,0 +1,8 @@ +using Vizhvizh.BuildingBlocks.Domain.Contract; +using Vizhvizh.Shop.ApplicationContract.Models.Products; +using Vizhvizh.Shop.Domain.Products.ValuesObjects; + +namespace Vizhvizh.Shop.ApplicationContract.Commands; + +public record CreateProductCommand(long ShopId, long CategoryId, string Title, string Description, string Image, + ProductConditionEnum ProductCondition, List ProductSpecifications) : CommandBase; \ No newline at end of file diff --git a/Vichvich.Shop.ApplicationContract/Commands/ShopCommands.cs b/Vichvich.Shop.ApplicationContract/Commands/ShopCommands.cs index 5b94a72..8d4bdd3 100644 --- a/Vichvich.Shop.ApplicationContract/Commands/ShopCommands.cs +++ b/Vichvich.Shop.ApplicationContract/Commands/ShopCommands.cs @@ -1,9 +1,9 @@ using Vizhvizh.BuildingBlocks.Domain.Contract; -using Vizhvizh.Shared.Domain.ValueObjects; using Vizhvizh.Shop.Domain.Shops.TypeIds; using Vizhvizh.Shop.Domain.Shops.ValuesObjects; namespace Vizhvizh.Shop.ApplicationContract.Commands; -public record CreateShopCommand(long OwnerId, string Title,string Telephone, string Description, string Email, ShopLocation ShopLocation) : CommandBase; -public record SetTitleShopCommand(ShopId ShopId,TitleVO Title) : CommandBase; \ No newline at end of file +public record CreateShopCommand(long OwnerId, string Title,string Telephone,string ShopBusinessLicenseImage,string ShopBusinessLicenseCode, + string Description, string Email, ShopLocation ShopLocation) : CommandBase; +public record SetTitleShopCommand(long ShopId,string Title) : CommandBase; \ No newline at end of file diff --git a/Vichvich.Shop.ApplicationContract/Models/Products/ProductSpecificationsModel.cs b/Vichvich.Shop.ApplicationContract/Models/Products/ProductSpecificationsModel.cs new file mode 100644 index 0000000..2f7bd4f --- /dev/null +++ b/Vichvich.Shop.ApplicationContract/Models/Products/ProductSpecificationsModel.cs @@ -0,0 +1,3 @@ +namespace Vizhvizh.Shop.ApplicationContract.Models.Products; + +public record ProductSpecificationsModel(string Title, List Values); diff --git a/Vichvich.Shop.ApplicationContract/Vizhvizh.Shop.ApplicationContract.csproj b/Vichvich.Shop.ApplicationContract/Vizhvizh.Shop.ApplicationContract.csproj index 65f53cc..fb2a893 100644 --- a/Vichvich.Shop.ApplicationContract/Vizhvizh.Shop.ApplicationContract.csproj +++ b/Vichvich.Shop.ApplicationContract/Vizhvizh.Shop.ApplicationContract.csproj @@ -6,10 +6,6 @@ enable - - - - diff --git a/Vichvich.Shop.Domain/Members/Entities/Member.cs b/Vichvich.Shop.Domain/Members/Entities/Member.cs index 4f4ba35..a773b79 100644 --- a/Vichvich.Shop.Domain/Members/Entities/Member.cs +++ b/Vichvich.Shop.Domain/Members/Entities/Member.cs @@ -2,6 +2,7 @@ using Vizhvizh.Shop.Domain.Members.TypeIds; using Vizhvizh.Shop.Domain.Members.ValuesObjects; using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shop.Domain.Members.Events; namespace Vizhvizh.Shop.Domain.Members.Entities; @@ -10,10 +11,11 @@ public class Member : Entity, IAggregateRoot private PhoneNumberVO _phoneNumber; private MemberFullName _fullName; private MemberAvatar? _avatar; + private MemberNationalCode? _nationalCode; private Member() { - + } private Member(PhoneNumberVO phoneNumber, MemberFullName fullName, MemberAvatar? avatar) { @@ -28,4 +30,12 @@ public class Member : Entity, IAggregateRoot public MemberFullName? FullName => _fullName; public PhoneNumberVO PhoneNumber => _phoneNumber; public MemberAvatar? Avatar => _avatar; + public MemberNationalCode? NationalCode => _nationalCode; + + public void SetNationalCode(MemberNationalCode nationalCode) + { + _nationalCode = nationalCode; + this.AddDomainEvent(new SetNationalCodeEvent(this)); + } + } diff --git a/Vichvich.Shop.Domain/Members/Events/SetNationalCodeEvent.cs b/Vichvich.Shop.Domain/Members/Events/SetNationalCodeEvent.cs new file mode 100644 index 0000000..621659a --- /dev/null +++ b/Vichvich.Shop.Domain/Members/Events/SetNationalCodeEvent.cs @@ -0,0 +1,9 @@ +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shop.Domain.Members.Entities; + +namespace Vizhvizh.Shop.Domain.Members.Events; + +public class SetNationalCodeEvent(Member member) : DomainEventBase +{ + public Member Member => member; +} diff --git a/Vichvich.Shop.Domain/Members/ValuesObjects/MemberNationalCode.cs b/Vichvich.Shop.Domain/Members/ValuesObjects/MemberNationalCode.cs new file mode 100644 index 0000000..49218df --- /dev/null +++ b/Vichvich.Shop.Domain/Members/ValuesObjects/MemberNationalCode.cs @@ -0,0 +1,17 @@ +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shared.Domain.Exceptions; + +namespace Vizhvizh.Shop.Domain.Members.ValuesObjects; + +public class MemberNationalCode : ValueObject +{ + public const short Limit = 10; + public MemberNationalCode(string value) + { + if (value.Length > Limit) + throw new CharacterLimitException(nameof(MemberNationalCode), Limit); + + Value = value; + } + public string Value { get; private set; } +} diff --git a/Vichvich.Shop.Domain/Products/Entities/Specifications.cs b/Vichvich.Shop.Domain/Products/Entities/Specifications.cs index dd9d147..1edd27f 100644 --- a/Vichvich.Shop.Domain/Products/Entities/Specifications.cs +++ b/Vichvich.Shop.Domain/Products/Entities/Specifications.cs @@ -27,7 +27,7 @@ public class Specifications : Entity _product = product; } - public static Specifications CreateNew(TitleVO title, Product product, List values) + internal static Specifications CreateNew(TitleVO title, Product product, List values) => new Specifications(title, product, values); public TitleVO Title => _title; diff --git a/Vichvich.Shop.Domain/Shops/Entities/Shop.cs b/Vichvich.Shop.Domain/Shops/Entities/Shop.cs index 967673c..85460eb 100644 --- a/Vichvich.Shop.Domain/Shops/Entities/Shop.cs +++ b/Vichvich.Shop.Domain/Shops/Entities/Shop.cs @@ -22,6 +22,8 @@ public class Shop : Entity, IAggregateRoot private TelephoneVO _telephoneVO; private ShopLogo _logo; private MemberId _ownerId; + private ShopStatus _shopStatus; + private ShopBusinessLicense _businessLicense; private Shop() { @@ -32,6 +34,7 @@ public class Shop : Entity, IAggregateRoot TitleVO title, ShopLocation location, TelephoneVO telephone, + ShopBusinessLicense businessLicense, DescriptionVO? description = null, EmailVO? email = null ) @@ -40,18 +43,22 @@ public class Shop : Entity, IAggregateRoot _title = title; _location = location; _description = description; + _businessLicense = businessLicense; _email = email; _telephoneVO = telephone; + _shopStatus = ShopStatus.CreateNew(ShopStatusEnum.PendingApproval); + } public static Shop CreateNew(MemberId ownerId, TitleVO title, ShopLocation location, TelephoneVO telephone, + ShopBusinessLicense businessLicense, DescriptionVO? description = null, EmailVO? email = null) { - return new Shop(ownerId, title, location, telephone, description, email); + return new Shop(ownerId, title, location, telephone, businessLicense, description, email); } public MemberId OwnerId => _ownerId; public Management Management => _management; @@ -61,6 +68,8 @@ public class Shop : Entity, IAggregateRoot public EmailVO? Email => _email; public TelephoneVO Telephone => _telephoneVO; public ShopLogo Logo => _logo; + public ShopStatus Status => _shopStatus; + public ShopBusinessLicense BusinessLicense => _businessLicense; public IReadOnlyList Products => _products; public IReadOnlyList ShippingMethods => _shippingMethods; public IReadOnlyList Members => _members; diff --git a/Vichvich.Shop.Domain/Shops/ValuesObjects/ShopBusinessLicense.cs b/Vichvich.Shop.Domain/Shops/ValuesObjects/ShopBusinessLicense.cs new file mode 100644 index 0000000..c19f041 --- /dev/null +++ b/Vichvich.Shop.Domain/Shops/ValuesObjects/ShopBusinessLicense.cs @@ -0,0 +1,31 @@ +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shared.Domain.Exceptions; + +namespace Vizhvizh.Shop.Domain.Shops.ValuesObjects; + +/// +/// پروانه کسب +/// +public class ShopBusinessLicense : ValueObject +{ + public const short ImageLimit = 150; + public const short CodeLimit = 50; + + private ShopBusinessLicense(string image, string code) + { + if (image.Length > ImageLimit) + throw new CharacterLimitException("ShopBusinessLicenseImage", ImageLimit); + if (code.Length > CodeLimit) + throw new CharacterLimitException("ShopBusinessLicenseCode", CodeLimit); + + Image = image; + Code = code; + } + + public string Image { get; private set; } + public string Code { get; private set; } + + public static ShopBusinessLicense CreateNew(string image, string code) + => new ShopBusinessLicense(image, code); + +} diff --git a/Vichvich.Shop.Domain/Shops/ValuesObjects/ShopStatus.cs b/Vichvich.Shop.Domain/Shops/ValuesObjects/ShopStatus.cs new file mode 100644 index 0000000..9d8698f --- /dev/null +++ b/Vichvich.Shop.Domain/Shops/ValuesObjects/ShopStatus.cs @@ -0,0 +1,22 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Shops.ValuesObjects; + +public class ShopStatus : ValueObject +{ + public ShopStatus(ShopStatusEnum value) + { + Value = value; + } + public ShopStatusEnum Value { get; private set; } + + public static ShopStatus CreateNew(ShopStatusEnum value) + => new(value); +} + +public enum ShopStatusEnum +{ + Creating = 1, + PendingApproval, + Available, +} \ No newline at end of file diff --git a/Vichvich.Shop.Domain/Vizhvizh.Shop.Domain.csproj b/Vichvich.Shop.Domain/Vizhvizh.Shop.Domain.csproj index 5106873..d659f72 100644 --- a/Vichvich.Shop.Domain/Vizhvizh.Shop.Domain.csproj +++ b/Vichvich.Shop.Domain/Vizhvizh.Shop.Domain.csproj @@ -12,7 +12,6 @@ - diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/MemberConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/MemberConfiguration.cs index 56bc795..d4fe072 100644 --- a/Vichvich.Shop.Infrastructure/EF/Configurations/MemberConfiguration.cs +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/MemberConfiguration.cs @@ -32,5 +32,13 @@ internal class MemberConfiguration : IEntityTypeConfiguration .HasMaxLength(MemberAvatar.Limit) .HasColumnName("Avatar"); }); + + builder.OwnsOne(x => x.NationalCode, sa => + { + sa.Property(x => x.Value) + .IsRequired(false) + .HasMaxLength(MemberNationalCode.Limit) + .HasColumnName("NationalCode"); + }); } } diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/ShopConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/ShopConfiguration.cs index 132fa7a..9b02ff4 100644 --- a/Vichvich.Shop.Infrastructure/EF/Configurations/ShopConfiguration.cs +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/ShopConfiguration.cs @@ -31,6 +31,17 @@ public class ShopConfiguration : IEntityTypeConfiguration x.BusinessLicense, sa => + { + sa.Property(x => x.Image) + .HasMaxLength(ShopBusinessLicense.ImageLimit) + .HasColumnName("ShopBusinessLicenseImage"); + + sa.Property(x => x.Code) + .HasMaxLength(ShopBusinessLicense.CodeLimit) + .HasColumnName("ShopBusinessLicenseCode"); + + }); builder.OwnsOne(x => x.Location, sa => { sa.Property(x => x.PostalCode).HasColumnName(nameof(ShopLocation.PostalCode)); diff --git a/Vichvich.UserAccess.Domain/Entities/User.cs b/Vichvich.UserAccess.Domain/Entities/User.cs index cb19bc5..e73c842 100644 --- a/Vichvich.UserAccess.Domain/Entities/User.cs +++ b/Vichvich.UserAccess.Domain/Entities/User.cs @@ -6,21 +6,21 @@ namespace Vizhvizh.UserAccess.Domain.Entities; public class User : Entity, IAggregateRoot { - private UserNationalCode _nationalCode; + private MemberNationalCode _nationalCode; private MemberId _memberId; private List _roles; - private User(UserNationalCode nationalCode,MemberId memberId,List roles) + private User(MemberNationalCode nationalCode,MemberId memberId,List roles) { _nationalCode = nationalCode; _memberId = memberId; _roles = roles; } - public static User CreateNew(UserNationalCode nationalCode, MemberId memberId, List roles) + public static User CreateNew(MemberNationalCode nationalCode, MemberId memberId, List roles) => new User(nationalCode, memberId, roles); - public UserNationalCode NationalCode => _nationalCode; + public MemberNationalCode NationalCode => _nationalCode; public MemberId MemberId => _memberId; public IReadOnlyList Roles => _roles; } diff --git a/Vichvich.UserAccess.Domain/ValueObjects/UserNationalCode.cs b/Vichvich.UserAccess.Domain/ValueObjects/MemberNationalCode.cs similarity index 94% rename from Vichvich.UserAccess.Domain/ValueObjects/UserNationalCode.cs rename to Vichvich.UserAccess.Domain/ValueObjects/MemberNationalCode.cs index 1712c0d..12c49b7 100644 --- a/Vichvich.UserAccess.Domain/ValueObjects/UserNationalCode.cs +++ b/Vichvich.UserAccess.Domain/ValueObjects/MemberNationalCode.cs @@ -3,7 +3,7 @@ using Vizhvizh.BuildingBlocks.Domain; namespace Vizhvizh.UserAccess.Domain.ValueObjects; -public class UserNationalCode : ValueObject +public class MemberNationalCode : ValueObject { public static bool IsValidNationalCode(string nationalCode) { @@ -37,7 +37,7 @@ public class UserNationalCode : ValueObject else return false; } - public UserNationalCode(string value) + public MemberNationalCode(string value) { if (!IsValidNationalCode(value)) throw new InvalidNationalCodeException();