diff --git a/src/Core/EnglishNote.Application/Abtractions/IDateTimeProvider.cs b/src/Core/EnglishNote.Application/Abtractions/IDateTimeProvider.cs new file mode 100644 index 0000000..7615c5b --- /dev/null +++ b/src/Core/EnglishNote.Application/Abtractions/IDateTimeProvider.cs @@ -0,0 +1,6 @@ +namespace EnglishNote.Application.Abtractions; +public interface IDateTimeProvider +{ + DateTime UtcNow { get; } + DateTime Now { get; } +} \ No newline at end of file diff --git a/src/Core/EnglishNote.Application/Abtractions/IGuidGenerator.cs b/src/Core/EnglishNote.Application/Abtractions/IGuidGenerator.cs new file mode 100644 index 0000000..2dda344 --- /dev/null +++ b/src/Core/EnglishNote.Application/Abtractions/IGuidGenerator.cs @@ -0,0 +1,5 @@ +namespace EnglishNote.Application.Abtractions; +public interface IGuidGenerator +{ + Guid NewGuid(); +} diff --git a/src/Core/EnglishNote.Application/IAssemblyMarker.cs b/src/Core/EnglishNote.Application/IAssemblyMarker.cs index 73579e1..df5ae12 100644 --- a/src/Core/EnglishNote.Application/IAssemblyMarker.cs +++ b/src/Core/EnglishNote.Application/IAssemblyMarker.cs @@ -1,4 +1,2 @@ namespace EnglishNote.Application; -internal interface IAssemblyMarker -{ -} +internal interface IAssemblyMarker; diff --git a/src/Core/EnglishNote.Application/UseCases/Tags/CreateTag/CreateTagCommandHandler.cs b/src/Core/EnglishNote.Application/UseCases/Tags/CreateTag/CreateTagCommandHandler.cs index 92809ef..b20086d 100644 --- a/src/Core/EnglishNote.Application/UseCases/Tags/CreateTag/CreateTagCommandHandler.cs +++ b/src/Core/EnglishNote.Application/UseCases/Tags/CreateTag/CreateTagCommandHandler.cs @@ -1,4 +1,5 @@ -using EnglishNote.Application.Abtractions.Authentication; +using EnglishNote.Application.Abtractions; +using EnglishNote.Application.Abtractions.Authentication; using EnglishNote.Application.Abtractions.Commands; using EnglishNote.Domain.AggregatesModel.Tags; using Shared; @@ -6,15 +7,17 @@ namespace EnglishNote.Application.UseCases.Tags.CreateTag; internal class CreateTagCommandHandler( ITagRepository tagRepository, - IIdentityService identityService) : ICommandHandler + IIdentityService identityService, + IGuidGenerator guidGenerator) : ICommandHandler { public async Task> Handle(CreateTagCommand request, CancellationToken cancellationToken) { - var tag = Tag.CreateTag(request.Name, + var tag = Tag.CreateTag(guidGenerator.NewGuid(), + request.Name, request.Description, identityService.GetUserIdentity()); - await tagRepository.AddAsync(tag); + await tagRepository.AddAsync(tag, cancellationToken); return tag.Id; } diff --git a/src/Core/EnglishNote.Application/UseCases/Words/CreateWord/CreateWordCommand.cs b/src/Core/EnglishNote.Application/UseCases/Words/CreateWord/CreateWordCommand.cs new file mode 100644 index 0000000..c7ddce5 --- /dev/null +++ b/src/Core/EnglishNote.Application/UseCases/Words/CreateWord/CreateWordCommand.cs @@ -0,0 +1,20 @@ +using EnglishNote.Application.Abtractions.Commands; +using EnglishNote.Domain.AggregatesModel.Words; + +namespace EnglishNote.Application.UseCases.Words.CreateWord; +public record CreateWordCommand(string WordText, + List Phonetics, + List Meanings) : ICommand; + +public record WordPhoneticRequest(string Text, + string? Audio, + string? CustomAudio); + +public record WordMeaningRequest(PartOfSpeech? PartOfSpeech, + CefrLevel? CefrLevel, + List Definitions); + +public record WorkDefinitionRequest(string DefinitionText, + List Synonyms, + List Antonyms, + List Examples); \ No newline at end of file diff --git a/src/Core/EnglishNote.Application/UseCases/Words/CreateWord/CreateWordCommandHandler.cs b/src/Core/EnglishNote.Application/UseCases/Words/CreateWord/CreateWordCommandHandler.cs new file mode 100644 index 0000000..6b90748 --- /dev/null +++ b/src/Core/EnglishNote.Application/UseCases/Words/CreateWord/CreateWordCommandHandler.cs @@ -0,0 +1,47 @@ +using EnglishNote.Application.Abtractions; +using EnglishNote.Application.Abtractions.Authentication; +using EnglishNote.Application.Abtractions.Commands; +using EnglishNote.Domain.AggregatesModel.Words; +using Shared; + +namespace EnglishNote.Application.UseCases.Words.CreateWord; +internal sealed class CreateWordCommandHandler(IGuidGenerator guidGenerator, + IIdentityService identityService, + IWordRepository wordRepository) : ICommandHandler +{ + public async Task> Handle(CreateWordCommand request, CancellationToken cancellationToken) + { + var word = Word.Create(id: guidGenerator.NewGuid(), + wordText: request.WordText, + tagId: null, + vocabularySetId: null, + userId: identityService.GetUserIdentity(), + null); + + foreach (var item in request.Phonetics) + { + word.AddPhonetic(item.Text, item.Audio, item.CustomAudio); + } + + foreach (var meaning in request.Meanings) + { + if(meaning is null) continue; + + var mean = word.CreateAndAddMeaning(meaning.PartOfSpeech, meaning.CefrLevel); + + foreach (var definition in meaning.Definitions) + { + if(definition is null) continue; + + word.AddDefinition(mean, + definition.DefinitionText, + definition.Synonyms, + definition.Antonyms, + definition.Examples); + } + } + + await wordRepository.AddAsync(word, cancellationToken); + return word.Id; + } +} diff --git a/src/Core/EnglishNote.Domain/AggregatesModel/Tags/ITagRepository.cs b/src/Core/EnglishNote.Domain/AggregatesModel/Tags/ITagRepository.cs index 53ca5a9..0decd22 100644 --- a/src/Core/EnglishNote.Domain/AggregatesModel/Tags/ITagRepository.cs +++ b/src/Core/EnglishNote.Domain/AggregatesModel/Tags/ITagRepository.cs @@ -1,5 +1,5 @@ namespace EnglishNote.Domain.AggregatesModel.Tags; public interface ITagRepository { - Task AddAsync(Tag tag); + Task AddAsync(Tag tag, CancellationToken cancellationToken = default); } diff --git a/src/Core/EnglishNote.Domain/AggregatesModel/Tags/Tag.cs b/src/Core/EnglishNote.Domain/AggregatesModel/Tags/Tag.cs index 8c8edd5..c9e98ef 100644 --- a/src/Core/EnglishNote.Domain/AggregatesModel/Tags/Tag.cs +++ b/src/Core/EnglishNote.Domain/AggregatesModel/Tags/Tag.cs @@ -19,11 +19,14 @@ public class Tag : AggregateRoot private Tag() { } - public static Tag CreateTag(string name, string? description, Guid userId) + public static Tag CreateTag(Guid id, + string name, + string? description, + Guid userId) { return new Tag() { - Id = Guid.CreateVersion7(), + Id = id, Name = name, Description = description, UserId = userId diff --git a/src/Core/EnglishNote.Domain/AggregatesModel/Words/Antonym.cs b/src/Core/EnglishNote.Domain/AggregatesModel/Words/Antonym.cs index d41d2bb..8ac470b 100644 --- a/src/Core/EnglishNote.Domain/AggregatesModel/Words/Antonym.cs +++ b/src/Core/EnglishNote.Domain/AggregatesModel/Words/Antonym.cs @@ -3,9 +3,19 @@ namespace EnglishNote.Domain.AggregatesModel.Words; public class Antonym : ValueObject { - public string Value { get; private set; } + private Antonym() { } + + public string? Value { get; private set; } protected override IEnumerable GetEqualityComponents() { yield return Value; } + + internal static Antonym Create(string value) + { + return new Antonym() + { + Value = value + }; + } } diff --git a/src/Core/EnglishNote.Domain/AggregatesModel/Words/CefrLevel.cs b/src/Core/EnglishNote.Domain/AggregatesModel/Words/CefrLevel.cs new file mode 100644 index 0000000..5047f0a --- /dev/null +++ b/src/Core/EnglishNote.Domain/AggregatesModel/Words/CefrLevel.cs @@ -0,0 +1,10 @@ +namespace EnglishNote.Domain.AggregatesModel.Words; +public enum CefrLevel +{ + A1 = 1, + A2 = 2, + B1 = 3, + B2 = 4, + C1 = 5, + C2 = 6, +} diff --git a/src/Core/EnglishNote.Domain/AggregatesModel/Words/Definition.cs b/src/Core/EnglishNote.Domain/AggregatesModel/Words/Definition.cs index b741702..13b461a 100644 --- a/src/Core/EnglishNote.Domain/AggregatesModel/Words/Definition.cs +++ b/src/Core/EnglishNote.Domain/AggregatesModel/Words/Definition.cs @@ -3,6 +3,8 @@ namespace EnglishNote.Domain.AggregatesModel.Words; public class Definition : ValueObject { + private Definition() { } + public string DefinitionText { get; private set; } public IReadOnlyCollection Synonyms => _synonyms.AsReadOnly(); public IReadOnlyCollection Antonyms => _antonyms.AsReadOnly(); @@ -19,4 +21,44 @@ protected override IEnumerable GetEqualityComponents() yield return Antonyms; yield return Examples; } + + internal static Definition Create(string definitionText, + List synonyms, + List antonyms, + List examples) + { + var definition = new Definition() + { + DefinitionText = definitionText + }; + + definition.AddExample(examples); + definition.AddSynonyms(synonyms); + definition.AddAntonyms(antonyms); + + return definition; + } + + internal void AddSynonyms(List synonyms) { + foreach (var item in synonyms) + { + _synonyms.Add(Synonym.Create(item)); + } + } + + internal void AddAntonyms(List antonyms) + { + foreach (var item in antonyms) + { + _antonyms.Add(Antonym.Create(item)); + } + } + + internal void AddExample(List examples) + { + foreach(var item in examples) + { + _examples.Add(Example.Create(item)); + } + } } diff --git a/src/Core/EnglishNote.Domain/AggregatesModel/Words/Example.cs b/src/Core/EnglishNote.Domain/AggregatesModel/Words/Example.cs index f3634c8..daf6099 100644 --- a/src/Core/EnglishNote.Domain/AggregatesModel/Words/Example.cs +++ b/src/Core/EnglishNote.Domain/AggregatesModel/Words/Example.cs @@ -3,9 +3,19 @@ namespace EnglishNote.Domain.AggregatesModel.Words; public class Example : ValueObject { + private Example() { } + public string Value { get; private set; } protected override IEnumerable GetEqualityComponents() { yield return Value; } + + internal static Example Create(string value) + { + return new Example() + { + Value = value + }; + } } diff --git a/src/Core/EnglishNote.Domain/AggregatesModel/Words/IWordRepository.cs b/src/Core/EnglishNote.Domain/AggregatesModel/Words/IWordRepository.cs new file mode 100644 index 0000000..8789769 --- /dev/null +++ b/src/Core/EnglishNote.Domain/AggregatesModel/Words/IWordRepository.cs @@ -0,0 +1,5 @@ +namespace EnglishNote.Domain.AggregatesModel.Words; +public interface IWordRepository +{ + Task AddAsync(Word word, CancellationToken cancellationToken = default); +} diff --git a/src/Core/EnglishNote.Domain/AggregatesModel/Words/Meaning.cs b/src/Core/EnglishNote.Domain/AggregatesModel/Words/Meaning.cs deleted file mode 100644 index 7b8f227..0000000 --- a/src/Core/EnglishNote.Domain/AggregatesModel/Words/Meaning.cs +++ /dev/null @@ -1,21 +0,0 @@ -using EnglishNote.Domain.SeedWork; - -namespace EnglishNote.Domain.AggregatesModel.Words; - -public class Meaning : ValueObject -{ - public string PartOfSpeech { get; private set; } - - public string CefrLevel { get; private set; } - - public IReadOnlyList Definitions => _definition.AsReadOnly(); - - private readonly List _definition = []; - - protected override IEnumerable GetEqualityComponents() - { - yield return PartOfSpeech; - yield return CefrLevel; - yield return Definitions; - } -} \ No newline at end of file diff --git a/src/Core/EnglishNote.Domain/AggregatesModel/Words/PartOfSpeech.cs b/src/Core/EnglishNote.Domain/AggregatesModel/Words/PartOfSpeech.cs new file mode 100644 index 0000000..3f5b7e6 --- /dev/null +++ b/src/Core/EnglishNote.Domain/AggregatesModel/Words/PartOfSpeech.cs @@ -0,0 +1,12 @@ +namespace EnglishNote.Domain.AggregatesModel.Words; +public enum PartOfSpeech +{ + Noun = 1, + Pronoun = 2, + Verb = 3, + Adjective = 4, + Adverb = 5, + Preposition = 6, + Conjunction = 7, + Interjection = 8 +} diff --git a/src/Core/EnglishNote.Domain/AggregatesModel/Words/Synonym.cs b/src/Core/EnglishNote.Domain/AggregatesModel/Words/Synonym.cs index 298f0e6..fed6311 100644 --- a/src/Core/EnglishNote.Domain/AggregatesModel/Words/Synonym.cs +++ b/src/Core/EnglishNote.Domain/AggregatesModel/Words/Synonym.cs @@ -3,9 +3,16 @@ namespace EnglishNote.Domain.AggregatesModel.Words; public class Synonym : ValueObject { + private Synonym() { } + public string Value { get; private set; } protected override IEnumerable GetEqualityComponents() { yield return Value; } + + internal static Synonym Create(string value) + { + return new Synonym() { Value = value }; + } } diff --git a/src/Core/EnglishNote.Domain/AggregatesModel/Words/Word.cs b/src/Core/EnglishNote.Domain/AggregatesModel/Words/Word.cs index 78060e7..2451163 100644 --- a/src/Core/EnglishNote.Domain/AggregatesModel/Words/Word.cs +++ b/src/Core/EnglishNote.Domain/AggregatesModel/Words/Word.cs @@ -8,19 +8,71 @@ namespace EnglishNote.Domain.AggregatesModel.Words; public class Word : AggregateRoot { public string WordText { get; private set; } - public IReadOnlyList Phonetics => _phonetics.AsReadOnly(); - public IReadOnlyList Meanings => _meanings.AsReadOnly(); + public IReadOnlyList Phonetics => _phonetics.AsReadOnly(); + public IReadOnlyList Meanings => _meanings.AsReadOnly(); public MemoryLevel? MemoryLevel { get; private set; } - public Tag Tag { get; private set; } - public Guid TagId { get; private set; } + public Tag? Tag { get; private set; } + public Guid? TagId { get; private set; } public Guid UserId { get; private set; } public ApplicationUser User { get; private set; } - public VocabularySet VocabularySet { get; private set; } - public Guid VocabularySetId { get; private set; } + public VocabularySet? VocabularySet { get; private set; } + public Guid? VocabularySetId { get; private set; } - private readonly List _phonetics = []; - private readonly List _meanings = []; -} \ No newline at end of file + private readonly List _phonetics = []; + private readonly List _meanings = []; + + public static Word Create(Guid id, + string wordText, + Guid? tagId, + Guid? vocabularySetId, + Guid userId, + MemoryLevel? memoryLevel + + ) + { + var word = new Word() + { + Id = id, + WordText = wordText, + TagId = tagId, + VocabularySetId = vocabularySetId, + UserId = userId, + MemoryLevel = memoryLevel + }; + + return word; + } + + public void AddPhonetic(string text, + string? audio, + string? customAudio) + { + var phonetic = WordPhonetic.Create(text, audio, customAudio); + _phonetics.Add(phonetic); + } + + public void AddMeaning(PartOfSpeech? partOfSpeech, CefrLevel? cefrLevel) + { + var meaning = WordMeaning.Create(partOfSpeech, cefrLevel); + _meanings.Add(meaning); + } + + public WordMeaning CreateAndAddMeaning(PartOfSpeech? partOfSpeech, CefrLevel? cefrLevel) + { + var meaning = WordMeaning.Create(partOfSpeech, cefrLevel); + _meanings.Add(meaning); + return meaning; + } + + public void AddDefinition(WordMeaning meaning, + string definitionText, + List synonyms, + List antonyms, + List examples) + { + meaning.AddDefinition(definitionText, synonyms, antonyms, examples); + } +} diff --git a/src/Core/EnglishNote.Domain/AggregatesModel/Words/WordManner.cs b/src/Core/EnglishNote.Domain/AggregatesModel/Words/WordManner.cs new file mode 100644 index 0000000..c5f5f2b --- /dev/null +++ b/src/Core/EnglishNote.Domain/AggregatesModel/Words/WordManner.cs @@ -0,0 +1,7 @@ +using EnglishNote.Domain.SeedWork; + +namespace EnglishNote.Domain.AggregatesModel.Words; +public sealed class WordManner : DomainService +{ + +} diff --git a/src/Core/EnglishNote.Domain/AggregatesModel/Words/WordMeaning.cs b/src/Core/EnglishNote.Domain/AggregatesModel/Words/WordMeaning.cs new file mode 100644 index 0000000..4f2a90d --- /dev/null +++ b/src/Core/EnglishNote.Domain/AggregatesModel/Words/WordMeaning.cs @@ -0,0 +1,42 @@ +using EnglishNote.Domain.SeedWork; + +namespace EnglishNote.Domain.AggregatesModel.Words; + +public class WordMeaning : ValueObject +{ + private WordMeaning() { } + + public PartOfSpeech? PartOfSpeech { get; private set; } + + public CefrLevel? CefrLevel { get; private set; } + + public IReadOnlyList Definitions => _definitions.AsReadOnly(); + + private readonly List _definitions = []; + + protected override IEnumerable GetEqualityComponents() + { + yield return PartOfSpeech; + yield return CefrLevel; + yield return Definitions; + } + + internal static WordMeaning Create(PartOfSpeech? partOfSpeech, CefrLevel? cefrLevel) + { + var meaning = new WordMeaning + { + PartOfSpeech = partOfSpeech, + CefrLevel = cefrLevel, + }; + return meaning; + } + + internal void AddDefinition(string definitionText, + List synonyms, + List antonyms, + List examples) + { + var definition = Definition.Create(definitionText, synonyms, antonyms, examples); + _definitions.Add(definition); + } +} \ No newline at end of file diff --git a/src/Core/EnglishNote.Domain/AggregatesModel/Words/Phonetic.cs b/src/Core/EnglishNote.Domain/AggregatesModel/Words/WordPhonetic.cs similarity index 50% rename from src/Core/EnglishNote.Domain/AggregatesModel/Words/Phonetic.cs rename to src/Core/EnglishNote.Domain/AggregatesModel/Words/WordPhonetic.cs index 32499ff..cc275eb 100644 --- a/src/Core/EnglishNote.Domain/AggregatesModel/Words/Phonetic.cs +++ b/src/Core/EnglishNote.Domain/AggregatesModel/Words/WordPhonetic.cs @@ -1,8 +1,10 @@ using EnglishNote.Domain.SeedWork; namespace EnglishNote.Domain.AggregatesModel.Words; -public class Phonetic : ValueObject +public class WordPhonetic : ValueObject { + private WordPhonetic() { } + public string Text { get; private set; } public string? Audio { get; private set; } public string? CustomAudio { get; private set; } @@ -13,4 +15,15 @@ protected override IEnumerable GetEqualityComponents() yield return Audio; yield return CustomAudio; } + + internal static WordPhonetic Create(string text, + string? audio, + string? customAudio) + { + return new WordPhonetic() { + Text = text, + Audio = audio, + CustomAudio = customAudio + }; + } } \ No newline at end of file diff --git a/src/Core/EnglishNote.Domain/SeedWork/IDomainService.cs b/src/Core/EnglishNote.Domain/SeedWork/IDomainService.cs new file mode 100644 index 0000000..2cc109e --- /dev/null +++ b/src/Core/EnglishNote.Domain/SeedWork/IDomainService.cs @@ -0,0 +1,2 @@ +namespace EnglishNote.Domain.SeedWork; +public abstract class DomainService { } diff --git a/src/Host/EnglishNote.Presentation/EndpointSchema.cs b/src/Host/EnglishNote.Presentation/EndpointSchema.cs index 290de68..d5e9910 100644 --- a/src/Host/EnglishNote.Presentation/EndpointSchema.cs +++ b/src/Host/EnglishNote.Presentation/EndpointSchema.cs @@ -3,5 +3,9 @@ public class EndpointSchema { public const string Tag = "tag"; + public const string Word = "word"; + public const string Test = "test"; + + public const string Default = ""; } diff --git a/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/CreateWordEndpoint.cs b/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/CreateWordEndpoint.cs new file mode 100644 index 0000000..4624430 --- /dev/null +++ b/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/CreateWordEndpoint.cs @@ -0,0 +1,23 @@ +using EnglishNote.Application.UseCases.Words.CreateWord; +using MapsterMapper; +using MediatR; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Routing; + +namespace EnglishNote.Presentation.Private.WordEndpoints.CreateWord; +internal class CreateWordEndpoint : IPrivateEndpoint +{ + public string EndpointName => EndpointSchema.Word; + + public void MapEndpoint(IEndpointRouteBuilder app) + { + app.MapPost("", async ( + CreateWordRequest request, + IMapper mapper, + ISender sender) => + { + var command = mapper.Map(request); + return await sender.Send(command); + }); + } +} diff --git a/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/CreateWordRequest.cs b/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/CreateWordRequest.cs new file mode 100644 index 0000000..5004f22 --- /dev/null +++ b/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/CreateWordRequest.cs @@ -0,0 +1,19 @@ +using EnglishNote.Domain.AggregatesModel.Words; + +namespace EnglishNote.Presentation.Private.WordEndpoints.CreateWord; +public record CreateWordRequest(string WordText, + List Phonetics, + List Meanings); + +public record WordPhoneticRequest(string Text, + string? Audio, + string? CustomAudio); + +public record WordMeaningRequest(PartOfSpeech? PartOfSpeech, + CefrLevel? CefrLevel, + List Definitions); + +public record WorkDefinitionRequest(string DefinitionText, + List Synonyms, + List Antonyms, + List Examples); \ No newline at end of file diff --git a/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/CreateWordRequestValidator.cs b/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/CreateWordRequestValidator.cs new file mode 100644 index 0000000..f2a23fc --- /dev/null +++ b/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/CreateWordRequestValidator.cs @@ -0,0 +1,22 @@ +using FluentValidation; + +namespace EnglishNote.Presentation.Private.WordEndpoints.CreateWord; +internal sealed class CreateWordRequestValidator : AbstractValidator +{ + public CreateWordRequestValidator() + { + RuleFor(x => x.WordText) + .NotEmpty() + .NotNull(); + + RuleFor(x => x.Phonetics) + .Must(phonetics => phonetics is not null && phonetics.Count > 0) + .WithMessage("The list of phonetics must conataina at least one item") + .ForEach(phonetic => phonetic.SetValidator(new WordPhoneticRequestValidator())); + + RuleFor(word => word.Meanings) + .Must(meanings => meanings != null && meanings.Count > 0) + .WithMessage("The list of meanings must contain at least one item.") + .ForEach(mean => mean.SetValidator(new WordMeaningRequestValidator())); + } +} diff --git a/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/WordMeaningRequestValidator.cs b/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/WordMeaningRequestValidator.cs new file mode 100644 index 0000000..bf34638 --- /dev/null +++ b/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/WordMeaningRequestValidator.cs @@ -0,0 +1,14 @@ +using FluentValidation; + +namespace EnglishNote.Presentation.Private.WordEndpoints.CreateWord; +internal class WordMeaningRequestValidator : AbstractValidator +{ + public WordMeaningRequestValidator() + { + RuleFor(x => x.Definitions) + .NotEmpty() + .NotNull() + .Must(x => x.Count > 0) + .ForEach(definition => definition.SetValidator(new WorkDefinitionRequestValidator())); + } +} diff --git a/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/WordPhoneticRequestValidator.cs b/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/WordPhoneticRequestValidator.cs new file mode 100644 index 0000000..3311c88 --- /dev/null +++ b/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/WordPhoneticRequestValidator.cs @@ -0,0 +1,11 @@ +using FluentValidation; + +namespace EnglishNote.Presentation.Private.WordEndpoints.CreateWord; +internal class WordPhoneticRequestValidator : AbstractValidator +{ + public WordPhoneticRequestValidator() + { + RuleFor(x => x.Text) + .NotNull(); + } +} diff --git a/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/WorkDefinitionRequestValidator.cs b/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/WorkDefinitionRequestValidator.cs new file mode 100644 index 0000000..f0cf1e8 --- /dev/null +++ b/src/Host/EnglishNote.Presentation/Private/WordEndpoints/CreateWord/WorkDefinitionRequestValidator.cs @@ -0,0 +1,20 @@ +using FluentValidation; + +namespace EnglishNote.Presentation.Private.WordEndpoints.CreateWord; +internal class WorkDefinitionRequestValidator : AbstractValidator +{ + public WorkDefinitionRequestValidator() + { + RuleFor(x => x.Examples) + .NotEmpty() + .Must(x => !x.Any(item => string.IsNullOrEmpty(item))); + + RuleFor(x => x.Antonyms) + .NotEmpty() + .Must(x => !x.Any(item => string.IsNullOrEmpty(item))); + + RuleFor(x => x.Synonyms) + .NotEmpty() + .Must(x => !x.Any(item => string.IsNullOrEmpty(item))); + } +} diff --git a/src/Infrastructure/EnglishNote.Infrastructure.Persistence/EntityConfigurations/WordEntityTypeConfiguration.cs b/src/Infrastructure/EnglishNote.Infrastructure.Persistence/EntityConfigurations/WordEntityTypeConfiguration.cs index 87843a7..2def8e7 100644 --- a/src/Infrastructure/EnglishNote.Infrastructure.Persistence/EntityConfigurations/WordEntityTypeConfiguration.cs +++ b/src/Infrastructure/EnglishNote.Infrastructure.Persistence/EntityConfigurations/WordEntityTypeConfiguration.cs @@ -25,11 +25,9 @@ public void Configure(EntityTypeBuilder builder) .HasMaxLength(500); phoneticBuilder.Property(x => x.Audio) - .IsRequired() .HasMaxLength(500); phoneticBuilder.Property(x => x.CustomAudio) - .IsRequired() .HasMaxLength(36); }); @@ -38,10 +36,12 @@ public void Configure(EntityTypeBuilder builder) { meaningBuilder .Property(x => x.CefrLevel) + .HasConversion() .HasMaxLength(10); meaningBuilder .Property(x => x.PartOfSpeech) + .HasConversion() .HasMaxLength(50); meaningBuilder @@ -49,6 +49,7 @@ public void Configure(EntityTypeBuilder builder) { definitionBuilder .Property(x => x.DefinitionText) + .IsRequired() .HasMaxLength(1024); definitionBuilder diff --git a/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/20241123052016_InitDb.Designer.cs b/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/20241127071802_InitDb.Designer.cs similarity index 84% rename from src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/20241123052016_InitDb.Designer.cs rename to src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/20241127071802_InitDb.Designer.cs index faa79ee..c34420c 100644 --- a/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/20241123052016_InitDb.Designer.cs +++ b/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/20241127071802_InitDb.Designer.cs @@ -12,7 +12,7 @@ namespace EnglishNote.Infrastructure.Persistence.Migrations { [DbContext(typeof(ApplicationWriteDbContext))] - [Migration("20241123052016_InitDb")] + [Migration("20241127071802_InitDb")] partial class InitDb { /// @@ -25,7 +25,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - modelBuilder.Entity("EnglishNote.Domain.Identity.ApplicationRole", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Identity.ApplicationRole", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -53,7 +53,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetRoles", (string)null); }); - modelBuilder.Entity("EnglishNote.Domain.Identity.ApplicationUser", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -127,7 +127,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetUsers", (string)null); }); - modelBuilder.Entity("EnglishNote.Domain.QuizSessions.QuizSession", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.QuizSessions.QuizSession", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -167,7 +167,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("QuizSessions"); }); - modelBuilder.Entity("EnglishNote.Domain.Tags.Tag", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Tags.Tag", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -193,7 +193,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("Tags"); }); - modelBuilder.Entity("EnglishNote.Domain.VocabularySets.VocabularySet", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.VocabularySets.VocabularySet", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -225,7 +225,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("VocabularySets"); }); - modelBuilder.Entity("EnglishNote.Domain.Words.Word", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Words.Word", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -235,13 +235,13 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasMaxLength(50) .HasColumnType("nvarchar(50)"); - b.Property("TagId") + b.Property("TagId") .HasColumnType("uniqueidentifier"); b.Property("UserId") .HasColumnType("uniqueidentifier"); - b.Property("VocabularySetId") + b.Property("VocabularySetId") .HasColumnType("uniqueidentifier"); b.Property("WordText") @@ -363,17 +363,17 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.ToTable("AspNetUserTokens", (string)null); }); - modelBuilder.Entity("EnglishNote.Domain.QuizSessions.QuizSession", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.QuizSessions.QuizSession", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", "User") + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", "User") .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("EnglishNote.Domain.VocabularySets.VocabularySet", "VocabularySet") + b.HasOne("EnglishNote.Domain.AggregatesModel.VocabularySets.VocabularySet", "VocabularySet") .WithOne("QuizSession") - .HasForeignKey("EnglishNote.Domain.QuizSessions.QuizSession", "VocabularySetId") + .HasForeignKey("EnglishNote.Domain.AggregatesModel.QuizSessions.QuizSession", "VocabularySetId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); @@ -382,9 +382,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("VocabularySet"); }); - modelBuilder.Entity("EnglishNote.Domain.Tags.Tag", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Tags.Tag", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", "User") + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", "User") .WithMany("Tags") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Restrict) @@ -393,9 +393,9 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("User"); }); - modelBuilder.Entity("EnglishNote.Domain.VocabularySets.VocabularySet", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.VocabularySets.VocabularySet", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", "User") + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", "User") .WithMany("VocabularySets") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -404,27 +404,25 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("User"); }); - modelBuilder.Entity("EnglishNote.Domain.Words.Word", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Words.Word", b => { - b.HasOne("EnglishNote.Domain.Tags.Tag", "Tag") + b.HasOne("EnglishNote.Domain.AggregatesModel.Tags.Tag", "Tag") .WithMany("Words") .HasForeignKey("TagId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); + .OnDelete(DeleteBehavior.Restrict); - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", "User") + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", "User") .WithMany("Words") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("EnglishNote.Domain.VocabularySets.VocabularySet", "VocabularySet") + b.HasOne("EnglishNote.Domain.AggregatesModel.VocabularySets.VocabularySet", "VocabularySet") .WithMany("Words") .HasForeignKey("VocabularySetId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); + .OnDelete(DeleteBehavior.Restrict); - b.OwnsMany("EnglishNote.Domain.Words.Meaning", "Meanings", b1 => + b.OwnsMany("EnglishNote.Domain.AggregatesModel.Words.WordMeaning", "Meanings", b1 => { b1.Property("WordId") .HasColumnType("uniqueidentifier"); @@ -436,28 +434,26 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); b1.Property("CefrLevel") - .IsRequired() .HasMaxLength(10) .HasColumnType("nvarchar(10)"); b1.Property("PartOfSpeech") - .IsRequired() .HasMaxLength(50) .HasColumnType("nvarchar(50)"); b1.HasKey("WordId", "Id"); - b1.ToTable("Meaning"); + b1.ToTable("WordMeaning"); b1.WithOwner() .HasForeignKey("WordId"); - b1.OwnsMany("EnglishNote.Domain.Words.Definition", "Definitions", b2 => + b1.OwnsMany("EnglishNote.Domain.AggregatesModel.Words.Definition", "Definitions", b2 => { - b2.Property("MeaningWordId") + b2.Property("WordMeaningWordId") .HasColumnType("uniqueidentifier"); - b2.Property("MeaningId") + b2.Property("WordMeaningId") .HasColumnType("int"); b2.Property("Id") @@ -471,19 +467,19 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasMaxLength(1024) .HasColumnType("nvarchar(1024)"); - b2.HasKey("MeaningWordId", "MeaningId", "Id"); + b2.HasKey("WordMeaningWordId", "WordMeaningId", "Id"); b2.ToTable("Definition"); b2.WithOwner() - .HasForeignKey("MeaningWordId", "MeaningId"); + .HasForeignKey("WordMeaningWordId", "WordMeaningId"); - b2.OwnsMany("EnglishNote.Domain.Words.Antonym", "Antonyms", b3 => + b2.OwnsMany("EnglishNote.Domain.AggregatesModel.Words.Antonym", "Antonyms", b3 => { - b3.Property("DefinitionMeaningWordId") + b3.Property("DefinitionWordMeaningWordId") .HasColumnType("uniqueidentifier"); - b3.Property("DefinitionMeaningId") + b3.Property("DefinitionWordMeaningId") .HasColumnType("int"); b3.Property("DefinitionId") @@ -500,20 +496,20 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasMaxLength(126) .HasColumnType("nvarchar(126)"); - b3.HasKey("DefinitionMeaningWordId", "DefinitionMeaningId", "DefinitionId", "Id"); + b3.HasKey("DefinitionWordMeaningWordId", "DefinitionWordMeaningId", "DefinitionId", "Id"); b3.ToTable("Antonym"); b3.WithOwner() - .HasForeignKey("DefinitionMeaningWordId", "DefinitionMeaningId", "DefinitionId"); + .HasForeignKey("DefinitionWordMeaningWordId", "DefinitionWordMeaningId", "DefinitionId"); }); - b2.OwnsMany("EnglishNote.Domain.Words.Example", "Examples", b3 => + b2.OwnsMany("EnglishNote.Domain.AggregatesModel.Words.Example", "Examples", b3 => { - b3.Property("DefinitionMeaningWordId") + b3.Property("DefinitionWordMeaningWordId") .HasColumnType("uniqueidentifier"); - b3.Property("DefinitionMeaningId") + b3.Property("DefinitionWordMeaningId") .HasColumnType("int"); b3.Property("DefinitionId") @@ -530,20 +526,20 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasMaxLength(1024) .HasColumnType("nvarchar(1024)"); - b3.HasKey("DefinitionMeaningWordId", "DefinitionMeaningId", "DefinitionId", "Id"); + b3.HasKey("DefinitionWordMeaningWordId", "DefinitionWordMeaningId", "DefinitionId", "Id"); b3.ToTable("Example"); b3.WithOwner() - .HasForeignKey("DefinitionMeaningWordId", "DefinitionMeaningId", "DefinitionId"); + .HasForeignKey("DefinitionWordMeaningWordId", "DefinitionWordMeaningId", "DefinitionId"); }); - b2.OwnsMany("EnglishNote.Domain.Words.Synonym", "Synonyms", b3 => + b2.OwnsMany("EnglishNote.Domain.AggregatesModel.Words.Synonym", "Synonyms", b3 => { - b3.Property("DefinitionMeaningWordId") + b3.Property("DefinitionWordMeaningWordId") .HasColumnType("uniqueidentifier"); - b3.Property("DefinitionMeaningId") + b3.Property("DefinitionWordMeaningId") .HasColumnType("int"); b3.Property("DefinitionId") @@ -560,12 +556,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) .HasMaxLength(126) .HasColumnType("nvarchar(126)"); - b3.HasKey("DefinitionMeaningWordId", "DefinitionMeaningId", "DefinitionId", "Id"); + b3.HasKey("DefinitionWordMeaningWordId", "DefinitionWordMeaningId", "DefinitionId", "Id"); b3.ToTable("Synonym"); b3.WithOwner() - .HasForeignKey("DefinitionMeaningWordId", "DefinitionMeaningId", "DefinitionId"); + .HasForeignKey("DefinitionWordMeaningWordId", "DefinitionWordMeaningId", "DefinitionId"); }); b2.Navigation("Antonyms"); @@ -578,7 +574,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b1.Navigation("Definitions"); }); - b.OwnsMany("EnglishNote.Domain.Words.Phonetic", "Phonetics", b1 => + b.OwnsMany("EnglishNote.Domain.AggregatesModel.Words.WordPhonetic", "Phonetics", b1 => { b1.Property("WordId") .HasColumnType("uniqueidentifier"); @@ -590,12 +586,10 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); b1.Property("Audio") - .IsRequired() .HasMaxLength(500) .HasColumnType("nvarchar(500)"); b1.Property("CustomAudio") - .IsRequired() .HasMaxLength(36) .HasColumnType("nvarchar(36)"); @@ -606,7 +600,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b1.HasKey("WordId", "Id"); - b1.ToTable("Phonetic"); + b1.ToTable("WordPhonetic"); b1.WithOwner() .HasForeignKey("WordId"); @@ -625,7 +619,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationRole", null) + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationRole", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) @@ -634,7 +628,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", null) + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -643,7 +637,7 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", null) + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -652,13 +646,13 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationRole", null) + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationRole", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", null) + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -667,14 +661,14 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", null) + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("EnglishNote.Domain.Identity.ApplicationUser", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", b => { b.Navigation("Tags"); @@ -683,12 +677,12 @@ protected override void BuildTargetModel(ModelBuilder modelBuilder) b.Navigation("Words"); }); - modelBuilder.Entity("EnglishNote.Domain.Tags.Tag", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Tags.Tag", b => { b.Navigation("Words"); }); - modelBuilder.Entity("EnglishNote.Domain.VocabularySets.VocabularySet", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.VocabularySets.VocabularySet", b => { b.Navigation("QuizSession") .IsRequired(); diff --git a/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/20241123052016_InitDb.cs b/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/20241127071802_InitDb.cs similarity index 88% rename from src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/20241123052016_InitDb.cs rename to src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/20241127071802_InitDb.cs index 831e26b..7b3f443 100644 --- a/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/20241123052016_InitDb.cs +++ b/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/20241127071802_InitDb.cs @@ -238,9 +238,9 @@ protected override void Up(MigrationBuilder migrationBuilder) Id = table.Column(type: "uniqueidentifier", nullable: false), WordText = table.Column(type: "nvarchar(512)", maxLength: 512, nullable: false), MemoryLevel = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), - TagId = table.Column(type: "uniqueidentifier", nullable: false), + TagId = table.Column(type: "uniqueidentifier", nullable: true), UserId = table.Column(type: "uniqueidentifier", nullable: false), - VocabularySetId = table.Column(type: "uniqueidentifier", nullable: false) + VocabularySetId = table.Column(type: "uniqueidentifier", nullable: true) }, constraints: table => { @@ -266,20 +266,20 @@ protected override void Up(MigrationBuilder migrationBuilder) }); migrationBuilder.CreateTable( - name: "Meaning", + name: "WordMeaning", columns: table => new { WordId = table.Column(type: "uniqueidentifier", nullable: false), Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), - PartOfSpeech = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), - CefrLevel = table.Column(type: "nvarchar(10)", maxLength: 10, nullable: false) + PartOfSpeech = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + CefrLevel = table.Column(type: "nvarchar(10)", maxLength: 10, nullable: true) }, constraints: table => { - table.PrimaryKey("PK_Meaning", x => new { x.WordId, x.Id }); + table.PrimaryKey("PK_WordMeaning", x => new { x.WordId, x.Id }); table.ForeignKey( - name: "FK_Meaning_Words_WordId", + name: "FK_WordMeaning_Words_WordId", column: x => x.WordId, principalTable: "Words", principalColumn: "Id", @@ -287,21 +287,21 @@ protected override void Up(MigrationBuilder migrationBuilder) }); migrationBuilder.CreateTable( - name: "Phonetic", + name: "WordPhonetic", columns: table => new { WordId = table.Column(type: "uniqueidentifier", nullable: false), Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), Text = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: false), - Audio = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: false), - CustomAudio = table.Column(type: "nvarchar(36)", maxLength: 36, nullable: false) + Audio = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: true), + CustomAudio = table.Column(type: "nvarchar(36)", maxLength: 36, nullable: true) }, constraints: table => { - table.PrimaryKey("PK_Phonetic", x => new { x.WordId, x.Id }); + table.PrimaryKey("PK_WordPhonetic", x => new { x.WordId, x.Id }); table.ForeignKey( - name: "FK_Phonetic_Words_WordId", + name: "FK_WordPhonetic_Words_WordId", column: x => x.WordId, principalTable: "Words", principalColumn: "Id", @@ -312,19 +312,19 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "Definition", columns: table => new { - MeaningWordId = table.Column(type: "uniqueidentifier", nullable: false), - MeaningId = table.Column(type: "int", nullable: false), + WordMeaningWordId = table.Column(type: "uniqueidentifier", nullable: false), + WordMeaningId = table.Column(type: "int", nullable: false), Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), DefinitionText = table.Column(type: "nvarchar(1024)", maxLength: 1024, nullable: false) }, constraints: table => { - table.PrimaryKey("PK_Definition", x => new { x.MeaningWordId, x.MeaningId, x.Id }); + table.PrimaryKey("PK_Definition", x => new { x.WordMeaningWordId, x.WordMeaningId, x.Id }); table.ForeignKey( - name: "FK_Definition_Meaning_MeaningWordId_MeaningId", - columns: x => new { x.MeaningWordId, x.MeaningId }, - principalTable: "Meaning", + name: "FK_Definition_WordMeaning_WordMeaningWordId_WordMeaningId", + columns: x => new { x.WordMeaningWordId, x.WordMeaningId }, + principalTable: "WordMeaning", principalColumns: new[] { "WordId", "Id" }, onDelete: ReferentialAction.Cascade); }); @@ -333,8 +333,8 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "Antonym", columns: table => new { - DefinitionMeaningWordId = table.Column(type: "uniqueidentifier", nullable: false), - DefinitionMeaningId = table.Column(type: "int", nullable: false), + DefinitionWordMeaningWordId = table.Column(type: "uniqueidentifier", nullable: false), + DefinitionWordMeaningId = table.Column(type: "int", nullable: false), DefinitionId = table.Column(type: "int", nullable: false), Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), @@ -342,12 +342,12 @@ protected override void Up(MigrationBuilder migrationBuilder) }, constraints: table => { - table.PrimaryKey("PK_Antonym", x => new { x.DefinitionMeaningWordId, x.DefinitionMeaningId, x.DefinitionId, x.Id }); + table.PrimaryKey("PK_Antonym", x => new { x.DefinitionWordMeaningWordId, x.DefinitionWordMeaningId, x.DefinitionId, x.Id }); table.ForeignKey( - name: "FK_Antonym_Definition_DefinitionMeaningWordId_DefinitionMeaningId_DefinitionId", - columns: x => new { x.DefinitionMeaningWordId, x.DefinitionMeaningId, x.DefinitionId }, + name: "FK_Antonym_Definition_DefinitionWordMeaningWordId_DefinitionWordMeaningId_DefinitionId", + columns: x => new { x.DefinitionWordMeaningWordId, x.DefinitionWordMeaningId, x.DefinitionId }, principalTable: "Definition", - principalColumns: new[] { "MeaningWordId", "MeaningId", "Id" }, + principalColumns: new[] { "WordMeaningWordId", "WordMeaningId", "Id" }, onDelete: ReferentialAction.Cascade); }); @@ -355,8 +355,8 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "Example", columns: table => new { - DefinitionMeaningWordId = table.Column(type: "uniqueidentifier", nullable: false), - DefinitionMeaningId = table.Column(type: "int", nullable: false), + DefinitionWordMeaningWordId = table.Column(type: "uniqueidentifier", nullable: false), + DefinitionWordMeaningId = table.Column(type: "int", nullable: false), DefinitionId = table.Column(type: "int", nullable: false), Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), @@ -364,12 +364,12 @@ protected override void Up(MigrationBuilder migrationBuilder) }, constraints: table => { - table.PrimaryKey("PK_Example", x => new { x.DefinitionMeaningWordId, x.DefinitionMeaningId, x.DefinitionId, x.Id }); + table.PrimaryKey("PK_Example", x => new { x.DefinitionWordMeaningWordId, x.DefinitionWordMeaningId, x.DefinitionId, x.Id }); table.ForeignKey( - name: "FK_Example_Definition_DefinitionMeaningWordId_DefinitionMeaningId_DefinitionId", - columns: x => new { x.DefinitionMeaningWordId, x.DefinitionMeaningId, x.DefinitionId }, + name: "FK_Example_Definition_DefinitionWordMeaningWordId_DefinitionWordMeaningId_DefinitionId", + columns: x => new { x.DefinitionWordMeaningWordId, x.DefinitionWordMeaningId, x.DefinitionId }, principalTable: "Definition", - principalColumns: new[] { "MeaningWordId", "MeaningId", "Id" }, + principalColumns: new[] { "WordMeaningWordId", "WordMeaningId", "Id" }, onDelete: ReferentialAction.Cascade); }); @@ -377,8 +377,8 @@ protected override void Up(MigrationBuilder migrationBuilder) name: "Synonym", columns: table => new { - DefinitionMeaningWordId = table.Column(type: "uniqueidentifier", nullable: false), - DefinitionMeaningId = table.Column(type: "int", nullable: false), + DefinitionWordMeaningWordId = table.Column(type: "uniqueidentifier", nullable: false), + DefinitionWordMeaningId = table.Column(type: "int", nullable: false), DefinitionId = table.Column(type: "int", nullable: false), Id = table.Column(type: "int", nullable: false) .Annotation("SqlServer:Identity", "1, 1"), @@ -386,12 +386,12 @@ protected override void Up(MigrationBuilder migrationBuilder) }, constraints: table => { - table.PrimaryKey("PK_Synonym", x => new { x.DefinitionMeaningWordId, x.DefinitionMeaningId, x.DefinitionId, x.Id }); + table.PrimaryKey("PK_Synonym", x => new { x.DefinitionWordMeaningWordId, x.DefinitionWordMeaningId, x.DefinitionId, x.Id }); table.ForeignKey( - name: "FK_Synonym_Definition_DefinitionMeaningWordId_DefinitionMeaningId_DefinitionId", - columns: x => new { x.DefinitionMeaningWordId, x.DefinitionMeaningId, x.DefinitionId }, + name: "FK_Synonym_Definition_DefinitionWordMeaningWordId_DefinitionWordMeaningId_DefinitionId", + columns: x => new { x.DefinitionWordMeaningWordId, x.DefinitionWordMeaningId, x.DefinitionId }, principalTable: "Definition", - principalColumns: new[] { "MeaningWordId", "MeaningId", "Id" }, + principalColumns: new[] { "WordMeaningWordId", "WordMeaningId", "Id" }, onDelete: ReferentialAction.Cascade); }); @@ -495,15 +495,15 @@ protected override void Down(MigrationBuilder migrationBuilder) migrationBuilder.DropTable( name: "Example"); - migrationBuilder.DropTable( - name: "Phonetic"); - migrationBuilder.DropTable( name: "QuizSessions"); migrationBuilder.DropTable( name: "Synonym"); + migrationBuilder.DropTable( + name: "WordPhonetic"); + migrationBuilder.DropTable( name: "AspNetRoles"); @@ -511,7 +511,7 @@ protected override void Down(MigrationBuilder migrationBuilder) name: "Definition"); migrationBuilder.DropTable( - name: "Meaning"); + name: "WordMeaning"); migrationBuilder.DropTable( name: "Words"); diff --git a/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/ApplicationWriteDbContextModelSnapshot.cs b/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/ApplicationWriteDbContextModelSnapshot.cs index c0fb952..176a271 100644 --- a/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/ApplicationWriteDbContextModelSnapshot.cs +++ b/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Migrations/ApplicationWriteDbContextModelSnapshot.cs @@ -22,7 +22,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - modelBuilder.Entity("EnglishNote.Domain.Identity.ApplicationRole", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Identity.ApplicationRole", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -50,7 +50,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AspNetRoles", (string)null); }); - modelBuilder.Entity("EnglishNote.Domain.Identity.ApplicationUser", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -124,7 +124,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AspNetUsers", (string)null); }); - modelBuilder.Entity("EnglishNote.Domain.QuizSessions.QuizSession", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.QuizSessions.QuizSession", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -164,7 +164,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("QuizSessions"); }); - modelBuilder.Entity("EnglishNote.Domain.Tags.Tag", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Tags.Tag", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -190,7 +190,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("Tags"); }); - modelBuilder.Entity("EnglishNote.Domain.VocabularySets.VocabularySet", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.VocabularySets.VocabularySet", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -222,7 +222,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("VocabularySets"); }); - modelBuilder.Entity("EnglishNote.Domain.Words.Word", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Words.Word", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -232,13 +232,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasMaxLength(50) .HasColumnType("nvarchar(50)"); - b.Property("TagId") + b.Property("TagId") .HasColumnType("uniqueidentifier"); b.Property("UserId") .HasColumnType("uniqueidentifier"); - b.Property("VocabularySetId") + b.Property("VocabularySetId") .HasColumnType("uniqueidentifier"); b.Property("WordText") @@ -360,17 +360,17 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("AspNetUserTokens", (string)null); }); - modelBuilder.Entity("EnglishNote.Domain.QuizSessions.QuizSession", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.QuizSessions.QuizSession", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", "User") + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", "User") .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("EnglishNote.Domain.VocabularySets.VocabularySet", "VocabularySet") + b.HasOne("EnglishNote.Domain.AggregatesModel.VocabularySets.VocabularySet", "VocabularySet") .WithOne("QuizSession") - .HasForeignKey("EnglishNote.Domain.QuizSessions.QuizSession", "VocabularySetId") + .HasForeignKey("EnglishNote.Domain.AggregatesModel.QuizSessions.QuizSession", "VocabularySetId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); @@ -379,9 +379,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("VocabularySet"); }); - modelBuilder.Entity("EnglishNote.Domain.Tags.Tag", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Tags.Tag", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", "User") + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", "User") .WithMany("Tags") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Restrict) @@ -390,9 +390,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("User"); }); - modelBuilder.Entity("EnglishNote.Domain.VocabularySets.VocabularySet", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.VocabularySets.VocabularySet", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", "User") + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", "User") .WithMany("VocabularySets") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -401,27 +401,25 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("User"); }); - modelBuilder.Entity("EnglishNote.Domain.Words.Word", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Words.Word", b => { - b.HasOne("EnglishNote.Domain.Tags.Tag", "Tag") + b.HasOne("EnglishNote.Domain.AggregatesModel.Tags.Tag", "Tag") .WithMany("Words") .HasForeignKey("TagId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); + .OnDelete(DeleteBehavior.Restrict); - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", "User") + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", "User") .WithMany("Words") .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Restrict) .IsRequired(); - b.HasOne("EnglishNote.Domain.VocabularySets.VocabularySet", "VocabularySet") + b.HasOne("EnglishNote.Domain.AggregatesModel.VocabularySets.VocabularySet", "VocabularySet") .WithMany("Words") .HasForeignKey("VocabularySetId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired(); + .OnDelete(DeleteBehavior.Restrict); - b.OwnsMany("EnglishNote.Domain.Words.Meaning", "Meanings", b1 => + b.OwnsMany("EnglishNote.Domain.AggregatesModel.Words.WordMeaning", "Meanings", b1 => { b1.Property("WordId") .HasColumnType("uniqueidentifier"); @@ -433,28 +431,26 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); b1.Property("CefrLevel") - .IsRequired() .HasMaxLength(10) .HasColumnType("nvarchar(10)"); b1.Property("PartOfSpeech") - .IsRequired() .HasMaxLength(50) .HasColumnType("nvarchar(50)"); b1.HasKey("WordId", "Id"); - b1.ToTable("Meaning"); + b1.ToTable("WordMeaning"); b1.WithOwner() .HasForeignKey("WordId"); - b1.OwnsMany("EnglishNote.Domain.Words.Definition", "Definitions", b2 => + b1.OwnsMany("EnglishNote.Domain.AggregatesModel.Words.Definition", "Definitions", b2 => { - b2.Property("MeaningWordId") + b2.Property("WordMeaningWordId") .HasColumnType("uniqueidentifier"); - b2.Property("MeaningId") + b2.Property("WordMeaningId") .HasColumnType("int"); b2.Property("Id") @@ -468,19 +464,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasMaxLength(1024) .HasColumnType("nvarchar(1024)"); - b2.HasKey("MeaningWordId", "MeaningId", "Id"); + b2.HasKey("WordMeaningWordId", "WordMeaningId", "Id"); b2.ToTable("Definition"); b2.WithOwner() - .HasForeignKey("MeaningWordId", "MeaningId"); + .HasForeignKey("WordMeaningWordId", "WordMeaningId"); - b2.OwnsMany("EnglishNote.Domain.Words.Antonym", "Antonyms", b3 => + b2.OwnsMany("EnglishNote.Domain.AggregatesModel.Words.Antonym", "Antonyms", b3 => { - b3.Property("DefinitionMeaningWordId") + b3.Property("DefinitionWordMeaningWordId") .HasColumnType("uniqueidentifier"); - b3.Property("DefinitionMeaningId") + b3.Property("DefinitionWordMeaningId") .HasColumnType("int"); b3.Property("DefinitionId") @@ -497,20 +493,20 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasMaxLength(126) .HasColumnType("nvarchar(126)"); - b3.HasKey("DefinitionMeaningWordId", "DefinitionMeaningId", "DefinitionId", "Id"); + b3.HasKey("DefinitionWordMeaningWordId", "DefinitionWordMeaningId", "DefinitionId", "Id"); b3.ToTable("Antonym"); b3.WithOwner() - .HasForeignKey("DefinitionMeaningWordId", "DefinitionMeaningId", "DefinitionId"); + .HasForeignKey("DefinitionWordMeaningWordId", "DefinitionWordMeaningId", "DefinitionId"); }); - b2.OwnsMany("EnglishNote.Domain.Words.Example", "Examples", b3 => + b2.OwnsMany("EnglishNote.Domain.AggregatesModel.Words.Example", "Examples", b3 => { - b3.Property("DefinitionMeaningWordId") + b3.Property("DefinitionWordMeaningWordId") .HasColumnType("uniqueidentifier"); - b3.Property("DefinitionMeaningId") + b3.Property("DefinitionWordMeaningId") .HasColumnType("int"); b3.Property("DefinitionId") @@ -527,20 +523,20 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasMaxLength(1024) .HasColumnType("nvarchar(1024)"); - b3.HasKey("DefinitionMeaningWordId", "DefinitionMeaningId", "DefinitionId", "Id"); + b3.HasKey("DefinitionWordMeaningWordId", "DefinitionWordMeaningId", "DefinitionId", "Id"); b3.ToTable("Example"); b3.WithOwner() - .HasForeignKey("DefinitionMeaningWordId", "DefinitionMeaningId", "DefinitionId"); + .HasForeignKey("DefinitionWordMeaningWordId", "DefinitionWordMeaningId", "DefinitionId"); }); - b2.OwnsMany("EnglishNote.Domain.Words.Synonym", "Synonyms", b3 => + b2.OwnsMany("EnglishNote.Domain.AggregatesModel.Words.Synonym", "Synonyms", b3 => { - b3.Property("DefinitionMeaningWordId") + b3.Property("DefinitionWordMeaningWordId") .HasColumnType("uniqueidentifier"); - b3.Property("DefinitionMeaningId") + b3.Property("DefinitionWordMeaningId") .HasColumnType("int"); b3.Property("DefinitionId") @@ -557,12 +553,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasMaxLength(126) .HasColumnType("nvarchar(126)"); - b3.HasKey("DefinitionMeaningWordId", "DefinitionMeaningId", "DefinitionId", "Id"); + b3.HasKey("DefinitionWordMeaningWordId", "DefinitionWordMeaningId", "DefinitionId", "Id"); b3.ToTable("Synonym"); b3.WithOwner() - .HasForeignKey("DefinitionMeaningWordId", "DefinitionMeaningId", "DefinitionId"); + .HasForeignKey("DefinitionWordMeaningWordId", "DefinitionWordMeaningId", "DefinitionId"); }); b2.Navigation("Antonyms"); @@ -575,7 +571,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b1.Navigation("Definitions"); }); - b.OwnsMany("EnglishNote.Domain.Words.Phonetic", "Phonetics", b1 => + b.OwnsMany("EnglishNote.Domain.AggregatesModel.Words.WordPhonetic", "Phonetics", b1 => { b1.Property("WordId") .HasColumnType("uniqueidentifier"); @@ -587,12 +583,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property("Id")); b1.Property("Audio") - .IsRequired() .HasMaxLength(500) .HasColumnType("nvarchar(500)"); b1.Property("CustomAudio") - .IsRequired() .HasMaxLength(36) .HasColumnType("nvarchar(36)"); @@ -603,7 +597,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b1.HasKey("WordId", "Id"); - b1.ToTable("Phonetic"); + b1.ToTable("WordPhonetic"); b1.WithOwner() .HasForeignKey("WordId"); @@ -622,7 +616,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationRole", null) + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationRole", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) @@ -631,7 +625,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", null) + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -640,7 +634,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", null) + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -649,13 +643,13 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationRole", null) + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationRole", null) .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", null) + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) @@ -664,14 +658,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => { - b.HasOne("EnglishNote.Domain.Identity.ApplicationUser", null) + b.HasOne("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", null) .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); }); - modelBuilder.Entity("EnglishNote.Domain.Identity.ApplicationUser", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Identity.ApplicationUser", b => { b.Navigation("Tags"); @@ -680,12 +674,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Words"); }); - modelBuilder.Entity("EnglishNote.Domain.Tags.Tag", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.Tags.Tag", b => { b.Navigation("Words"); }); - modelBuilder.Entity("EnglishNote.Domain.VocabularySets.VocabularySet", b => + modelBuilder.Entity("EnglishNote.Domain.AggregatesModel.VocabularySets.VocabularySet", b => { b.Navigation("QuizSession") .IsRequired(); diff --git a/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Repositories/TagRepository.cs b/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Repositories/TagRepository.cs index 52555e3..ff0986a 100644 --- a/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Repositories/TagRepository.cs +++ b/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Repositories/TagRepository.cs @@ -4,8 +4,8 @@ namespace EnglishNote.Infrastructure.Persistence.Repositories; internal sealed class TagRepository(ApplicationWriteDbContext applicationWriteDbContext) : ITagRepository { - public async Task AddAsync(Tag tag) + public async Task AddAsync(Tag tag, CancellationToken cancellationToken) => await applicationWriteDbContext .Tags - .AddAsync(tag); + .AddAsync(tag, cancellationToken); } diff --git a/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Repositories/WordRepository.cs b/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Repositories/WordRepository.cs new file mode 100644 index 0000000..66fef4c --- /dev/null +++ b/src/Infrastructure/EnglishNote.Infrastructure.Persistence/Repositories/WordRepository.cs @@ -0,0 +1,9 @@ +using EnglishNote.Domain.AggregatesModel.Words; +using EnglishNote.Infrastructure.Persistence.Contexts; + +namespace EnglishNote.Infrastructure.Persistence.Repositories; +internal sealed class WordRepository(ApplicationWriteDbContext context) : IWordRepository +{ + public async Task AddAsync(Word word, CancellationToken cancellationToken = default) + => await context.AddAsync(word, cancellationToken); +} diff --git a/src/Infrastructure/EnglishNote.Infrastructure.Persistence/ServiceExtensions.cs b/src/Infrastructure/EnglishNote.Infrastructure.Persistence/ServiceExtensions.cs index 21a8a2b..b46d6ed 100644 --- a/src/Infrastructure/EnglishNote.Infrastructure.Persistence/ServiceExtensions.cs +++ b/src/Infrastructure/EnglishNote.Infrastructure.Persistence/ServiceExtensions.cs @@ -1,5 +1,6 @@ using EnglishNote.Application.Abtractions.Data; using EnglishNote.Domain.AggregatesModel.Tags; +using EnglishNote.Domain.AggregatesModel.Words; using EnglishNote.Infrastructure.Persistence.Contexts; using EnglishNote.Infrastructure.Persistence.Repositories; using Microsoft.EntityFrameworkCore; @@ -21,6 +22,7 @@ public static IServiceCollection AddRepositoryService(this IServiceCollection se { services.AddScoped(); services.AddScoped(); + services.AddScoped(); return services; } diff --git a/src/Infrastructure/EnglishNote.Infrastructure/ServiceExtensions.cs b/src/Infrastructure/EnglishNote.Infrastructure/ServiceExtensions.cs index 5bac8af..82c1168 100644 --- a/src/Infrastructure/EnglishNote.Infrastructure/ServiceExtensions.cs +++ b/src/Infrastructure/EnglishNote.Infrastructure/ServiceExtensions.cs @@ -1,6 +1,8 @@ -using EnglishNote.Application.Abtractions.Authentication; +using EnglishNote.Application.Abtractions; +using EnglishNote.Application.Abtractions.Authentication; using EnglishNote.Infrastructure.Authentication; using EnglishNote.Infrastructure.Persistence; +using EnglishNote.Infrastructure.Services; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -14,8 +16,18 @@ public static IServiceCollection AddInfrastructureLayer( { services.AddScoped(); - services.AddPersistenceLayer(configuration); + services + .AddServiesLayer() + .AddPersistenceLayer(configuration); return services; } + + public static IServiceCollection AddServiesLayer(this IServiceCollection services) + { + services.AddScoped(); + services.AddScoped(); + + return services; + } } diff --git a/src/Infrastructure/EnglishNote.Infrastructure/Services/DateTimeProvider.cs b/src/Infrastructure/EnglishNote.Infrastructure/Services/DateTimeProvider.cs new file mode 100644 index 0000000..538d8ad --- /dev/null +++ b/src/Infrastructure/EnglishNote.Infrastructure/Services/DateTimeProvider.cs @@ -0,0 +1,9 @@ +using EnglishNote.Application.Abtractions; + +namespace EnglishNote.Infrastructure.Services; +public class DateTimeProvider : IDateTimeProvider +{ + public DateTime UtcNow => DateTime.UtcNow; + + public DateTime Now => DateTime.Now; +} \ No newline at end of file diff --git a/src/Infrastructure/EnglishNote.Infrastructure/Services/GuidGenerator.cs b/src/Infrastructure/EnglishNote.Infrastructure/Services/GuidGenerator.cs new file mode 100644 index 0000000..1cfa48b --- /dev/null +++ b/src/Infrastructure/EnglishNote.Infrastructure/Services/GuidGenerator.cs @@ -0,0 +1,10 @@ +using EnglishNote.Application.Abtractions; + +namespace EnglishNote.Infrastructure.Services; +internal sealed class GuidGenerator : IGuidGenerator +{ + public Guid NewGuid() + { + return Guid.CreateVersion7(); + } +}