commit 49591985ac177685335274ed1b1a3790e3dcd8f5 Author: HosseinJavadi Date: Thu Apr 16 21:05:21 2026 +0430 first commit diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..fe1152b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,30 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md +!**/.gitignore +!.git/HEAD +!.git/config +!.git/packed-refs +!.git/refs/heads/** \ No newline at end of file diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9491a2f --- /dev/null +++ b/.gitignore @@ -0,0 +1,363 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/VichVich.BuildingBlocks.Application/Configuration/Commnad/ICommandHandler.cs b/VichVich.BuildingBlocks.Application/Configuration/Commnad/ICommandHandler.cs new file mode 100644 index 0000000..e86bb06 --- /dev/null +++ b/VichVich.BuildingBlocks.Application/Configuration/Commnad/ICommandHandler.cs @@ -0,0 +1,16 @@ +using Vizhvizh.BuildingBlocks.Application.Contract; +using Vizhvizh.BuildingBlocks.Domain.Contract; + +namespace Vizhvizh.BuildingBlocks.Application.Configuration.Commnad; + +public interface ICommandHandler + where TCommand : ICommand +{ + Task Handle(TCommand request, CancellationToken cancellationToken); +} + +public interface ICommandHandler + where TCommand : ICommand +{ + Task Handle(TCommand request, CancellationToken cancellationToken); +} diff --git a/VichVich.BuildingBlocks.Application/Configuration/Notification/INotificationHandler.cs b/VichVich.BuildingBlocks.Application/Configuration/Notification/INotificationHandler.cs new file mode 100644 index 0000000..7afc234 --- /dev/null +++ b/VichVich.BuildingBlocks.Application/Configuration/Notification/INotificationHandler.cs @@ -0,0 +1,9 @@ +using Vizhvizh.BuildingBlocks.Domain.Contract; + +namespace Vizhvizh.BuildingBlocks.Application.Contract; + +public interface INotificationHandler + where T : INotification +{ + Task Handle(T notification, CancellationToken cancellationToken); +} diff --git a/VichVich.BuildingBlocks.Application/Configuration/Query/IQueryHandler.cs b/VichVich.BuildingBlocks.Application/Configuration/Query/IQueryHandler.cs new file mode 100644 index 0000000..b982540 --- /dev/null +++ b/VichVich.BuildingBlocks.Application/Configuration/Query/IQueryHandler.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Application.Contract; +using Vizhvizh.BuildingBlocks.Domain.Contract; + +namespace Vizhvizh.BuildingBlocks.Application.Configuration.Query; + +public interface IQueryHandler + where TQuery : IQuery +{ + Task Handle(TQuery request, CancellationToken cancellationToken); +} diff --git a/VichVich.BuildingBlocks.Application/Contract/IExecutionContextAccessor.cs b/VichVich.BuildingBlocks.Application/Contract/IExecutionContextAccessor.cs new file mode 100644 index 0000000..552a838 --- /dev/null +++ b/VichVich.BuildingBlocks.Application/Contract/IExecutionContextAccessor.cs @@ -0,0 +1,8 @@ + +namespace Vizhvizh.BuildingBlocks.Application.Contract; + +public interface IExecutionContextAccessor +{ + Guid UserId { get; } + bool IsAvailable { get; } +} diff --git a/VichVich.BuildingBlocks.Application/Data/ISqlConnectionFactory.cs b/VichVich.BuildingBlocks.Application/Data/ISqlConnectionFactory.cs new file mode 100644 index 0000000..583bba1 --- /dev/null +++ b/VichVich.BuildingBlocks.Application/Data/ISqlConnectionFactory.cs @@ -0,0 +1,12 @@ +using System.Data; + +namespace Vizhvizh.BuildingBlocks.Application.Data; + +public interface ISqlConnectionFactory : IDisposable +{ + IDbConnection GetOpenConnection(); + + IDbConnection CreateNewConnection(); + + string GetConnectionString(); +} diff --git a/VichVich.BuildingBlocks.Application/Events/DomainNotificationBase.cs b/VichVich.BuildingBlocks.Application/Events/DomainNotificationBase.cs new file mode 100644 index 0000000..72e52ac --- /dev/null +++ b/VichVich.BuildingBlocks.Application/Events/DomainNotificationBase.cs @@ -0,0 +1,17 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.BuildingBlocks.Application.Events; + +public class DomainNotificationBase : IDomainEventNotification + where T : IDomainEvent +{ + public T DomainEvent { get; } + + public Guid Id { get; } + + public DomainNotificationBase(T domainEvent, Guid id) + { + this.Id = id; + this.DomainEvent = domainEvent; + } +} diff --git a/VichVich.BuildingBlocks.Application/Events/IDomainEventNotification.cs b/VichVich.BuildingBlocks.Application/Events/IDomainEventNotification.cs new file mode 100644 index 0000000..165ee5d --- /dev/null +++ b/VichVich.BuildingBlocks.Application/Events/IDomainEventNotification.cs @@ -0,0 +1,14 @@ +using Vizhvizh.BuildingBlocks.Application.Contract; +using Vizhvizh.BuildingBlocks.Domain.Contract; + +namespace Vizhvizh.BuildingBlocks.Application.Events; + +public interface IDomainEventNotification : IDomainEventNotification +{ + TEventType DomainEvent { get; } +} + +public interface IDomainEventNotification : INotification +{ + Guid Id { get; } +} diff --git a/VichVich.BuildingBlocks.Application/Outbox/IOutbox.cs b/VichVich.BuildingBlocks.Application/Outbox/IOutbox.cs new file mode 100644 index 0000000..623827a --- /dev/null +++ b/VichVich.BuildingBlocks.Application/Outbox/IOutbox.cs @@ -0,0 +1,8 @@ +namespace Vizhvizh.BuildingBlocks.Application.Outbox; + +public interface IOutbox +{ + void Add(OutboxMessage message); + + Task Save(); +} diff --git a/VichVich.BuildingBlocks.Application/Outbox/OutboxMessage.cs b/VichVich.BuildingBlocks.Application/Outbox/OutboxMessage.cs new file mode 100644 index 0000000..47e9209 --- /dev/null +++ b/VichVich.BuildingBlocks.Application/Outbox/OutboxMessage.cs @@ -0,0 +1,26 @@ +namespace Vizhvizh.BuildingBlocks.Application.Outbox; + +public class OutboxMessage +{ + public Guid Id { get; set; } + + public DateTime OccurredOn { get; set; } + + public string Type { get; set; } + + public string Data { get; set; } + + public DateTime? ProcessedDate { get; set; } + + public OutboxMessage(Guid id, DateTime occurredOn, string type, string data) + { + this.Id = id; + this.OccurredOn = occurredOn; + this.Type = type; + this.Data = data; + } + + private OutboxMessage() + { + } +} diff --git a/VichVich.BuildingBlocks.Application/SelectBuilders/ISqlDialect.cs b/VichVich.BuildingBlocks.Application/SelectBuilders/ISqlDialect.cs new file mode 100644 index 0000000..33745c3 --- /dev/null +++ b/VichVich.BuildingBlocks.Application/SelectBuilders/ISqlDialect.cs @@ -0,0 +1,8 @@ +namespace Vizhvizh.BuildingBlocks.Application.SelectBuilders; + +// Interface برای پشتیبانی از دیتابیس‌های مختلف +public interface ISqlDialect +{ + string BuildSelectQuery(List columns, string table, + List whereConditions, string? orderBy, int? top, (int pageNumber, int pageSize)? pagination); +} diff --git a/VichVich.BuildingBlocks.Application/SelectBuilders/ISqlSelectBuilder.cs b/VichVich.BuildingBlocks.Application/SelectBuilders/ISqlSelectBuilder.cs new file mode 100644 index 0000000..b093cf8 --- /dev/null +++ b/VichVich.BuildingBlocks.Application/SelectBuilders/ISqlSelectBuilder.cs @@ -0,0 +1,23 @@ +using System.Linq.Expressions; + +namespace Vizhvizh.BuildingBlocks.Application.SelectBuilders; + +public interface ISqlSelectBuilder +{ + ISqlSelectBuilder From(string tableName); + + // حالت ساده: فقط یک Expression (وقتی نام ستون = نام پراپرتی DTO) + ISqlSelectBuilder Select(params Expression>[] selectors); + + // حالت پیشرفته: جفت (Domain Prop, DTO Prop) + ISqlSelectBuilder Select(params (Expression> Domain, Expression> Dto)[] mappings); + + ISqlSelectBuilder Where(Expression> property, object? value); + ISqlSelectBuilder WhereLike(Expression> property, string pattern); + ISqlSelectBuilder Top(int count); + ISqlSelectBuilder OrderBy(Expression> property, bool ascending = true); + + ISqlSelectBuilder Pagination(int pageNumber, int pageSize); + ISqlSelectBuilder Pagination(int pageNumber, int pageSize, Expression> property, bool ascending = true); + (string Sql, object Parameters) Build(); +} diff --git a/VichVich.BuildingBlocks.Application/Vizhvizh.BuildingBlocks.Application.csproj b/VichVich.BuildingBlocks.Application/Vizhvizh.BuildingBlocks.Application.csproj new file mode 100644 index 0000000..a24bee2 --- /dev/null +++ b/VichVich.BuildingBlocks.Application/Vizhvizh.BuildingBlocks.Application.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/VichVich.BuildingBlocks.Domain/Contract/CommandBase.cs b/VichVich.BuildingBlocks.Domain/Contract/CommandBase.cs new file mode 100644 index 0000000..f504d59 --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/Contract/CommandBase.cs @@ -0,0 +1,27 @@ +namespace Vizhvizh.BuildingBlocks.Domain.Contract; + +public abstract record CommandBase : ICommand +{ + public Guid Id { get; private set; } + protected CommandBase() + { + Id = Guid.NewGuid(); + } + protected CommandBase(Guid id) + { + Id = id; + } +} + +public abstract record CommandBase : ICommand +{ + public Guid Id { get; private set; } + protected CommandBase() + { + Id = Guid.NewGuid(); + } + protected CommandBase(Guid id) + { + Id = id; + } +} \ No newline at end of file diff --git a/VichVich.BuildingBlocks.Domain/Contract/ICommand.cs b/VichVich.BuildingBlocks.Domain/Contract/ICommand.cs new file mode 100644 index 0000000..865a132 --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/Contract/ICommand.cs @@ -0,0 +1,11 @@ +namespace Vizhvizh.BuildingBlocks.Domain.Contract; + +public interface ICommand +{ + Guid Id { get; } +} + +public interface ICommand +{ + Guid Id { get; } +} diff --git a/VichVich.BuildingBlocks.Domain/Contract/INotification.cs b/VichVich.BuildingBlocks.Domain/Contract/INotification.cs new file mode 100644 index 0000000..d09b37c --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/Contract/INotification.cs @@ -0,0 +1,5 @@ +namespace Vizhvizh.BuildingBlocks.Domain.Contract; + +public interface INotification +{ +} diff --git a/VichVich.BuildingBlocks.Domain/Contract/IQuery.cs b/VichVich.BuildingBlocks.Domain/Contract/IQuery.cs new file mode 100644 index 0000000..813ccfb --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/Contract/IQuery.cs @@ -0,0 +1,5 @@ +namespace Vizhvizh.BuildingBlocks.Domain.Contract; + +public interface IQuery +{ +} \ No newline at end of file diff --git a/VichVich.BuildingBlocks.Domain/DomainEventBase.cs b/VichVich.BuildingBlocks.Domain/DomainEventBase.cs new file mode 100644 index 0000000..f4eda5a --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/DomainEventBase.cs @@ -0,0 +1,14 @@ +namespace Vizhvizh.BuildingBlocks.Domain; + +public class DomainEventBase : IDomainEvent +{ + public Guid Id { get; } + + public DateTime OccurredOn { get; } + + public DomainEventBase() + { + this.Id = Guid.NewGuid(); + this.OccurredOn = DateTime.UtcNow; + } +} diff --git a/VichVich.BuildingBlocks.Domain/Entity.cs b/VichVich.BuildingBlocks.Domain/Entity.cs new file mode 100644 index 0000000..12454ec --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/Entity.cs @@ -0,0 +1,37 @@ + +using Vizhvizh.BuildingBlocks.Domain.Exceptions; + +namespace Vizhvizh.BuildingBlocks.Domain; + +public abstract class Entity + where T : ITypeIdValueBase +{ + public Entity() + { + CreateOn = DateTime.Now; + } + public T Id { get; protected set; } + public DateTime CreateOn { get; init ; } + private List _domainEvents; + + public void ClearDomainEvents() + { + _domainEvents?.Clear(); + } + + protected void AddDomainEvent(IDomainEvent domainEvent) + { + _domainEvents ??= []; + + this._domainEvents.Add(domainEvent); + } + public IReadOnlyList DomainEvents => _domainEvents; + protected void CheckRule(IBusinessRule rule) + { + if (rule.IsBroken()) + { + throw new BusinessRuleValidationException(rule); + } + } + +} diff --git a/VichVich.BuildingBlocks.Domain/Exceptions/BusinessRuleValidationException.cs b/VichVich.BuildingBlocks.Domain/Exceptions/BusinessRuleValidationException.cs new file mode 100644 index 0000000..ad2cfc0 --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/Exceptions/BusinessRuleValidationException.cs @@ -0,0 +1,20 @@ +namespace Vizhvizh.BuildingBlocks.Domain.Exceptions; + +public class BusinessRuleValidationException : Exception +{ + public IBusinessRule BrokenRule { get; } + + public string Details { get; } + + public BusinessRuleValidationException(IBusinessRule brokenRule) + : base(brokenRule.Message) + { + BrokenRule = brokenRule; + this.Details = brokenRule.Message; + } + + public override string ToString() + { + return $"{BrokenRule.GetType().FullName}: {BrokenRule.Message}"; + } +} diff --git a/VichVich.BuildingBlocks.Domain/Exceptions/IBusinessRule.cs b/VichVich.BuildingBlocks.Domain/Exceptions/IBusinessRule.cs new file mode 100644 index 0000000..48c0792 --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/Exceptions/IBusinessRule.cs @@ -0,0 +1,8 @@ +namespace Vizhvizh.BuildingBlocks.Domain.Exceptions; + +public interface IBusinessRule +{ + bool IsBroken(); + + string Message { get; } +} diff --git a/VichVich.BuildingBlocks.Domain/Exceptions/ValueObjectValidationException.cs b/VichVich.BuildingBlocks.Domain/Exceptions/ValueObjectValidationException.cs new file mode 100644 index 0000000..89ffc4b --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/Exceptions/ValueObjectValidationException.cs @@ -0,0 +1,9 @@ +namespace Vizhvizh.BuildingBlocks.Domain.Exceptions; + +public class ValueObjectValidationException : Exception +{ + public ValueObjectValidationException(string message) + :base(message) + { + } +} diff --git a/VichVich.BuildingBlocks.Domain/Extensions/EnumExtensions.cs b/VichVich.BuildingBlocks.Domain/Extensions/EnumExtensions.cs new file mode 100644 index 0000000..77337f9 --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/Extensions/EnumExtensions.cs @@ -0,0 +1,54 @@ +using System.Collections.Concurrent; +using System.ComponentModel.DataAnnotations; +using System.Reflection; + +namespace Vizhvizh.BuildingBlocks.Domain.Extensions; + +public static class EnumExtensions +{ + // Cache to store display names of enum values + private static readonly ConcurrentDictionary DisplayNameCache = new(); + + /// + /// Gets an attribute on an enum field value. + /// + /// The type of the attribute to retrieve. + /// The enum value. + /// + /// The attribute of the specified type or null. + /// + public static T GetAttributeOfType(this Enum enumValue) where T : Attribute + { + var type = enumValue.GetType(); + // Use GetField to get the field info for the enum value + var memInfo = type.GetField(enumValue.ToString(), BindingFlags.Public | BindingFlags.Static); + + if (memInfo == null) + return null; + + // Retrieve the custom attributes of type T + var attributes = memInfo.GetCustomAttributes(false); + return attributes.FirstOrDefault(); + } + + /// + /// Gets the enum display name. + /// + /// The enum value. + /// + /// Use if it exists. + /// Otherwise, use the standard string representation. + /// + public static string GetDisplayName(this Enum enumValue) + { + // Retrieve the display name from the cache if it exists + return DisplayNameCache.GetOrAdd(enumValue, e => + { + // Get the DisplayAttribute + var attribute = e.GetAttributeOfType(); + + // Return the DisplayAttribute name if it exists, otherwise return the enum's string representation + return attribute == null ? e.ToString() : attribute.Name; + }); + } +} \ No newline at end of file diff --git a/VichVich.BuildingBlocks.Domain/IAggregateRoot.cs b/VichVich.BuildingBlocks.Domain/IAggregateRoot.cs new file mode 100644 index 0000000..149365b --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/IAggregateRoot.cs @@ -0,0 +1,7 @@ + + +namespace Vizhvizh.BuildingBlocks.Domain; + +public interface IAggregateRoot +{ +} diff --git a/VichVich.BuildingBlocks.Domain/IDomainEvent.cs b/VichVich.BuildingBlocks.Domain/IDomainEvent.cs new file mode 100644 index 0000000..b7e89ee --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/IDomainEvent.cs @@ -0,0 +1,12 @@ + +using Vizhvizh.BuildingBlocks.Domain.Contract; + +namespace Vizhvizh.BuildingBlocks.Domain +{ + public interface IDomainEvent : INotification + { + Guid Id { get; } + + DateTime OccurredOn { get; } + } +} diff --git a/VichVich.BuildingBlocks.Domain/IRepositoryBase.cs b/VichVich.BuildingBlocks.Domain/IRepositoryBase.cs new file mode 100644 index 0000000..16adb9a --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/IRepositoryBase.cs @@ -0,0 +1,10 @@ +namespace Vizhvizh.BuildingBlocks.Domain; + +public interface IRepositoryBase + where TDomain : Entity where TId : ITypeIdValueBase +{ + Task CreateAsync(TDomain entity, CancellationToken cancellationToken = default); + Task UpdateAsync(TDomain entity, CancellationToken cancellationToken = default); + Task DeleteAsync(TId id, CancellationToken cancellationToken = default); + Task GetByIdAsync(TId id, CancellationToken cancellationToken = default); +} diff --git a/VichVich.BuildingBlocks.Domain/IgnoreMemberAttribute.cs b/VichVich.BuildingBlocks.Domain/IgnoreMemberAttribute.cs new file mode 100644 index 0000000..4458906 --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/IgnoreMemberAttribute.cs @@ -0,0 +1,6 @@ +namespace Vizhvizh.BuildingBlocks.Domain; + +[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] +public class IgnoreMemberAttribute : Attribute +{ +} diff --git a/VichVich.BuildingBlocks.Domain/TypeIdValueBase.cs b/VichVich.BuildingBlocks.Domain/TypeIdValueBase.cs new file mode 100644 index 0000000..7332327 --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/TypeIdValueBase.cs @@ -0,0 +1,59 @@ +namespace Vizhvizh.BuildingBlocks.Domain; + +public abstract class TypedIdValueBase : IEquatable> , ITypeIdValueBase +{ + public T Value { get; } + + protected TypedIdValueBase(T value) + { + + if (EqualityComparer.Default.Equals(value, default(T))) + { + throw new InvalidOperationException($"Id value cannot be empty ! : id is {value}"); + } + + Value = value; + } + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + return obj is TypedIdValueBase other && Equals(other); + } + + public override int GetHashCode() + { + return Value!.GetHashCode(); + } + + public bool Equals(TypedIdValueBase? other) + { + return EqualityComparer.Default.Equals(this.Value, other.Value); + } + + public static bool operator ==(TypedIdValueBase? obj1, TypedIdValueBase? obj2) + { + if (object.Equals(obj1, null)) + { + if (object.Equals(obj2, null)) + { + return true; + } + + return false; + } + + return obj1.Equals(obj2); + } + + public static bool operator !=(TypedIdValueBase? x, TypedIdValueBase? y) + { + return !(x == y); + } +} +public interface ITypeIdValueBase { } + diff --git a/VichVich.BuildingBlocks.Domain/ValueObject.cs b/VichVich.BuildingBlocks.Domain/ValueObject.cs new file mode 100644 index 0000000..3347aa9 --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/ValueObject.cs @@ -0,0 +1,123 @@ + + +using System.Reflection; +using Vizhvizh.BuildingBlocks.Domain.Exceptions; + +namespace Vizhvizh.BuildingBlocks.Domain; + +public abstract class ValueObject : IEquatable +{ + private List _properties; + + private List _fields; + + public static bool operator ==(ValueObject? obj1, ValueObject? obj2) + { + if (object.Equals(obj1, null)) + { + if (object.Equals(obj2, null)) + { + return true; + } + + return false; + } + + return obj1.Equals(obj2); + } + + public static bool operator !=(ValueObject? obj1, ValueObject? obj2) + { + return !(obj1 == obj2); + } + + public bool Equals(ValueObject? obj) + { + return Equals(obj as object); + } + + public override bool Equals(object? obj) + { + if (obj == null || GetType() != obj.GetType()) + { + return false; + } + + return GetProperties().All(p => PropertiesAreEqual(obj, p)) + && GetFields().All(f => FieldsAreEqual(obj, f)); + } + + public override int GetHashCode() + { + unchecked + { + int hash = 17; + foreach (var prop in GetProperties()) + { + var value = prop.GetValue(this, null); + hash = HashValue(hash, value); + } + + foreach (var field in GetFields()) + { + var value = field.GetValue(this); + hash = HashValue(hash, value); + } + + return hash; + } + } + + protected static void CheckRule(IBusinessRule rule) + { + if (rule.IsBroken()) + { + throw new BusinessRuleValidationException(rule); + } + } + + private bool PropertiesAreEqual(object obj, PropertyInfo p) + { + return object.Equals(p.GetValue(this, null), p.GetValue(obj, null)); + } + + private bool FieldsAreEqual(object obj, FieldInfo f) + { + return object.Equals(f.GetValue(this), f.GetValue(obj)); + } + + private IEnumerable GetProperties() + { + if (this._properties == null) + { + this._properties = GetType() + .GetProperties(BindingFlags.Instance | BindingFlags.Public) + .Where(p => p.GetCustomAttribute(typeof(IgnoreMemberAttribute)) == null) + .ToList(); + + // Not available in Core + // !Attribute.IsDefined(p, typeof(IgnoreMemberAttribute))).ToList(); + } + + return this._properties; + } + + private IEnumerable GetFields() + { + if (this._fields == null) + { + this._fields = GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + .Where(p => p.GetCustomAttribute(typeof(IgnoreMemberAttribute)) == null) + .ToList(); + } + + return this._fields; + } + + private int HashValue(int seed, object value) + { + var currentHash = value?.GetHashCode() ?? 0; + + return (seed * 23) + currentHash; + } +} diff --git a/VichVich.BuildingBlocks.Domain/Vizhvizh.BuildingBlocks.Domain.csproj b/VichVich.BuildingBlocks.Domain/Vizhvizh.BuildingBlocks.Domain.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/VichVich.BuildingBlocks.Domain/Vizhvizh.BuildingBlocks.Domain.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/VichVich.BuildingBlocks.Infrastructure/BiDictionary.cs b/VichVich.BuildingBlocks.Infrastructure/BiDictionary.cs new file mode 100644 index 0000000..2c2feaa --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/BiDictionary.cs @@ -0,0 +1,30 @@ +namespace Vizhvizh.BuildingBlocks.Infrastructure; + +public class BiDictionary +{ + private readonly IDictionary _firstToSecond = new Dictionary(); + + private readonly IDictionary _secondToFirst = new Dictionary(); + + public void Add(TFirst first, TSecond second) + { + if (_firstToSecond.ContainsKey(first) || + _secondToFirst.ContainsKey(second)) + { + throw new ArgumentException("Duplicate first or second"); + } + + _firstToSecond.Add(first, second); + _secondToFirst.Add(second, first); + } + + public bool TryGetByFirst(TFirst first, out TSecond second) + { + return _firstToSecond.TryGetValue(first, out second); + } + + public bool TryGetBySecond(TSecond second, out TFirst first) + { + return _secondToFirst.TryGetValue(second, out first); + } +} diff --git a/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/DomainEventsAccessor.cs b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/DomainEventsAccessor.cs new file mode 100644 index 0000000..ad758af --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/DomainEventsAccessor.cs @@ -0,0 +1,35 @@ +using Microsoft.EntityFrameworkCore; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.BuildingBlocks.Infrastructure.DomainEventsDispatching; + +public class DomainEventsAccessor : IDomainEventsAccessor +{ + private readonly DbContext _dbContext; + + public DomainEventsAccessor(DbContext dbContext) + { + _dbContext = dbContext; + } + + public IReadOnlyCollection GetAllDomainEvents() + { + var domainEntities = this._dbContext.ChangeTracker + .Entries>() + .Where(x => x.Entity.DomainEvents != null && x.Entity.DomainEvents.Any()).ToList(); + + return domainEntities + .SelectMany(x => x.Entity.DomainEvents) + .ToList(); + } + + public void ClearAllDomainEvents() + { + var domainEntities = this._dbContext.ChangeTracker + .Entries>() + .Where(x => x.Entity.DomainEvents != null && x.Entity.DomainEvents.Any()).ToList(); + + domainEntities + .ForEach(entity => entity.Entity.ClearDomainEvents()); + } +} diff --git a/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/DomainEventsDispatcher.cs b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/DomainEventsDispatcher.cs new file mode 100644 index 0000000..0710581 --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/DomainEventsDispatcher.cs @@ -0,0 +1,77 @@ +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using Vizhvizh.BuildingBlocks.Application.Events; +using Vizhvizh.BuildingBlocks.Application.Outbox; +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.BuildingBlocks.Infrastructure.Serialization; + +namespace Vizhvizh.BuildingBlocks.Infrastructure.DomainEventsDispatching; + +public class DomainEventsDispatcher : IDomainEventsDispatcher +{ + private readonly IExecutor _executor; + + private readonly IServiceProvider _provider; + + private readonly IOutbox _outbox; + + private readonly IDomainEventsAccessor _domainEventsProvider; + + private readonly IDomainNotificationsMapper _domainNotificationsMapper; + + public DomainEventsDispatcher( + IExecutor executor, + IServiceProvider provider, + IOutbox outbox, + IDomainEventsAccessor domainEventsProvider, + IDomainNotificationsMapper domainNotificationsMapper) + { + _executor = executor; + _provider = provider; + _outbox = outbox; + _domainEventsProvider = domainEventsProvider; + _domainNotificationsMapper = domainNotificationsMapper; + } + + public async Task DispatchEventsAsync() + { + var domainEvents = _domainEventsProvider.GetAllDomainEvents(); + + List> domainEventNotifications = []; + foreach (var domainEvent in domainEvents) + { + Type domainEvenNotificationType = typeof(IDomainEventNotification<>); + var domainNotificationWithGenericType = domainEvenNotificationType.MakeGenericType(domainEvent.GetType()); + var domainNotification = _provider.GetServices(domainNotificationWithGenericType); + + if (domainNotification != null) + { + domainEventNotifications.Add(domainNotification as IDomainEventNotification); + } + } + + _domainEventsProvider.ClearAllDomainEvents(); + + foreach (var domainEvent in domainEvents) + { + await _executor.Execute(domainEvent); + } + + foreach (var domainEventNotification in domainEventNotifications) + { + var type = _domainNotificationsMapper.GetName(domainEventNotification.GetType()); + var data = JsonConvert.SerializeObject(domainEventNotification, new JsonSerializerSettings + { + ContractResolver = new AllPropertiesContractResolver() + }); + + var outboxMessage = new OutboxMessage( + domainEventNotification.Id, + domainEventNotification.DomainEvent.OccurredOn, + type, + data); + + _outbox.Add(outboxMessage); + } + } +} diff --git a/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/DomainEventsDispatcherNotificationHandlerDecorator.cs b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/DomainEventsDispatcherNotificationHandlerDecorator.cs new file mode 100644 index 0000000..5d799ec --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/DomainEventsDispatcherNotificationHandlerDecorator.cs @@ -0,0 +1,27 @@ + +using Vizhvizh.BuildingBlocks.Application.Contract; +using Vizhvizh.BuildingBlocks.Domain.Contract; + +namespace Vizhvizh.BuildingBlocks.Infrastructure.DomainEventsDispatching; + +public class DomainEventsDispatcherNotificationHandlerDecorator : INotificationHandler + where T : INotification +{ + private readonly INotificationHandler _decorated; + private readonly IDomainEventsDispatcher _domainEventsDispatcher; + + public DomainEventsDispatcherNotificationHandlerDecorator( + IDomainEventsDispatcher domainEventsDispatcher, + INotificationHandler decorated) + { + _domainEventsDispatcher = domainEventsDispatcher; + _decorated = decorated; + } + + public async Task Handle(T notification, CancellationToken cancellationToken) + { + await _decorated.Handle(notification, cancellationToken); + + await _domainEventsDispatcher.DispatchEventsAsync(); + } +} \ No newline at end of file diff --git a/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/DomainNotificationsMapper.cs b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/DomainNotificationsMapper.cs new file mode 100644 index 0000000..b8c9390 --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/DomainNotificationsMapper.cs @@ -0,0 +1,21 @@ +namespace Vizhvizh.BuildingBlocks.Infrastructure.DomainEventsDispatching; + +public class DomainNotificationsMapper : IDomainNotificationsMapper +{ + private readonly BiDictionary _domainNotificationsMap; + + public DomainNotificationsMapper(BiDictionary domainNotificationsMap) + { + _domainNotificationsMap = domainNotificationsMap; + } + + public string GetName(Type type) + { + return _domainNotificationsMap.TryGetBySecond(type, out var name) ? name : null; + } + + public Type GetType(string name) + { + return _domainNotificationsMap.TryGetByFirst(name, out var type) ? type : null; + } +} \ No newline at end of file diff --git a/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/IDomainEventsAccessor.cs b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/IDomainEventsAccessor.cs new file mode 100644 index 0000000..fa78006 --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/IDomainEventsAccessor.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.BuildingBlocks.Infrastructure.DomainEventsDispatching; + +public interface IDomainEventsAccessor +{ + IReadOnlyCollection GetAllDomainEvents(); + + void ClearAllDomainEvents(); +} diff --git a/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/IDomainEventsDispatcher.cs b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/IDomainEventsDispatcher.cs new file mode 100644 index 0000000..c84c5d1 --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/IDomainEventsDispatcher.cs @@ -0,0 +1,8 @@ + + +namespace Vizhvizh.BuildingBlocks.Infrastructure.DomainEventsDispatching; + +public interface IDomainEventsDispatcher +{ + Task DispatchEventsAsync(); +} diff --git a/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/IDomainNotificationsMapper.cs b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/IDomainNotificationsMapper.cs new file mode 100644 index 0000000..bf1ecd6 --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/IDomainNotificationsMapper.cs @@ -0,0 +1,7 @@ +namespace Vizhvizh.BuildingBlocks.Infrastructure.DomainEventsDispatching; +public interface IDomainNotificationsMapper +{ + string GetName(Type type); + + Type GetType(string name); +} diff --git a/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/UnitOfWorkCommandHandlerDecorator.cs b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/UnitOfWorkCommandHandlerDecorator.cs new file mode 100644 index 0000000..630069a --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/DomainEventsDispatching/UnitOfWorkCommandHandlerDecorator.cs @@ -0,0 +1,50 @@ +using Vizhvizh.BuildingBlocks.Application.Configuration.Commnad; +using Vizhvizh.BuildingBlocks.Application.Contract; +using Vizhvizh.BuildingBlocks.Domain.Contract; + +namespace Vizhvizh.BuildingBlocks.Infrastructure.DomainEventsDispatching; + +public class UnitOfWorkCommandHandlerDecorator : ICommandHandler + where TCommand : ICommand +{ + private readonly ICommandHandler _decorated; + private readonly IUnitOfWork _unitOfWork; + + public UnitOfWorkCommandHandlerDecorator( + ICommandHandler decorated, + IUnitOfWork unitOfWork) + { + _decorated = decorated; + _unitOfWork = unitOfWork; + } + + public async Task Handle(TCommand command, CancellationToken cancellationToken) + { + await this._decorated.Handle(command, cancellationToken); + + await this._unitOfWork.CommitAsync(cancellationToken); + } +} +public class UnitOfWorkCommandHandlerDecorator : ICommandHandler + where TCommand : ICommand +{ + private readonly ICommandHandler _decorated; + private readonly IUnitOfWork _unitOfWork; + + public UnitOfWorkCommandHandlerDecorator( + ICommandHandler decorated, + IUnitOfWork unitOfWork) + { + _decorated = decorated; + _unitOfWork = unitOfWork; + } + + public async Task Handle(TCommand command, CancellationToken cancellationToken) + { + var result = await this._decorated.Handle(command, cancellationToken); + + await this._unitOfWork.CommitAsync(cancellationToken); + + return result; + } +} \ No newline at end of file diff --git a/VichVich.BuildingBlocks.Infrastructure/IExecutor.cs b/VichVich.BuildingBlocks.Infrastructure/IExecutor.cs new file mode 100644 index 0000000..3fdcbd1 --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/IExecutor.cs @@ -0,0 +1,12 @@ +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.BuildingBlocks.Domain.Contract; + +namespace Vizhvizh.BuildingBlocks.Infrastructure; + +public interface IExecutor +{ + Task Execute(ICommand command, CancellationToken cancellationToken); + Task Execute(ICommand command, CancellationToken cancellationToken); + Task Execute(IQuery query, CancellationToken cancellationToken); + Task Execute(IDomainEvent notification, CancellationToken cancellationToken = default); +} diff --git a/VichVich.BuildingBlocks.Infrastructure/IUnitOfWork.cs b/VichVich.BuildingBlocks.Infrastructure/IUnitOfWork.cs new file mode 100644 index 0000000..6710714 --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/IUnitOfWork.cs @@ -0,0 +1,7 @@ +namespace Vizhvizh.BuildingBlocks.Infrastructure; + +public interface IUnitOfWork +{ + Task CommitAsync( + CancellationToken cancellationToken = default); +} diff --git a/VichVich.BuildingBlocks.Infrastructure/Inbox/InboxMessage.cs b/VichVich.BuildingBlocks.Infrastructure/Inbox/InboxMessage.cs new file mode 100644 index 0000000..aa4d60c --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/Inbox/InboxMessage.cs @@ -0,0 +1,26 @@ +namespace Vizhvizh.BuildingBlocks.Infrastructure.Inbox; + +public class InboxMessage +{ + public Guid Id { get; set; } + + public DateTime OccurredOn { get; set; } + + public string Type { get; set; } + + public string Data { get; set; } + + public DateTime? ProcessedDate { get; set; } + + public InboxMessage(DateTime occurredOn, string type, string data) + { + this.Id = Guid.NewGuid(); + this.OccurredOn = occurredOn; + this.Type = type; + this.Data = data; + } + + private InboxMessage() + { + } +} diff --git a/VichVich.BuildingBlocks.Infrastructure/Mapper/ReplaceMediatorOpenTypes.cs b/VichVich.BuildingBlocks.Infrastructure/Mapper/ReplaceMediatorOpenTypes.cs new file mode 100644 index 0000000..f032947 --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/Mapper/ReplaceMediatorOpenTypes.cs @@ -0,0 +1,12 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Vizhvizh.BuildingBlocks.Infrastructure.Mapper; + +internal static class ReplaceMediatorOpenTypes +{ + public static void Replace(this IServiceCollection services) + { + //services.Replace(new ServiceDescriptor()) // ToDo + } +} diff --git a/VichVich.BuildingBlocks.Infrastructure/SelectBuilders/PostgreSqlDialect.cs b/VichVich.BuildingBlocks.Infrastructure/SelectBuilders/PostgreSqlDialect.cs new file mode 100644 index 0000000..491e005 --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/SelectBuilders/PostgreSqlDialect.cs @@ -0,0 +1,44 @@ +using System.Text; +using Vizhvizh.BuildingBlocks.Application.SelectBuilders; + +namespace Vizhvizh.BuildingBlocks.Infrastructure.SelectBuilders +{ + // پیاده‌سازی برای PostgreSQL (مثال) + public class PostgreSqlDialect : ISqlDialect + { + public string BuildSelectQuery( + List columns, + string table, + List whereConditions, + string? orderBy, + int? top, + (int pageNumber, int pageSize)? pagination) + { + var stringBuilder = new StringBuilder(); + stringBuilder.Append($"SELECT {string.Join(", ", columns)} FROM {table}"); + + if (whereConditions.Any()) + stringBuilder.Append( $" WHERE {string.Join(" AND ", whereConditions)}"); + + if (!string.IsNullOrEmpty(orderBy)) + stringBuilder.Append($" ORDER BY {orderBy}"); + else if (pagination.HasValue) + throw new InvalidOperationException("ORDER BY is required for pagination"); + + // اولویت با Pagination است (اگر وجود داشته باشد) + if (pagination.HasValue) + { + var (pageNumber, pageSize) = pagination.Value; + var offset = (pageNumber - 1) * pageSize; + stringBuilder.Append($" LIMIT {pageSize} OFFSET {offset}"); + } + // اگر Pagination نبود ولی Top داشت + else if (top.HasValue) + { + stringBuilder.Append($" LIMIT {top.Value}"); + } + + return stringBuilder.ToString(); + } + } +} \ No newline at end of file diff --git a/VichVich.BuildingBlocks.Infrastructure/SelectBuilders/SqlSelectBuilder.cs b/VichVich.BuildingBlocks.Infrastructure/SelectBuilders/SqlSelectBuilder.cs new file mode 100644 index 0000000..93215ef --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/SelectBuilders/SqlSelectBuilder.cs @@ -0,0 +1,153 @@ +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq.Expressions; +using System.Reflection; +using Vizhvizh.BuildingBlocks.Application.SelectBuilders; + +namespace Vizhvizh.BuildingBlocks.Infrastructure.SelectBuilders; + +public class SqlSelectBuilder : ISqlSelectBuilder +{ + private string _tableName = null!; + private readonly List _selectedColumns = new(); + private readonly List _whereConditions = new(); + private readonly Dictionary _parameters = new(); + private string? _orderBy; + private int? _top; + private readonly ISqlDialect _dialect; + private (int pageSize, int pageNumber)? _pagination; + public SqlSelectBuilder(ISqlDialect? dialect = null) + { + _dialect = dialect ?? new SqlServerDialect(); + } + + public ISqlSelectBuilder From(string tableName) + { + _tableName = tableName; + return this; + } + + // حالت ساده: یکسان بودن نام ستون و DTO Property + public ISqlSelectBuilder Select(params Expression>[] selectors) + { + foreach (var selector in selectors) + { + var memberInfo = GetMemberInfo(selector); + var columnName = GetColumnName(memberInfo); + var alias = memberInfo.Name; + + _selectedColumns.Add($"[{columnName}] as {alias}"); + } + return this; + } + + // حالت پیشرفته: Domain Property و DTO Property متفاوت + public ISqlSelectBuilder Select(params (Expression> Domain, Expression> Dto)[] mappings) + { + foreach (var (domainExpr, dtoExpr) in mappings) + { + var domainMember = GetMemberInfo(domainExpr); + var dtoMember = GetMemberInfo(dtoExpr); + + var columnName = GetColumnName(domainMember); + var alias = dtoMember.Name; + + _selectedColumns.Add($"[{columnName}] as {alias}"); + } + return this; + } + + public ISqlSelectBuilder Where(Expression> property, object? value) + { + var memberInfo = GetMemberInfo(property); + var columnName = GetColumnName(memberInfo); + var paramName = $"p{_parameters.Count}"; + + _whereConditions.Add($"[{columnName}] = @{paramName}"); + _parameters[paramName] = value ?? DBNull.Value; + + return this; + } + + public ISqlSelectBuilder WhereLike(Expression> property, string pattern) + { + var memberInfo = GetMemberInfo(property); + var columnName = GetColumnName(memberInfo); + var paramName = $"p{_parameters.Count}"; + + _whereConditions.Add($"[{columnName}] LIKE @{paramName}"); + _parameters[paramName] = pattern; + + return this; + } + + public ISqlSelectBuilder Top(int count) + { + _top = count; + return this; + } + + public ISqlSelectBuilder OrderBy(Expression> property, bool ascending = true) + { + var memberInfo = GetMemberInfo(property); + var columnName = GetColumnName(memberInfo); + _orderBy = $"[{columnName}] {(ascending ? "ASC" : "DESC")}"; + return this; + } + + + public ISqlSelectBuilder Pagination(int pageNumber, int pageSize) + { + _pagination = (pageNumber, pageSize); + return this; + } + + public ISqlSelectBuilder Pagination(int pageNumber, int pageSize, Expression> property, bool ascending = true) + { + OrderBy(property, ascending); + Pagination(pageNumber, pageSize); + return this; + + } + public (string Sql, object Parameters) Build() + { + if (string.IsNullOrEmpty(_tableName)) + throw new InvalidOperationException("Table name not specified"); + + if (_selectedColumns.Count == 0) + _selectedColumns.Add("*"); + + var sql = _dialect.BuildSelectQuery( + _selectedColumns, + _tableName, + _whereConditions, + _orderBy, + _top, + _pagination); + + return (sql, _parameters); + } + + private MemberInfo GetMemberInfo(Expression expression) + { + var lambda = (LambdaExpression)expression; + var body = lambda.Body; + + if (body is UnaryExpression unary) + body = unary.Operand; + + if (body is MemberExpression member) + return member.Member; + + if (body is MethodCallExpression methodCall && methodCall.Method.Name == "Single") + return ((MemberExpression)methodCall.Arguments[0]).Member; + + throw new InvalidOperationException($"Cannot get member info from {expression}"); + } + + private string GetColumnName(MemberInfo member) + { + var columnAttr = member.GetCustomAttribute(); + return columnAttr?.Name ?? member.Name; + } + +} \ No newline at end of file diff --git a/VichVich.BuildingBlocks.Infrastructure/SelectBuilders/SqlServerDialect.cs b/VichVich.BuildingBlocks.Infrastructure/SelectBuilders/SqlServerDialect.cs new file mode 100644 index 0000000..5e57f35 --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/SelectBuilders/SqlServerDialect.cs @@ -0,0 +1,45 @@ +using System.Text; +using Vizhvizh.BuildingBlocks.Application.SelectBuilders; + +namespace Vizhvizh.BuildingBlocks.Infrastructure.SelectBuilders; + +// پیاده‌سازی برای SQL Server +public class SqlServerDialect : ISqlDialect +{ + public string BuildSelectQuery( + List columns, + string table, + List whereConditions, + string? orderBy, + int? top, + (int pageNumber, int pageSize)? pagination) + { + var stringBuilder = new StringBuilder(); + + stringBuilder.Append($"SELECT {(top.HasValue ? $"TOP {top.Value}" : "")} " + + $"{string.Join(", ", columns)} " + + $"FROM {table}"); + + if (whereConditions.Any()) + stringBuilder.Append($" WHERE {string.Join(" AND ", whereConditions)}"); + + // برای Pagination حتماً ORDER BY نیاز است + if (pagination.HasValue && string.IsNullOrEmpty(orderBy)) + throw new InvalidOperationException("ORDER BY is required for pagination"); + + if (!string.IsNullOrEmpty(orderBy)) + stringBuilder.Append($" ORDER BY {orderBy}"); + + // پیاده‌سازی Pagination در SQL Server (با استفاده از OFFSET/FETCH) + if (pagination.HasValue) + { + var (pageNumber, pageSize) = pagination.Value; + var offset = (pageNumber - 1) * pageSize; + + // اگر ORDER BY نداشتیم، قبلاً خطا دادیم + stringBuilder.Append($" OFFSET {offset} ROWS FETCH NEXT {pageSize} ROWS ONLY"); + } + + return stringBuilder.ToString(); + } +} diff --git a/VichVich.BuildingBlocks.Infrastructure/Serialization/AllPropertiesContractResolver.cs b/VichVich.BuildingBlocks.Infrastructure/Serialization/AllPropertiesContractResolver.cs new file mode 100644 index 0000000..4e6e631 --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/Serialization/AllPropertiesContractResolver.cs @@ -0,0 +1,25 @@ +using Newtonsoft.Json.Serialization; +using Newtonsoft.Json; +using System.Reflection; + +namespace Vizhvizh.BuildingBlocks.Infrastructure.Serialization; +public class AllPropertiesContractResolver : DefaultContractResolver +{ + protected override IList CreateProperties(Type type, MemberSerialization memberSerialization) + { + var properties = type.GetProperties( + BindingFlags.Public | + BindingFlags.NonPublic | + BindingFlags.Instance) + .Select(p => this.CreateProperty(p, memberSerialization)) + .ToList(); + + properties.ForEach(p => + { + p.Writable = true; + p.Readable = true; + }); + + return properties; + } +} diff --git a/VichVich.BuildingBlocks.Infrastructure/SqlConnectionFactory.cs b/VichVich.BuildingBlocks.Infrastructure/SqlConnectionFactory.cs new file mode 100644 index 0000000..9467fd2 --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/SqlConnectionFactory.cs @@ -0,0 +1,48 @@ +using Microsoft.Data.SqlClient; +using System.Data; +using Vizhvizh.BuildingBlocks.Application.Data; + +namespace Vizhvizh.BuildingBlocks.Infrastructure; + +public class SqlConnectionFactory : ISqlConnectionFactory +{ + private readonly string _connectionString; + private IDbConnection _connection; + + public SqlConnectionFactory(string connectionString) + { + this._connectionString = connectionString; + } + + public IDbConnection GetOpenConnection() + { + if (this._connection == null || this._connection.State != ConnectionState.Open) + { + this._connection = new SqlConnection(_connectionString); + this._connection.Open(); + } + + return this._connection; + } + + public IDbConnection CreateNewConnection() + { + var connection = new SqlConnection(_connectionString); + connection.Open(); + + return connection; + } + + public string GetConnectionString() + { + return _connectionString; + } + + public void Dispose() + { + if (this._connection != null && this._connection.State == ConnectionState.Open) + { + this._connection.Dispose(); + } + } +} diff --git a/VichVich.BuildingBlocks.Infrastructure/UnitOfWork.cs b/VichVich.BuildingBlocks.Infrastructure/UnitOfWork.cs new file mode 100644 index 0000000..3a580a6 --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/UnitOfWork.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore; +using Vizhvizh.BuildingBlocks.Infrastructure.DomainEventsDispatching; + +namespace Vizhvizh.BuildingBlocks.Infrastructure; + +public class UnitOfWork : IUnitOfWork +{ + private readonly DbContext _context; + private readonly IDomainEventsDispatcher _domainEventsDispatcher; + + public UnitOfWork( + DbContext context, + IDomainEventsDispatcher domainEventsDispatcher) + { + this._context = context; + this._domainEventsDispatcher = domainEventsDispatcher; + } + + public async Task CommitAsync( + CancellationToken cancellationToken = default) + { + await this._domainEventsDispatcher.DispatchEventsAsync(); + + return await _context.SaveChangesAsync(cancellationToken); + } +} \ No newline at end of file diff --git a/VichVich.BuildingBlocks.Infrastructure/Vizhvizh.BuildingBlocks.Infrastructure.csproj b/VichVich.BuildingBlocks.Infrastructure/Vizhvizh.BuildingBlocks.Infrastructure.csproj new file mode 100644 index 0000000..6ef520c --- /dev/null +++ b/VichVich.BuildingBlocks.Infrastructure/Vizhvizh.BuildingBlocks.Infrastructure.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + + diff --git a/VichVich.Shared.Domain.Resource/EntityResources.Designer.cs b/VichVich.Shared.Domain.Resource/EntityResources.Designer.cs new file mode 100644 index 0000000..d94ccb8 --- /dev/null +++ b/VichVich.Shared.Domain.Resource/EntityResources.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.Shared.Domain.Resource { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class EntityResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal EntityResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.Shared.Domain.Resource.EntityResources", typeof(EntityResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to سامانه فروشگاه. + /// + public static string ModuleNamesEnum_Shop { + get { + return ResourceManager.GetString("ModuleNamesEnum_Shop", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to سامانه مدیریت کاربران. + /// + public static string ModuleNamesEnum_UserAccess { + get { + return ResourceManager.GetString("ModuleNamesEnum_UserAccess", resourceCulture); + } + } + } +} diff --git a/VichVich.Shared.Domain.Resource/EntityResources.resx b/VichVich.Shared.Domain.Resource/EntityResources.resx new file mode 100644 index 0000000..94b9105 --- /dev/null +++ b/VichVich.Shared.Domain.Resource/EntityResources.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + سامانه فروشگاه + + + سامانه مدیریت کاربران + + \ No newline at end of file diff --git a/VichVich.Shared.Domain.Resource/ExceptionResources.Designer.cs b/VichVich.Shared.Domain.Resource/ExceptionResources.Designer.cs new file mode 100644 index 0000000..5129529 --- /dev/null +++ b/VichVich.Shared.Domain.Resource/ExceptionResources.Designer.cs @@ -0,0 +1,99 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.Shared.Domain.Resource { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class ExceptionResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ExceptionResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.Shared.Domain.Resource.ExceptionResources", typeof(ExceptionResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to {0} نمیتواند بیشتر از {1} کارکتر باشد. + /// + public static string CharacterLimitException { + get { + return ResourceManager.GetString("CharacterLimitException", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ایمیل معتبر نمی باشد. + /// + public static string InvalidEmailException { + get { + return ResourceManager.GetString("InvalidEmailException", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to شماره همراه معتبر نمی باشد. + /// + public static string InvalidPhoneNumberException { + get { + return ResourceManager.GetString("InvalidPhoneNumberException", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to تلفن همراه معتبر نمی باشد. + /// + public static string InvalidTelephoneException { + get { + return ResourceManager.GetString("InvalidTelephoneException", resourceCulture); + } + } + } +} diff --git a/VichVich.Shared.Domain.Resource/ExceptionResources.resx b/VichVich.Shared.Domain.Resource/ExceptionResources.resx new file mode 100644 index 0000000..c5a2950 --- /dev/null +++ b/VichVich.Shared.Domain.Resource/ExceptionResources.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + {0} نمیتواند بیشتر از {1} کارکتر باشد + + + ایمیل معتبر نمی باشد + + + شماره همراه معتبر نمی باشد + + + تلفن همراه معتبر نمی باشد + + \ No newline at end of file diff --git a/VichVich.Shared.Domain.Resource/ValueObjectResources.Designer.cs b/VichVich.Shared.Domain.Resource/ValueObjectResources.Designer.cs new file mode 100644 index 0000000..0a2d16d --- /dev/null +++ b/VichVich.Shared.Domain.Resource/ValueObjectResources.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.Shared.Domain.Resource { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class ValueObjectResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ValueObjectResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.Shared.Domain.Resource.ValueObjectResources", typeof(ValueObjectResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to توضیحات. + /// + public static string Description { + get { + return ResourceManager.GetString("Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to عنوان. + /// + public static string Title { + get { + return ResourceManager.GetString("Title", resourceCulture); + } + } + } +} diff --git a/VichVich.Shared.Domain.Resource/ValueObjectResources.resx b/VichVich.Shared.Domain.Resource/ValueObjectResources.resx new file mode 100644 index 0000000..8a8ea29 --- /dev/null +++ b/VichVich.Shared.Domain.Resource/ValueObjectResources.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + توضیحات + + + عنوان + + \ No newline at end of file diff --git a/VichVich.Shared.Domain.Resource/Vizhvizh.Shared.Domain.Resource.csproj b/VichVich.Shared.Domain.Resource/Vizhvizh.Shared.Domain.Resource.csproj new file mode 100644 index 0000000..aaf5237 --- /dev/null +++ b/VichVich.Shared.Domain.Resource/Vizhvizh.Shared.Domain.Resource.csproj @@ -0,0 +1,42 @@ + + + + net8.0 + enable + enable + + + + + EntityResources.resx + True + True + + + ExceptionResources.resx + True + True + + + ValueObjectResources.resx + True + True + + + + + + EntityResources.Designer.cs + PublicResXFileCodeGenerator + + + ExceptionResources.Designer.cs + PublicResXFileCodeGenerator + + + ValueObjectResources.Designer.cs + PublicResXFileCodeGenerator + + + + diff --git a/VichVich.Shop.Domain.Resource/Members/EntityResources.Designer.cs b/VichVich.Shop.Domain.Resource/Members/EntityResources.Designer.cs new file mode 100644 index 0000000..8c34e34 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Members/EntityResources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.Shop.Domain.Resource.Members { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class EntityResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal EntityResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.Shop.Domain.Resource.Members.EntityResources", typeof(EntityResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/VichVich.Shop.Domain.Resource/Members/EntityResources.resx b/VichVich.Shop.Domain.Resource/Members/EntityResources.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Members/EntityResources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/VichVich.Shop.Domain.Resource/Members/ExceptionResources.Designer.cs b/VichVich.Shop.Domain.Resource/Members/ExceptionResources.Designer.cs new file mode 100644 index 0000000..321a121 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Members/ExceptionResources.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.Shop.Domain.Resource.Members { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class ExceptionResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ExceptionResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.Shop.Domain.Resource.Members.ExceptionResources", typeof(ExceptionResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to نام یا نام خانوادگی نمیتواند خالی باشد. + /// + public static string MemberFullNameNullOrEmptyException { + get { + return ResourceManager.GetString("MemberFullNameNullOrEmptyException", resourceCulture); + } + } + } +} diff --git a/VichVich.Shop.Domain.Resource/Members/ExceptionResources.resx b/VichVich.Shop.Domain.Resource/Members/ExceptionResources.resx new file mode 100644 index 0000000..ed58c17 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Members/ExceptionResources.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + نام یا نام خانوادگی نمیتواند خالی باشد + + \ No newline at end of file diff --git a/VichVich.Shop.Domain.Resource/Members/ValueObjectResources.Designer.cs b/VichVich.Shop.Domain.Resource/Members/ValueObjectResources.Designer.cs new file mode 100644 index 0000000..45fb344 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Members/ValueObjectResources.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.Shop.Domain.Resource.Members { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class ValueObjectResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ValueObjectResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.Shop.Domain.Resource.Members.ValueObjectResources", typeof(ValueObjectResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to نام و نام خانوادگی. + /// + public static string MemberFullName { + get { + return ResourceManager.GetString("MemberFullName", resourceCulture); + } + } + } +} diff --git a/VichVich.Shop.Domain.Resource/Members/ValueObjectResources.resx b/VichVich.Shop.Domain.Resource/Members/ValueObjectResources.resx new file mode 100644 index 0000000..7824784 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Members/ValueObjectResources.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + نام و نام خانوادگی + + \ No newline at end of file diff --git a/VichVich.Shop.Domain.Resource/Products/EntityResources.Designer.cs b/VichVich.Shop.Domain.Resource/Products/EntityResources.Designer.cs new file mode 100644 index 0000000..72ddcf7 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Products/EntityResources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.Shop.Domain.Resource.Products { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class EntityResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal EntityResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.Shop.Domain.Resource.Products.EntityResources", typeof(EntityResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/VichVich.Shop.Domain.Resource/Products/EntityResources.resx b/VichVich.Shop.Domain.Resource/Products/EntityResources.resx new file mode 100644 index 0000000..4fdb1b6 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Products/EntityResources.resx @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/VichVich.Shop.Domain.Resource/Products/ExceptionResources.Designer.cs b/VichVich.Shop.Domain.Resource/Products/ExceptionResources.Designer.cs new file mode 100644 index 0000000..1b2a735 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Products/ExceptionResources.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.Shop.Domain.Resource.Products { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class ExceptionResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ExceptionResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.Shop.Domain.Resource.Products.ExceptionResources", typeof(ExceptionResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to مقدار {0} برای ویژگی با نوع {1} معتبر نمی‌باشد. + /// + public static string InvalidProductVariantValueException { + get { + return ResourceManager.GetString("InvalidProductVariantValueException", resourceCulture); + } + } + } +} diff --git a/VichVich.Shop.Domain.Resource/Products/ExceptionResources.resx b/VichVich.Shop.Domain.Resource/Products/ExceptionResources.resx new file mode 100644 index 0000000..c2ee0b2 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Products/ExceptionResources.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + مقدار {0} برای ویژگی با نوع {1} معتبر نمی‌باشد + + \ No newline at end of file diff --git a/VichVich.Shop.Domain.Resource/Products/ValueObjectResources.Designer.cs b/VichVich.Shop.Domain.Resource/Products/ValueObjectResources.Designer.cs new file mode 100644 index 0000000..763aa03 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Products/ValueObjectResources.Designer.cs @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.Shop.Domain.Resource.Products { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class ValueObjectResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ValueObjectResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.Shop.Domain.Resource.Products.ValueObjectResources", typeof(ValueObjectResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to نو. + /// + public static string ProductConditionEnum_BrandNew { + get { + return ResourceManager.GetString("ProductConditionEnum_BrandNew", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to در حد نو. + /// + public static string ProductConditionEnum_LikeNew { + get { + return ResourceManager.GetString("ProductConditionEnum_LikeNew", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to کارکرده. + /// + public static string ProductConditionEnum_Used { + get { + return ResourceManager.GetString("ProductConditionEnum_Used", resourceCulture); + } + } + } +} diff --git a/VichVich.Shop.Domain.Resource/Products/ValueObjectResources.resx b/VichVich.Shop.Domain.Resource/Products/ValueObjectResources.resx new file mode 100644 index 0000000..1af7d35 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Products/ValueObjectResources.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + نو + + + در حد نو + + + کارکرده + + \ No newline at end of file diff --git a/VichVich.Shop.Domain.Resource/Shops/EntityResources.Designer.cs b/VichVich.Shop.Domain.Resource/Shops/EntityResources.Designer.cs new file mode 100644 index 0000000..e758c53 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Shops/EntityResources.Designer.cs @@ -0,0 +1,99 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.Shop.Domain.Resource.Shops { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class EntityResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal EntityResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.Shop.Domain.Resource.Shops.EntityResources", typeof(EntityResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to مدیریت فروشگاه. + /// + public static string Management { + get { + return ResourceManager.GetString("Management", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to عضو. + /// + public static string Member { + get { + return ResourceManager.GetString("Member", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to نوع ارسال مرسوله. + /// + public static string ShippingMethod { + get { + return ResourceManager.GetString("ShippingMethod", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to فروشگاه. + /// + public static string Shop { + get { + return ResourceManager.GetString("Shop", resourceCulture); + } + } + } +} diff --git a/VichVich.Shop.Domain.Resource/Shops/EntityResources.resx b/VichVich.Shop.Domain.Resource/Shops/EntityResources.resx new file mode 100644 index 0000000..55ceb56 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Shops/EntityResources.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + مدیریت فروشگاه + + + عضو + + + نوع ارسال مرسوله + + + فروشگاه + + \ No newline at end of file diff --git a/VichVich.Shop.Domain.Resource/Shops/ExceptionResources.Designer.cs b/VichVich.Shop.Domain.Resource/Shops/ExceptionResources.Designer.cs new file mode 100644 index 0000000..dde03a1 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Shops/ExceptionResources.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.Shop.Domain.Resource.Shops { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class ExceptionResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ExceptionResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.Shop.Domain.Resource.Shops.ExceptionResources", typeof(ExceptionResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to آدرس اینترنتی اسلایدر نمیتواند خالی باشد. + /// + public static string IsNullOrEmptySliderUrlException { + get { + return ResourceManager.GetString("IsNullOrEmptySliderUrlException", resourceCulture); + } + } + } +} diff --git a/VichVich.Shop.Domain.Resource/Shops/ExceptionResources.resx b/VichVich.Shop.Domain.Resource/Shops/ExceptionResources.resx new file mode 100644 index 0000000..1881bac --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Shops/ExceptionResources.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + آدرس اینترنتی اسلایدر نمیتواند خالی باشد + + \ No newline at end of file diff --git a/VichVich.Shop.Domain.Resource/Shops/ValueObjectResources.Designer.cs b/VichVich.Shop.Domain.Resource/Shops/ValueObjectResources.Designer.cs new file mode 100644 index 0000000..e39b90f --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Shops/ValueObjectResources.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.Shop.Domain.Resource.Shops { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class ValueObjectResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ValueObjectResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.Shop.Domain.Resource.Shops.ValueObjectResources", typeof(ValueObjectResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to نام و نام خانوادگی. + /// + public static string MemberFullName { + get { + return ResourceManager.GetString("MemberFullName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to لوکیشین فروشگاه. + /// + public static string ShopLocation { + get { + return ResourceManager.GetString("ShopLocation", resourceCulture); + } + } + } +} diff --git a/VichVich.Shop.Domain.Resource/Shops/ValueObjectResources.resx b/VichVich.Shop.Domain.Resource/Shops/ValueObjectResources.resx new file mode 100644 index 0000000..c19287e --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Shops/ValueObjectResources.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + نام و نام خانوادگی + + + لوکیشین فروشگاه + + \ No newline at end of file diff --git a/VichVich.Shop.Domain.Resource/Users/EntityResources.Designer.cs b/VichVich.Shop.Domain.Resource/Users/EntityResources.Designer.cs new file mode 100644 index 0000000..32303fa --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Users/EntityResources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.Shop.Domain.Resource.Users { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class EntityResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal EntityResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.Shop.Domain.Resource.Users.EntityResources", typeof(EntityResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/VichVich.Shop.Domain.Resource/Users/EntityResources.resx b/VichVich.Shop.Domain.Resource/Users/EntityResources.resx new file mode 100644 index 0000000..4fdb1b6 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Users/EntityResources.resx @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/VichVich.Shop.Domain.Resource/Users/ExceptionResources.Designer.cs b/VichVich.Shop.Domain.Resource/Users/ExceptionResources.Designer.cs new file mode 100644 index 0000000..43d30fc --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Users/ExceptionResources.Designer.cs @@ -0,0 +1,72 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.Shop.Domain.Resource.Users { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class ExceptionResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ExceptionResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.Shop.Domain.Resource.Users.ExceptionResources", typeof(ExceptionResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to کد ملی معتبر نمی باشد. + /// + public static string InvalidNationalCodeException { + get { + return ResourceManager.GetString("InvalidNationalCodeException", resourceCulture); + } + } + } +} diff --git a/VichVich.Shop.Domain.Resource/Users/ExceptionResources.resx b/VichVich.Shop.Domain.Resource/Users/ExceptionResources.resx new file mode 100644 index 0000000..cc7357c --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Users/ExceptionResources.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + کد ملی معتبر نمی باشد + + \ No newline at end of file diff --git a/VichVich.Shop.Domain.Resource/Users/ValueObjectResources.Designer.cs b/VichVich.Shop.Domain.Resource/Users/ValueObjectResources.Designer.cs new file mode 100644 index 0000000..7616519 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Users/ValueObjectResources.Designer.cs @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.Shop.Domain.Resource.Users { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class ValueObjectResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ValueObjectResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.Shop.Domain.Resource.Users.ValueObjectResources", typeof(ValueObjectResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to خواندن. + /// + public static string AccessLevelEnum_Read { + get { + return ResourceManager.GetString("AccessLevelEnum_Read", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to خواندن/نوشتن. + /// + public static string AccessLevelEnum_ReadWrite { + get { + return ResourceManager.GetString("AccessLevelEnum_ReadWrite", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to نوشتن. + /// + public static string AccessLevelEnum_Write { + get { + return ResourceManager.GetString("AccessLevelEnum_Write", resourceCulture); + } + } + } +} diff --git a/VichVich.Shop.Domain.Resource/Users/ValueObjectResources.resx b/VichVich.Shop.Domain.Resource/Users/ValueObjectResources.resx new file mode 100644 index 0000000..7b26589 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Users/ValueObjectResources.resx @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + خواندن + + + خواندن/نوشتن + + + نوشتن + + \ No newline at end of file diff --git a/VichVich.Shop.Domain.Resource/Vizhvizh.Shop.Domain.Resource.csproj b/VichVich.Shop.Domain.Resource/Vizhvizh.Shop.Domain.Resource.csproj new file mode 100644 index 0000000..62ef4b2 --- /dev/null +++ b/VichVich.Shop.Domain.Resource/Vizhvizh.Shop.Domain.Resource.csproj @@ -0,0 +1,123 @@ + + + + net8.0 + enable + enable + + + + + EntityResources.resx + True + True + + + ExceptionResources.resx + True + True + + + ValueObjectResources.resx + True + True + + + True + True + EntityResources.resx + + + True + True + ExceptionResources.resx + + + True + True + ValueObjectResources.resx + + + True + True + EntityResources.resx + + + ExceptionResources.resx + True + True + + + True + True + ValueObjectResources.resx + + + EntityResources.resx + True + True + + + ExceptionResources.resx + True + True + + + ValueObjectResources.resx + True + True + + + + + + EntityResources.Designer.cs + PublicResXFileCodeGenerator + + + ExceptionResources.Designer.cs + PublicResXFileCodeGenerator + + + ValueObjectResources.Designer.cs + PublicResXFileCodeGenerator + + + PublicResXFileCodeGenerator + EntityResources.Designer.cs + + + PublicResXFileCodeGenerator + ExceptionResources.Designer.cs + + + PublicResXFileCodeGenerator + ValueObjectResources.Designer.cs + + + PublicResXFileCodeGenerator + EntityResources.Designer.cs + + + ExceptionResources.Designer.cs + PublicResXFileCodeGenerator + + + PublicResXFileCodeGenerator + ValueObjectResources.Designer.cs + + + EntityResources.Designer.cs + PublicResXFileCodeGenerator + + + ExceptionResources.Designer.cs + PublicResXFileCodeGenerator + + + ValueObjectResources.Designer.cs + PublicResXFileCodeGenerator + + + + diff --git a/Vichvich.Geteway/Program.cs b/Vichvich.Geteway/Program.cs new file mode 100644 index 0000000..2edcfd9 --- /dev/null +++ b/Vichvich.Geteway/Program.cs @@ -0,0 +1,28 @@ +using Microsoft.OpenApi.Models; +using Ocelot.DependencyInjection; +using Ocelot.Middleware; +using Ocelot.Values; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddOcelot(); +builder.Services.AddSwaggerForOcelot(builder.Configuration); +builder.Configuration.SetBasePath(builder.Environment.ContentRootPath); +builder.Configuration.AddJsonFile("ocelot.json"); +builder.WebHost.UseIIS() + .UseContentRoot(Directory.GetCurrentDirectory()) + .UseIISIntegration(); + +builder.Services.AddSwaggerGen(); + +builder.Services.AddMvc(); + +var app = builder.Build(); + +app.UseSwaggerForOcelotUI(opt => +{ + opt.PathToSwaggerGenerator = "/swagger/docs"; +}); +app.UseOcelot().Wait(); + +app.Run(); \ No newline at end of file diff --git a/Vichvich.Geteway/Properties/launchSettings.json b/Vichvich.Geteway/Properties/launchSettings.json new file mode 100644 index 0000000..a800bf4 --- /dev/null +++ b/Vichvich.Geteway/Properties/launchSettings.json @@ -0,0 +1,40 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:17619", + "sslPort": 44373 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger/index.html", + "applicationUrl": "http://localhost:5192", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger/index.html", + "applicationUrl": "https://localhost:7135;http://localhost:5192", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Vichvich.Geteway/Vizhvizh.Geteway.csproj b/Vichvich.Geteway/Vizhvizh.Geteway.csproj new file mode 100644 index 0000000..d5a6f6c --- /dev/null +++ b/Vichvich.Geteway/Vizhvizh.Geteway.csproj @@ -0,0 +1,17 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + diff --git a/Vichvich.Geteway/appsettings.Development.json b/Vichvich.Geteway/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Vichvich.Geteway/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Vichvich.Geteway/appsettings.json b/Vichvich.Geteway/appsettings.json new file mode 100644 index 0000000..9ae7d37 --- /dev/null +++ b/Vichvich.Geteway/appsettings.json @@ -0,0 +1,21 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "SwaggerEndPoints": [ + { + "Key": "shop", + "Config": [ + { + "Name": "Shop API", + "Version": "v1", + "Url": "https://localhost:44331/swagger/v1/swagger.json" + } + ] + } + ], + "AllowedHosts": "*" +} diff --git a/Vichvich.Geteway/ocelot.json b/Vichvich.Geteway/ocelot.json new file mode 100644 index 0000000..a199d21 --- /dev/null +++ b/Vichvich.Geteway/ocelot.json @@ -0,0 +1,34 @@ +{ + "Routes": [ + { + "DownstreamPathTemplate": "/api/Values/AddShop", + "DownstreamScheme": "https", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 44331 + } + ], + "UpstreamPathTemplate": "/shop/AddShop", + "UpstreamHttpMethod": [ "Post" ], + "SwaggerKey": "shop" + }, + { + "DownstreamPathTemplate": "/api/Values/GetById", + "DownstreamScheme": "https", + "DownstreamHostAndPorts": [ + { + "Host": "localhost", + "Port": 44331 + } + ], + "UpstreamPathTemplate": "/shop/GetById", + "UpstreamHttpMethod": [ "Get" ], + "SwaggerKey": "shop" + } + ], + + "GlobalConfiguration": { + "BaseUrl": "https://localhost:7135" + } +} \ No newline at end of file diff --git a/Vichvich.Location.Domain/Entities/City.cs b/Vichvich.Location.Domain/Entities/City.cs new file mode 100644 index 0000000..ee75e4b --- /dev/null +++ b/Vichvich.Location.Domain/Entities/City.cs @@ -0,0 +1,8 @@ +using Vizhvizh.Shared.Domain.TypeIds; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shared.Domain.Entities; + +public class City : Entity +{ +} diff --git a/Vichvich.Location.Domain/Entities/Province.cs b/Vichvich.Location.Domain/Entities/Province.cs new file mode 100644 index 0000000..9804da3 --- /dev/null +++ b/Vichvich.Location.Domain/Entities/Province.cs @@ -0,0 +1,8 @@ +using Vizhvizh.Shared.Domain.TypeIds; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shared.Domain.Entities; + +public class Province : Entity +{ +} diff --git a/Vichvich.Location.Domain/TypeIds/CityId.cs b/Vichvich.Location.Domain/TypeIds/CityId.cs new file mode 100644 index 0000000..25b25c9 --- /dev/null +++ b/Vichvich.Location.Domain/TypeIds/CityId.cs @@ -0,0 +1,11 @@ + +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shared.Domain.TypeIds; + +public class CityId : TypedIdValueBase +{ + public CityId(int value) : base(value) + { + } +} diff --git a/Vichvich.Location.Domain/TypeIds/ProvinceId.cs b/Vichvich.Location.Domain/TypeIds/ProvinceId.cs new file mode 100644 index 0000000..e8d1b8a --- /dev/null +++ b/Vichvich.Location.Domain/TypeIds/ProvinceId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shared.Domain.TypeIds; + +public class ProvinceId : TypedIdValueBase +{ + public ProvinceId(int value) : base(value) + { + } +} diff --git a/Vichvich.Location.Domain/Vizhvizh.Location.Domain.csproj b/Vichvich.Location.Domain/Vizhvizh.Location.Domain.csproj new file mode 100644 index 0000000..c65615f --- /dev/null +++ b/Vichvich.Location.Domain/Vizhvizh.Location.Domain.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + diff --git a/Vichvich.Shared.Application/Vizhvizh.Shared.Application.csproj b/Vichvich.Shared.Application/Vizhvizh.Shared.Application.csproj new file mode 100644 index 0000000..c4b1694 --- /dev/null +++ b/Vichvich.Shared.Application/Vizhvizh.Shared.Application.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + + + + + + + + diff --git a/Vichvich.Shared.Domain/Entities/ModuleInformation.cs b/Vichvich.Shared.Domain/Entities/ModuleInformation.cs new file mode 100644 index 0000000..0e79870 --- /dev/null +++ b/Vichvich.Shared.Domain/Entities/ModuleInformation.cs @@ -0,0 +1,17 @@ +using Vizhvizh.Shared.Domain.TypeIds; +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shared.Domain.Entities; + +public class ModuleInformation : Entity +{ + private List<(ModuleNameVO, AppVersionVO)> _modulesInformation = []; + + public ModuleInformation() + { + _modulesInformation.Add(new (ModuleNameVO.UserAccess, new AppVersionVO(1,0,0,0))); + _modulesInformation.Add(new (ModuleNameVO.Shop, new AppVersionVO(1,0,0,0))); + } +} + diff --git a/Vichvich.Shared.Domain/Exceptions/CharacterLimitException.cs b/Vichvich.Shared.Domain/Exceptions/CharacterLimitException.cs new file mode 100644 index 0000000..b64866e --- /dev/null +++ b/Vichvich.Shared.Domain/Exceptions/CharacterLimitException.cs @@ -0,0 +1,12 @@ +using Vizhvizh.Shared.Domain.Resource; +using Vizhvizh.BuildingBlocks.Domain.Exceptions; + +namespace Vizhvizh.Shared.Domain.Exceptions; + +public class CharacterLimitException : ValueObjectValidationException +{ + public CharacterLimitException(string name,short limit) + : base(string.Format(ExceptionResources.CharacterLimitException, name, limit)) + { + } +} diff --git a/Vichvich.Shared.Domain/Exceptions/InvalidEmailException.cs b/Vichvich.Shared.Domain/Exceptions/InvalidEmailException.cs new file mode 100644 index 0000000..affc37a --- /dev/null +++ b/Vichvich.Shared.Domain/Exceptions/InvalidEmailException.cs @@ -0,0 +1,11 @@ +using Vizhvizh.Shared.Domain.Resource; +using Vizhvizh.BuildingBlocks.Domain.Exceptions; + +namespace Vizhvizh.Shared.Domain.Exceptions; + +public class InvalidEmailException : ValueObjectValidationException +{ + public InvalidEmailException() : base(ExceptionResources.InvalidEmailException) + { + } +} diff --git a/Vichvich.Shared.Domain/Exceptions/InvalidPhoneNumberException.cs b/Vichvich.Shared.Domain/Exceptions/InvalidPhoneNumberException.cs new file mode 100644 index 0000000..76aac82 --- /dev/null +++ b/Vichvich.Shared.Domain/Exceptions/InvalidPhoneNumberException.cs @@ -0,0 +1,11 @@ +using Vizhvizh.Shared.Domain.Resource; +using Vizhvizh.BuildingBlocks.Domain.Exceptions; + + +namespace Vizhvizh.Shared.Domain.Exceptions; +public class InvalidPhoneNumberException : ValueObjectValidationException +{ + public InvalidPhoneNumberException() : base(ExceptionResources.InvalidPhoneNumberException) + { + } +} diff --git a/Vichvich.Shared.Domain/Exceptions/InvalidTelephoneException.cs b/Vichvich.Shared.Domain/Exceptions/InvalidTelephoneException.cs new file mode 100644 index 0000000..b7172d5 --- /dev/null +++ b/Vichvich.Shared.Domain/Exceptions/InvalidTelephoneException.cs @@ -0,0 +1,10 @@ +using Vizhvizh.Shared.Domain.Resource; +using Vizhvizh.BuildingBlocks.Domain.Exceptions; + +namespace Vizhvizh.Shared.Domain.Exceptions; +public class InvalidTelephoneException : ValueObjectValidationException +{ + public InvalidTelephoneException() : base(ExceptionResources.InvalidTelephoneException) + { + } +} diff --git a/Vichvich.Shared.Domain/TypeIds/ModuleInformationId.cs b/Vichvich.Shared.Domain/TypeIds/ModuleInformationId.cs new file mode 100644 index 0000000..0af75c2 --- /dev/null +++ b/Vichvich.Shared.Domain/TypeIds/ModuleInformationId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shared.Domain.TypeIds; + +public class ModuleInformationId : TypedIdValueBase +{ + public ModuleInformationId(int value) : base(value) + { + } +} diff --git a/Vichvich.Shared.Domain/ValueObjects/AppVersionVO.cs b/Vichvich.Shared.Domain/ValueObjects/AppVersionVO.cs new file mode 100644 index 0000000..f1000fd --- /dev/null +++ b/Vichvich.Shared.Domain/ValueObjects/AppVersionVO.cs @@ -0,0 +1,28 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shared.Domain.ValueObjects; + +/// +/// MAJOR.MINOR.REVISION.BUILDNUMBER, where: +/// MAJOR is a major release(usually many new features or changes to the UI or underlying OS) +/// MINOR is a minor release(perhaps some new features) on a previous major release +/// REVISION is usually a fix for a previous minor release(no new functionality) +/// BUILDNUMBER is incremented for each latest build of a revision. +/// +public class AppVersionVO : ValueObject +{ + public AppVersionVO(int major, int minor, int revision, int build) + { + Major = major; + Minor = minor; + Revision = revision; + Build = build; + } + public int Major { get; init; } + public int Minor { get; init; } + public int Revision { get; init; } + public int Build { get; init; } + + public override string ToString() + => $"{Major}.{Minor}.{Revision}.{Build}"; +} diff --git a/Vichvich.Shared.Domain/ValueObjects/DateTimeVO.cs b/Vichvich.Shared.Domain/ValueObjects/DateTimeVO.cs new file mode 100644 index 0000000..303f719 --- /dev/null +++ b/Vichvich.Shared.Domain/ValueObjects/DateTimeVO.cs @@ -0,0 +1,28 @@ +using System.Globalization; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shared.Domain.ValueObjects; + +public class DateTimeVO : ValueObject +{ + public DateTime Value { get; } + + private DateTimeVO(DateTime dateTime) + => Value = dateTime; + + public static DateTimeVO CreateNew(DateTime dateTime) + => new DateTimeVO(dateTime); + + public string ToShamsiDateTime() + { + var persianCalendar = new PersianCalendar(); + persianCalendar.ToDateTime(Value.Year, Value.Month, Value.Day, Value.Hour, Value.Minute, Value.Second, 0); + return persianCalendar.ToString()!; + } + + public static implicit operator DateTimeVO(DateTime dateTime) + => CreateNew(dateTime); + + public static implicit operator DateTime(DateTimeVO dateTime) + => dateTime.Value; +} diff --git a/Vichvich.Shared.Domain/ValueObjects/DescriptionVO.cs b/Vichvich.Shared.Domain/ValueObjects/DescriptionVO.cs new file mode 100644 index 0000000..157d716 --- /dev/null +++ b/Vichvich.Shared.Domain/ValueObjects/DescriptionVO.cs @@ -0,0 +1,30 @@ +using Vizhvizh.Shared.Domain.Exceptions; +using Vizhvizh.Shared.Domain.Resource; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shared.Domain.ValueObjects; + +/// +/// توضیحات ، معرفی +/// +public class DescriptionVO : ValueObject +{ + public const short Limit = 500; + public string Value { get; } + private DescriptionVO(string description) + { + if (description.Length > Limit) + throw new CharacterLimitException(ValueObjectResources.Description, limit: Limit); + + Value = description; + } + + public static DescriptionVO CreateNew(string description) + => new DescriptionVO(description); + + public static implicit operator DescriptionVO(string value) + => CreateNew(value); + + public static implicit operator string(DescriptionVO value) + => value.Value; +} diff --git a/Vichvich.Shared.Domain/ValueObjects/EmailVO.cs b/Vichvich.Shared.Domain/ValueObjects/EmailVO.cs new file mode 100644 index 0000000..db25e13 --- /dev/null +++ b/Vichvich.Shared.Domain/ValueObjects/EmailVO.cs @@ -0,0 +1,31 @@ +using System.Net.Mail; +using Vizhvizh.Shared.Domain.Exceptions; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shared.Domain.ValueObjects; + +public class EmailVO : ValueObject +{ + public const short Limit = 200; + private EmailVO(string value) + { + if (value.Length > Limit) + throw new CharacterLimitException("Email", Limit); + try { new MailAddress(value); } + catch + { + throw new InvalidEmailException(); + } + + Value = value; + } + public static EmailVO CreateNew(string value) + => new EmailVO(value); + public string Value { get; private set; } + + public static implicit operator EmailVO(string value) + => CreateNew(value); + + public static implicit operator string(EmailVO value) + => value.Value; +} diff --git a/Vichvich.Shared.Domain/ValueObjects/ModuleNameVO.cs b/Vichvich.Shared.Domain/ValueObjects/ModuleNameVO.cs new file mode 100644 index 0000000..51120af --- /dev/null +++ b/Vichvich.Shared.Domain/ValueObjects/ModuleNameVO.cs @@ -0,0 +1,28 @@ +using System.ComponentModel.DataAnnotations; +using Vizhvizh.Shared.Domain.Resource; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shared.Domain.ValueObjects; + +public class ModuleNameVO : ValueObject +{ + public static ModuleNameVO Shop = new(ModuleNamesEnum.Shop); + public static ModuleNameVO UserAccess = new(ModuleNamesEnum.UserAccess); + + + private ModuleNameVO(ModuleNamesEnum module) + { + Value = module; + } + public static ModuleNameVO CreateNew(ModuleNamesEnum module) + => new ModuleNameVO(module); + + public ModuleNamesEnum Value { get; init; } +} + public enum ModuleNamesEnum +{ + [Display(Name = nameof(EntityResources.ModuleNamesEnum_Shop), ResourceType = typeof(EntityResources))] + Shop = 0, + [Display(Name = nameof(EntityResources.ModuleNamesEnum_UserAccess), ResourceType = typeof(EntityResources))] + UserAccess = 1 +} diff --git a/Vichvich.Shared.Domain/ValueObjects/PhoneNumberVO.cs b/Vichvich.Shared.Domain/ValueObjects/PhoneNumberVO.cs new file mode 100644 index 0000000..e621e2b --- /dev/null +++ b/Vichvich.Shared.Domain/ValueObjects/PhoneNumberVO.cs @@ -0,0 +1,31 @@ +using System.Text.RegularExpressions; +using Vizhvizh.Shared.Domain.Exceptions; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shared.Domain.ValueObjects; + +public class PhoneNumberVO : ValueObject +{ + public const short Limit = 11; + private PhoneNumberVO(string value) + { + if(value.Length > Limit) + throw new InvalidPhoneNumberException(); + + var reg = new Regex("(0?9)\\d{9}"); + if (!reg.IsMatch(value)) + throw new InvalidPhoneNumberException(); + + Value = value; + + } + public static PhoneNumberVO CreateNew(string value) + => new PhoneNumberVO(value); + public string Value { get; private set; } + + public static implicit operator PhoneNumberVO(string value) + => CreateNew(value); + + public static implicit operator string(PhoneNumberVO value) + => value.Value; +} diff --git a/Vichvich.Shared.Domain/ValueObjects/TelephoneVO.cs b/Vichvich.Shared.Domain/ValueObjects/TelephoneVO.cs new file mode 100644 index 0000000..6a94ff2 --- /dev/null +++ b/Vichvich.Shared.Domain/ValueObjects/TelephoneVO.cs @@ -0,0 +1,24 @@ +using System.Text.RegularExpressions; +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shared.Domain.Exceptions; + +namespace Vizhvizh.Shared.Domain.ValueObjects; + +public class TelephoneVO : ValueObject +{ + public const short Limit = 11; + private TelephoneVO(string value) + { + if (value.Length > Limit) + throw new InvalidTelephoneException(); + + var reg = new Regex("^0[0-9]{2,}[0-9]{7,}$"); + if (!reg.IsMatch(value)) + throw new InvalidTelephoneException(); + + Value = value; + } + public static TelephoneVO CreateNew(string value) + => new TelephoneVO(value); + public string Value { get; init; } +} diff --git a/Vichvich.Shared.Domain/ValueObjects/TitleVO.cs b/Vichvich.Shared.Domain/ValueObjects/TitleVO.cs new file mode 100644 index 0000000..7c4de67 --- /dev/null +++ b/Vichvich.Shared.Domain/ValueObjects/TitleVO.cs @@ -0,0 +1,32 @@ +using Vizhvizh.Shared.Domain.Exceptions; +using Vizhvizh.Shared.Domain.Resource; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shared.Domain.ValueObjects; +/// +/// عنوان +/// +public class TitleVO : ValueObject +{ + public const short Limit = 60; + + public string Value { get; } + + public static TitleVO CreateNew(string title) + => new TitleVO(title); + + private TitleVO(string title) + { + if (title.Length > Limit) + throw new CharacterLimitException(ValueObjectResources.Title,limit: Limit); + + Value = title; + } + + + public static implicit operator TitleVO(string value) + => CreateNew(value); + + public static implicit operator string(TitleVO value) + => value.Value; +} diff --git a/Vichvich.Shared.Domain/Vizhvizh.Shared.Domain.csproj b/Vichvich.Shared.Domain/Vizhvizh.Shared.Domain.csproj new file mode 100644 index 0000000..5b805b3 --- /dev/null +++ b/Vichvich.Shared.Domain/Vizhvizh.Shared.Domain.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + + + + + + + + diff --git a/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/DateTimeConverter.cs b/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/DateTimeConverter.cs new file mode 100644 index 0000000..f4e5f16 --- /dev/null +++ b/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/DateTimeConverter.cs @@ -0,0 +1,12 @@ +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Vizhvizh.Shared.Domain.ValueObjects; + +namespace Vizhvizh.Shared.Infrastructure.EF.Configurations.Converters; + +public class DateTimeConverter : ValueConverter +{ + public DateTimeConverter() + : base(x=>x.Value, x=> DateTimeVO.CreateNew(x)) + { + } +} diff --git a/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/DescriptionConverter.cs b/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/DescriptionConverter.cs new file mode 100644 index 0000000..b848a63 --- /dev/null +++ b/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/DescriptionConverter.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using System.Linq.Expressions; +using Vizhvizh.Shared.Domain.ValueObjects; + +namespace Vizhvizh.Shared.Infrastructure.EF.Configurations.Converters; + +public class DescriptionConverter : ValueConverter +{ + public DescriptionConverter() + : base(x=>x.Value, x=> DescriptionVO.CreateNew(x)) + { + } +} diff --git a/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/EmailConverter.cs b/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/EmailConverter.cs new file mode 100644 index 0000000..b783209 --- /dev/null +++ b/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/EmailConverter.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using System.Linq.Expressions; +using Vizhvizh.Shared.Domain.ValueObjects; + +namespace Vizhvizh.Shared.Infrastructure.EF.Configurations.Converters; + +public class EmailConverter : ValueConverter +{ + public EmailConverter() + : base(x=>x.Value, x=> EmailVO.CreateNew(x)) + { + } +} diff --git a/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/ModuleNameConverter.cs b/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/ModuleNameConverter.cs new file mode 100644 index 0000000..77c9b5f --- /dev/null +++ b/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/ModuleNameConverter.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using System.Linq.Expressions; +using Vizhvizh.Shared.Domain.ValueObjects; + +namespace Vizhvizh.Shared.Infrastructure.EF.Configurations.Converters; + +public class ModuleNameConverter : ValueConverter +{ + public ModuleNameConverter() + : base(x=>x.Value, x=> ModuleNameVO.CreateNew(x)) + { + } +} diff --git a/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/PhoneNumberConverter.cs b/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/PhoneNumberConverter.cs new file mode 100644 index 0000000..e1ab634 --- /dev/null +++ b/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/PhoneNumberConverter.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using System.Linq.Expressions; +using Vizhvizh.Shared.Domain.ValueObjects; + +namespace Vizhvizh.Shared.Infrastructure.EF.Configurations.Converters; + +public class PhoneNumberConverter : ValueConverter +{ + public PhoneNumberConverter() + : base(x=>x.Value, x=> PhoneNumberVO.CreateNew(x)) + { + } +} diff --git a/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/TelephoneConverter.cs b/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/TelephoneConverter.cs new file mode 100644 index 0000000..3e4f72e --- /dev/null +++ b/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/TelephoneConverter.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using System.Linq.Expressions; +using Vizhvizh.Shared.Domain.ValueObjects; + +namespace Vizhvizh.Shared.Infrastructure.EF.Configurations.Converters; + +public class TelephoneConverter : ValueConverter +{ + public TelephoneConverter() + : base(x=>x.Value, x=> TelephoneVO.CreateNew(x)) + { + } +} diff --git a/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/TitleConverter.cs b/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/TitleConverter.cs new file mode 100644 index 0000000..f856478 --- /dev/null +++ b/Vichvich.Shared.Infrastructure/EF/Configurations/Converters/TitleConverter.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using System.Linq.Expressions; +using Vizhvizh.Shared.Domain.ValueObjects; + +namespace Vizhvizh.Shared.Infrastructure.EF.Configurations.Converters; + +public class TitleConverter : ValueConverter +{ + public TitleConverter() + : base(x=>x.Value, x=> TitleVO.CreateNew(x)) + { + } +} diff --git a/Vichvich.Shared.Infrastructure/Vizhvizh.Shared.Infrastructure.csproj b/Vichvich.Shared.Infrastructure/Vizhvizh.Shared.Infrastructure.csproj new file mode 100644 index 0000000..c7e9e1d --- /dev/null +++ b/Vichvich.Shared.Infrastructure/Vizhvizh.Shared.Infrastructure.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + + + + + + + + diff --git a/Vichvich.Shop.Api/Configurations/ExecutionContextAccessor.cs b/Vichvich.Shop.Api/Configurations/ExecutionContextAccessor.cs new file mode 100644 index 0000000..6b1c274 --- /dev/null +++ b/Vichvich.Shop.Api/Configurations/ExecutionContextAccessor.cs @@ -0,0 +1,36 @@ +using Vizhvizh.BuildingBlocks.Application.Contract; + +namespace Vizhvizh.Shop.Api.Configurations +{ + public class ExecutionContextAccessor : IExecutionContextAccessor + { + private readonly IHttpContextAccessor _httpContextAccessor; + + public ExecutionContextAccessor(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + + public Guid UserId + { + get + { + if (_httpContextAccessor + .HttpContext? + .User? + .Claims? + .SingleOrDefault(x => x.Type == "sub")? + .Value != null) + { + return Guid.Parse(_httpContextAccessor.HttpContext.User.Claims.Single( + x => x.Type == "sub").Value); + } + + throw new ApplicationException("User context is not available"); + } + } + + + public bool IsAvailable => _httpContextAccessor.HttpContext != null; + } +} diff --git a/Vichvich.Shop.Api/Controllers/ShopController.cs b/Vichvich.Shop.Api/Controllers/ShopController.cs new file mode 100644 index 0000000..22daf71 --- /dev/null +++ b/Vichvich.Shop.Api/Controllers/ShopController.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Mvc; +using Vizhvizh.BuildingBlocks.Infrastructure; +using Vizhvizh.Shop.ApplicationContract.DTOs; +using Vizhvizh.Shop.ApplicationContract.Queries; + +namespace Vizhvizh.Shop.Api.Controllers +{ + [Route("api/[controller]/[action]")] + [ApiController] + public class ShopController(IExecutor executor) : ControllerBase + { + [HttpGet] + public async Task> GetById([FromQuery] long shopId, CancellationToken cancellationToken) + => Ok(await executor.Execute(new GetShopByIdQuery(shopId), cancellationToken)); + + + } +} diff --git a/Vichvich.Shop.Api/Controllers/SliderController.cs b/Vichvich.Shop.Api/Controllers/SliderController.cs new file mode 100644 index 0000000..89a3fa8 --- /dev/null +++ b/Vichvich.Shop.Api/Controllers/SliderController.cs @@ -0,0 +1,45 @@ +using Microsoft.AspNetCore.Mvc; +using Vizhvizh.BuildingBlocks.Infrastructure; +using Vizhvizh.Shop.Api.RequestModels; +using Vizhvizh.Shop.ApplicationContract.Commands; +using Vizhvizh.Shop.ApplicationContract.DTOs; +using Vizhvizh.Shop.ApplicationContract.Queries; +using Vizhvizh.Shop.Domain.Sliders.ValuesObjects; + +namespace Vizhvizh.Shop.Api.Controllers +{ + + [Route("api/[controller]/[action]")] + [ApiController] + + public class SliderController(IExecutor executor) : ControllerBase + { + [HttpPost] + public async Task AddMainSlider([FromBody] CreateSliderRequestModel request, CancellationToken cancellationToken) + { + await executor.Execute(new CreateSliderCommand(request.Title, request.ImageUrl, request.LinkUrl, SliderKeyType.Main, null), cancellationToken); + return Ok(); + } + + [HttpPost] + public async Task AddShopSlider([FromHeader] long shopId, [FromBody] CreateSliderRequestModel request, CancellationToken cancellationToken) + { + await executor.Execute(new CreateSliderCommand(request.Title, request.ImageUrl, request.LinkUrl, SliderKeyType.Shop, shopId.ToString()), cancellationToken); + return Ok(); + } + + [HttpPost] + public async Task AddCategorySlider([FromHeader] long categoryId, [FromBody] CreateSliderRequestModel request, CancellationToken cancellationToken) + { + await executor.Execute(new CreateSliderCommand(request.Title, request.ImageUrl, request.LinkUrl, SliderKeyType.Category, categoryId.ToString()), cancellationToken); + return Ok(); + } + + [HttpGet] + public async Task>> GetByKey([FromQuery] GetSlidersByKeyQuery request,CancellationToken cancellationToken) + { + var result = await executor.Execute(request,cancellationToken); + return Ok(result); + } + } +} diff --git a/Vichvich.Shop.Api/Program.cs b/Vichvich.Shop.Api/Program.cs new file mode 100644 index 0000000..b65f267 --- /dev/null +++ b/Vichvich.Shop.Api/Program.cs @@ -0,0 +1,33 @@ +using Vizhvizh.BuildingBlocks.Application.Contract; +using Vizhvizh.Shop.Api.Configurations; +using Vizhvizh.Shop.Infrastructure; + +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + + +builder.Services.AddSingleton(); +builder.Services.AddSingleton(); + +ShopStartup.Initialize(builder.Services, builder.Configuration.GetConnectionString("Shop")!); + +builder.Services.AddControllers(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +app.UseSwagger(); +app.UseSwaggerUI(opt => +{ + opt.SwaggerEndpoint("/swagger/v1/swagger.json", "v1"); +}); + +//app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/Vichvich.Shop.Api/Properties/launchSettings.json b/Vichvich.Shop.Api/Properties/launchSettings.json new file mode 100644 index 0000000..fd9ab01 --- /dev/null +++ b/Vichvich.Shop.Api/Properties/launchSettings.json @@ -0,0 +1,51 @@ +{ + "profiles": { + "http": { + "commandName": "Project", + "launchBrowser": false, + "launchUrl": "swagger/index.html", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5034" + }, + "https": { + "commandName": "Project", + "launchBrowser": false, + "launchUrl": "swagger/index.html", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7220;http://localhost:5034" + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": false, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/weatherforecast", + "environmentVariables": { + "ASPNETCORE_HTTPS_PORTS": "8081", + "ASPNETCORE_HTTP_PORTS": "8080" + }, + "publishAllPorts": true, + "useSSL": true + } + }, + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:16715", + "sslPort": 44331 + } + } +} \ No newline at end of file diff --git a/Vichvich.Shop.Api/RequestModels/SliderRequestModels.cs b/Vichvich.Shop.Api/RequestModels/SliderRequestModels.cs new file mode 100644 index 0000000..0444624 --- /dev/null +++ b/Vichvich.Shop.Api/RequestModels/SliderRequestModels.cs @@ -0,0 +1,3 @@ +namespace Vizhvizh.Shop.Api.RequestModels; + +public record CreateSliderRequestModel(string Title,string ImageUrl, string LinkUrl); diff --git a/Vichvich.Shop.Api/Vichvich.Shop.Api.http b/Vichvich.Shop.Api/Vichvich.Shop.Api.http new file mode 100644 index 0000000..05b75c2 --- /dev/null +++ b/Vichvich.Shop.Api/Vichvich.Shop.Api.http @@ -0,0 +1,6 @@ +@Vizhvizh.Shop.Api_HostAddress = http://localhost:5034 + +GET {{Vizhvizh.Shop.Api_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/Vichvich.Shop.Api/Vizhvizh.Shop.Api.csproj b/Vichvich.Shop.Api/Vizhvizh.Shop.Api.csproj new file mode 100644 index 0000000..e373cfb --- /dev/null +++ b/Vichvich.Shop.Api/Vizhvizh.Shop.Api.csproj @@ -0,0 +1,26 @@ + + + + net8.0 + enable + enable + false + 04e2646d-0282-4616-88fd-1df92577ae95 + Linux + ..\compose.dcproj + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + diff --git a/Vichvich.Shop.Api/appsettings.Development.json b/Vichvich.Shop.Api/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Vichvich.Shop.Api/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Vichvich.Shop.Api/appsettings.json b/Vichvich.Shop.Api/appsettings.json new file mode 100644 index 0000000..592964d --- /dev/null +++ b/Vichvich.Shop.Api/appsettings.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "ConnectionStrings": { + "Shop": "Data Source=.;Initial Catalog=Vizhvizh.Shop;Integrated Security=True;Trusted_Connection=True; MultipleActiveResultSets=true;TrustServerCertificate=True;" + }, + "AllowedHosts": "*" +} diff --git a/Vichvich.Shop.Application/CommandHandlers/Shops/CreateShopCommandHandler.cs b/Vichvich.Shop.Application/CommandHandlers/Shops/CreateShopCommandHandler.cs new file mode 100644 index 0000000..f8816d1 --- /dev/null +++ b/Vichvich.Shop.Application/CommandHandlers/Shops/CreateShopCommandHandler.cs @@ -0,0 +1,24 @@ +using Vizhvizh.BuildingBlocks.Application.Configuration.Commnad; +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.Shop.ApplicationContract.Commands; +using Vizhvizh.Shop.Domain.Shops.Repositories; +using Vizhvizh.Shop.Domain.Shops.TypeIds; +using Vizhvizh.Shop.Domain.Shops.ValuesObjects; + +namespace Vizhvizh.Shop.Application.CommandHandlers.Shops; + +public class CreateShopCommandHandler(IShopRepository shopRepository) : ICommandHandler +{ + 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 shop = Domain.Shops.Entities.Shop.CreateNew(request.OwnerId, request.Title, + location,TelephoneVO.CreateNew(request.Telephone), request.Description); + + await shopRepository.AddAsync(shop, cancellationToken); + + return shop.Id; + } +} diff --git a/Vichvich.Shop.Application/CommandHandlers/Shops/SetTitleShopCommandHandler.cs b/Vichvich.Shop.Application/CommandHandlers/Shops/SetTitleShopCommandHandler.cs new file mode 100644 index 0000000..9baec8a --- /dev/null +++ b/Vichvich.Shop.Application/CommandHandlers/Shops/SetTitleShopCommandHandler.cs @@ -0,0 +1,14 @@ +using Vizhvizh.BuildingBlocks.Application.Configuration.Commnad; +using Vizhvizh.Shop.ApplicationContract.Commands; +using Vizhvizh.Shop.Domain.Shops.Repositories; + +namespace Vizhvizh.Shop.Application.CommandHandlers.Shops; + +public class SetTitleShopCommandHandler(IShopRepository shopRepository) : ICommandHandler +{ + public async Task Handle(SetTitleShopCommand request, CancellationToken cancellationToken) + { + var shop = await shopRepository.FindByIdAsync(request.ShopId, cancellationToken); + shop.SetTitle(request.Title); + } +} diff --git a/Vichvich.Shop.Application/CommandHandlers/Sliders/CreateSliderCommandHandler.cs b/Vichvich.Shop.Application/CommandHandlers/Sliders/CreateSliderCommandHandler.cs new file mode 100644 index 0000000..f23ab33 --- /dev/null +++ b/Vichvich.Shop.Application/CommandHandlers/Sliders/CreateSliderCommandHandler.cs @@ -0,0 +1,18 @@ +using Vizhvizh.BuildingBlocks.Application.Configuration.Commnad; +using Vizhvizh.Shop.ApplicationContract.Commands; +using Vizhvizh.Shop.Domain.Sliders.Entities; +using Vizhvizh.Shop.Domain.Sliders.Repositories; +using Vizhvizh.Shop.Domain.Sliders.ValuesObjects; + +namespace Vizhvizh.Shop.Application.CommandHandlers.Sliders; + +public class CreateSliderCommandHandler(ISliderRepository sliderRepository) : ICommandHandler +{ + public async Task Handle(CreateSliderCommand request, CancellationToken cancellationToken) + { + var slider = Slider.CreateNew(request.Title, SliderImage.CreateNew(request.ImageUrl), + SliderUrl.CreateNew(request.LinkUrl), new SliderKey(request.SliderKeyType, request.SliderKey)); + + await sliderRepository.AddAsync(slider, cancellationToken); + } +} diff --git a/Vichvich.Shop.Application/IShopModule.cs b/Vichvich.Shop.Application/IShopModule.cs new file mode 100644 index 0000000..1367a4e --- /dev/null +++ b/Vichvich.Shop.Application/IShopModule.cs @@ -0,0 +1,13 @@ +using Vizhvizh.BuildingBlocks.Application.Contract; +using Vizhvizh.BuildingBlocks.Domain.Contract; + +namespace Vizhvizh.Shop.Application; + +public interface IShopModule +{ + Task ExecuteCommandAsync(ICommand command,CancellationToken cancellationToken); + + Task ExecuteCommandAsync(ICommand command, CancellationToken cancellationToken); + + Task ExecuteQueryAsync(IQuery query, CancellationToken cancellationToken); +} diff --git a/Vichvich.Shop.Application/QueryHandlers/Shops/GetShopByIdQueryHandler.cs b/Vichvich.Shop.Application/QueryHandlers/Shops/GetShopByIdQueryHandler.cs new file mode 100644 index 0000000..955eb41 --- /dev/null +++ b/Vichvich.Shop.Application/QueryHandlers/Shops/GetShopByIdQueryHandler.cs @@ -0,0 +1,33 @@ +using Dapper; +using Vizhvizh.BuildingBlocks.Application.Configuration.Query; +using Vizhvizh.BuildingBlocks.Application.Data; +using Vizhvizh.BuildingBlocks.Application.SelectBuilders; +using Vizhvizh.Shop.ApplicationContract.DTOs; +using Vizhvizh.Shop.ApplicationContract.Queries; + +namespace Vizhvizh.Shop.Application.QueryHandlers.Shops; + +public class GetShopByIdQueryHandler(ISqlConnectionFactory connectionFactory, ISqlSelectBuilder sqlSelectBuilder) : IQueryHandler +{ + public async Task Handle(GetShopByIdQuery request, CancellationToken cancellationToken) + { + var connection = connectionFactory.GetOpenConnection(); + + var (sql, parameters) = sqlSelectBuilder + .From("Shop.Shops") + .Select( + (d => d.Id, dto => dto.Id), + (d => d.OwnerId, dto => dto.OwnerId), + (d => d.Title, dto => dto.Title), + (d => d.Description, dto => dto.Description), + (d => d.Email, dto => dto.Email), + (d => d.Telephone, dto => dto.Telephone), + (d => d.Logo, dto => dto.Logo) + ) + .Where(s => s.Id, request.ShopId) + .Build(); + + var result = await connection.QueryFirstOrDefaultAsync(sql, parameters); + return result; + } +} diff --git a/Vichvich.Shop.Application/QueryHandlers/Sliders/GetSlidersByKeyQueryHandler.cs b/Vichvich.Shop.Application/QueryHandlers/Sliders/GetSlidersByKeyQueryHandler.cs new file mode 100644 index 0000000..be325ca --- /dev/null +++ b/Vichvich.Shop.Application/QueryHandlers/Sliders/GetSlidersByKeyQueryHandler.cs @@ -0,0 +1,31 @@ +using Dapper; +using Vizhvizh.BuildingBlocks.Application.Configuration.Query; +using Vizhvizh.BuildingBlocks.Application.Data; +using Vizhvizh.BuildingBlocks.Application.SelectBuilders; +using Vizhvizh.Shop.ApplicationContract.DTOs; +using Vizhvizh.Shop.ApplicationContract.Queries; +using Vizhvizh.Shop.Domain.Sliders.Entities; + +namespace Vizhvizh.Shop.Application.QueryHandlers.Sliders; + +public class GetSlidersByKeyQueryHandler(ISqlConnectionFactory sqlConnectionFactory, ISqlSelectBuilder sqlSelectBuilder) + : IQueryHandler> +{ + public async Task> Handle(GetSlidersByKeyQuery request, CancellationToken cancellationToken) + { + var connection = sqlConnectionFactory.GetOpenConnection(); + + var (sql, parameters) = sqlSelectBuilder.From("Shop.Sliders") + .Select( + (d => d.Title, dto => dto.Title), + (d => d.Image, dto => dto.Image), + (d => d.Url, dto => dto.LinkUrl) + ) + .Pagination(request.PageNumber, request.PageSize, x => x.CreateOn, false) + .Where(x => x.Key, request.Key) + .Build(); + + var result = await connection.QueryAsync(sql, parameters); + return result; + } +} diff --git a/Vichvich.Shop.Application/Vizhvizh.Shop.Application.csproj b/Vichvich.Shop.Application/Vizhvizh.Shop.Application.csproj new file mode 100644 index 0000000..a655872 --- /dev/null +++ b/Vichvich.Shop.Application/Vizhvizh.Shop.Application.csproj @@ -0,0 +1,17 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + diff --git a/Vichvich.Shop.ApplicationContract/Commands/ShopCommands.cs b/Vichvich.Shop.ApplicationContract/Commands/ShopCommands.cs new file mode 100644 index 0000000..5b94a72 --- /dev/null +++ b/Vichvich.Shop.ApplicationContract/Commands/ShopCommands.cs @@ -0,0 +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 diff --git a/Vichvich.Shop.ApplicationContract/Commands/SliderCommands.cs b/Vichvich.Shop.ApplicationContract/Commands/SliderCommands.cs new file mode 100644 index 0000000..460ec19 --- /dev/null +++ b/Vichvich.Shop.ApplicationContract/Commands/SliderCommands.cs @@ -0,0 +1,6 @@ +using Vizhvizh.BuildingBlocks.Domain.Contract; +using Vizhvizh.Shop.Domain.Sliders.ValuesObjects; + +namespace Vizhvizh.Shop.ApplicationContract.Commands; + +public record CreateSliderCommand(string Title, string ImageUrl,string LinkUrl, SliderKeyType SliderKeyType, string? SliderKey) : CommandBase; \ No newline at end of file diff --git a/Vichvich.Shop.ApplicationContract/DTOs/ShopDTO.cs b/Vichvich.Shop.ApplicationContract/DTOs/ShopDTO.cs new file mode 100644 index 0000000..b18e387 --- /dev/null +++ b/Vichvich.Shop.ApplicationContract/DTOs/ShopDTO.cs @@ -0,0 +1,13 @@ +namespace Vizhvizh.Shop.ApplicationContract.DTOs; + +public class ShopDTO +{ + public long Id { get; set; } + public long OwnerId{ get; set; } + public string Title { get; set; } = null!; + public string? Description{ get; set; } + public string? Email { get; set; } + public string Telephone { get; set; } = null!; + public string Logo{ get; set; } = null!; + public ShopLocationDTO ShopLocation { get; set; } = null!; +} diff --git a/Vichvich.Shop.ApplicationContract/DTOs/ShopLocationDTO.cs b/Vichvich.Shop.ApplicationContract/DTOs/ShopLocationDTO.cs new file mode 100644 index 0000000..3fe7d50 --- /dev/null +++ b/Vichvich.Shop.ApplicationContract/DTOs/ShopLocationDTO.cs @@ -0,0 +1,9 @@ +using Newtonsoft.Json; + +namespace Vizhvizh.Shop.ApplicationContract.DTOs; + +public record ShopLocationDTO(double Latitude,double Longitude,int ProvinceId, int CityId,string Address, string PostalCode) +{ + public static implicit operator ShopLocationDTO(string address) + => JsonConvert.DeserializeObject(address)!; +} diff --git a/Vichvich.Shop.ApplicationContract/DTOs/SliderDTO.cs b/Vichvich.Shop.ApplicationContract/DTOs/SliderDTO.cs new file mode 100644 index 0000000..54a7f95 --- /dev/null +++ b/Vichvich.Shop.ApplicationContract/DTOs/SliderDTO.cs @@ -0,0 +1,3 @@ +namespace Vizhvizh.Shop.ApplicationContract.DTOs; + +public record SliderDTO(string Title, string Image,string LinkUrl); diff --git a/Vichvich.Shop.ApplicationContract/Queries/PaginationQuery.cs b/Vichvich.Shop.ApplicationContract/Queries/PaginationQuery.cs new file mode 100644 index 0000000..9585677 --- /dev/null +++ b/Vichvich.Shop.ApplicationContract/Queries/PaginationQuery.cs @@ -0,0 +1,7 @@ +namespace Vizhvizh.Shop.ApplicationContract.Queries; + +public class PaginationQuery +{ + public int PageNumber { get; set; } + public int PageSize { get; set; } +} diff --git a/Vichvich.Shop.ApplicationContract/Queries/ShopQueries.cs b/Vichvich.Shop.ApplicationContract/Queries/ShopQueries.cs new file mode 100644 index 0000000..f8f162c --- /dev/null +++ b/Vichvich.Shop.ApplicationContract/Queries/ShopQueries.cs @@ -0,0 +1,7 @@ +using Vizhvizh.BuildingBlocks.Domain.Contract; +using Vizhvizh.Shop.ApplicationContract.DTOs; +using Vizhvizh.Shop.Domain.Shops.TypeIds; + +namespace Vizhvizh.Shop.ApplicationContract.Queries; + +public record GetShopByIdQuery(long ShopId) : IQuery; diff --git a/Vichvich.Shop.ApplicationContract/Queries/SliderQueries.cs b/Vichvich.Shop.ApplicationContract/Queries/SliderQueries.cs new file mode 100644 index 0000000..717dd78 --- /dev/null +++ b/Vichvich.Shop.ApplicationContract/Queries/SliderQueries.cs @@ -0,0 +1,9 @@ +using Vizhvizh.BuildingBlocks.Domain.Contract; +using Vizhvizh.Shop.ApplicationContract.DTOs; + +namespace Vizhvizh.Shop.ApplicationContract.Queries; + +public class GetSlidersByKeyQuery : PaginationQuery, IQuery> +{ + public string Key { get; set; } +} diff --git a/Vichvich.Shop.ApplicationContract/Vizhvizh.Shop.ApplicationContract.csproj b/Vichvich.Shop.ApplicationContract/Vizhvizh.Shop.ApplicationContract.csproj new file mode 100644 index 0000000..65f53cc --- /dev/null +++ b/Vichvich.Shop.ApplicationContract/Vizhvizh.Shop.ApplicationContract.csproj @@ -0,0 +1,23 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + + + diff --git a/Vichvich.Shop.Domain/Members/Entities/Member.cs b/Vichvich.Shop.Domain/Members/Entities/Member.cs new file mode 100644 index 0000000..4f4ba35 --- /dev/null +++ b/Vichvich.Shop.Domain/Members/Entities/Member.cs @@ -0,0 +1,31 @@ +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.Shop.Domain.Members.TypeIds; +using Vizhvizh.Shop.Domain.Members.ValuesObjects; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Members.Entities; + +public class Member : Entity, IAggregateRoot +{ + private PhoneNumberVO _phoneNumber; + private MemberFullName _fullName; + private MemberAvatar? _avatar; + + private Member() + { + + } + private Member(PhoneNumberVO phoneNumber, MemberFullName fullName, MemberAvatar? avatar) + { + _fullName = fullName; + _phoneNumber = phoneNumber; + _avatar = avatar; + } + public static Member CreateNew(PhoneNumberVO phoneNumber, MemberFullName fullName, MemberAvatar? avatar = null) + { + return new Member(phoneNumber, fullName, avatar); + } + public MemberFullName? FullName => _fullName; + public PhoneNumberVO PhoneNumber => _phoneNumber; + public MemberAvatar? Avatar => _avatar; +} diff --git a/Vichvich.Shop.Domain/Members/Exceptions/MemberFullNameNullOrEmptyException.cs b/Vichvich.Shop.Domain/Members/Exceptions/MemberFullNameNullOrEmptyException.cs new file mode 100644 index 0000000..8ad92e6 --- /dev/null +++ b/Vichvich.Shop.Domain/Members/Exceptions/MemberFullNameNullOrEmptyException.cs @@ -0,0 +1,11 @@ +using Vizhvizh.Shop.Domain.Resource.Members; +using Vizhvizh.BuildingBlocks.Domain.Exceptions; + +namespace Vizhvizh.Shop.Domain.Members.Exceptions; + +public class MemberFullNameNullOrEmptyException : ValueObjectValidationException +{ + public MemberFullNameNullOrEmptyException() : base(ExceptionResources.MemberFullNameNullOrEmptyException) + { + } +} diff --git a/Vichvich.Shop.Domain/Members/TypeIds/MemberId.cs b/Vichvich.Shop.Domain/Members/TypeIds/MemberId.cs new file mode 100644 index 0000000..86d5c92 --- /dev/null +++ b/Vichvich.Shop.Domain/Members/TypeIds/MemberId.cs @@ -0,0 +1,16 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Members.TypeIds; + +public class MemberId : TypedIdValueBase +{ + public MemberId(long value) : base(value) + { + } + + public static implicit operator MemberId(long value) + => new MemberId(value); + + public static implicit operator long(MemberId value) + => value.Value; +} diff --git a/Vichvich.Shop.Domain/Members/ValuesObjects/MemberAvatar.cs b/Vichvich.Shop.Domain/Members/ValuesObjects/MemberAvatar.cs new file mode 100644 index 0000000..7ced3a7 --- /dev/null +++ b/Vichvich.Shop.Domain/Members/ValuesObjects/MemberAvatar.cs @@ -0,0 +1,17 @@ +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shared.Domain.Exceptions; + +namespace Vizhvizh.Shop.Domain.Members.ValuesObjects; + +public class MemberAvatar : ValueObject +{ + public const short Limit = 150; + public MemberAvatar(string value) + { + if (value.Length > Limit) + throw new CharacterLimitException(nameof(MemberAvatar), Limit); + + Value = value; + } + public string Value { get; init; } +} diff --git a/Vichvich.Shop.Domain/Members/ValuesObjects/MemberFullName.cs b/Vichvich.Shop.Domain/Members/ValuesObjects/MemberFullName.cs new file mode 100644 index 0000000..1a37b56 --- /dev/null +++ b/Vichvich.Shop.Domain/Members/ValuesObjects/MemberFullName.cs @@ -0,0 +1,30 @@ +using Vizhvizh.Shared.Domain.Exceptions; +using Vizhvizh.Shop.Domain.Members.Exceptions; +using Vizhvizh.Shop.Domain.Resource.Members; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Members.ValuesObjects; + +public class MemberFullName : ValueObject +{ + public const short FirstNameLimit = 50; + public const short LastNameLimit = 50; + public MemberFullName(string firstName, string lastName) + { + if (string.IsNullOrWhiteSpace(firstName) || string.IsNullOrWhiteSpace(lastName)) + throw new MemberFullNameNullOrEmptyException(); + + if (firstName.Length > FirstNameLimit || lastName.Length > LastNameLimit) + throw new CharacterLimitException(ValueObjectResources.MemberFullName, FirstNameLimit + LastNameLimit); + + FirstName = firstName; + LastName = lastName; + } + public string FirstName { get; init; } + public string LastName { get; init; } + + public override string ToString() + { + return $"{FirstName} {LastName}"; + } +} diff --git a/Vichvich.Shop.Domain/Products/Entities/Category.cs b/Vichvich.Shop.Domain/Products/Entities/Category.cs new file mode 100644 index 0000000..f0c67f3 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/Entities/Category.cs @@ -0,0 +1,61 @@ +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.Shop.Domain.Products.TypeIds; +using Vizhvizh.Shop.Domain.Products.ValuesObjects; +using Vizhvizh.BuildingBlocks.Domain; +using System.IO; + +namespace Vizhvizh.Shop.Domain.Products.Entities; + +/// +/// دسته بندی +/// +public class Category : Entity +{ + private TitleVO _title; + private DescriptionVO _description; + private CategoryImage _image; + private CategoryId? _parentId; + private CategoryPath _path; + + #region Relationships + private List _products; + private List _categoryVariantUnits; + #endregion + + private Category() + { + + } + private Category(TitleVO title, + DescriptionVO description, + CategoryImage image, + CategoryPath path, + CategoryId? parentId = null) + { + _title = title; + _description = description; + _image = image; + _parentId = parentId; + _path = path; + + } + + public static Category CreateNew(TitleVO title, + DescriptionVO description, + CategoryImage image, + CategoryPath path, + CategoryId? parentId = null) + { + return new Category(title, description, image, path, parentId); + } + + public TitleVO Title => _title; + public DescriptionVO Description => _description; + public CategoryImage Image => _image; + public CategoryId? ParentId => _parentId; + public CategoryPath Path => _path; + public IReadOnlyList Products => _products; + public IReadOnlyList CategoryVariantUnits => _categoryVariantUnits; + + +} diff --git a/Vichvich.Shop.Domain/Products/Entities/CategoryVariantUnit.cs b/Vichvich.Shop.Domain/Products/Entities/CategoryVariantUnit.cs new file mode 100644 index 0000000..311da9b --- /dev/null +++ b/Vichvich.Shop.Domain/Products/Entities/CategoryVariantUnit.cs @@ -0,0 +1,37 @@ +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shop.Domain.Products.TypeIds; + +namespace Vizhvizh.Shop.Domain.Products.Entities; + +public class CategoryVariantUnit : Entity +{ + private CategoryId _categoryId; + private VariantUnitId _variantUnitId; + + private Category _category; + private VariantUnit _variantUnit; + private CategoryVariantUnit() + { + + } + private CategoryVariantUnit(Category category , VariantUnit variantUnit) + { + _category = category; + _variantUnit = variantUnit; + } + private CategoryVariantUnit(CategoryId categoryId, VariantUnitId variantUnitId) + { + _categoryId = categoryId; + _variantUnitId = variantUnitId; + } + public Category Category => _category; + public VariantUnit VariantUnit => _variantUnit; + + public CategoryId CategoryId => _categoryId; + public VariantUnitId VariantUnitId => _variantUnitId; + + public static CategoryVariantUnit CreateNew(Category category, VariantUnit variantUnit) + => new(category, variantUnit); + public static CategoryVariantUnit CreateNew(CategoryId categoryId, VariantUnitId variantUnitId) + => new(categoryId,variantUnitId); +} diff --git a/Vichvich.Shop.Domain/Products/Entities/Product.cs b/Vichvich.Shop.Domain/Products/Entities/Product.cs new file mode 100644 index 0000000..588a765 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/Entities/Product.cs @@ -0,0 +1,71 @@ +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.Shop.Domain.Products.TypeIds; +using Vizhvizh.Shop.Domain.Products.ValuesObjects; +using Vizhvizh.BuildingBlocks.Domain; + + +namespace Vizhvizh.Shop.Domain.Products.Entities; + +/// +/// محصول +/// +public class Product : Entity, IAggregateRoot +{ + private Category _category; + private List _specifications; + + private ProductCondition _productCondition; + private TitleVO _title; + private DescriptionVO _description; + private ProductScore _score; + private List _variants; + /// + ///عکس اصلی + /// + private ProductImage _image; + + + private Product() + { + + } + private Product(TitleVO title, + DescriptionVO description, + ProductCondition productCondition, + Category category, + List specifications, + List variants, + ProductImage image + ) + { + _title = title; + _description = description; + _productCondition = productCondition; + _category = category; + _category = category; + _specifications = specifications; + _variants = variants; + _image = image; + } + + public static Product CreateNew(TitleVO title, + DescriptionVO description, + ProductCondition productCondition, + Category category, + List specifications, + List variants, + ProductImage image) + { + return new(title, description, productCondition, category, specifications, variants, image); + } + + public Category Category => _category; + public ProductCondition ProductCondition => _productCondition; + public TitleVO Title => _title; + public DescriptionVO Description => _description; + public ProductScore Score => _score; + public ProductImage Image => _image; + public IReadOnlyList Variants => _variants; + public IReadOnlyList Specifications => _specifications; + +} diff --git a/Vichvich.Shop.Domain/Products/Entities/ProductVariant.cs b/Vichvich.Shop.Domain/Products/Entities/ProductVariant.cs new file mode 100644 index 0000000..81538b5 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/Entities/ProductVariant.cs @@ -0,0 +1,42 @@ +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shop.Domain.Products.TypeIds; +using Vizhvizh.Shop.Domain.Products.ValuesObjects; + +namespace Vizhvizh.Shop.Domain.Products.Entities; + +public class ProductVariant : Entity +{ + private VariantUnit _variantUnit; + private MoneyValue _price; + private ProductScore _score; + private ProductQuantity _quantity; + private ProductVariantValue _value; + private List _gallery; + + #region Relationships + private Product _product; + #endregion + private ProductVariant() + { + + } + private ProductVariant(VariantUnit variantUnit, MoneyValue price, ProductQuantity quantity, ProductVariantValue value) + { + _variantUnit = variantUnit; + _price = price; + _quantity = quantity; + _value = value; + } + + public VariantUnit VariantUnit => _variantUnit; + public MoneyValue Price => _price; + public ProductScore Score => _score; + public ProductQuantity Quantity => _quantity; + public ProductVariantValue Value => _value; + public Product Product => _product; + public IReadOnlyList Gallery => _gallery; + + public static ProductVariant CreateNew(VariantUnit variantUnit, MoneyValue price, ProductQuantity quantity, ProductVariantValue productVariantValue) + => new(variantUnit, price, quantity, productVariantValue); +} + diff --git a/Vichvich.Shop.Domain/Products/Entities/Specifications.cs b/Vichvich.Shop.Domain/Products/Entities/Specifications.cs new file mode 100644 index 0000000..dd9d147 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/Entities/Specifications.cs @@ -0,0 +1,37 @@ +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.Shop.Domain.Products.TypeIds; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Products.Entities; + +/// +/// مشخصات محصول +/// +public class Specifications : Entity +{ + private TitleVO _title; + + private List _itemValues; + + #region RelationShips + private Product _product; + private Specifications() + { + + } + #endregion + private Specifications(TitleVO title, Product product, List itemValues) + { + _title = title; + _itemValues = itemValues; + _product = product; + } + + public static Specifications CreateNew(TitleVO title, Product product, List values) + => new Specifications(title, product, values); + + public TitleVO Title => _title; + public Product Product => _product; + public IReadOnlyList ItemValues => _itemValues; + +} \ No newline at end of file diff --git a/Vichvich.Shop.Domain/Products/Entities/Unit.cs b/Vichvich.Shop.Domain/Products/Entities/Unit.cs new file mode 100644 index 0000000..222f146 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/Entities/Unit.cs @@ -0,0 +1,32 @@ +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.Shop.Domain.Products.TypeIds; + +namespace Vizhvizh.Shop.Domain.Products.Entities; + +/// +/// واحد اندازه گیری +/// +public class Unit : Entity +{ + private TitleVO _title; + + #region RelationShips + private List _variantUnits; + #endregion + + private Unit() + { + + } + private Unit(TitleVO title) + { + _title = title; + } + + public TitleVO Title => _title; + public IReadOnlyList VariantUnits => _variantUnits; + + public static Unit CreateNew(TitleVO title) + => new(title); +} diff --git a/Vichvich.Shop.Domain/Products/Entities/Variant.cs b/Vichvich.Shop.Domain/Products/Entities/Variant.cs new file mode 100644 index 0000000..32a54aa --- /dev/null +++ b/Vichvich.Shop.Domain/Products/Entities/Variant.cs @@ -0,0 +1,27 @@ +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.Shop.Domain.Products.TypeIds; + +namespace Vizhvizh.Shop.Domain.Products.Entities; + +public class Variant : Entity +{ + private TitleVO _title; + + #region RelationShips + private List _variantUnits; + #endregion + private Variant() + { + + } + private Variant(TitleVO title) + { + _title = title; + } + public TitleVO Title => _title; + + public IReadOnlyList VariantUnits => _variantUnits; + public static Variant CreateNew(TitleVO title) + => new Variant(title); +} diff --git a/Vichvich.Shop.Domain/Products/Entities/VariantUnit.cs b/Vichvich.Shop.Domain/Products/Entities/VariantUnit.cs new file mode 100644 index 0000000..9e02176 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/Entities/VariantUnit.cs @@ -0,0 +1,53 @@ +using Microsoft.VisualBasic; +using System.ComponentModel.DataAnnotations; +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shop.Domain.Products.TypeIds; + +namespace Vizhvizh.Shop.Domain.Products.Entities; + +public class VariantUnit : Entity +{ + + private VariantUnitType _variantUnitType; + + #region Relationships + private Variant _variant; + private Unit _unit; + private List _productVariants; + private List _categoryVariantUnits; + + #endregion + private VariantUnit() + { + + } + private VariantUnit(Unit unit, Variant variant, VariantUnitType variantUnitType) + { + _variant = variant; + _unit = unit; + _variantUnitType = variantUnitType; + + } + + public Unit Unit => _unit; + public Variant Variant => _variant; + public VariantUnitType VariantUnitType => _variantUnitType; + public IReadOnlyList ProductVariants => _productVariants; + public IReadOnlyList CategoryVariantUnits => _categoryVariantUnits; + public static VariantUnit CreateNew(Unit unit, Variant variant, VariantUnitType variantUnitType) + => new VariantUnit(unit, variant, variantUnitType); +} + +public enum VariantUnitType +{ + [Display(Name = "رنگ")] + Color, + [Display(Name = "عدد صحیح")] + Number, + [Display(Name = "ارز")] + Currency, + [Display(Name = "متن")] + Text, + [Display(Name = "عدد اعشاری")] + Decimal +} diff --git a/Vichvich.Shop.Domain/Products/Exceptions/InvalidProductVariantValueException.cs b/Vichvich.Shop.Domain/Products/Exceptions/InvalidProductVariantValueException.cs new file mode 100644 index 0000000..7ee72e4 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/Exceptions/InvalidProductVariantValueException.cs @@ -0,0 +1,14 @@ +using Vizhvizh.BuildingBlocks.Domain.Exceptions; +using Vizhvizh.Shop.Domain.Resource.Products; + +namespace Vizhvizh.Shop.Domain.Products.Exceptions +{ + public class InvalidProductVariantValueException : ValueObjectValidationException + { + public InvalidProductVariantValueException(string value, string typeName) + : base(string.Format(ExceptionResources.InvalidProductVariantValueException, value, typeName)) + { + + } + } +} diff --git a/Vichvich.Shop.Domain/Products/Repositories/IProductRepository.cs b/Vichvich.Shop.Domain/Products/Repositories/IProductRepository.cs new file mode 100644 index 0000000..f3826b0 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/Repositories/IProductRepository.cs @@ -0,0 +1,9 @@ +using Vizhvizh.Shop.Domain.Products.Entities; +using Vizhvizh.Shop.Domain.Products.TypeIds; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Products.Repositories; + +public interface IProductRepository : IRepositoryBase +{ +} diff --git a/Vichvich.Shop.Domain/Products/TypeIds/CategoryId.cs b/Vichvich.Shop.Domain/Products/TypeIds/CategoryId.cs new file mode 100644 index 0000000..af61459 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/TypeIds/CategoryId.cs @@ -0,0 +1,13 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Products.TypeIds; + +/// +/// +/// +public class CategoryId : TypedIdValueBase +{ + public CategoryId(long value) : base(value) + { + } +} diff --git a/Vichvich.Shop.Domain/Products/TypeIds/CategoryVariantUnitId.cs b/Vichvich.Shop.Domain/Products/TypeIds/CategoryVariantUnitId.cs new file mode 100644 index 0000000..3ac630e --- /dev/null +++ b/Vichvich.Shop.Domain/Products/TypeIds/CategoryVariantUnitId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Products.TypeIds; + +public class CategoryVariantUnitId : TypedIdValueBase +{ + public CategoryVariantUnitId(long value) : base(value) + { + } +} diff --git a/Vichvich.Shop.Domain/Products/TypeIds/ModelId.cs b/Vichvich.Shop.Domain/Products/TypeIds/ModelId.cs new file mode 100644 index 0000000..82ec2e7 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/TypeIds/ModelId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Products.TypeIds; + +public class ModelId : TypedIdValueBase +{ + public ModelId(long value) : base(value) + { + } +} diff --git a/Vichvich.Shop.Domain/Products/TypeIds/ProductId.cs b/Vichvich.Shop.Domain/Products/TypeIds/ProductId.cs new file mode 100644 index 0000000..7f98689 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/TypeIds/ProductId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Products.TypeIds; + +public class ProductId : TypedIdValueBase +{ + public ProductId(long value) : base(value) + { + } +} diff --git a/Vichvich.Shop.Domain/Products/TypeIds/ProductVariantId.cs b/Vichvich.Shop.Domain/Products/TypeIds/ProductVariantId.cs new file mode 100644 index 0000000..9401dfb --- /dev/null +++ b/Vichvich.Shop.Domain/Products/TypeIds/ProductVariantId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Products.TypeIds; + +public class ProductVariantId : TypedIdValueBase +{ + public ProductVariantId(long value) : base(value) + { + } +} diff --git a/Vichvich.Shop.Domain/Products/TypeIds/SpecificationsId.cs b/Vichvich.Shop.Domain/Products/TypeIds/SpecificationsId.cs new file mode 100644 index 0000000..5a440c7 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/TypeIds/SpecificationsId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Products.TypeIds; + +public class SpecificationsId : TypedIdValueBase +{ + public SpecificationsId(long value) : base(value) + { + } +} diff --git a/Vichvich.Shop.Domain/Products/TypeIds/UnitId.cs b/Vichvich.Shop.Domain/Products/TypeIds/UnitId.cs new file mode 100644 index 0000000..4f9a7f7 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/TypeIds/UnitId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Products.TypeIds; + +public class UnitId : TypedIdValueBase +{ + public UnitId(long value) : base(value) + { + } +} diff --git a/Vichvich.Shop.Domain/Products/TypeIds/VariantId.cs b/Vichvich.Shop.Domain/Products/TypeIds/VariantId.cs new file mode 100644 index 0000000..cfb2ecb --- /dev/null +++ b/Vichvich.Shop.Domain/Products/TypeIds/VariantId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Products.TypeIds; + +public class VariantId : TypedIdValueBase +{ + public VariantId(long value) : base(value) + { + } +} diff --git a/Vichvich.Shop.Domain/Products/TypeIds/VariantUnitId.cs b/Vichvich.Shop.Domain/Products/TypeIds/VariantUnitId.cs new file mode 100644 index 0000000..184d79e --- /dev/null +++ b/Vichvich.Shop.Domain/Products/TypeIds/VariantUnitId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Products.TypeIds; + +public class VariantUnitId : TypedIdValueBase +{ + public VariantUnitId(long value) : base(value) + { + } +} diff --git a/Vichvich.Shop.Domain/Products/ValuesObjects/CategoryImage.cs b/Vichvich.Shop.Domain/Products/ValuesObjects/CategoryImage.cs new file mode 100644 index 0000000..648307c --- /dev/null +++ b/Vichvich.Shop.Domain/Products/ValuesObjects/CategoryImage.cs @@ -0,0 +1,20 @@ + +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shared.Domain.Exceptions; + +namespace Vizhvizh.Shop.Domain.Products.ValuesObjects; +public class CategoryImage : ValueObject +{ + public const short Limit = 150; + private CategoryImage(string value) + { + if (value.Length > Limit) + throw new CharacterLimitException(nameof(CategoryImage), Limit); + + Value = value; + } + public static CategoryImage CreateNew(string value) + => new CategoryImage(value); + + public string Value { get; init; } +} diff --git a/Vichvich.Shop.Domain/Products/ValuesObjects/CategoryPath.cs b/Vichvich.Shop.Domain/Products/ValuesObjects/CategoryPath.cs new file mode 100644 index 0000000..8b73253 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/ValuesObjects/CategoryPath.cs @@ -0,0 +1,16 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Products.ValuesObjects; + +public class CategoryPath : ValueObject +{ + private CategoryPath(string value) + { + + Value = value; + } + public string Value { get; private set; } + public static CategoryPath CreateNew(string value) + => new CategoryPath(value); + +} diff --git a/Vichvich.Shop.Domain/Products/ValuesObjects/MoneyValue.cs b/Vichvich.Shop.Domain/Products/ValuesObjects/MoneyValue.cs new file mode 100644 index 0000000..5ad179e --- /dev/null +++ b/Vichvich.Shop.Domain/Products/ValuesObjects/MoneyValue.cs @@ -0,0 +1,34 @@ +using Vizhvizh.Shared.Domain.Exceptions; + +namespace Vizhvizh.Shop.Domain.Products.ValuesObjects; + +/// +/// پول +/// +public class MoneyValue +{ + public const short CurrencyLimit = 150; + + public decimal Value { get; } + + public string Currency { get; } + + public static MoneyValue CreateNew(decimal value, string currency) + { + return new MoneyValue(value, currency); + } + + private MoneyValue(decimal value, string currency) + { + if(currency.Length > CurrencyLimit) + throw new CharacterLimitException(nameof(Currency), CurrencyLimit); + + this.Value = value; + this.Currency = currency; + } + + public static MoneyValue operator *(int left, MoneyValue right) + { + return new MoneyValue(right.Value * left, right.Currency); + } +} diff --git a/Vichvich.Shop.Domain/Products/ValuesObjects/ProductCondition.cs b/Vichvich.Shop.Domain/Products/ValuesObjects/ProductCondition.cs new file mode 100644 index 0000000..6726b86 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/ValuesObjects/ProductCondition.cs @@ -0,0 +1,29 @@ +using System.ComponentModel.DataAnnotations; +using Vizhvizh.Shop.Domain.Resource.Products; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Products.ValuesObjects; + +/// +/// وضعیت محصول نو، کارکرده +/// +public class ProductCondition : ValueObject +{ + private ProductCondition(ProductConditionEnum value) + { + Value = value; + } + public static ProductCondition CreateNew(ProductConditionEnum value) + => new ProductCondition(value); + + public ProductConditionEnum Value { get; init; } +} +public enum ProductConditionEnum +{ + [Display(Name = nameof(ValueObjectResources.ProductConditionEnum_BrandNew), ResourceType = typeof(ValueObjectResources))] + BrandNew = 0, + [Display(Name = nameof(ValueObjectResources.ProductConditionEnum_LikeNew), ResourceType = typeof(ValueObjectResources))] + LikeNew = 1, + [Display(Name = nameof(ValueObjectResources.ProductConditionEnum_Used), ResourceType = typeof(ValueObjectResources))] + Used = 2, +} diff --git a/Vichvich.Shop.Domain/Products/ValuesObjects/ProductImage.cs b/Vichvich.Shop.Domain/Products/ValuesObjects/ProductImage.cs new file mode 100644 index 0000000..f0382de --- /dev/null +++ b/Vichvich.Shop.Domain/Products/ValuesObjects/ProductImage.cs @@ -0,0 +1,23 @@ +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shared.Domain.Exceptions; + +namespace Vizhvizh.Shop.Domain.Products.ValuesObjects; + +/// +/// عکس محصولات +/// +public class ProductImage : ValueObject +{ + public const short Limit = 150; + private ProductImage(string value) + { + if (value.Length > Limit) + throw new CharacterLimitException(nameof(ProductImage), Limit); + + Value = value; + } + public static ProductImage CreateNew(string value) + => new ProductImage(value); + + public string Value { get; init; } +} diff --git a/Vichvich.Shop.Domain/Products/ValuesObjects/ProductQuantity.cs b/Vichvich.Shop.Domain/Products/ValuesObjects/ProductQuantity.cs new file mode 100644 index 0000000..de8309f --- /dev/null +++ b/Vichvich.Shop.Domain/Products/ValuesObjects/ProductQuantity.cs @@ -0,0 +1,18 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Products.ValuesObjects; +/// +/// تعداد +/// +public class ProductQuantity : ValueObject +{ + private ProductQuantity(double value) + { + Value = value; + } + + public static ProductQuantity CreateNew(double value) + => new ProductQuantity(value); + + public double Value { get; init; } +} diff --git a/Vichvich.Shop.Domain/Products/ValuesObjects/ProductScore.cs b/Vichvich.Shop.Domain/Products/ValuesObjects/ProductScore.cs new file mode 100644 index 0000000..1313ea3 --- /dev/null +++ b/Vichvich.Shop.Domain/Products/ValuesObjects/ProductScore.cs @@ -0,0 +1,20 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Products.ValuesObjects; + +/// +/// امتیاز +/// +public class ProductScore : ValueObject +{ + private ProductScore(byte score, int totalVoters) + { + Score = score; + TotalVoters = totalVoters; + } + public static ProductScore CreateNew(byte score, int totalVoters) + => new ProductScore(score, totalVoters); + + public byte Score { get; private set; } + public int TotalVoters { get; private set; } +} diff --git a/Vichvich.Shop.Domain/Products/ValuesObjects/ProductVariantValue.cs b/Vichvich.Shop.Domain/Products/ValuesObjects/ProductVariantValue.cs new file mode 100644 index 0000000..27b016a --- /dev/null +++ b/Vichvich.Shop.Domain/Products/ValuesObjects/ProductVariantValue.cs @@ -0,0 +1,56 @@ +using System.ComponentModel.DataAnnotations; +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.BuildingBlocks.Domain.Extensions; +using Vizhvizh.Shared.Domain.Exceptions; +using Vizhvizh.Shop.Domain.Products.Entities; +using Vizhvizh.Shop.Domain.Products.Exceptions; + +namespace Vizhvizh.Shop.Domain.Products.ValuesObjects; + +public class ProductVariantValue : ValueObject +{ + public const short Limit = 120; + private ProductVariantValue() + { + + } + private ProductVariantValue(string value, VariantUnitType type) + { + CheckValidation(value, type); + + Value = value; + } + public string Value { get; private set; } + + public static ProductVariantValue CreateNew(string value, VariantUnitType type) + => new(value, type); + + + public static void CheckValidation(string value, VariantUnitType type) + { + if (string.IsNullOrWhiteSpace(value)) + throw new InvalidProductVariantValueException(value, type.GetDisplayName()); + if (value.Length > Limit) + throw new CharacterLimitException(type.GetDisplayName(), Limit); + + switch (type) + { + case VariantUnitType.Color: + if (!value.StartsWith('#')) + throw new InvalidProductVariantValueException(value, type.GetDisplayName()); + break; + case VariantUnitType.Number: + if (!long.TryParse(value, out var _)) + throw new InvalidProductVariantValueException(value, type.GetDisplayName()); + break; + case VariantUnitType.Currency: + if (!long.TryParse(value, out var _)) + throw new InvalidProductVariantValueException(value, type.GetDisplayName()); + break; + case VariantUnitType.Decimal: + if (!decimal.TryParse(value, out var _)) + throw new InvalidProductVariantValueException(value, type.GetDisplayName()); + break; + } + } +} diff --git a/Vichvich.Shop.Domain/Shops/Entities/Management.cs b/Vichvich.Shop.Domain/Shops/Entities/Management.cs new file mode 100644 index 0000000..c645939 --- /dev/null +++ b/Vichvich.Shop.Domain/Shops/Entities/Management.cs @@ -0,0 +1,19 @@ +using Vizhvizh.Shop.Domain.Products.TypeIds; +using Vizhvizh.Shop.Domain.Shops.TypeIds; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Shops.Entities; +/// +/// مدیریت فروشگاه +/// +public class Management : Entity +{ + private Shop _shop; + + private Management() + { + } + internal static Management CreateNew() + => new Management(); + public Shop Shop => _shop; +} diff --git a/Vichvich.Shop.Domain/Shops/Entities/ShippingMethod.cs b/Vichvich.Shop.Domain/Shops/Entities/ShippingMethod.cs new file mode 100644 index 0000000..05711d6 --- /dev/null +++ b/Vichvich.Shop.Domain/Shops/Entities/ShippingMethod.cs @@ -0,0 +1,33 @@ +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.Shop.Domain.Shops.TypeIds; +using Vizhvizh.Shop.Domain.Shops.ValuesObjects; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Shops.Entities; + +/// +/// (نوع ارسال (پست و تیپاکس +/// +public class ShippingMethod : Entity +{ + private TitleVO _title; + private DescriptionVO _description; + private ShippingMethodImage _image; + private Shop _shop; + + private ShippingMethod() + { + + } + public ShippingMethod(TitleVO title, DescriptionVO description, ShippingMethodImage image) + { + _title = title; + _description = description; + _image = image; + } + public TitleVO Title => _title; + public DescriptionVO Description => _description; + public ShippingMethodImage Image => _image; + + public Shop Shop => _shop; +} diff --git a/Vichvich.Shop.Domain/Shops/Entities/Shop.cs b/Vichvich.Shop.Domain/Shops/Entities/Shop.cs new file mode 100644 index 0000000..967673c --- /dev/null +++ b/Vichvich.Shop.Domain/Shops/Entities/Shop.cs @@ -0,0 +1,70 @@ +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.Shop.Domain.Members.Entities; +using Vizhvizh.Shop.Domain.Members.TypeIds; +using Vizhvizh.Shop.Domain.Products.Entities; +using Vizhvizh.Shop.Domain.Shops.TypeIds; +using Vizhvizh.Shop.Domain.Shops.ValuesObjects; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Shops.Entities; + +public class Shop : Entity, IAggregateRoot +{ + private Management _management; + private List _products; + private List _shippingMethods; + private List _members; + + private ShopLocation _location; + private TitleVO _title; + private DescriptionVO? _description; + private EmailVO? _email; + private TelephoneVO _telephoneVO; + private ShopLogo _logo; + private MemberId _ownerId; + + private Shop() + { + + } + private Shop( + MemberId ownerId, + TitleVO title, + ShopLocation location, + TelephoneVO telephone, + DescriptionVO? description = null, + EmailVO? email = null + ) + { + _ownerId = ownerId; + _title = title; + _location = location; + _description = description; + _email = email; + _telephoneVO = telephone; + } + + public static Shop CreateNew(MemberId ownerId, + TitleVO title, + ShopLocation location, + TelephoneVO telephone, + DescriptionVO? description = null, + EmailVO? email = null) + { + return new Shop(ownerId, title, location, telephone, description, email); + } + public MemberId OwnerId => _ownerId; + public Management Management => _management; + public ShopLocation Location => _location; + public TitleVO Title => _title; + public DescriptionVO? Description => _description; + public EmailVO? Email => _email; + public TelephoneVO Telephone => _telephoneVO; + public ShopLogo Logo => _logo; + public IReadOnlyList Products => _products; + public IReadOnlyList ShippingMethods => _shippingMethods; + public IReadOnlyList Members => _members; + + public void SetTitle(TitleVO title) + => _title = title; +} diff --git a/Vichvich.Shop.Domain/Shops/Repositories/IShopRepository.cs b/Vichvich.Shop.Domain/Shops/Repositories/IShopRepository.cs new file mode 100644 index 0000000..4ccdaf6 --- /dev/null +++ b/Vichvich.Shop.Domain/Shops/Repositories/IShopRepository.cs @@ -0,0 +1,9 @@ +using Vizhvizh.Shop.Domain.Shops.TypeIds; + +namespace Vizhvizh.Shop.Domain.Shops.Repositories; + +public interface IShopRepository +{ + Task AddAsync(Entities.Shop shop, CancellationToken cancellationToken); + Task FindByIdAsync(ShopId id, CancellationToken cancellationToken); +} diff --git a/Vichvich.Shop.Domain/Shops/TypeIds/ShippingMethodId.cs b/Vichvich.Shop.Domain/Shops/TypeIds/ShippingMethodId.cs new file mode 100644 index 0000000..de08747 --- /dev/null +++ b/Vichvich.Shop.Domain/Shops/TypeIds/ShippingMethodId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Shops.TypeIds; + +public class ShippingMethodId : TypedIdValueBase +{ + public ShippingMethodId(byte value) : base(value) + { + } +} diff --git a/Vichvich.Shop.Domain/Shops/TypeIds/ShopId.cs b/Vichvich.Shop.Domain/Shops/TypeIds/ShopId.cs new file mode 100644 index 0000000..a9dab84 --- /dev/null +++ b/Vichvich.Shop.Domain/Shops/TypeIds/ShopId.cs @@ -0,0 +1,15 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Shops.TypeIds; + +public class ShopId : TypedIdValueBase +{ + public ShopId(long value) : base(value) + { + } + public static implicit operator ShopId(long value) + => new ShopId(value); + + public static implicit operator long(ShopId value) + => value.Value; +} diff --git a/Vichvich.Shop.Domain/Shops/ValuesObjects/ShippingMethodImage.cs b/Vichvich.Shop.Domain/Shops/ValuesObjects/ShippingMethodImage.cs new file mode 100644 index 0000000..1ae0b67 --- /dev/null +++ b/Vichvich.Shop.Domain/Shops/ValuesObjects/ShippingMethodImage.cs @@ -0,0 +1,19 @@ +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shared.Domain.Exceptions; + +namespace Vizhvizh.Shop.Domain.Shops.ValuesObjects; + +public class ShippingMethodImage : ValueObject +{ + public const short Limit = 150; + private ShippingMethodImage(string value) + { + if (value.Length > Limit) + throw new CharacterLimitException(nameof(ShippingMethodImage), Limit); + Value = value; + } + public static ShippingMethodImage CreateNew(string value) + => new ShippingMethodImage(value); + + public string Value { get; init; } +} diff --git a/Vichvich.Shop.Domain/Shops/ValuesObjects/ShopLocation.cs b/Vichvich.Shop.Domain/Shops/ValuesObjects/ShopLocation.cs new file mode 100644 index 0000000..de193a2 --- /dev/null +++ b/Vichvich.Shop.Domain/Shops/ValuesObjects/ShopLocation.cs @@ -0,0 +1,26 @@ +using Vizhvizh.BuildingBlocks.Domain; + + +namespace Vizhvizh.Shop.Domain.Shops.ValuesObjects; + +public class ShopLocation : ValueObject +{ + public ShopLocation(double latitude, double longitude, int provinceId, int cityId, string address, string postalCode) + { + Latitude = latitude; + Longitude = longitude; + ProvinceId = provinceId; + CityId = cityId; + Address = address; + PostalCode = postalCode; + } + public static ShopLocation CreateNew(double latitude, double longitude, int provinceId, int cityId, string address, string postalCode) + => new ShopLocation(latitude, longitude, provinceId, cityId, address, postalCode); + + public double Latitude { get; private set; } + public double Longitude { get; private set; } + public int ProvinceId { get; private set; } + public int CityId { get; private set; } + public string Address { get; private set; } + public string PostalCode { get; private set; } +} diff --git a/Vichvich.Shop.Domain/Shops/ValuesObjects/ShopLogo.cs b/Vichvich.Shop.Domain/Shops/ValuesObjects/ShopLogo.cs new file mode 100644 index 0000000..c57535a --- /dev/null +++ b/Vichvich.Shop.Domain/Shops/ValuesObjects/ShopLogo.cs @@ -0,0 +1,19 @@ +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shared.Domain.Exceptions; + +namespace Vizhvizh.Shop.Domain.Shops.ValuesObjects; + +public class ShopLogo : ValueObject +{ + public const short Limit = 150; + private ShopLogo(string value) + { + if (string.IsNullOrWhiteSpace(value) || value.Length > Limit) + throw new CharacterLimitException(nameof(ShopLogo), Limit); + + Value = value; + } + public static ShopLogo CreateNew(string value) + => new ShopLogo(value); + public string? Value { get; init; } +} diff --git a/Vichvich.Shop.Domain/Sliders/Entities/Slider.cs b/Vichvich.Shop.Domain/Sliders/Entities/Slider.cs new file mode 100644 index 0000000..46ad94b --- /dev/null +++ b/Vichvich.Shop.Domain/Sliders/Entities/Slider.cs @@ -0,0 +1,35 @@ +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.Shop.Domain.Shops.ValuesObjects; +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shop.Domain.Sliders.TypeIds; +using Vizhvizh.Shop.Domain.Sliders.ValuesObjects; + +namespace Vizhvizh.Shop.Domain.Sliders.Entities; + +public class Slider : Entity +{ + private TitleVO _title; + private SliderImage _image; + private SliderUrl _url; + private SliderKey _key; + private Slider() + { + + } + private Slider(TitleVO title, SliderImage image, SliderUrl url, SliderKey key) + { + _title = title; + _image = image; + _url = url; + _key = key; + } + public static Slider CreateNew(TitleVO title, SliderImage image, SliderUrl url, SliderKey key) + { + return new Slider(title, image, url, key); + } + + public TitleVO Title => _title; + public SliderImage Image => _image; + public SliderUrl Url => _url; + public SliderKey Key => _key; +} diff --git a/Vichvich.Shop.Domain/Sliders/Exceptions/IsNullOrEmptySliderUrlException.cs b/Vichvich.Shop.Domain/Sliders/Exceptions/IsNullOrEmptySliderUrlException.cs new file mode 100644 index 0000000..a00e2b6 --- /dev/null +++ b/Vichvich.Shop.Domain/Sliders/Exceptions/IsNullOrEmptySliderUrlException.cs @@ -0,0 +1,11 @@ +using Vizhvizh.Shop.Domain.Resource.Shops; +using Vizhvizh.BuildingBlocks.Domain.Exceptions; + +namespace Vizhvizh.Shop.Domain.Sliders.Exceptions; + +public class IsNullOrEmptySliderUrlException : ValueObjectValidationException +{ + public IsNullOrEmptySliderUrlException() : base(ExceptionResources.IsNullOrEmptySliderUrlException) + { + } +} diff --git a/Vichvich.Shop.Domain/Sliders/Repositories/ISliderRepository.cs b/Vichvich.Shop.Domain/Sliders/Repositories/ISliderRepository.cs new file mode 100644 index 0000000..00408df --- /dev/null +++ b/Vichvich.Shop.Domain/Sliders/Repositories/ISliderRepository.cs @@ -0,0 +1,10 @@ +using Vizhvizh.Shop.Domain.Sliders.Entities; +using Vizhvizh.Shop.Domain.Sliders.TypeIds; + +namespace Vizhvizh.Shop.Domain.Sliders.Repositories; + +public interface ISliderRepository +{ + Task AddAsync(Slider slider, CancellationToken cancellationToken); + Task GetByIdAsync(SliderId id,CancellationToken cancellationToken); +} diff --git a/Vichvich.Shop.Domain/Sliders/TypeIds/SliderId.cs b/Vichvich.Shop.Domain/Sliders/TypeIds/SliderId.cs new file mode 100644 index 0000000..ae5abeb --- /dev/null +++ b/Vichvich.Shop.Domain/Sliders/TypeIds/SliderId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Sliders.TypeIds; + +public class SliderId : TypedIdValueBase +{ + public SliderId(long value) : base(value) + { + } +} diff --git a/Vichvich.Shop.Domain/Sliders/ValuesObjects/SliderImage.cs b/Vichvich.Shop.Domain/Sliders/ValuesObjects/SliderImage.cs new file mode 100644 index 0000000..d29894c --- /dev/null +++ b/Vichvich.Shop.Domain/Sliders/ValuesObjects/SliderImage.cs @@ -0,0 +1,20 @@ +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shared.Domain.Exceptions; + +namespace Vizhvizh.Shop.Domain.Sliders.ValuesObjects; + +public class SliderImage : ValueObject +{ + public const short Limit = 150; + private SliderImage(string value) + { + if (value.Length > Limit) + throw new CharacterLimitException(nameof(SliderImage), Limit); + + Value = value; + } + public static SliderImage CreateNew(string value) + => new SliderImage(value); + + public string Value { get; init; } +} diff --git a/Vichvich.Shop.Domain/Sliders/ValuesObjects/SliderKey.cs b/Vichvich.Shop.Domain/Sliders/ValuesObjects/SliderKey.cs new file mode 100644 index 0000000..e7155ec --- /dev/null +++ b/Vichvich.Shop.Domain/Sliders/ValuesObjects/SliderKey.cs @@ -0,0 +1,30 @@ +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shared.Domain.Exceptions; + +namespace Vizhvizh.Shop.Domain.Sliders.ValuesObjects; + +public class SliderKey : ValueObject +{ + public const short Limit = 150; + private SliderKey() + { + + } + public SliderKey(SliderKeyType type, string? key) + { + Type = type; + Value = $"{type}/{key}"; + + if (Value.Length > Limit) + throw new CharacterLimitException(nameof(SliderKey), Limit); + } + public SliderKeyType Type { get; private set; } + public string Value { get; private set; } +} + +public enum SliderKeyType +{ + Main = 1, + Shop, + Category +} \ No newline at end of file diff --git a/Vichvich.Shop.Domain/Sliders/ValuesObjects/SliderUrl.cs b/Vichvich.Shop.Domain/Sliders/ValuesObjects/SliderUrl.cs new file mode 100644 index 0000000..7864286 --- /dev/null +++ b/Vichvich.Shop.Domain/Sliders/ValuesObjects/SliderUrl.cs @@ -0,0 +1,23 @@ +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.Shared.Domain.Exceptions; +using Vizhvizh.Shop.Domain.Sliders.Exceptions; + +namespace Vizhvizh.Shop.Domain.Sliders.ValuesObjects; + +public class SliderUrl : ValueObject +{ + public const short Limit = 150; + private SliderUrl(string value) + { + if (string.IsNullOrWhiteSpace(value)) + throw new IsNullOrEmptySliderUrlException(); + if(value.Length > Limit) + throw new CharacterLimitException(nameof(SliderUrl), Limit); + + Value = value.Trim(); + } + public static SliderUrl CreateNew(string value) + => new SliderUrl(value); + + public string Value { get; init; } +} diff --git a/Vichvich.Shop.Domain/Users/Entities/Resource.cs b/Vichvich.Shop.Domain/Users/Entities/Resource.cs new file mode 100644 index 0000000..bb9c255 --- /dev/null +++ b/Vichvich.Shop.Domain/Users/Entities/Resource.cs @@ -0,0 +1,36 @@ +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.Shop.Domain.Users.TypeIds; +using Vizhvizh.Shop.Domain.Users.ValueObjects; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Users.Entities; + +public class Resource : Entity +{ + private List _roles; + private TitleVO _title; + private DescriptionVO _description; + private ModuleNameVO _moduleName; + private ResourceKey _resourceKey; + + private Resource() + { + + } + public Resource(TitleVO title, DescriptionVO description, ModuleNameVO moduleNames, ResourceKey resourceKey, List roles) + { + _description = description; + _title = title; + _moduleName = moduleNames; + _resourceKey = resourceKey; + _roles = roles; + } + public static Resource CreateNew(TitleVO title, DescriptionVO description, ModuleNameVO moduleNames, ResourceKey resourceKey, List roles) + => new Resource(title, description, moduleNames, resourceKey, roles); + + public TitleVO Title => _title; + public DescriptionVO Description => _description; + public ModuleNameVO ModuleName => _moduleName; + public ResourceKey ResourceKey => _resourceKey; + public IReadOnlyList Roles => _roles; +} diff --git a/Vichvich.Shop.Domain/Users/Entities/Role.cs b/Vichvich.Shop.Domain/Users/Entities/Role.cs new file mode 100644 index 0000000..67590a3 --- /dev/null +++ b/Vichvich.Shop.Domain/Users/Entities/Role.cs @@ -0,0 +1,26 @@ +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.Shop.Domain.Users.TypeIds; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Users.Entities; + +public class Role : Entity +{ + private TitleVO _title; + private List _roleResources; + private Role() + { + + } + private Role(TitleVO title, List roleResources) + { + _title = title; + _roleResources = roleResources; + } + public static Role CreateNew(TitleVO title, List roleResources) + => new Role(title, roleResources); + + public TitleVO Title => _title; + public IReadOnlyList RoleResources => _roleResources; + +} diff --git a/Vichvich.Shop.Domain/Users/Entities/RoleResource.cs b/Vichvich.Shop.Domain/Users/Entities/RoleResource.cs new file mode 100644 index 0000000..b4dd341 --- /dev/null +++ b/Vichvich.Shop.Domain/Users/Entities/RoleResource.cs @@ -0,0 +1,32 @@ +using Vizhvizh.Shop.Domain.Users.TypeIds; +using Vizhvizh.Shop.Domain.Users.ValueObjects; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Users.Entities; + +public class RoleResource : Entity +{ + private AccessLevel _accessLevel; + + private User _user; + private Role _role; + + private RoleResource() + { + + } + private RoleResource(AccessLevel accessLevel, User user, Role role) + { + _accessLevel = accessLevel; + _user = user; + _role = role; + } + + public static RoleResource CreateNew(AccessLevel accessLevel, User user, Role role) + => new RoleResource(accessLevel, user, role); + + public AccessLevel AccessLevel => _accessLevel; + public User User => _user; + public Role Role => _role; + +} diff --git a/Vichvich.Shop.Domain/Users/Entities/User.cs b/Vichvich.Shop.Domain/Users/Entities/User.cs new file mode 100644 index 0000000..e916b73 --- /dev/null +++ b/Vichvich.Shop.Domain/Users/Entities/User.cs @@ -0,0 +1,30 @@ +using Vizhvizh.Shop.Domain.Members.TypeIds; +using Vizhvizh.Shop.Domain.Users.TypeIds; +using Vizhvizh.Shop.Domain.Users.ValueObjects; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Users.Entities; + +public class User : Entity, IAggregateRoot +{ + //private UserNationalCode _nationalCode; + private MemberId _memberId; + private List _roles; + + private User() + { + + } + private User(MemberId memberId, List roles) + { + _memberId = memberId; + _roles = roles; + } + + public static User CreateNew(MemberId memberId, List roles) + => new User(memberId, roles); + + //public UserNationalCode NationalCode => _nationalCode; + public MemberId MemberId => _memberId; + public IReadOnlyList Roles => _roles; +} diff --git a/Vichvich.Shop.Domain/Users/Exceptions/InvalidNationalCodeException.cs b/Vichvich.Shop.Domain/Users/Exceptions/InvalidNationalCodeException.cs new file mode 100644 index 0000000..37f694d --- /dev/null +++ b/Vichvich.Shop.Domain/Users/Exceptions/InvalidNationalCodeException.cs @@ -0,0 +1,11 @@ +using Vizhvizh.Shop.Domain.Resource.Users; +using Vizhvizh.BuildingBlocks.Domain.Exceptions; + +namespace Vizhvizh.Shop.Domain.Users.Exceptions; + +public class InvalidNationalCodeException : ValueObjectValidationException +{ + public InvalidNationalCodeException() : base(ExceptionResources.InvalidNationalCodeException) + { + } +} diff --git a/Vichvich.Shop.Domain/Users/TypeIds/ResourceId.cs b/Vichvich.Shop.Domain/Users/TypeIds/ResourceId.cs new file mode 100644 index 0000000..592df99 --- /dev/null +++ b/Vichvich.Shop.Domain/Users/TypeIds/ResourceId.cs @@ -0,0 +1,11 @@ + +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Users.TypeIds; + +public class ResourceId : TypedIdValueBase +{ + public ResourceId(long value) : base(value) + { + } +} diff --git a/Vichvich.Shop.Domain/Users/TypeIds/RoleId.cs b/Vichvich.Shop.Domain/Users/TypeIds/RoleId.cs new file mode 100644 index 0000000..40695e2 --- /dev/null +++ b/Vichvich.Shop.Domain/Users/TypeIds/RoleId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Users.TypeIds; + +public class RoleId : TypedIdValueBase +{ + public RoleId(int value) : base(value) + { + } +} diff --git a/Vichvich.Shop.Domain/Users/TypeIds/RoleResourceId.cs b/Vichvich.Shop.Domain/Users/TypeIds/RoleResourceId.cs new file mode 100644 index 0000000..e9c5010 --- /dev/null +++ b/Vichvich.Shop.Domain/Users/TypeIds/RoleResourceId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Users.TypeIds; + +public class RoleResourceId : TypedIdValueBase +{ + public RoleResourceId(long value) : base(value) + { + } +} diff --git a/Vichvich.Shop.Domain/Users/TypeIds/UserId.cs b/Vichvich.Shop.Domain/Users/TypeIds/UserId.cs new file mode 100644 index 0000000..7813896 --- /dev/null +++ b/Vichvich.Shop.Domain/Users/TypeIds/UserId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Users.TypeIds; + +public class UserId : TypedIdValueBase +{ + public UserId(long value) : base(value) + { + } +} diff --git a/Vichvich.Shop.Domain/Users/ValuesObjects/AccessLevel.cs b/Vichvich.Shop.Domain/Users/ValuesObjects/AccessLevel.cs new file mode 100644 index 0000000..52f9c49 --- /dev/null +++ b/Vichvich.Shop.Domain/Users/ValuesObjects/AccessLevel.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations; +using Vizhvizh.Shop.Domain.Resource.Users; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Users.ValueObjects; + +public class AccessLevel : ValueObject +{ + private AccessLevel(AccessLevelEnum value) + { + Value = (int)value; + } + public static AccessLevel CreateNew(AccessLevelEnum value) + => new AccessLevel(value); + public int Value { get; init;} +} +public enum AccessLevelEnum +{ + [Display(Name = nameof(ValueObjectResources.AccessLevelEnum_Write), ResourceType = typeof(ValueObjectResources))] + Write = 0, + [Display(Name = nameof(ValueObjectResources.AccessLevelEnum_Read), ResourceType = typeof(ValueObjectResources))] + Read = 1, + [Display(Name = nameof(ValueObjectResources.AccessLevelEnum_ReadWrite), ResourceType = typeof(ValueObjectResources))] + ReadWrite = 2 +} diff --git a/Vichvich.Shop.Domain/Users/ValuesObjects/ResourceKey.cs b/Vichvich.Shop.Domain/Users/ValuesObjects/ResourceKey.cs new file mode 100644 index 0000000..097aafa --- /dev/null +++ b/Vichvich.Shop.Domain/Users/ValuesObjects/ResourceKey.cs @@ -0,0 +1,20 @@ +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Users.ValueObjects; + +public class ResourceKey : ValueObject +{ + private ResourceKey(ModuleNameVO module, TitleVO resourceTitle, params string[] parts) + { + Value = $"{module.Value}_{string.Join('.', parts)}_{resourceTitle.Value}"; + } + public static ResourceKey CreateNew(string value) + { + string[] valueSplit = value.Split('_'); + ModuleNamesEnum module = Enum.Parse(valueSplit[0]); + string[] paths = valueSplit[1]?.Split('.') ?? []; + return new ResourceKey(ModuleNameVO.CreateNew(module), TitleVO.CreateNew(valueSplit[2]), paths); + } + public string Value { get; init; } +} diff --git a/Vichvich.Shop.Domain/Users/ValuesObjects/UserNationalCode.cs b/Vichvich.Shop.Domain/Users/ValuesObjects/UserNationalCode.cs new file mode 100644 index 0000000..9bfbcfd --- /dev/null +++ b/Vichvich.Shop.Domain/Users/ValuesObjects/UserNationalCode.cs @@ -0,0 +1,48 @@ +using Vizhvizh.Shop.Domain.Users.Exceptions; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.Shop.Domain.Users.ValueObjects; + +public class UserNationalCode : ValueObject +{ + public static bool IsValidNationalCode(string nationalCode) + { + if (nationalCode is null || nationalCode.Length > 10) + return false; + + // تبدیل به آرایه + var arr = nationalCode.ToArray().Select(n => int.Parse(n.ToString())); + + //بر عکس کردن اجزا + var arrReduce = arr.Reverse().ToList(); + + // بدست آوردن رقم کنترل اخر کد ملی + var numberControl = arrReduce.First(); + arrReduce.RemoveAt(0); + + // تمام 9 رقم سمت چپ کد ملی ضرب در موقعیت خودش میشه بعد همه جمع میشن بعدش تقسیم به یازده و باقی مانده رو میگیرم + //کد ملی 0700454713 + //موقیعت 07 به ترتیب 9و10 هست از اونجایی ک ما رقم کنترل رو برداشتیم پس باید ایندکس ب اضافه ی 2 شه + var remaining = decimal.Parse($"{arrReduce.Select((n, i) => n * (i + 2)).Sum() % 11}"); + + if (remaining <= 2.0m) + { + if (numberControl == remaining) + return true; + else + return false; + } + else if (11m - remaining == numberControl) + return true; + else + return false; + } + public UserNationalCode(string value) + { + if (!IsValidNationalCode(value)) + throw new InvalidNationalCodeException(); + + Value = value; + } + public string Value { get; init; } +} diff --git a/Vichvich.Shop.Domain/Vizhvizh.Shop.Domain.csproj b/Vichvich.Shop.Domain/Vizhvizh.Shop.Domain.csproj new file mode 100644 index 0000000..5106873 --- /dev/null +++ b/Vichvich.Shop.Domain/Vizhvizh.Shop.Domain.csproj @@ -0,0 +1,28 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + + + + + + + + diff --git a/Vichvich.Shop.Infrastructure/Configuration/Assemblies.cs b/Vichvich.Shop.Infrastructure/Configuration/Assemblies.cs new file mode 100644 index 0000000..584d333 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/Configuration/Assemblies.cs @@ -0,0 +1,10 @@ +using System.Reflection; +using Vizhvizh.Shop.Application; + +namespace Vizhvizh.Shop.Infrastructure.Configuration; + +internal static class Assemblies +{ + public static Assembly Application = typeof(IShopModule).Assembly; + public static Assembly Infrastructure = typeof(ShopStartup).Assembly; +} diff --git a/Vichvich.Shop.Infrastructure/Configuration/Executor.cs b/Vichvich.Shop.Infrastructure/Configuration/Executor.cs new file mode 100644 index 0000000..4990f6d --- /dev/null +++ b/Vichvich.Shop.Infrastructure/Configuration/Executor.cs @@ -0,0 +1,52 @@ +using Microsoft.Extensions.DependencyInjection; +using Vizhvizh.BuildingBlocks.Application.Configuration.Commnad; +using Vizhvizh.BuildingBlocks.Application.Configuration.Query; +using Vizhvizh.BuildingBlocks.Application.Contract; +using Vizhvizh.BuildingBlocks.Domain; +using Vizhvizh.BuildingBlocks.Domain.Contract; +using Vizhvizh.BuildingBlocks.Infrastructure; + +namespace Vizhvizh.Shop.Infrastructure.Configuration; + +public class Executor : IExecutor +{ + private readonly IServiceProvider _serviceProvider; + public Executor(IServiceProvider serviceProvider) + { + _serviceProvider = serviceProvider; + } + public async Task Execute(ICommand command, CancellationToken cancellationToken) + { + var handlerType = typeof(ICommandHandler<>).MakeGenericType(command.GetType()); + var handler = _serviceProvider.GetRequiredService(handlerType); + dynamic dynamicHandler = handler; + dynamic dynamicCommand = command; + await dynamicHandler.Handle(dynamicCommand, cancellationToken); + } + + public async Task Execute(ICommand command, CancellationToken cancellationToken) + { + var handlerType = typeof(ICommandHandler<,>).MakeGenericType(command.GetType(),typeof(TResult)); + var handler = _serviceProvider.GetRequiredService(handlerType); + dynamic dynamicHandler = handler; + dynamic dynamicCommand = command; + return await dynamicHandler.Handle(dynamicCommand, cancellationToken); + } + public async Task Execute(IQuery query, CancellationToken cancellationToken) + { + var handlerType = typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TResult)); + var handler = _serviceProvider.GetRequiredService(handlerType); + dynamic dynamicHandler = handler; + dynamic dynamicQuery = query; + return await dynamicHandler.Handle(dynamicQuery, cancellationToken); + } + + public async Task Execute(IDomainEvent notification, CancellationToken cancellationToken = default) + { + var handlerType = typeof(INotificationHandler<>).MakeGenericType(notification.GetType()); + var handler = _serviceProvider.GetRequiredService(handlerType); + dynamic dynamicHandler = handler; + dynamic dynamicNotification = notification; + await dynamicHandler.Handle(dynamicNotification, cancellationToken); + } +} diff --git a/Vichvich.Shop.Infrastructure/Configuration/ShopModule.cs b/Vichvich.Shop.Infrastructure/Configuration/ShopModule.cs new file mode 100644 index 0000000..c76a14a --- /dev/null +++ b/Vichvich.Shop.Infrastructure/Configuration/ShopModule.cs @@ -0,0 +1,29 @@ +using Vizhvizh.Shop.Application; +using Vizhvizh.BuildingBlocks.Application.Contract; +using Vizhvizh.BuildingBlocks.Domain.Contract; +using Vizhvizh.BuildingBlocks.Infrastructure; + +namespace Vizhvizh.Shop.Infrastructure.Configuration; + +internal class ShopModule : IShopModule +{ + private readonly IExecutor _executor; + public ShopModule(IExecutor executor) + { + _executor = executor; + } + public async Task ExecuteCommandAsync(ICommand command, CancellationToken cancellationToken) + { + return await _executor.Execute(command, cancellationToken); + } + + public async Task ExecuteCommandAsync(ICommand command, CancellationToken cancellationToken) + { + await _executor.Execute(command, cancellationToken); + } + + public async Task ExecuteQueryAsync(IQuery query, CancellationToken cancellationToken) + { + return await _executor.Execute(query, cancellationToken); + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/CategoryConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/CategoryConfiguration.cs new file mode 100644 index 0000000..ce00f22 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/CategoryConfiguration.cs @@ -0,0 +1,47 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Vizhvizh.Shop.Domain.Products.Entities; +using Vizhvizh.Shop.Domain.Products.ValuesObjects; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +internal class CategoryConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Categories", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .HasConversion(x => x.Value, x => new Domain.Products.TypeIds.CategoryId(x)) + .ValueGeneratedOnAdd(); + + builder.Property(x => x.Title) + .HasField("_title") + .IsRequired(); + + builder.Property(x => x.Description) + .IsRequired(false) + .HasField("_description"); + builder.Property(x => x.ParentId) + .HasConversion(x => x.Value, x => new Domain.Products.TypeIds.CategoryId(x)) + .IsRequired(false) + .HasField("_parentId"); + builder.OwnsOne(x => x.Image, sa => + { + sa.Property(x => x.Value) + .HasMaxLength(CategoryImage.Limit) + .HasColumnName("Image"); + }); + + builder.Property(x => x.Path) + .HasField("_path") + .IsRequired() + .HasConversion(x => x.Value, x => Domain.Products.ValuesObjects.CategoryPath.CreateNew(x)) + .HasColumnType("HIERARCHYID"); + + builder.Metadata.FindNavigation(nameof(Category.Products))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + builder.Metadata.FindNavigation(nameof(Category.CategoryVariantUnits))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/CategoryVariantUnitConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/CategoryVariantUnitConfiguration.cs new file mode 100644 index 0000000..efe2ae8 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/CategoryVariantUnitConfiguration.cs @@ -0,0 +1,33 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Vizhvizh.Shop.Domain.Products.Entities; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +internal class CategoryVariantUnitConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("CategoryVariantUnit", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .HasConversion(x => x.Value, x => new Domain.Products.TypeIds.CategoryVariantUnitId(x)) + .ValueGeneratedOnAdd(); + + builder.Property(x => x.VariantUnitId) + .HasField("_variantUnitId") + .HasConversion(x => x.Value, x => new Domain.Products.TypeIds.VariantUnitId(x)); + + builder.Property(x => x.CategoryId) + .HasField("_categoryId") + .HasConversion(x => x.Value, x => new Domain.Products.TypeIds.CategoryId(x)); + + builder.HasIndex(x=> new {x.VariantUnitId, x.CategoryId}) + .IsUnique(); + + builder.Metadata.FindNavigation(nameof(CategoryVariantUnit.VariantUnit))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + builder.Metadata.FindNavigation(nameof(CategoryVariantUnit.Category))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/Converter/MemberIdConverter.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/Converter/MemberIdConverter.cs new file mode 100644 index 0000000..7e7a8f5 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/Converter/MemberIdConverter.cs @@ -0,0 +1,13 @@ +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using System.Linq.Expressions; +using Vizhvizh.Shop.Domain.Members.TypeIds; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations.Converter; + +internal class MemberIdConverter : ValueConverter +{ + public MemberIdConverter() + : base(x=>x.Value, x=> new MemberId(x)) + { + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/Converter/ProductImageConverter.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/Converter/ProductImageConverter.cs new file mode 100644 index 0000000..f3748e9 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/Converter/ProductImageConverter.cs @@ -0,0 +1,14 @@ + +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using System.Linq.Expressions; +using Vizhvizh.Shop.Domain.Products.ValuesObjects; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations.Converter; + +internal class ProductImageConverter : ValueConverter +{ + public ProductImageConverter() + : base(x=>x.Value, x=> ProductImage.CreateNew(x)) + { + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/ManagementConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/ManagementConfiguration.cs new file mode 100644 index 0000000..63e2420 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/ManagementConfiguration.cs @@ -0,0 +1,20 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Vizhvizh.Shop.Domain.Shops.Entities; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +internal class ManagementConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Managements", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .HasConversion(x => x.Value, x => new Domain.Shops.TypeIds.ShopId(x)); + + builder.Metadata.FindNavigation(nameof(Management.Shop))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/MemberConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/MemberConfiguration.cs new file mode 100644 index 0000000..56bc795 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/MemberConfiguration.cs @@ -0,0 +1,36 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Vizhvizh.Shop.Domain.Members.Entities; +using Vizhvizh.Shop.Domain.Members.ValuesObjects; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +internal class MemberConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Members", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .ValueGeneratedOnAdd(); + + builder.Property(x => x.PhoneNumber) + .HasField("_phoneNumber"); + builder.OwnsOne(x => x.FullName, sa => + { + sa.Property(x => x.FirstName) + .HasMaxLength(MemberFullName.FirstNameLimit) + .HasColumnName("FirstName"); + + sa.Property(x => x.LastName) + .HasMaxLength(MemberFullName.LastNameLimit) + .HasColumnName("LastName"); + }); + builder.OwnsOne(x => x.Avatar, sa => + { + sa.Property(x => x.Value) + .HasMaxLength(MemberAvatar.Limit) + .HasColumnName("Avatar"); + }); + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/ProductConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/ProductConfiguration.cs new file mode 100644 index 0000000..4446d99 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/ProductConfiguration.cs @@ -0,0 +1,54 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using System.Drawing; +using Vizhvizh.Shop.Domain.Products.Entities; +using Vizhvizh.Shop.Domain.Products.ValuesObjects; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +internal class ProductConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Products", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .HasConversion(x => x.Value, x => new Domain.Products.TypeIds.ProductId(x)) + .ValueGeneratedOnAdd(); + + builder.OwnsOne(x => x.ProductCondition, sa => + { + sa.Property(x => x.Value).HasColumnName("ProductCondition"); + }); + builder.Property(x => x.Title) + .HasField("_title"); + + builder.Property(x => x.Description) + .HasField("_description"); + builder.OwnsOne(x => x.Score, sa => + { + sa.Property(x => x.Score).HasColumnType("Score") + .HasColumnType("TINYINT") + .HasDefaultValue(0); + + sa.Property(x => x.TotalVoters).HasColumnName("TotalVoters") + .HasColumnType("INT") + .HasDefaultValue(0); ; + }); + + + builder.OwnsOne(x => x.Image, sa => + { + sa.Property(x => x.Value) + .HasMaxLength(ProductImage.Limit) + .HasColumnName("Image"); + }); + + builder.Metadata.FindNavigation(nameof(Product.Specifications))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + builder.Metadata.FindNavigation(nameof(Product.Category))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + builder.Metadata.FindNavigation(nameof(Product.Variants))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/ProductVariantConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/ProductVariantConfiguration.cs new file mode 100644 index 0000000..c28403d --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/ProductVariantConfiguration.cs @@ -0,0 +1,58 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Vizhvizh.Shop.Domain.Products.Entities; +using Vizhvizh.Shop.Domain.Products.ValuesObjects; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +internal class ProductVariantConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("ProductVariants", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .HasConversion(x => x.Value, x => new Domain.Products.TypeIds.ProductVariantId(x)) + .ValueGeneratedOnAdd(); + + builder.OwnsOne(x => x.Score, sa => + { + sa.Property(x => x.Score) + .HasColumnName("Score") + .HasColumnType("TINYINT") + .HasDefaultValue(0); + + sa.Property(x => x.TotalVoters) + .HasColumnName("TotalVoters") + .HasColumnType("INT") + .HasDefaultValue(0); + }); + + builder.OwnsOne(x => x.Value, sa => + { + sa.Property(x => x.Value) + .HasMaxLength(ProductVariantValue.Limit) + .HasColumnName("Value") + .IsRequired(); + }); + builder.OwnsOne(x => x.Price, x => + { + x.Property(x => x.Value).HasColumnName("Price").IsRequired(); + x.Property(x => x.Currency) + .HasMaxLength(MoneyValue.CurrencyLimit) + .HasColumnName("Currency").IsRequired(); + }); + builder.OwnsOne(x => x.Quantity, sa => + { + sa.Property(x => x.Value).HasColumnName("Quantity"); + }); + builder.OwnsMany(x => x.Gallery, sa => + { + sa.Property(x => x.Value).HasColumnName("Gallery"); + sa.ToJson(); + }); + + builder.Metadata.FindNavigation(nameof(ProductVariant.Product))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/ResourceConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/ResourceConfiguration.cs new file mode 100644 index 0000000..41b9686 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/ResourceConfiguration.cs @@ -0,0 +1,36 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.Shop.Domain.Users.Entities; +using Vizhvizh.Shop.Domain.Users.ValueObjects; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +public class ResourceConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Resources", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .HasConversion(x => x.Value, x => new Domain.Users.TypeIds.ResourceId(x)) + .ValueGeneratedOnAdd(); + + builder.Property(x => x.Title) + .HasField("_title"); + builder.Property(x => x.Description) + .HasField("_description"); + builder.Property(x => x.ModuleName) + .HasField("_moduleName") + .HasColumnType("int") + .HasConversion(x=> (int)x.Value, x=> ModuleNameVO.CreateNew((ModuleNamesEnum)x)); + + builder.Property(x => x.ResourceKey) + .HasConversion(x=>x.Value, x=> ResourceKey.CreateNew(x)) + .HasField("_resourceKey"); + + + builder.Metadata.FindNavigation(nameof(Resource.Roles))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/RoleConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/RoleConfiguration.cs new file mode 100644 index 0000000..a1c3c73 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/RoleConfiguration.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Vizhvizh.Shop.Domain.Users.Entities; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +public class RoleConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Roles", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .HasConversion(x => x.Value, x => new Domain.Users.TypeIds.RoleId(x)) + .ValueGeneratedOnAdd(); + + builder.Property(x => x.Title) + .HasField("_title"); + + builder.Metadata.FindNavigation(nameof(Role.RoleResources))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/RoleResourceConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/RoleResourceConfiguration.cs new file mode 100644 index 0000000..0376986 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/RoleResourceConfiguration.cs @@ -0,0 +1,27 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Vizhvizh.Shop.Domain.Users.Entities; +using Vizhvizh.Shop.Domain.Users.ValueObjects; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +public class RoleResourceConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("RoleResources", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .HasConversion(x => x.Value, x => new Domain.Users.TypeIds.RoleResourceId(x)) + .ValueGeneratedOnAdd(); + + builder.Property(x=>x.AccessLevel) + .HasConversion(x=>x.Value, x=> AccessLevel.CreateNew((AccessLevelEnum)x)); + + + builder.Metadata.FindNavigation(nameof(RoleResource.User))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + builder.Metadata.FindNavigation(nameof(RoleResource.Role))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/ShippingMethodConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/ShippingMethodConfiguration.cs new file mode 100644 index 0000000..fffe466 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/ShippingMethodConfiguration.cs @@ -0,0 +1,31 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Vizhvizh.Shop.Domain.Shops.Entities; +using Vizhvizh.Shop.Domain.Shops.ValuesObjects; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +internal class ShippingMethodConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("ShippingMethods", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .HasConversion(x => x.Value, x => new Domain.Shops.TypeIds.ShippingMethodId(x)) + .ValueGeneratedOnAdd(); + + builder.Property(x => x.Title) + .HasField("_title"); + builder.Property(x => x.Description) + .HasField("_description"); + builder.OwnsOne(x => x.Image, sa => + { + sa.Property(x => x.Value) + .HasMaxLength(ShippingMethodImage.Limit) + .HasColumnName("Image"); + }); + builder.Metadata.FindNavigation(nameof(ShippingMethod.Shop))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/ShopConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/ShopConfiguration.cs new file mode 100644 index 0000000..132fa7a --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/ShopConfiguration.cs @@ -0,0 +1,59 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Vizhvizh.Shop.Domain.Shops.Entities; +using Vizhvizh.Shop.Domain.Shops.ValuesObjects; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +public class ShopConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Shops", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .HasConversion(x => x.Value, x => new Domain.Shops.TypeIds.ShopId(x)) + .ValueGeneratedOnAdd(); + + builder.Property(x => x.OwnerId) + .HasField("_ownerId"); + builder.Property(x => x.Title) + .HasField("_title"); + builder.Property(x => x.Description) + .HasField("_description"); + builder.Property(x => x.Email) + .HasField("_email"); + builder.Property(x => x.Telephone) + .HasField("_telephoneVO"); + builder.OwnsOne(x => x.Logo, sa => + { + sa.Property(x => x.Value) + .HasMaxLength(ShopLogo.Limit) + .HasColumnName("Logo"); + }); + builder.OwnsOne(x => x.Location, sa => + { + sa.Property(x => x.PostalCode).HasColumnName(nameof(ShopLocation.PostalCode)); + sa.Property(x => x.ProvinceId).HasColumnName(nameof(ShopLocation.ProvinceId)); + sa.Property(x => x.CityId).HasColumnName(nameof(ShopLocation.CityId)); + sa.Property(x => x.Address).HasColumnName(nameof(ShopLocation.Address)); + sa.Property(x => x.Latitude).HasColumnName(nameof(ShopLocation.Latitude)); + sa.Property(x => x.Longitude).HasColumnName(nameof(ShopLocation.Longitude)); + sa.ToJson(); + }); + + builder.HasOne(x => x.Management) + .WithOne(x => x.Shop) + .HasForeignKey(x => x.Id); + + builder.Metadata.FindNavigation(nameof(Domain.Shops.Entities.Shop.Management))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + builder.Metadata.FindNavigation(nameof(Domain.Shops.Entities.Shop.Products))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + builder.Metadata.FindNavigation(nameof(Domain.Shops.Entities.Shop.ShippingMethods))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + builder.Metadata.FindNavigation(nameof(Domain.Shops.Entities.Shop.Members))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/SliderConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/SliderConfiguration.cs new file mode 100644 index 0000000..78d12f5 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/SliderConfiguration.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Vizhvizh.Shop.Domain.Sliders.Entities; +using Vizhvizh.Shop.Domain.Sliders.ValuesObjects; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +internal class SliderConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Sliders", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .HasConversion(x => x.Value, x => new Domain.Sliders.TypeIds.SliderId(x)) + .ValueGeneratedOnAdd(); + + builder.Property(x => x.Title) + .HasField("_title"); + builder.OwnsOne(x => x.Image, sa => + { + sa.Property(x => x.Value) + .HasMaxLength(SliderImage.Limit) + .HasColumnName("Image"); + }); + builder.OwnsOne(x => x.Url, sa => + { + sa.Property(x => x.Value) + .HasMaxLength(SliderUrl.Limit) + .HasColumnName("Url"); + }); + builder.OwnsOne(x => x.Key, sa => + { + sa.Property(x => x.Value) + .HasColumnName("Key") + .HasMaxLength(SliderKey.Limit); + + sa.Property(x => x.Type) + .HasColumnName("Type") + .HasColumnType("INT"); + + }); + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/SpecificationsConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/SpecificationsConfiguration.cs new file mode 100644 index 0000000..a179b24 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/SpecificationsConfiguration.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Newtonsoft.Json; +using Vizhvizh.Shop.Domain.Products.Entities; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +internal class SpecificationsConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("ProductSpecifications", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .HasConversion(x=>x.Value, x=> new Domain.Products.TypeIds.SpecificationsId(x)) + .ValueGeneratedOnAdd(); + + builder.Property(x => x.Title) + .HasField("_title"); + builder.Property(x => x.ItemValues) + .HasConversion(x=> JsonConvert.SerializeObject(x), x=> JsonConvert.DeserializeObject>(x)!) + .HasField("_itemValues"); + + builder.Metadata.FindNavigation(nameof(Specifications.Product))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/UnitConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/UnitConfiguration.cs new file mode 100644 index 0000000..deb404f --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/UnitConfiguration.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Vizhvizh.Shop.Domain.Products.Entities; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +internal class UnitConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Units", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .HasConversion(x => x.Value, x => new Domain.Products.TypeIds.UnitId(x)); + + builder.Property(x => x.Title) + .HasField("_title"); + + builder.Metadata.FindNavigation(nameof(Unit.VariantUnits))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/UserConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/UserConfiguration.cs new file mode 100644 index 0000000..dd7e143 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/UserConfiguration.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Vizhvizh.Shop.Domain.Users.Entities; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +public class UserConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Users", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .HasConversion(x => x.Value, x => new Domain.Users.TypeIds.UserId(x)) + .ValueGeneratedOnAdd(); + + //builder.OwnsOne(x => x.NationalCode, sa => + //{ + // sa.Property(x => x.Value).HasColumnName("NationalCode"); + //}); + builder.Property(x => x.MemberId); + + builder.Metadata.FindNavigation(nameof(User.Roles))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/VariantConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/VariantConfiguration.cs new file mode 100644 index 0000000..c4376f3 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/VariantConfiguration.cs @@ -0,0 +1,23 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Vizhvizh.Shop.Domain.Products.Entities; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +internal class VariantConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("Variants", schema: "Shop"); + builder.HasKey(x => x.Id); + builder.Property(x => x.Id) + .HasConversion(x => x.Value, x => new Domain.Products.TypeIds.VariantId(x)); + + builder.Property(x => x.Title) + .HasField("_title"); + + builder.Metadata.FindNavigation(nameof(Variant.VariantUnits))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/Configurations/VariantUnitConfiguration.cs b/Vichvich.Shop.Infrastructure/EF/Configurations/VariantUnitConfiguration.cs new file mode 100644 index 0000000..cb0dedf --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/Configurations/VariantUnitConfiguration.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Vizhvizh.Shop.Domain.Products.Entities; + +namespace Vizhvizh.Shop.Infrastructure.EF.Configurations; + +internal class VariantUnitConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.ToTable("VariantUnits", schema: "Shop"); + builder.HasKey(x=>x.Id); + builder.Property(x => x.Id) + .HasConversion(x => x.Value, x => new Domain.Products.TypeIds.VariantUnitId(x)); + + builder.Property(x => x.VariantUnitType) + .HasColumnType("INT") + .HasField("_variantUnitType"); + + builder.Metadata.FindNavigation(nameof(VariantUnit.Variant))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + builder.Metadata.FindNavigation(nameof(VariantUnit.Unit))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + builder.Metadata.FindNavigation(nameof(VariantUnit.CategoryVariantUnits))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + builder.Metadata.FindNavigation(nameof(VariantUnit.ProductVariants))? + .SetPropertyAccessMode(PropertyAccessMode.Field); + } +} diff --git a/Vichvich.Shop.Infrastructure/EF/ShopDbContext.cs b/Vichvich.Shop.Infrastructure/EF/ShopDbContext.cs new file mode 100644 index 0000000..8a3a613 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/EF/ShopDbContext.cs @@ -0,0 +1,84 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Abstractions; +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.Shared.Infrastructure.EF.Configurations.Converters; +using Vizhvizh.Shop.Domain.Members.TypeIds; +using Vizhvizh.Shop.Domain.Sliders.Entities; +using Vizhvizh.Shop.Infrastructure.Configuration; +using Vizhvizh.Shop.Infrastructure.EF.Configurations.Converter; + +namespace Vizhvizh.Shop.Infrastructure.EF; + +internal class ShopDbContext : DbContext +{ + public ShopDbContext(DbContextOptions options) + : base(options) + { + + } + public virtual DbSet Members { get; set; } + + + public virtual DbSet Products { get; set; } + public virtual DbSet Categories { get; set; } + public virtual DbSet Specifications { get; set; } + + public virtual DbSet Shops { get; set; } + public virtual DbSet Sliders { get; set; } + public virtual DbSet ShippingMethods { get; set; } + public virtual DbSet Managements { get; set; } + + public virtual DbSet Users { get; set; } + public virtual DbSet RoleResources { get; set; } + public virtual DbSet Roles { get; set; } + public virtual DbSet Resources { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.ApplyConfigurationsFromAssembly(Assemblies.Infrastructure, FindConfigurations); + + foreach (var entityType in modelBuilder.Model.GetEntityTypes()) + { + var createOnProperty = entityType.FindProperty("CreateOn"); + if (createOnProperty != null && createOnProperty.ClrType == typeof(DateTime)) + { + createOnProperty.SetDefaultValueSql("GETDATE()"); + } + } + } + public bool FindConfigurations(Type type) + => type?.FullName?.Contains("Configurations") ?? false; + + protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) + { + configurationBuilder.Properties() + .HaveConversion(); + + configurationBuilder.Properties() + .HaveConversion(); + + configurationBuilder.Properties() + .HaveConversion() + .HaveMaxLength(TitleVO.Limit); + + configurationBuilder.Properties() + .HaveConversion() + .HaveMaxLength(DescriptionVO.Limit); + + configurationBuilder.Properties() + .HaveMaxLength(EmailVO.Limit) + .HaveConversion(); + + configurationBuilder.Properties() + .HaveConversion() + .HaveMaxLength(PhoneNumberVO.Limit); + + configurationBuilder.Properties() + .HaveConversion() + .HaveMaxLength(TelephoneVO.Limit); + + configurationBuilder.Properties() + .HaveConversion(); + } + +} diff --git a/Vichvich.Shop.Infrastructure/Migrations/20260414120342_initial.Designer.cs b/Vichvich.Shop.Infrastructure/Migrations/20260414120342_initial.Designer.cs new file mode 100644 index 0000000..4182732 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/Migrations/20260414120342_initial.Designer.cs @@ -0,0 +1,1095 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Vizhvizh.Shop.Infrastructure.EF; + +#nullable disable + +namespace Vizhvizh.Shop.Infrastructure.Migrations +{ + [DbContext(typeof(ShopDbContext))] + [Migration("20260414120342_initial")] + partial class initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.25") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Members.Entities.Member", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("PhoneNumber") + .IsRequired() + .HasMaxLength(11) + .HasColumnType("nvarchar(11)"); + + b.Property("ShopId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ShopId"); + + b.ToTable("Members", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("Path") + .IsRequired() + .HasColumnType("HIERARCHYID"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.ToTable("Categories", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.CategoryVariantUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("bigint"); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("VariantUnitId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("VariantUnitId", "CategoryId") + .IsUnique(); + + b.ToTable("CategoryVariantUnit", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("bigint"); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("ShopId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("ShopId"); + + b.ToTable("Products", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.ProductVariant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("ProductId") + .HasColumnType("bigint"); + + b.Property("VariantUnitId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ProductId"); + + b.HasIndex("VariantUnitId"); + + b.ToTable("ProductVariants", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Specifications", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("ItemValues") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ProductId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.HasIndex("ProductId"); + + b.ToTable("ProductSpecifications", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Unit", b => + { + b.Property("Id") + .HasColumnType("bigint"); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.ToTable("Units", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Variant", b => + { + b.Property("Id") + .HasColumnType("bigint"); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.ToTable("Variants", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.VariantUnit", b => + { + b.Property("Id") + .HasColumnType("bigint"); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("UnitId") + .HasColumnType("bigint"); + + b.Property("VariantId") + .HasColumnType("bigint"); + + b.Property("VariantUnitType") + .HasColumnType("INT"); + + b.HasKey("Id"); + + b.HasIndex("UnitId"); + + b.HasIndex("VariantId"); + + b.ToTable("VariantUnits", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Shops.Entities.Management", b => + { + b.Property("Id") + .HasColumnType("bigint"); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.HasKey("Id"); + + b.ToTable("Managements", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Shops.Entities.ShippingMethod", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("ShopId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.HasIndex("ShopId"); + + b.ToTable("ShippingMethods", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Shops.Entities.Shop", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("Email") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OwnerId") + .HasColumnType("bigint"); + + b.Property("Telephone") + .IsRequired() + .HasMaxLength(11) + .HasColumnType("nvarchar(11)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.ToTable("Shops", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Sliders.Entities.Slider", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.ToTable("Sliders", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.Resource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("ModuleName") + .HasColumnType("int"); + + b.Property("ResourceKey") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.ToTable("Resources", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("ResourceId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ResourceId"); + + b.HasIndex("UserId"); + + b.ToTable("Roles", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.RoleResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccessLevel") + .HasColumnType("int"); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("RoleId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleResources", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("MemberId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Users", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Members.Entities.Member", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Shops.Entities.Shop", null) + .WithMany("Members") + .HasForeignKey("ShopId"); + + b.OwnsOne("Vizhvizh.Shop.Domain.Members.ValuesObjects.MemberAvatar", "Avatar", b1 => + { + b1.Property("MemberId") + .HasColumnType("bigint"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Avatar"); + + b1.HasKey("MemberId"); + + b1.ToTable("Members", "Shop"); + + b1.WithOwner() + .HasForeignKey("MemberId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Members.ValuesObjects.MemberFullName", "FullName", b1 => + { + b1.Property("MemberId") + .HasColumnType("bigint"); + + b1.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)") + .HasColumnName("FirstName"); + + b1.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)") + .HasColumnName("LastName"); + + b1.HasKey("MemberId"); + + b1.ToTable("Members", "Shop"); + + b1.WithOwner() + .HasForeignKey("MemberId"); + }); + + b.Navigation("Avatar"); + + b.Navigation("FullName"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Category", b => + { + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.CategoryImage", "Image", b1 => + { + b1.Property("CategoryId") + .HasColumnType("bigint"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Image"); + + b1.HasKey("CategoryId"); + + b1.ToTable("Categories", "Shop"); + + b1.WithOwner() + .HasForeignKey("CategoryId"); + }); + + b.Navigation("Image") + .IsRequired(); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.CategoryVariantUnit", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.Category", null) + .WithMany("CategoryVariantUnits") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.VariantUnit", null) + .WithMany("CategoryVariantUnits") + .HasForeignKey("VariantUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Product", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.Category", null) + .WithMany("Products") + .HasForeignKey("CategoryId"); + + b.HasOne("Vizhvizh.Shop.Domain.Shops.Entities.Shop", null) + .WithMany("Products") + .HasForeignKey("ShopId"); + + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.ProductImage", "Image", b1 => + { + b1.Property("ProductId") + .HasColumnType("bigint"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Image"); + + b1.HasKey("ProductId"); + + b1.ToTable("Products", "Shop"); + + b1.WithOwner() + .HasForeignKey("ProductId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.ProductScore", "Score", b1 => + { + b1.Property("ProductId") + .HasColumnType("bigint"); + + b1.Property("Score") + .ValueGeneratedOnAdd() + .HasColumnType("TINYINT") + .HasDefaultValue((byte)0); + + b1.Property("TotalVoters") + .ValueGeneratedOnAdd() + .HasColumnType("INT") + .HasDefaultValue(0) + .HasColumnName("TotalVoters"); + + b1.HasKey("ProductId"); + + b1.ToTable("Products", "Shop"); + + b1.WithOwner() + .HasForeignKey("ProductId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.ProductCondition", "ProductCondition", b1 => + { + b1.Property("ProductId") + .HasColumnType("bigint"); + + b1.Property("Value") + .HasColumnType("int") + .HasColumnName("ProductCondition"); + + b1.HasKey("ProductId"); + + b1.ToTable("Products", "Shop"); + + b1.WithOwner() + .HasForeignKey("ProductId"); + }); + + b.Navigation("Image") + .IsRequired(); + + b.Navigation("ProductCondition") + .IsRequired(); + + b.Navigation("Score") + .IsRequired(); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.ProductVariant", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.Product", null) + .WithMany("Variants") + .HasForeignKey("ProductId"); + + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.VariantUnit", null) + .WithMany("ProductVariants") + .HasForeignKey("VariantUnitId"); + + b.OwnsMany("Vizhvizh.Shop.Domain.Products.ValuesObjects.ProductImage", "Gallery", b1 => + { + b1.Property("ProductVariantId") + .HasColumnType("bigint"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b1.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("Gallery"); + + b1.HasKey("ProductVariantId", "Id"); + + b1.ToTable("ProductVariants", "Shop"); + + b1.ToJson("Gallery"); + + b1.WithOwner() + .HasForeignKey("ProductVariantId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.ProductScore", "Score", b1 => + { + b1.Property("ProductVariantId") + .HasColumnType("bigint"); + + b1.Property("Score") + .ValueGeneratedOnAdd() + .HasColumnType("TINYINT") + .HasDefaultValue((byte)0) + .HasColumnName("Score"); + + b1.Property("TotalVoters") + .ValueGeneratedOnAdd() + .HasColumnType("INT") + .HasDefaultValue(0) + .HasColumnName("TotalVoters"); + + b1.HasKey("ProductVariantId"); + + b1.ToTable("ProductVariants", "Shop"); + + b1.WithOwner() + .HasForeignKey("ProductVariantId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.MoneyValue", "Price", b1 => + { + b1.Property("ProductVariantId") + .HasColumnType("bigint"); + + b1.Property("Currency") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Currency"); + + b1.Property("Value") + .HasColumnType("decimal(18,2)") + .HasColumnName("Price"); + + b1.HasKey("ProductVariantId"); + + b1.ToTable("ProductVariants", "Shop"); + + b1.WithOwner() + .HasForeignKey("ProductVariantId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.ProductQuantity", "Quantity", b1 => + { + b1.Property("ProductVariantId") + .HasColumnType("bigint"); + + b1.Property("Value") + .HasColumnType("float") + .HasColumnName("Quantity"); + + b1.HasKey("ProductVariantId"); + + b1.ToTable("ProductVariants", "Shop"); + + b1.WithOwner() + .HasForeignKey("ProductVariantId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.ProductVariantValue", "Value", b1 => + { + b1.Property("ProductVariantId") + .HasColumnType("bigint"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)") + .HasColumnName("Value"); + + b1.HasKey("ProductVariantId"); + + b1.ToTable("ProductVariants", "Shop"); + + b1.WithOwner() + .HasForeignKey("ProductVariantId"); + }); + + b.Navigation("Gallery"); + + b.Navigation("Price") + .IsRequired(); + + b.Navigation("Quantity") + .IsRequired(); + + b.Navigation("Score") + .IsRequired(); + + b.Navigation("Value") + .IsRequired(); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Specifications", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.Product", null) + .WithMany("Specifications") + .HasForeignKey("ProductId"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.VariantUnit", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.Unit", null) + .WithMany("VariantUnits") + .HasForeignKey("UnitId"); + + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.Variant", null) + .WithMany("VariantUnits") + .HasForeignKey("VariantId"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Shops.Entities.Management", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Shops.Entities.Shop", "Shop") + .WithOne("Management") + .HasForeignKey("Vizhvizh.Shop.Domain.Shops.Entities.Management", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Shops.Entities.ShippingMethod", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Shops.Entities.Shop", null) + .WithMany("ShippingMethods") + .HasForeignKey("ShopId"); + + b.OwnsOne("Vizhvizh.Shop.Domain.Shops.ValuesObjects.ShippingMethodImage", "Image", b1 => + { + b1.Property("ShippingMethodId") + .HasColumnType("tinyint"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Image"); + + b1.HasKey("ShippingMethodId"); + + b1.ToTable("ShippingMethods", "Shop"); + + b1.WithOwner() + .HasForeignKey("ShippingMethodId"); + }); + + b.Navigation("Image") + .IsRequired(); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Shops.Entities.Shop", b => + { + b.OwnsOne("Vizhvizh.Shop.Domain.Shops.ValuesObjects.ShopLocation", "Location", b1 => + { + b1.Property("ShopId") + .HasColumnType("bigint"); + + b1.Property("Address") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("Address"); + + b1.Property("CityId") + .HasColumnType("int") + .HasColumnName("CityId"); + + b1.Property("Latitude") + .HasColumnType("float") + .HasColumnName("Latitude"); + + b1.Property("Longitude") + .HasColumnType("float") + .HasColumnName("Longitude"); + + b1.Property("PostalCode") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("PostalCode"); + + b1.Property("ProvinceId") + .HasColumnType("int") + .HasColumnName("ProvinceId"); + + b1.HasKey("ShopId"); + + b1.ToTable("Shops", "Shop"); + + b1.ToJson("Location"); + + b1.WithOwner() + .HasForeignKey("ShopId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Shops.ValuesObjects.ShopLogo", "Logo", b1 => + { + b1.Property("ShopId") + .HasColumnType("bigint"); + + b1.Property("Value") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Logo"); + + b1.HasKey("ShopId"); + + b1.ToTable("Shops", "Shop"); + + b1.WithOwner() + .HasForeignKey("ShopId"); + }); + + b.Navigation("Location") + .IsRequired(); + + b.Navigation("Logo") + .IsRequired(); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Sliders.Entities.Slider", b => + { + b.OwnsOne("Vizhvizh.Shop.Domain.Sliders.ValuesObjects.SliderImage", "Image", b1 => + { + b1.Property("SliderId") + .HasColumnType("bigint"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Image"); + + b1.HasKey("SliderId"); + + b1.ToTable("Sliders", "Shop"); + + b1.WithOwner() + .HasForeignKey("SliderId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Sliders.ValuesObjects.SliderKey", "Key", b1 => + { + b1.Property("SliderId") + .HasColumnType("bigint"); + + b1.Property("Type") + .HasColumnType("INT") + .HasColumnName("Type"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Key"); + + b1.HasKey("SliderId"); + + b1.ToTable("Sliders", "Shop"); + + b1.WithOwner() + .HasForeignKey("SliderId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Sliders.ValuesObjects.SliderUrl", "Url", b1 => + { + b1.Property("SliderId") + .HasColumnType("bigint"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Url"); + + b1.HasKey("SliderId"); + + b1.ToTable("Sliders", "Shop"); + + b1.WithOwner() + .HasForeignKey("SliderId"); + }); + + b.Navigation("Image") + .IsRequired(); + + b.Navigation("Key") + .IsRequired(); + + b.Navigation("Url") + .IsRequired(); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.Role", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Users.Entities.Resource", null) + .WithMany("Roles") + .HasForeignKey("ResourceId"); + + b.HasOne("Vizhvizh.Shop.Domain.Users.Entities.User", null) + .WithMany("Roles") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.RoleResource", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Users.Entities.Role", null) + .WithMany("RoleResources") + .HasForeignKey("RoleId"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Category", b => + { + b.Navigation("CategoryVariantUnits"); + + b.Navigation("Products"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Product", b => + { + b.Navigation("Specifications"); + + b.Navigation("Variants"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Unit", b => + { + b.Navigation("VariantUnits"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Variant", b => + { + b.Navigation("VariantUnits"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.VariantUnit", b => + { + b.Navigation("CategoryVariantUnits"); + + b.Navigation("ProductVariants"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Shops.Entities.Shop", b => + { + b.Navigation("Management") + .IsRequired(); + + b.Navigation("Members"); + + b.Navigation("Products"); + + b.Navigation("ShippingMethods"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.Resource", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.Role", b => + { + b.Navigation("RoleResources"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.User", b => + { + b.Navigation("Roles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Vichvich.Shop.Infrastructure/Migrations/20260414120342_initial.cs b/Vichvich.Shop.Infrastructure/Migrations/20260414120342_initial.cs new file mode 100644 index 0000000..b19f65f --- /dev/null +++ b/Vichvich.Shop.Infrastructure/Migrations/20260414120342_initial.cs @@ -0,0 +1,565 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Vizhvizh.Shop.Infrastructure.Migrations +{ + /// + public partial class initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "Shop"); + + migrationBuilder.CreateTable( + name: "Categories", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Title = table.Column(type: "nvarchar(60)", maxLength: 60, nullable: false), + Description = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: true), + Image = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: false), + ParentId = table.Column(type: "bigint", nullable: true), + Path = table.Column(type: "HIERARCHYID", nullable: false), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()") + }, + constraints: table => + { + table.PrimaryKey("PK_Categories", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Resources", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Title = table.Column(type: "nvarchar(60)", maxLength: 60, nullable: false), + Description = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: false), + ModuleName = table.Column(type: "int", nullable: false), + ResourceKey = table.Column(type: "nvarchar(max)", nullable: false), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()") + }, + constraints: table => + { + table.PrimaryKey("PK_Resources", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Shops", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + OwnerId = table.Column(type: "bigint", nullable: false), + Title = table.Column(type: "nvarchar(60)", maxLength: 60, nullable: false), + Description = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: true), + Email = table.Column(type: "nvarchar(200)", maxLength: 200, nullable: true), + Telephone = table.Column(type: "nvarchar(11)", maxLength: 11, nullable: false), + Logo = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: true), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()"), + Location = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Shops", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Sliders", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Title = table.Column(type: "nvarchar(60)", maxLength: 60, nullable: false), + Image = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: false), + Url = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: false), + Type = table.Column(type: "INT", nullable: false), + Key = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: false), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()") + }, + constraints: table => + { + table.PrimaryKey("PK_Sliders", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Units", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false), + Title = table.Column(type: "nvarchar(60)", maxLength: 60, nullable: false), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()") + }, + constraints: table => + { + table.PrimaryKey("PK_Units", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Users", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + MemberId = table.Column(type: "bigint", nullable: false), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()") + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Variants", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false), + Title = table.Column(type: "nvarchar(60)", maxLength: 60, nullable: false), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()") + }, + constraints: table => + { + table.PrimaryKey("PK_Variants", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Managements", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()") + }, + constraints: table => + { + table.PrimaryKey("PK_Managements", x => x.Id); + table.ForeignKey( + name: "FK_Managements_Shops_Id", + column: x => x.Id, + principalSchema: "Shop", + principalTable: "Shops", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Members", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + FirstName = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + LastName = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: true), + PhoneNumber = table.Column(type: "nvarchar(11)", maxLength: 11, nullable: false), + Avatar = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: true), + ShopId = table.Column(type: "bigint", nullable: true), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()") + }, + constraints: table => + { + table.PrimaryKey("PK_Members", x => x.Id); + table.ForeignKey( + name: "FK_Members_Shops_ShopId", + column: x => x.ShopId, + principalSchema: "Shop", + principalTable: "Shops", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "Products", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ProductCondition = table.Column(type: "int", nullable: false), + Title = table.Column(type: "nvarchar(60)", maxLength: 60, nullable: false), + Description = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: false), + Score_Score = table.Column(type: "TINYINT", nullable: false, defaultValue: (byte)0), + TotalVoters = table.Column(type: "INT", nullable: false, defaultValue: 0), + Image = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: false), + CategoryId = table.Column(type: "bigint", nullable: true), + ShopId = table.Column(type: "bigint", nullable: true), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()") + }, + constraints: table => + { + table.PrimaryKey("PK_Products", x => x.Id); + table.ForeignKey( + name: "FK_Products_Categories_CategoryId", + column: x => x.CategoryId, + principalSchema: "Shop", + principalTable: "Categories", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Products_Shops_ShopId", + column: x => x.ShopId, + principalSchema: "Shop", + principalTable: "Shops", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "ShippingMethods", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "tinyint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Title = table.Column(type: "nvarchar(60)", maxLength: 60, nullable: false), + Description = table.Column(type: "nvarchar(500)", maxLength: 500, nullable: false), + Image = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: false), + ShopId = table.Column(type: "bigint", nullable: true), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()") + }, + constraints: table => + { + table.PrimaryKey("PK_ShippingMethods", x => x.Id); + table.ForeignKey( + name: "FK_ShippingMethods_Shops_ShopId", + column: x => x.ShopId, + principalSchema: "Shop", + principalTable: "Shops", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "Roles", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Title = table.Column(type: "nvarchar(60)", maxLength: 60, nullable: false), + ResourceId = table.Column(type: "bigint", nullable: true), + UserId = table.Column(type: "bigint", nullable: true), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()") + }, + constraints: table => + { + table.PrimaryKey("PK_Roles", x => x.Id); + table.ForeignKey( + name: "FK_Roles_Resources_ResourceId", + column: x => x.ResourceId, + principalSchema: "Shop", + principalTable: "Resources", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Roles_Users_UserId", + column: x => x.UserId, + principalSchema: "Shop", + principalTable: "Users", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "VariantUnits", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false), + VariantUnitType = table.Column(type: "INT", nullable: false), + UnitId = table.Column(type: "bigint", nullable: true), + VariantId = table.Column(type: "bigint", nullable: true), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()") + }, + constraints: table => + { + table.PrimaryKey("PK_VariantUnits", x => x.Id); + table.ForeignKey( + name: "FK_VariantUnits_Units_UnitId", + column: x => x.UnitId, + principalSchema: "Shop", + principalTable: "Units", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_VariantUnits_Variants_VariantId", + column: x => x.VariantId, + principalSchema: "Shop", + principalTable: "Variants", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "ProductSpecifications", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Title = table.Column(type: "nvarchar(60)", maxLength: 60, nullable: false), + ItemValues = table.Column(type: "nvarchar(max)", nullable: false), + ProductId = table.Column(type: "bigint", nullable: true), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()") + }, + constraints: table => + { + table.PrimaryKey("PK_ProductSpecifications", x => x.Id); + table.ForeignKey( + name: "FK_ProductSpecifications_Products_ProductId", + column: x => x.ProductId, + principalSchema: "Shop", + principalTable: "Products", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "RoleResources", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + AccessLevel = table.Column(type: "int", nullable: false), + RoleId = table.Column(type: "int", nullable: true), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()") + }, + constraints: table => + { + table.PrimaryKey("PK_RoleResources", x => x.Id); + table.ForeignKey( + name: "FK_RoleResources_Roles_RoleId", + column: x => x.RoleId, + principalSchema: "Shop", + principalTable: "Roles", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "CategoryVariantUnit", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + CategoryId = table.Column(type: "bigint", nullable: false), + VariantUnitId = table.Column(type: "bigint", nullable: false), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()") + }, + constraints: table => + { + table.PrimaryKey("PK_CategoryVariantUnit", x => x.Id); + table.ForeignKey( + name: "FK_CategoryVariantUnit_Categories_CategoryId", + column: x => x.CategoryId, + principalSchema: "Shop", + principalTable: "Categories", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_CategoryVariantUnit_VariantUnits_VariantUnitId", + column: x => x.VariantUnitId, + principalSchema: "Shop", + principalTable: "VariantUnits", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ProductVariants", + schema: "Shop", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Price = table.Column(type: "decimal(18,2)", nullable: false), + Currency = table.Column(type: "nvarchar(150)", maxLength: 150, nullable: false), + Score = table.Column(type: "TINYINT", nullable: false, defaultValue: (byte)0), + TotalVoters = table.Column(type: "INT", nullable: false, defaultValue: 0), + Quantity = table.Column(type: "float", nullable: false), + Value = table.Column(type: "nvarchar(120)", maxLength: 120, nullable: false), + ProductId = table.Column(type: "bigint", nullable: true), + VariantUnitId = table.Column(type: "bigint", nullable: true), + CreateOn = table.Column(type: "datetime2", nullable: false, defaultValueSql: "GETDATE()"), + Gallery = table.Column(type: "nvarchar(max)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_ProductVariants", x => x.Id); + table.ForeignKey( + name: "FK_ProductVariants_Products_ProductId", + column: x => x.ProductId, + principalSchema: "Shop", + principalTable: "Products", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_ProductVariants_VariantUnits_VariantUnitId", + column: x => x.VariantUnitId, + principalSchema: "Shop", + principalTable: "VariantUnits", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_CategoryVariantUnit_CategoryId", + schema: "Shop", + table: "CategoryVariantUnit", + column: "CategoryId"); + + migrationBuilder.CreateIndex( + name: "IX_CategoryVariantUnit_VariantUnitId_CategoryId", + schema: "Shop", + table: "CategoryVariantUnit", + columns: new[] { "VariantUnitId", "CategoryId" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_Members_ShopId", + schema: "Shop", + table: "Members", + column: "ShopId"); + + migrationBuilder.CreateIndex( + name: "IX_Products_CategoryId", + schema: "Shop", + table: "Products", + column: "CategoryId"); + + migrationBuilder.CreateIndex( + name: "IX_Products_ShopId", + schema: "Shop", + table: "Products", + column: "ShopId"); + + migrationBuilder.CreateIndex( + name: "IX_ProductSpecifications_ProductId", + schema: "Shop", + table: "ProductSpecifications", + column: "ProductId"); + + migrationBuilder.CreateIndex( + name: "IX_ProductVariants_ProductId", + schema: "Shop", + table: "ProductVariants", + column: "ProductId"); + + migrationBuilder.CreateIndex( + name: "IX_ProductVariants_VariantUnitId", + schema: "Shop", + table: "ProductVariants", + column: "VariantUnitId"); + + migrationBuilder.CreateIndex( + name: "IX_RoleResources_RoleId", + schema: "Shop", + table: "RoleResources", + column: "RoleId"); + + migrationBuilder.CreateIndex( + name: "IX_Roles_ResourceId", + schema: "Shop", + table: "Roles", + column: "ResourceId"); + + migrationBuilder.CreateIndex( + name: "IX_Roles_UserId", + schema: "Shop", + table: "Roles", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_ShippingMethods_ShopId", + schema: "Shop", + table: "ShippingMethods", + column: "ShopId"); + + migrationBuilder.CreateIndex( + name: "IX_VariantUnits_UnitId", + schema: "Shop", + table: "VariantUnits", + column: "UnitId"); + + migrationBuilder.CreateIndex( + name: "IX_VariantUnits_VariantId", + schema: "Shop", + table: "VariantUnits", + column: "VariantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "CategoryVariantUnit", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "Managements", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "Members", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "ProductSpecifications", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "ProductVariants", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "RoleResources", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "ShippingMethods", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "Sliders", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "Products", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "VariantUnits", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "Roles", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "Categories", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "Shops", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "Units", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "Variants", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "Resources", + schema: "Shop"); + + migrationBuilder.DropTable( + name: "Users", + schema: "Shop"); + } + } +} diff --git a/Vichvich.Shop.Infrastructure/Migrations/ShopDbContextModelSnapshot.cs b/Vichvich.Shop.Infrastructure/Migrations/ShopDbContextModelSnapshot.cs new file mode 100644 index 0000000..7f205aa --- /dev/null +++ b/Vichvich.Shop.Infrastructure/Migrations/ShopDbContextModelSnapshot.cs @@ -0,0 +1,1092 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Vizhvizh.Shop.Infrastructure.EF; + +#nullable disable + +namespace Vizhvizh.Shop.Infrastructure.Migrations +{ + [DbContext(typeof(ShopDbContext))] + partial class ShopDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.25") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Members.Entities.Member", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("PhoneNumber") + .IsRequired() + .HasMaxLength(11) + .HasColumnType("nvarchar(11)"); + + b.Property("ShopId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ShopId"); + + b.ToTable("Members", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Category", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("ParentId") + .HasColumnType("bigint"); + + b.Property("Path") + .IsRequired() + .HasColumnType("HIERARCHYID"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.ToTable("Categories", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.CategoryVariantUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("bigint"); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("VariantUnitId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("VariantUnitId", "CategoryId") + .IsUnique(); + + b.ToTable("CategoryVariantUnit", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CategoryId") + .HasColumnType("bigint"); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("ShopId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.HasIndex("CategoryId"); + + b.HasIndex("ShopId"); + + b.ToTable("Products", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.ProductVariant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("ProductId") + .HasColumnType("bigint"); + + b.Property("VariantUnitId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ProductId"); + + b.HasIndex("VariantUnitId"); + + b.ToTable("ProductVariants", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Specifications", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("ItemValues") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("ProductId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.HasIndex("ProductId"); + + b.ToTable("ProductSpecifications", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Unit", b => + { + b.Property("Id") + .HasColumnType("bigint"); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.ToTable("Units", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Variant", b => + { + b.Property("Id") + .HasColumnType("bigint"); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.ToTable("Variants", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.VariantUnit", b => + { + b.Property("Id") + .HasColumnType("bigint"); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("UnitId") + .HasColumnType("bigint"); + + b.Property("VariantId") + .HasColumnType("bigint"); + + b.Property("VariantUnitType") + .HasColumnType("INT"); + + b.HasKey("Id"); + + b.HasIndex("UnitId"); + + b.HasIndex("VariantId"); + + b.ToTable("VariantUnits", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Shops.Entities.Management", b => + { + b.Property("Id") + .HasColumnType("bigint"); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.HasKey("Id"); + + b.ToTable("Managements", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Shops.Entities.ShippingMethod", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("tinyint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("ShopId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.HasIndex("ShopId"); + + b.ToTable("ShippingMethods", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Shops.Entities.Shop", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("Email") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("OwnerId") + .HasColumnType("bigint"); + + b.Property("Telephone") + .IsRequired() + .HasMaxLength(11) + .HasColumnType("nvarchar(11)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.ToTable("Shops", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Sliders.Entities.Slider", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.ToTable("Sliders", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.Resource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("ModuleName") + .HasColumnType("int"); + + b.Property("ResourceKey") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.ToTable("Resources", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("ResourceId") + .HasColumnType("bigint"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("ResourceId"); + + b.HasIndex("UserId"); + + b.ToTable("Roles", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.RoleResource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AccessLevel") + .HasColumnType("int"); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("RoleId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("RoleResources", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateOn") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasDefaultValueSql("GETDATE()"); + + b.Property("MemberId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.ToTable("Users", "Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Members.Entities.Member", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Shops.Entities.Shop", null) + .WithMany("Members") + .HasForeignKey("ShopId"); + + b.OwnsOne("Vizhvizh.Shop.Domain.Members.ValuesObjects.MemberAvatar", "Avatar", b1 => + { + b1.Property("MemberId") + .HasColumnType("bigint"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Avatar"); + + b1.HasKey("MemberId"); + + b1.ToTable("Members", "Shop"); + + b1.WithOwner() + .HasForeignKey("MemberId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Members.ValuesObjects.MemberFullName", "FullName", b1 => + { + b1.Property("MemberId") + .HasColumnType("bigint"); + + b1.Property("FirstName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)") + .HasColumnName("FirstName"); + + b1.Property("LastName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)") + .HasColumnName("LastName"); + + b1.HasKey("MemberId"); + + b1.ToTable("Members", "Shop"); + + b1.WithOwner() + .HasForeignKey("MemberId"); + }); + + b.Navigation("Avatar"); + + b.Navigation("FullName"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Category", b => + { + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.CategoryImage", "Image", b1 => + { + b1.Property("CategoryId") + .HasColumnType("bigint"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Image"); + + b1.HasKey("CategoryId"); + + b1.ToTable("Categories", "Shop"); + + b1.WithOwner() + .HasForeignKey("CategoryId"); + }); + + b.Navigation("Image") + .IsRequired(); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.CategoryVariantUnit", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.Category", null) + .WithMany("CategoryVariantUnits") + .HasForeignKey("CategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.VariantUnit", null) + .WithMany("CategoryVariantUnits") + .HasForeignKey("VariantUnitId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Product", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.Category", null) + .WithMany("Products") + .HasForeignKey("CategoryId"); + + b.HasOne("Vizhvizh.Shop.Domain.Shops.Entities.Shop", null) + .WithMany("Products") + .HasForeignKey("ShopId"); + + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.ProductImage", "Image", b1 => + { + b1.Property("ProductId") + .HasColumnType("bigint"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Image"); + + b1.HasKey("ProductId"); + + b1.ToTable("Products", "Shop"); + + b1.WithOwner() + .HasForeignKey("ProductId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.ProductScore", "Score", b1 => + { + b1.Property("ProductId") + .HasColumnType("bigint"); + + b1.Property("Score") + .ValueGeneratedOnAdd() + .HasColumnType("TINYINT") + .HasDefaultValue((byte)0); + + b1.Property("TotalVoters") + .ValueGeneratedOnAdd() + .HasColumnType("INT") + .HasDefaultValue(0) + .HasColumnName("TotalVoters"); + + b1.HasKey("ProductId"); + + b1.ToTable("Products", "Shop"); + + b1.WithOwner() + .HasForeignKey("ProductId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.ProductCondition", "ProductCondition", b1 => + { + b1.Property("ProductId") + .HasColumnType("bigint"); + + b1.Property("Value") + .HasColumnType("int") + .HasColumnName("ProductCondition"); + + b1.HasKey("ProductId"); + + b1.ToTable("Products", "Shop"); + + b1.WithOwner() + .HasForeignKey("ProductId"); + }); + + b.Navigation("Image") + .IsRequired(); + + b.Navigation("ProductCondition") + .IsRequired(); + + b.Navigation("Score") + .IsRequired(); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.ProductVariant", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.Product", null) + .WithMany("Variants") + .HasForeignKey("ProductId"); + + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.VariantUnit", null) + .WithMany("ProductVariants") + .HasForeignKey("VariantUnitId"); + + b.OwnsMany("Vizhvizh.Shop.Domain.Products.ValuesObjects.ProductImage", "Gallery", b1 => + { + b1.Property("ProductVariantId") + .HasColumnType("bigint"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b1.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("Gallery"); + + b1.HasKey("ProductVariantId", "Id"); + + b1.ToTable("ProductVariants", "Shop"); + + b1.ToJson("Gallery"); + + b1.WithOwner() + .HasForeignKey("ProductVariantId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.ProductScore", "Score", b1 => + { + b1.Property("ProductVariantId") + .HasColumnType("bigint"); + + b1.Property("Score") + .ValueGeneratedOnAdd() + .HasColumnType("TINYINT") + .HasDefaultValue((byte)0) + .HasColumnName("Score"); + + b1.Property("TotalVoters") + .ValueGeneratedOnAdd() + .HasColumnType("INT") + .HasDefaultValue(0) + .HasColumnName("TotalVoters"); + + b1.HasKey("ProductVariantId"); + + b1.ToTable("ProductVariants", "Shop"); + + b1.WithOwner() + .HasForeignKey("ProductVariantId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.MoneyValue", "Price", b1 => + { + b1.Property("ProductVariantId") + .HasColumnType("bigint"); + + b1.Property("Currency") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Currency"); + + b1.Property("Value") + .HasColumnType("decimal(18,2)") + .HasColumnName("Price"); + + b1.HasKey("ProductVariantId"); + + b1.ToTable("ProductVariants", "Shop"); + + b1.WithOwner() + .HasForeignKey("ProductVariantId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.ProductQuantity", "Quantity", b1 => + { + b1.Property("ProductVariantId") + .HasColumnType("bigint"); + + b1.Property("Value") + .HasColumnType("float") + .HasColumnName("Quantity"); + + b1.HasKey("ProductVariantId"); + + b1.ToTable("ProductVariants", "Shop"); + + b1.WithOwner() + .HasForeignKey("ProductVariantId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Products.ValuesObjects.ProductVariantValue", "Value", b1 => + { + b1.Property("ProductVariantId") + .HasColumnType("bigint"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)") + .HasColumnName("Value"); + + b1.HasKey("ProductVariantId"); + + b1.ToTable("ProductVariants", "Shop"); + + b1.WithOwner() + .HasForeignKey("ProductVariantId"); + }); + + b.Navigation("Gallery"); + + b.Navigation("Price") + .IsRequired(); + + b.Navigation("Quantity") + .IsRequired(); + + b.Navigation("Score") + .IsRequired(); + + b.Navigation("Value") + .IsRequired(); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Specifications", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.Product", null) + .WithMany("Specifications") + .HasForeignKey("ProductId"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.VariantUnit", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.Unit", null) + .WithMany("VariantUnits") + .HasForeignKey("UnitId"); + + b.HasOne("Vizhvizh.Shop.Domain.Products.Entities.Variant", null) + .WithMany("VariantUnits") + .HasForeignKey("VariantId"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Shops.Entities.Management", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Shops.Entities.Shop", "Shop") + .WithOne("Management") + .HasForeignKey("Vizhvizh.Shop.Domain.Shops.Entities.Management", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Shop"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Shops.Entities.ShippingMethod", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Shops.Entities.Shop", null) + .WithMany("ShippingMethods") + .HasForeignKey("ShopId"); + + b.OwnsOne("Vizhvizh.Shop.Domain.Shops.ValuesObjects.ShippingMethodImage", "Image", b1 => + { + b1.Property("ShippingMethodId") + .HasColumnType("tinyint"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Image"); + + b1.HasKey("ShippingMethodId"); + + b1.ToTable("ShippingMethods", "Shop"); + + b1.WithOwner() + .HasForeignKey("ShippingMethodId"); + }); + + b.Navigation("Image") + .IsRequired(); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Shops.Entities.Shop", b => + { + b.OwnsOne("Vizhvizh.Shop.Domain.Shops.ValuesObjects.ShopLocation", "Location", b1 => + { + b1.Property("ShopId") + .HasColumnType("bigint"); + + b1.Property("Address") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("Address"); + + b1.Property("CityId") + .HasColumnType("int") + .HasColumnName("CityId"); + + b1.Property("Latitude") + .HasColumnType("float") + .HasColumnName("Latitude"); + + b1.Property("Longitude") + .HasColumnType("float") + .HasColumnName("Longitude"); + + b1.Property("PostalCode") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnName("PostalCode"); + + b1.Property("ProvinceId") + .HasColumnType("int") + .HasColumnName("ProvinceId"); + + b1.HasKey("ShopId"); + + b1.ToTable("Shops", "Shop"); + + b1.ToJson("Location"); + + b1.WithOwner() + .HasForeignKey("ShopId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Shops.ValuesObjects.ShopLogo", "Logo", b1 => + { + b1.Property("ShopId") + .HasColumnType("bigint"); + + b1.Property("Value") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Logo"); + + b1.HasKey("ShopId"); + + b1.ToTable("Shops", "Shop"); + + b1.WithOwner() + .HasForeignKey("ShopId"); + }); + + b.Navigation("Location") + .IsRequired(); + + b.Navigation("Logo") + .IsRequired(); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Sliders.Entities.Slider", b => + { + b.OwnsOne("Vizhvizh.Shop.Domain.Sliders.ValuesObjects.SliderImage", "Image", b1 => + { + b1.Property("SliderId") + .HasColumnType("bigint"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Image"); + + b1.HasKey("SliderId"); + + b1.ToTable("Sliders", "Shop"); + + b1.WithOwner() + .HasForeignKey("SliderId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Sliders.ValuesObjects.SliderKey", "Key", b1 => + { + b1.Property("SliderId") + .HasColumnType("bigint"); + + b1.Property("Type") + .HasColumnType("INT") + .HasColumnName("Type"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Key"); + + b1.HasKey("SliderId"); + + b1.ToTable("Sliders", "Shop"); + + b1.WithOwner() + .HasForeignKey("SliderId"); + }); + + b.OwnsOne("Vizhvizh.Shop.Domain.Sliders.ValuesObjects.SliderUrl", "Url", b1 => + { + b1.Property("SliderId") + .HasColumnType("bigint"); + + b1.Property("Value") + .IsRequired() + .HasMaxLength(150) + .HasColumnType("nvarchar(150)") + .HasColumnName("Url"); + + b1.HasKey("SliderId"); + + b1.ToTable("Sliders", "Shop"); + + b1.WithOwner() + .HasForeignKey("SliderId"); + }); + + b.Navigation("Image") + .IsRequired(); + + b.Navigation("Key") + .IsRequired(); + + b.Navigation("Url") + .IsRequired(); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.Role", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Users.Entities.Resource", null) + .WithMany("Roles") + .HasForeignKey("ResourceId"); + + b.HasOne("Vizhvizh.Shop.Domain.Users.Entities.User", null) + .WithMany("Roles") + .HasForeignKey("UserId"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.RoleResource", b => + { + b.HasOne("Vizhvizh.Shop.Domain.Users.Entities.Role", null) + .WithMany("RoleResources") + .HasForeignKey("RoleId"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Category", b => + { + b.Navigation("CategoryVariantUnits"); + + b.Navigation("Products"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Product", b => + { + b.Navigation("Specifications"); + + b.Navigation("Variants"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Unit", b => + { + b.Navigation("VariantUnits"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.Variant", b => + { + b.Navigation("VariantUnits"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Products.Entities.VariantUnit", b => + { + b.Navigation("CategoryVariantUnits"); + + b.Navigation("ProductVariants"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Shops.Entities.Shop", b => + { + b.Navigation("Management") + .IsRequired(); + + b.Navigation("Members"); + + b.Navigation("Products"); + + b.Navigation("ShippingMethods"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.Resource", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.Role", b => + { + b.Navigation("RoleResources"); + }); + + modelBuilder.Entity("Vizhvizh.Shop.Domain.Users.Entities.User", b => + { + b.Navigation("Roles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Vichvich.Shop.Infrastructure/Repositories/ShopRepository.cs b/Vichvich.Shop.Infrastructure/Repositories/ShopRepository.cs new file mode 100644 index 0000000..fd63172 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/Repositories/ShopRepository.cs @@ -0,0 +1,15 @@ +using Vizhvizh.Shop.Domain.Shops.Repositories; +using Vizhvizh.Shop.Domain.Shops.TypeIds; +using Vizhvizh.Shop.Infrastructure.EF; + +namespace Vizhvizh.Shop.Infrastructure.Repositories +{ + internal class ShopRepository(ShopDbContext context) : IShopRepository + { + public async Task AddAsync(Domain.Shops.Entities.Shop shop, CancellationToken cancellationToken) + => await context.Shops.AddAsync(shop, cancellationToken); + + public async Task FindByIdAsync(ShopId id, CancellationToken cancellationToken) + => await context.Shops.FindAsync(id,cancellationToken).ConfigureAwait(false); + } +} diff --git a/Vichvich.Shop.Infrastructure/Repositories/SliderRepository.cs b/Vichvich.Shop.Infrastructure/Repositories/SliderRepository.cs new file mode 100644 index 0000000..bf72fcc --- /dev/null +++ b/Vichvich.Shop.Infrastructure/Repositories/SliderRepository.cs @@ -0,0 +1,18 @@ +using Vizhvizh.Shop.Domain.Sliders.Entities; +using Vizhvizh.Shop.Domain.Sliders.Repositories; +using Vizhvizh.Shop.Domain.Sliders.TypeIds; + +namespace Vizhvizh.Shop.Infrastructure.Repositories; + +public class SliderRepository : ISliderRepository +{ + public Task AddAsync(Slider slider, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + public Task GetByIdAsync(SliderId id, CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } +} diff --git a/Vichvich.Shop.Infrastructure/ShopStartup.cs b/Vichvich.Shop.Infrastructure/ShopStartup.cs new file mode 100644 index 0000000..72ab06a --- /dev/null +++ b/Vichvich.Shop.Infrastructure/ShopStartup.cs @@ -0,0 +1,80 @@ +using Vizhvizh.Shop.Application; +using Vizhvizh.Shop.Infrastructure.Configuration; +using Vizhvizh.Shop.Infrastructure.EF; +using Vizhvizh.BuildingBlocks.Application.Configuration.Commnad; +using Vizhvizh.BuildingBlocks.Application.Configuration.Query; +using Vizhvizh.BuildingBlocks.Application.Data; +using Vizhvizh.BuildingBlocks.Application.Events; +using Vizhvizh.BuildingBlocks.Application.Outbox; +using Vizhvizh.BuildingBlocks.Infrastructure; +using Vizhvizh.BuildingBlocks.Infrastructure.DomainEventsDispatching; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.EntityFrameworkCore; +using Vizhvizh.Shop.Domain.Shops.Repositories; +using Vizhvizh.Shop.Infrastructure.Repositories; +using Vizhvizh.BuildingBlocks.Infrastructure.SelectBuilders; +using Vizhvizh.BuildingBlocks.Application.SelectBuilders; +using Vizhvizh.Shop.Domain.Sliders.Repositories; + + +namespace Vizhvizh.Shop.Infrastructure; + +public class ShopStartup +{ + public static void Initialize(IServiceCollection services, string connectionString) + { + services.AddDbContext(op => + { + op.UseSqlServer(connectionString); + }); + services.AddScoped(sp => sp.GetRequiredService()); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.Scan(scan => scan. + FromAssemblies(Assemblies.Application, Assemblies.Infrastructure) + .AddClasses(classes => classes.AssignableTo(typeof(ICommandHandler<>)), publicOnly: false) + .AsImplementedInterfaces() + .WithScopedLifetime() + .AddClasses(classes => classes.AssignableTo(typeof(ICommandHandler<,>)), publicOnly: false) + .AsImplementedInterfaces() + .WithScopedLifetime() + .AddClasses(classes => classes.AssignableTo(typeof(IQueryHandler<,>)), publicOnly: false) + .AsImplementedInterfaces() + .WithScopedLifetime() + .AddClasses(classes => classes.AssignableTo(typeof(ICommandHandler<>)), publicOnly: false) + .AsImplementedInterfaces() + .WithScopedLifetime()); + services.Decorate(typeof(ICommandHandler<>), typeof(UnitOfWorkCommandHandlerDecorator<>)); + services.Decorate(typeof(ICommandHandler<,>), typeof(UnitOfWorkCommandHandlerDecorator<,>)); + services.AddScoped(sa => + { + var notifications = sa.GetServices(); + var notificationDic = new BiDictionary(); + foreach (var notification in notifications) + notificationDic.Add(notification!.ToString()!, notification!.GetType()); + + return notificationDic; + }); + services.AddScoped(sa => + { + return null; // ToDo + }); + + services.AddScoped(sp => + { + return new SqlConnectionFactory(connectionString); + }); + + services.AddScoped(); + services.AddScoped(); + + #region Repositories + services.AddScoped(); + services.AddScoped(); + #endregion + } +} diff --git a/Vichvich.Shop.Infrastructure/Vizhvizh.Shop.Infrastructure.csproj b/Vichvich.Shop.Infrastructure/Vizhvizh.Shop.Infrastructure.csproj new file mode 100644 index 0000000..d281444 --- /dev/null +++ b/Vichvich.Shop.Infrastructure/Vizhvizh.Shop.Infrastructure.csproj @@ -0,0 +1,25 @@ + + + + net8.0 + enable + enable + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + diff --git a/Vichvich.UserAccess.Api/Controllers/WeatherForecastController.cs b/Vichvich.UserAccess.Api/Controllers/WeatherForecastController.cs new file mode 100644 index 0000000..2e38f3d --- /dev/null +++ b/Vichvich.UserAccess.Api/Controllers/WeatherForecastController.cs @@ -0,0 +1,33 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Vizhvizh.UserAccess.Api.Controllers +{ + [ApiController] + [Route("[controller]")] + public class WeatherForecastController : ControllerBase + { + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} diff --git a/Vichvich.UserAccess.Api/Program.cs b/Vichvich.UserAccess.Api/Program.cs new file mode 100644 index 0000000..ac7c10a --- /dev/null +++ b/Vichvich.UserAccess.Api/Program.cs @@ -0,0 +1,17 @@ +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/Vichvich.UserAccess.Api/Properties/launchSettings.json b/Vichvich.UserAccess.Api/Properties/launchSettings.json new file mode 100644 index 0000000..a8a4679 --- /dev/null +++ b/Vichvich.UserAccess.Api/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:27147", + "sslPort": 44383 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "weatherforecast", + "applicationUrl": "http://localhost:5110", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "weatherforecast", + "applicationUrl": "https://localhost:7113;http://localhost:5110", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "weatherforecast", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Vichvich.UserAccess.Api/Vichvich.UserAccess.Api.http b/Vichvich.UserAccess.Api/Vichvich.UserAccess.Api.http new file mode 100644 index 0000000..60a6e8e --- /dev/null +++ b/Vichvich.UserAccess.Api/Vichvich.UserAccess.Api.http @@ -0,0 +1,6 @@ +@Vizhvizh.UserAccess.Api_HostAddress = http://localhost:5110 + +GET {{Vizhvizh.UserAccess.Api_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/Vichvich.UserAccess.Api/Vizhvizh.UserAccess.Api.csproj b/Vichvich.UserAccess.Api/Vizhvizh.UserAccess.Api.csproj new file mode 100644 index 0000000..8823928 --- /dev/null +++ b/Vichvich.UserAccess.Api/Vizhvizh.UserAccess.Api.csproj @@ -0,0 +1,10 @@ + + + + net8.0 + enable + enable + true + + + diff --git a/Vichvich.UserAccess.Api/WeatherForecast.cs b/Vichvich.UserAccess.Api/WeatherForecast.cs new file mode 100644 index 0000000..196f7c0 --- /dev/null +++ b/Vichvich.UserAccess.Api/WeatherForecast.cs @@ -0,0 +1,13 @@ +namespace Vizhvizh.UserAccess.Api +{ + public class WeatherForecast + { + public DateOnly Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } + } +} diff --git a/Vichvich.UserAccess.Api/appsettings.Development.json b/Vichvich.UserAccess.Api/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Vichvich.UserAccess.Api/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Vichvich.UserAccess.Api/appsettings.json b/Vichvich.UserAccess.Api/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Vichvich.UserAccess.Api/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/Vichvich.UserAccess.Application/Vizhvizh.UserAccess.Application.csproj b/Vichvich.UserAccess.Application/Vizhvizh.UserAccess.Application.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/Vichvich.UserAccess.Application/Vizhvizh.UserAccess.Application.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/Vichvich.UserAccess.Domain.Resource/EntityResources.Designer.cs b/Vichvich.UserAccess.Domain.Resource/EntityResources.Designer.cs new file mode 100644 index 0000000..25e8e3f --- /dev/null +++ b/Vichvich.UserAccess.Domain.Resource/EntityResources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.UserAccess.Domain.Resource { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class EntityResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal EntityResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.UserAccess.Domain.Resource.EntityResources", typeof(EntityResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Vichvich.UserAccess.Domain.Resource/EntityResources.resx b/Vichvich.UserAccess.Domain.Resource/EntityResources.resx new file mode 100644 index 0000000..4fdb1b6 --- /dev/null +++ b/Vichvich.UserAccess.Domain.Resource/EntityResources.resx @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Vichvich.UserAccess.Domain.Resource/ExceptionResources.Designer.cs b/Vichvich.UserAccess.Domain.Resource/ExceptionResources.Designer.cs new file mode 100644 index 0000000..56904a9 --- /dev/null +++ b/Vichvich.UserAccess.Domain.Resource/ExceptionResources.Designer.cs @@ -0,0 +1,81 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.UserAccess.Domain.Resource { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class ExceptionResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ExceptionResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.UserAccess.Domain.Resource.ExceptionResources", typeof(ExceptionResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to کد ملی معتبر نمی باشد. + /// + public static string InvalidNationalCodeException { + get { + return ResourceManager.GetString("InvalidNationalCodeException", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to نام یا نام خانوادگی نمیتواند خالی باشد. + /// + public static string MemberFullNameNullOrEmptyException { + get { + return ResourceManager.GetString("MemberFullNameNullOrEmptyException", resourceCulture); + } + } + } +} diff --git a/Vichvich.UserAccess.Domain.Resource/ExceptionResources.resx b/Vichvich.UserAccess.Domain.Resource/ExceptionResources.resx new file mode 100644 index 0000000..640415a --- /dev/null +++ b/Vichvich.UserAccess.Domain.Resource/ExceptionResources.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + کد ملی معتبر نمی باشد + + + نام یا نام خانوادگی نمیتواند خالی باشد + + \ No newline at end of file diff --git a/Vichvich.UserAccess.Domain.Resource/ValueObjectResources.Designer.cs b/Vichvich.UserAccess.Domain.Resource/ValueObjectResources.Designer.cs new file mode 100644 index 0000000..a50a613 --- /dev/null +++ b/Vichvich.UserAccess.Domain.Resource/ValueObjectResources.Designer.cs @@ -0,0 +1,99 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Vizhvizh.UserAccess.Domain.Resource { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class ValueObjectResources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal ValueObjectResources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Vizhvizh.UserAccess.Domain.Resource.ValueObjectResources", typeof(ValueObjectResources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to خواندن. + /// + public static string AccessLevelEnum_Read { + get { + return ResourceManager.GetString("AccessLevelEnum_Read", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to خواندن/نوشتن. + /// + public static string AccessLevelEnum_ReadWrite { + get { + return ResourceManager.GetString("AccessLevelEnum_ReadWrite", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to نوشتن. + /// + public static string AccessLevelEnum_Write { + get { + return ResourceManager.GetString("AccessLevelEnum_Write", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to نام و نام خانوادگی عضو. + /// + public static string MemberFullName { + get { + return ResourceManager.GetString("MemberFullName", resourceCulture); + } + } + } +} diff --git a/Vichvich.UserAccess.Domain.Resource/ValueObjectResources.resx b/Vichvich.UserAccess.Domain.Resource/ValueObjectResources.resx new file mode 100644 index 0000000..a70e64f --- /dev/null +++ b/Vichvich.UserAccess.Domain.Resource/ValueObjectResources.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + خواندن + + + خواندن/نوشتن + + + نوشتن + + + نام و نام خانوادگی عضو + + \ No newline at end of file diff --git a/Vichvich.UserAccess.Domain.Resource/Vizhvizh.UserAccess.Domain.Resource.csproj b/Vichvich.UserAccess.Domain.Resource/Vizhvizh.UserAccess.Domain.Resource.csproj new file mode 100644 index 0000000..aaf5237 --- /dev/null +++ b/Vichvich.UserAccess.Domain.Resource/Vizhvizh.UserAccess.Domain.Resource.csproj @@ -0,0 +1,42 @@ + + + + net8.0 + enable + enable + + + + + EntityResources.resx + True + True + + + ExceptionResources.resx + True + True + + + ValueObjectResources.resx + True + True + + + + + + EntityResources.Designer.cs + PublicResXFileCodeGenerator + + + ExceptionResources.Designer.cs + PublicResXFileCodeGenerator + + + ValueObjectResources.Designer.cs + PublicResXFileCodeGenerator + + + + diff --git a/Vichvich.UserAccess.Domain/Entities/Member.cs b/Vichvich.UserAccess.Domain/Entities/Member.cs new file mode 100644 index 0000000..44f3232 --- /dev/null +++ b/Vichvich.UserAccess.Domain/Entities/Member.cs @@ -0,0 +1,34 @@ +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.UserAccess.Domain.TypeIds; +using Vizhvizh.UserAccess.Domain.ValueObjects; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.Entities; + +/// +/// عضو +/// +public class Member : Entity +{ + private MemberFullName _fullName; + private PhoneNumberVO _phoneNumber; + private MemberAvatar? _avatar; + private List _addresses; + + private Member(MemberFullName fullName, PhoneNumberVO phoneNumber, MemberAvatar? avatar, List? addresses) + { + _fullName = fullName; + _phoneNumber = phoneNumber; + _avatar = avatar; + _addresses = addresses ?? []; + } + public static Member CreateNew(MemberFullName fullName, PhoneNumberVO phoneNumber, MemberAvatar? avatar, List? addresses = null) + { + return new Member(fullName, phoneNumber, avatar, addresses); + } + public MemberFullName FullName => _fullName; + public PhoneNumberVO PhoneNumber => _phoneNumber; + public MemberAvatar? Avatar => _avatar; + public IReadOnlyList Addresses => _addresses; + +} diff --git a/Vichvich.UserAccess.Domain/Entities/Resource.cs b/Vichvich.UserAccess.Domain/Entities/Resource.cs new file mode 100644 index 0000000..86b8fe5 --- /dev/null +++ b/Vichvich.UserAccess.Domain/Entities/Resource.cs @@ -0,0 +1,32 @@ +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.UserAccess.Domain.TypeIds; +using Vizhvizh.UserAccess.Domain.ValueObjects; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.Entities; + +public class Resource : Entity +{ + private List _roles; + private TitleVO _title; + private DescriptionVO _description; + private ModuleNameVO _moduleNames; + private ResourceKey _resourceKey; + + public Resource(TitleVO title, DescriptionVO description, ModuleNameVO moduleNames, ResourceKey resourceKey, List roles) + { + _description = description; + _title = title; + _moduleNames = moduleNames; + _resourceKey = resourceKey; + _roles = roles; + } + public static Resource CreateNew(TitleVO title, DescriptionVO description, ModuleNameVO moduleNames, ResourceKey resourceKey, List roles) + => new Resource(title, description, moduleNames, resourceKey, roles); + + public TitleVO Title => _title; + public DescriptionVO Description => _description; + public ModuleNameVO ModuleNames => _moduleNames; + public ResourceKey ResourceKey => _resourceKey; + public IReadOnlyList Roles => _roles; +} diff --git a/Vichvich.UserAccess.Domain/Entities/Role.cs b/Vichvich.UserAccess.Domain/Entities/Role.cs new file mode 100644 index 0000000..632ac99 --- /dev/null +++ b/Vichvich.UserAccess.Domain/Entities/Role.cs @@ -0,0 +1,22 @@ +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.UserAccess.Domain.TypeIds; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.Entities; + +public class Role : Entity +{ + private TitleVO _title; + private List _roleResources; + private Role(TitleVO title,List roleResources) + { + _title = title; + _roleResources = roleResources; + } + public static Role CreateNew(TitleVO title , List roleResources) + => new Role(title, roleResources); + + public TitleVO Title => _title; + public IReadOnlyList RoleResources => _roleResources; + +} diff --git a/Vichvich.UserAccess.Domain/Entities/RoleResource.cs b/Vichvich.UserAccess.Domain/Entities/RoleResource.cs new file mode 100644 index 0000000..9c5eb7d --- /dev/null +++ b/Vichvich.UserAccess.Domain/Entities/RoleResource.cs @@ -0,0 +1,28 @@ +using Vizhvizh.UserAccess.Domain.TypeIds; +using Vizhvizh.UserAccess.Domain.ValueObjects; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.Entities; + +public class RoleResource : Entity +{ + private AccessLevel _accessLevel; + + private UserId _userId; + private RoleId _roleId; + + private RoleResource(AccessLevel accessLevel, UserId userId, RoleId roleId) + { + _accessLevel = accessLevel; + _userId = userId; + _roleId = roleId; + } + + public static RoleResource CreateNew(AccessLevel accessLevel, UserId userId, RoleId roleId) + => new RoleResource(accessLevel, userId, roleId); + + public AccessLevel AccessLevel => _accessLevel; + public UserId UserId => _userId; + public RoleId RoleId => _roleId; + +} diff --git a/Vichvich.UserAccess.Domain/Entities/User.cs b/Vichvich.UserAccess.Domain/Entities/User.cs new file mode 100644 index 0000000..cb19bc5 --- /dev/null +++ b/Vichvich.UserAccess.Domain/Entities/User.cs @@ -0,0 +1,26 @@ +using Vizhvizh.UserAccess.Domain.TypeIds; +using Vizhvizh.UserAccess.Domain.ValueObjects; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.Entities; + +public class User : Entity, IAggregateRoot +{ + private UserNationalCode _nationalCode; + private MemberId _memberId; + private List _roles; + + private User(UserNationalCode nationalCode,MemberId memberId,List roles) + { + _nationalCode = nationalCode; + _memberId = memberId; + _roles = roles; + } + + public static User CreateNew(UserNationalCode nationalCode, MemberId memberId, List roles) + => new User(nationalCode, memberId, roles); + + public UserNationalCode NationalCode => _nationalCode; + public MemberId MemberId => _memberId; + public IReadOnlyList Roles => _roles; +} diff --git a/Vichvich.UserAccess.Domain/Exceptions/InvalidNationalCodeException.cs b/Vichvich.UserAccess.Domain/Exceptions/InvalidNationalCodeException.cs new file mode 100644 index 0000000..34c567d --- /dev/null +++ b/Vichvich.UserAccess.Domain/Exceptions/InvalidNationalCodeException.cs @@ -0,0 +1,11 @@ +using Vizhvizh.UserAccess.Domain.Resource; +using Vizhvizh.BuildingBlocks.Domain.Exceptions; + +namespace Vizhvizh.UserAccess.Domain.Exceptions; + +public class InvalidNationalCodeException : ValueObjectValidationException +{ + public InvalidNationalCodeException() : base(ExceptionResources.InvalidNationalCodeException) + { + } +} diff --git a/Vichvich.UserAccess.Domain/Exceptions/MemberFullNameNullOrEmptyException.cs b/Vichvich.UserAccess.Domain/Exceptions/MemberFullNameNullOrEmptyException.cs new file mode 100644 index 0000000..4ae3a4b --- /dev/null +++ b/Vichvich.UserAccess.Domain/Exceptions/MemberFullNameNullOrEmptyException.cs @@ -0,0 +1,11 @@ +using Vizhvizh.UserAccess.Domain.Resource; +using Vizhvizh.BuildingBlocks.Domain.Exceptions; + +namespace Vizhvizh.UserAccess.Domain.Exceptions; + +public class MemberFullNameNullOrEmptyException : ValueObjectValidationException +{ + public MemberFullNameNullOrEmptyException() : base(ExceptionResources.MemberFullNameNullOrEmptyException) + { + } +} diff --git a/Vichvich.UserAccess.Domain/TypeIds/MemberId.cs b/Vichvich.UserAccess.Domain/TypeIds/MemberId.cs new file mode 100644 index 0000000..b124271 --- /dev/null +++ b/Vichvich.UserAccess.Domain/TypeIds/MemberId.cs @@ -0,0 +1,11 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.TypeIds; + + +public class MemberId : TypedIdValueBase +{ + public MemberId(long value) : base(value) + { + } +} diff --git a/Vichvich.UserAccess.Domain/TypeIds/ResourceId.cs b/Vichvich.UserAccess.Domain/TypeIds/ResourceId.cs new file mode 100644 index 0000000..2d32419 --- /dev/null +++ b/Vichvich.UserAccess.Domain/TypeIds/ResourceId.cs @@ -0,0 +1,11 @@ + +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.TypeIds; + +public class ResourceId : TypedIdValueBase +{ + public ResourceId(long value) : base(value) + { + } +} diff --git a/Vichvich.UserAccess.Domain/TypeIds/RoleId.cs b/Vichvich.UserAccess.Domain/TypeIds/RoleId.cs new file mode 100644 index 0000000..9af6587 --- /dev/null +++ b/Vichvich.UserAccess.Domain/TypeIds/RoleId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.TypeIds; + +public class RoleId : TypedIdValueBase +{ + public RoleId(int value) : base(value) + { + } +} diff --git a/Vichvich.UserAccess.Domain/TypeIds/RoleResourceId.cs b/Vichvich.UserAccess.Domain/TypeIds/RoleResourceId.cs new file mode 100644 index 0000000..3f19e86 --- /dev/null +++ b/Vichvich.UserAccess.Domain/TypeIds/RoleResourceId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.TypeIds; + +public class RoleResourceId : TypedIdValueBase +{ + public RoleResourceId(long value) : base(value) + { + } +} diff --git a/Vichvich.UserAccess.Domain/TypeIds/UserId.cs b/Vichvich.UserAccess.Domain/TypeIds/UserId.cs new file mode 100644 index 0000000..9cb7831 --- /dev/null +++ b/Vichvich.UserAccess.Domain/TypeIds/UserId.cs @@ -0,0 +1,10 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.TypeIds; + +public class UserId : TypedIdValueBase +{ + public UserId(long value) : base(value) + { + } +} diff --git a/Vichvich.UserAccess.Domain/ValueObjects/AccessLevel.cs b/Vichvich.UserAccess.Domain/ValueObjects/AccessLevel.cs new file mode 100644 index 0000000..7914e2b --- /dev/null +++ b/Vichvich.UserAccess.Domain/ValueObjects/AccessLevel.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations; +using Vizhvizh.UserAccess.Domain.Resource; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.ValueObjects; + +public class AccessLevel : ValueObject +{ + public AccessLevel(AccessLevelEnum value) + { + Value = (int)value; + } + public int Value { get; init;} +} +public enum AccessLevelEnum +{ + [Display(Name = nameof(ValueObjectResources.AccessLevelEnum_Write), ResourceType = typeof(ValueObjectResources))] + Write = 0, + [Display(Name = nameof(ValueObjectResources.AccessLevelEnum_Read), ResourceType = typeof(ValueObjectResources))] + Read = 1, + [Display(Name = nameof(ValueObjectResources.AccessLevelEnum_ReadWrite), ResourceType = typeof(ValueObjectResources))] + ReadWrite = 2 +} diff --git a/Vichvich.UserAccess.Domain/ValueObjects/MemberAddress.cs b/Vichvich.UserAccess.Domain/ValueObjects/MemberAddress.cs new file mode 100644 index 0000000..7662cf8 --- /dev/null +++ b/Vichvich.UserAccess.Domain/ValueObjects/MemberAddress.cs @@ -0,0 +1,23 @@ +using Vizhvizh.Shared.Domain.TypeIds; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.ValueObjects; + +public class MemberAddress : ValueObject +{ + public MemberAddress(double latitude, double longitude, int provinceId, int cityId, string address, string postalCode) + { + Latitude = latitude; + Longitude = longitude; + ProvinceId = provinceId; + CityId = cityId; + Address = address; + PostalCode = postalCode; + } + public double Latitude { get; init; } + public double Longitude { get; init; } + public int ProvinceId { get; set; } + public int CityId { get; set; } + public string Address { get; set; } + public string PostalCode { get; set; } +} diff --git a/Vichvich.UserAccess.Domain/ValueObjects/MemberAvatar.cs b/Vichvich.UserAccess.Domain/ValueObjects/MemberAvatar.cs new file mode 100644 index 0000000..38097db --- /dev/null +++ b/Vichvich.UserAccess.Domain/ValueObjects/MemberAvatar.cs @@ -0,0 +1,12 @@ +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.ValueObjects; + +public class MemberAvatar : ValueObject +{ + public MemberAvatar(string value) + { + Value = value; + } + public string Value { get; init; } +} diff --git a/Vichvich.UserAccess.Domain/ValueObjects/MemberFullName.cs b/Vichvich.UserAccess.Domain/ValueObjects/MemberFullName.cs new file mode 100644 index 0000000..5bd5d5d --- /dev/null +++ b/Vichvich.UserAccess.Domain/ValueObjects/MemberFullName.cs @@ -0,0 +1,29 @@ +using Vizhvizh.Shared.Domain.Exceptions; +using Vizhvizh.UserAccess.Domain.Exceptions; +using Vizhvizh.UserAccess.Domain.Resource; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.ValueObjects; + +public class MemberFullName : ValueObject +{ + public const short Limit = 100; + public MemberFullName(string firstName, string lastName) + { + if (string.IsNullOrWhiteSpace(firstName) || string.IsNullOrWhiteSpace(lastName)) + throw new MemberFullNameNullOrEmptyException(); + + if ((firstName + lastName).Length > Limit) + throw new CharacterLimitException(ValueObjectResources.MemberFullName, Limit); + + FirstName = firstName; + LastName = lastName; + } + public string FirstName { get; init; } + public string LastName { get; init; } + + public override string ToString() + { + return $"{FirstName} {LastName}"; + } +} diff --git a/Vichvich.UserAccess.Domain/ValueObjects/ResourceKey.cs b/Vichvich.UserAccess.Domain/ValueObjects/ResourceKey.cs new file mode 100644 index 0000000..20196a1 --- /dev/null +++ b/Vichvich.UserAccess.Domain/ValueObjects/ResourceKey.cs @@ -0,0 +1,13 @@ +using Vizhvizh.Shared.Domain.ValueObjects; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.ValueObjects; + +public class ResourceKey : ValueObject +{ + public ResourceKey(ModuleNameVO module,TitleVO resourceTitle, params string[] parts) + { + Value = $"{module.Value}.{string.Join('.',parts)}.{resourceTitle.Value}"; + } + public string Value { get; init; } +} diff --git a/Vichvich.UserAccess.Domain/ValueObjects/UserNationalCode.cs b/Vichvich.UserAccess.Domain/ValueObjects/UserNationalCode.cs new file mode 100644 index 0000000..1712c0d --- /dev/null +++ b/Vichvich.UserAccess.Domain/ValueObjects/UserNationalCode.cs @@ -0,0 +1,48 @@ +using Vizhvizh.UserAccess.Domain.Exceptions; +using Vizhvizh.BuildingBlocks.Domain; + +namespace Vizhvizh.UserAccess.Domain.ValueObjects; + +public class UserNationalCode : ValueObject +{ + public static bool IsValidNationalCode(string nationalCode) + { + if (nationalCode is null || nationalCode.Length > 10) + return false; + + // تبدیل به آرایه + var arr = nationalCode.ToArray().Select(n => int.Parse(n.ToString())); + + //بر عکس کردن اجزا + var arrReduce = arr.Reverse().ToList(); + + // بدست آوردن رقم کنترل اخر کد ملی + var numberControl = arrReduce.First(); + arrReduce.RemoveAt(0); + + // تمام 9 رقم سمت چپ کد ملی ضرب در موقعیت خودش میشه بعد همه جمع میشن بعدش تقسیم به یازده و باقی مانده رو میگیرم + //کد ملی 0700454713 + //موقیعت 07 به ترتیب 9و10 هست از اونجایی ک ما رقم کنترل رو برداشتیم پس باید ایندکس ب اضافه ی 2 شه + var remaining = decimal.Parse($"{arrReduce.Select((n, i) => n * (i + 2)).Sum() % 11}"); + + if (remaining <= 2.0m) + { + if (numberControl == remaining) + return true; + else + return false; + } + else if (11m - remaining == numberControl) + return true; + else + return false; + } + public UserNationalCode(string value) + { + if (!IsValidNationalCode(value)) + throw new InvalidNationalCodeException(); + + Value = value; + } + public string Value { get; init; } +} diff --git a/Vichvich.UserAccess.Domain/Vizhvizh.UserAccess.Domain.csproj b/Vichvich.UserAccess.Domain/Vizhvizh.UserAccess.Domain.csproj new file mode 100644 index 0000000..8dd3f56 --- /dev/null +++ b/Vichvich.UserAccess.Domain/Vizhvizh.UserAccess.Domain.csproj @@ -0,0 +1,14 @@ + + + + net8.0 + enable + enable + + + + + + + + diff --git a/Vichvich.UserAccess.Infrastructure/Vizhvizh.UserAccess.Infrastructure.csproj b/Vichvich.UserAccess.Infrastructure/Vizhvizh.UserAccess.Infrastructure.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/Vichvich.UserAccess.Infrastructure/Vizhvizh.UserAccess.Infrastructure.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/Vizhvizh.Shared.Api/Program.cs b/Vizhvizh.Shared.Api/Program.cs new file mode 100644 index 0000000..8489cc9 --- /dev/null +++ b/Vizhvizh.Shared.Api/Program.cs @@ -0,0 +1,9 @@ +var builder = WebApplication.CreateBuilder(args); + + +builder.Services.AddControllers(); + +var app = builder.Build(); + + +app.Run(); diff --git a/Vizhvizh.Shared.Api/Properties/launchSettings.json b/Vizhvizh.Shared.Api/Properties/launchSettings.json new file mode 100644 index 0000000..350f675 --- /dev/null +++ b/Vizhvizh.Shared.Api/Properties/launchSettings.json @@ -0,0 +1,38 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:42968", + "sslPort": 44324 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "http://localhost:5143", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:7200;http://localhost:5143", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/Vizhvizh.Shared.Api/Vizhvizh.Shared.Api.csproj b/Vizhvizh.Shared.Api/Vizhvizh.Shared.Api.csproj new file mode 100644 index 0000000..a398713 --- /dev/null +++ b/Vizhvizh.Shared.Api/Vizhvizh.Shared.Api.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/Vizhvizh.Shared.Api/appsettings.Development.json b/Vizhvizh.Shared.Api/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/Vizhvizh.Shared.Api/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/Vizhvizh.Shared.Api/appsettings.json b/Vizhvizh.Shared.Api/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/Vizhvizh.Shared.Api/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/Vizhvizh.Shared.Presentation/Vizhvizh.Shared.Presentation.csproj b/Vizhvizh.Shared.Presentation/Vizhvizh.Shared.Presentation.csproj new file mode 100644 index 0000000..fa71b7a --- /dev/null +++ b/Vizhvizh.Shared.Presentation/Vizhvizh.Shared.Presentation.csproj @@ -0,0 +1,9 @@ + + + + net8.0 + enable + enable + + + diff --git a/Vizhvizh.sln b/Vizhvizh.sln new file mode 100644 index 0000000..6bcf786 --- /dev/null +++ b/Vizhvizh.sln @@ -0,0 +1,235 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34330.188 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shop", "Shop", "{75B96843-617C-4481-B649-139990528EAC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildingBlocks", "BuildingBlocks", "{230DF7E5-6F87-4A34-A4AD-C8F83EF56D9D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application", "{D90687B2-3CF8-4E5A-A2F2-780EB843BCBE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Domain", "Domain", "{7454001E-46CB-4235-BC10-32DD22B81A9A}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Presentation", "Presentation", "{879CD38B-1297-45D6-AAB4-88D50CDC5D70}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{D0A68E4E-D314-48A9-BE4B-84BC45DFBF5D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.Shop.Application", "Vichvich.Shop.Application\Vizhvizh.Shop.Application.csproj", "{A824D8A6-15E2-4C6E-BC99-D5598F7497CB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.Shop.Domain", "Vichvich.Shop.Domain\Vizhvizh.Shop.Domain.csproj", "{F2B080E4-9C2A-46BB-909B-E625B5C2DC09}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.Shop.Infrastructure", "Vichvich.Shop.Infrastructure\Vizhvizh.Shop.Infrastructure.csproj", "{1AE94D93-4092-435E-9AE6-25BC0EEEDFAC}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Domain", "Domain", "{6507BDC1-AC70-498F-87A9-F7E3E56EDB74}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application", "{0A8FBC21-1C75-4A01-A93D-261AABF2E694}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{387CB942-5C6A-488B-9170-1F939C5CC2F1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Presentation", "Presentation", "{E6CE9F53-AA1F-4E1A-907E-35344E124B27}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.BuildingBlocks.Domain", "VichVich.BuildingBlocks.Domain\Vizhvizh.BuildingBlocks.Domain.csproj", "{5A7472C3-A95C-4E9E-A7E2-EE4D32CA4EAF}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dictionary", "Dictionary", "{7C23B8CD-8B5A-4968-8383-83D26A0B1751}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.Shop.Domain.Resource", "VichVich.Shop.Domain.Resource\Vizhvizh.Shop.Domain.Resource.csproj", "{35622169-5EA2-4BA2-A35D-4E741EB44C1D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{56899278-A89E-46A6-8492-3C0F95B2E2B4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application", "{DC8302F3-1358-498E-9F91-1BFAC45026D9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{E50B8541-6FF2-4B56-907B-2F7584EBC3E7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Domain", "Domain", "{2FB5CD25-2DB9-48C3-B2D8-CB7332D95B1D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.Shared.Domain", "Vichvich.Shared.Domain\Vizhvizh.Shared.Domain.csproj", "{AE018993-0BD1-4894-B3BE-4DA69EC14913}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{64F8E6C2-F045-4974-86B2-35E63072093D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UserAccess", "UserAccess", "{669FF1AD-2E1A-4FB5-9BC4-723081C43052}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application", "{B02D2602-474D-402D-BCBD-F22AD4B9C6E1}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Domain", "Domain", "{97DB76D0-A7CD-49FF-9FC9-35538F0FBFE2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{1921E8C1-F02E-4013-9B9A-7835972B30E3}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Presentation", "Presentation", "{85F22432-8023-4245-B2A7-7191976A0C6B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.UserAccess.Application", "Vichvich.UserAccess.Application\Vizhvizh.UserAccess.Application.csproj", "{39D2C7D1-D5F8-4048-A4F0-A70719336AF6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.UserAccess.Domain", "Vichvich.UserAccess.Domain\Vizhvizh.UserAccess.Domain.csproj", "{AF9AA287-D274-4FA6-BACF-063F2A47C073}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.UserAccess.Infrastructure", "Vichvich.UserAccess.Infrastructure\Vizhvizh.UserAccess.Infrastructure.csproj", "{B9B3630E-05CA-4A2A-B147-28298A32048E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.UserAccess.Domain.Resource", "Vichvich.UserAccess.Domain.Resource\Vizhvizh.UserAccess.Domain.Resource.csproj", "{6CDD6424-BFF2-4187-A008-AF9E19B8636F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.Shared.Domain.Resource", "VichVich.Shared.Domain.Resource\Vizhvizh.Shared.Domain.Resource.csproj", "{B976DBDB-BBAF-4B90-9E96-7A16292B66EE}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Location", "Location", "{D06CE705-E20D-4EA6-8521-134C3E14BD39}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Application", "Application", "{549194DA-8CF9-4DBD-A7CF-5588F0A0253D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Domain", "Domain", "{8494341F-D5E9-44EE-B916-67E08F803F52}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{3BEF5D17-A6AF-4D23-B159-C5C0E7F46B4A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.Location.Domain", "Vichvich.Location.Domain\Vizhvizh.Location.Domain.csproj", "{6DCCA78E-A266-4CF9-9326-CD4D5E8F2783}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Geteway", "Geteway", "{E5B91D44-2A62-4C5C-A16F-E7732D56AA42}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.Geteway", "Vichvich.Geteway\Vizhvizh.Geteway.csproj", "{9EA0DD3D-E67B-4D46-8B45-2D17CA604004}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.UserAccess.Api", "Vichvich.UserAccess.Api\Vizhvizh.UserAccess.Api.csproj", "{1A8A47DE-1670-40D9-97F1-9E60EDD6AEC1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.Shop.Api", "Vichvich.Shop.Api\Vizhvizh.Shop.Api.csproj", "{CE7F7BB1-926A-4A87-93A7-D1B07A768F2E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.BuildingBlocks.Infrastructure", "VichVich.BuildingBlocks.Infrastructure\Vizhvizh.BuildingBlocks.Infrastructure.csproj", "{1BE613F0-2B51-4A22-B312-52863501D16B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.BuildingBlocks.Application", "VichVich.BuildingBlocks.Application\Vizhvizh.BuildingBlocks.Application.csproj", "{16C0F9C6-0EBD-4A35-B172-138A50588B96}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.Shop.ApplicationContract", "Vichvich.Shop.ApplicationContract\Vizhvizh.Shop.ApplicationContract.csproj", "{BB74BFF4-131B-4BAE-9345-6043C15F97F6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.Shared.Infrastructure", "Vichvich.Shared.Infrastructure\Vizhvizh.Shared.Infrastructure.csproj", "{503F6D97-9DDF-44B0-A861-F532A81D3BAC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Vizhvizh.Shared.Application", "Vichvich.Shared.Application\Vizhvizh.Shared.Application.csproj", "{54310E26-B264-42EE-8D53-CE490133F4FC}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A824D8A6-15E2-4C6E-BC99-D5598F7497CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A824D8A6-15E2-4C6E-BC99-D5598F7497CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A824D8A6-15E2-4C6E-BC99-D5598F7497CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A824D8A6-15E2-4C6E-BC99-D5598F7497CB}.Release|Any CPU.Build.0 = Release|Any CPU + {F2B080E4-9C2A-46BB-909B-E625B5C2DC09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F2B080E4-9C2A-46BB-909B-E625B5C2DC09}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F2B080E4-9C2A-46BB-909B-E625B5C2DC09}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F2B080E4-9C2A-46BB-909B-E625B5C2DC09}.Release|Any CPU.Build.0 = Release|Any CPU + {1AE94D93-4092-435E-9AE6-25BC0EEEDFAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1AE94D93-4092-435E-9AE6-25BC0EEEDFAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1AE94D93-4092-435E-9AE6-25BC0EEEDFAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1AE94D93-4092-435E-9AE6-25BC0EEEDFAC}.Release|Any CPU.Build.0 = Release|Any CPU + {5A7472C3-A95C-4E9E-A7E2-EE4D32CA4EAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A7472C3-A95C-4E9E-A7E2-EE4D32CA4EAF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5A7472C3-A95C-4E9E-A7E2-EE4D32CA4EAF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5A7472C3-A95C-4E9E-A7E2-EE4D32CA4EAF}.Release|Any CPU.Build.0 = Release|Any CPU + {35622169-5EA2-4BA2-A35D-4E741EB44C1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35622169-5EA2-4BA2-A35D-4E741EB44C1D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35622169-5EA2-4BA2-A35D-4E741EB44C1D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35622169-5EA2-4BA2-A35D-4E741EB44C1D}.Release|Any CPU.Build.0 = Release|Any CPU + {AE018993-0BD1-4894-B3BE-4DA69EC14913}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AE018993-0BD1-4894-B3BE-4DA69EC14913}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AE018993-0BD1-4894-B3BE-4DA69EC14913}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AE018993-0BD1-4894-B3BE-4DA69EC14913}.Release|Any CPU.Build.0 = Release|Any CPU + {39D2C7D1-D5F8-4048-A4F0-A70719336AF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {39D2C7D1-D5F8-4048-A4F0-A70719336AF6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {39D2C7D1-D5F8-4048-A4F0-A70719336AF6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {39D2C7D1-D5F8-4048-A4F0-A70719336AF6}.Release|Any CPU.Build.0 = Release|Any CPU + {AF9AA287-D274-4FA6-BACF-063F2A47C073}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AF9AA287-D274-4FA6-BACF-063F2A47C073}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AF9AA287-D274-4FA6-BACF-063F2A47C073}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AF9AA287-D274-4FA6-BACF-063F2A47C073}.Release|Any CPU.Build.0 = Release|Any CPU + {B9B3630E-05CA-4A2A-B147-28298A32048E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9B3630E-05CA-4A2A-B147-28298A32048E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9B3630E-05CA-4A2A-B147-28298A32048E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9B3630E-05CA-4A2A-B147-28298A32048E}.Release|Any CPU.Build.0 = Release|Any CPU + {6CDD6424-BFF2-4187-A008-AF9E19B8636F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CDD6424-BFF2-4187-A008-AF9E19B8636F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CDD6424-BFF2-4187-A008-AF9E19B8636F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CDD6424-BFF2-4187-A008-AF9E19B8636F}.Release|Any CPU.Build.0 = Release|Any CPU + {B976DBDB-BBAF-4B90-9E96-7A16292B66EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B976DBDB-BBAF-4B90-9E96-7A16292B66EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B976DBDB-BBAF-4B90-9E96-7A16292B66EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B976DBDB-BBAF-4B90-9E96-7A16292B66EE}.Release|Any CPU.Build.0 = Release|Any CPU + {6DCCA78E-A266-4CF9-9326-CD4D5E8F2783}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6DCCA78E-A266-4CF9-9326-CD4D5E8F2783}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6DCCA78E-A266-4CF9-9326-CD4D5E8F2783}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6DCCA78E-A266-4CF9-9326-CD4D5E8F2783}.Release|Any CPU.Build.0 = Release|Any CPU + {9EA0DD3D-E67B-4D46-8B45-2D17CA604004}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9EA0DD3D-E67B-4D46-8B45-2D17CA604004}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9EA0DD3D-E67B-4D46-8B45-2D17CA604004}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9EA0DD3D-E67B-4D46-8B45-2D17CA604004}.Release|Any CPU.Build.0 = Release|Any CPU + {1A8A47DE-1670-40D9-97F1-9E60EDD6AEC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1A8A47DE-1670-40D9-97F1-9E60EDD6AEC1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1A8A47DE-1670-40D9-97F1-9E60EDD6AEC1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1A8A47DE-1670-40D9-97F1-9E60EDD6AEC1}.Release|Any CPU.Build.0 = Release|Any CPU + {CE7F7BB1-926A-4A87-93A7-D1B07A768F2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE7F7BB1-926A-4A87-93A7-D1B07A768F2E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE7F7BB1-926A-4A87-93A7-D1B07A768F2E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CE7F7BB1-926A-4A87-93A7-D1B07A768F2E}.Release|Any CPU.Build.0 = Release|Any CPU + {1BE613F0-2B51-4A22-B312-52863501D16B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1BE613F0-2B51-4A22-B312-52863501D16B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1BE613F0-2B51-4A22-B312-52863501D16B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1BE613F0-2B51-4A22-B312-52863501D16B}.Release|Any CPU.Build.0 = Release|Any CPU + {16C0F9C6-0EBD-4A35-B172-138A50588B96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {16C0F9C6-0EBD-4A35-B172-138A50588B96}.Debug|Any CPU.Build.0 = Debug|Any CPU + {16C0F9C6-0EBD-4A35-B172-138A50588B96}.Release|Any CPU.ActiveCfg = Release|Any CPU + {16C0F9C6-0EBD-4A35-B172-138A50588B96}.Release|Any CPU.Build.0 = Release|Any CPU + {BB74BFF4-131B-4BAE-9345-6043C15F97F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BB74BFF4-131B-4BAE-9345-6043C15F97F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB74BFF4-131B-4BAE-9345-6043C15F97F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BB74BFF4-131B-4BAE-9345-6043C15F97F6}.Release|Any CPU.Build.0 = Release|Any CPU + {503F6D97-9DDF-44B0-A861-F532A81D3BAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {503F6D97-9DDF-44B0-A861-F532A81D3BAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {503F6D97-9DDF-44B0-A861-F532A81D3BAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {503F6D97-9DDF-44B0-A861-F532A81D3BAC}.Release|Any CPU.Build.0 = Release|Any CPU + {54310E26-B264-42EE-8D53-CE490133F4FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {54310E26-B264-42EE-8D53-CE490133F4FC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {54310E26-B264-42EE-8D53-CE490133F4FC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {54310E26-B264-42EE-8D53-CE490133F4FC}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {75B96843-617C-4481-B649-139990528EAC} = {64F8E6C2-F045-4974-86B2-35E63072093D} + {D90687B2-3CF8-4E5A-A2F2-780EB843BCBE} = {75B96843-617C-4481-B649-139990528EAC} + {7454001E-46CB-4235-BC10-32DD22B81A9A} = {75B96843-617C-4481-B649-139990528EAC} + {879CD38B-1297-45D6-AAB4-88D50CDC5D70} = {75B96843-617C-4481-B649-139990528EAC} + {D0A68E4E-D314-48A9-BE4B-84BC45DFBF5D} = {75B96843-617C-4481-B649-139990528EAC} + {A824D8A6-15E2-4C6E-BC99-D5598F7497CB} = {D90687B2-3CF8-4E5A-A2F2-780EB843BCBE} + {F2B080E4-9C2A-46BB-909B-E625B5C2DC09} = {7454001E-46CB-4235-BC10-32DD22B81A9A} + {1AE94D93-4092-435E-9AE6-25BC0EEEDFAC} = {D0A68E4E-D314-48A9-BE4B-84BC45DFBF5D} + {6507BDC1-AC70-498F-87A9-F7E3E56EDB74} = {230DF7E5-6F87-4A34-A4AD-C8F83EF56D9D} + {0A8FBC21-1C75-4A01-A93D-261AABF2E694} = {230DF7E5-6F87-4A34-A4AD-C8F83EF56D9D} + {387CB942-5C6A-488B-9170-1F939C5CC2F1} = {230DF7E5-6F87-4A34-A4AD-C8F83EF56D9D} + {E6CE9F53-AA1F-4E1A-907E-35344E124B27} = {230DF7E5-6F87-4A34-A4AD-C8F83EF56D9D} + {5A7472C3-A95C-4E9E-A7E2-EE4D32CA4EAF} = {6507BDC1-AC70-498F-87A9-F7E3E56EDB74} + {35622169-5EA2-4BA2-A35D-4E741EB44C1D} = {7C23B8CD-8B5A-4968-8383-83D26A0B1751} + {56899278-A89E-46A6-8492-3C0F95B2E2B4} = {64F8E6C2-F045-4974-86B2-35E63072093D} + {DC8302F3-1358-498E-9F91-1BFAC45026D9} = {56899278-A89E-46A6-8492-3C0F95B2E2B4} + {E50B8541-6FF2-4B56-907B-2F7584EBC3E7} = {56899278-A89E-46A6-8492-3C0F95B2E2B4} + {2FB5CD25-2DB9-48C3-B2D8-CB7332D95B1D} = {56899278-A89E-46A6-8492-3C0F95B2E2B4} + {AE018993-0BD1-4894-B3BE-4DA69EC14913} = {2FB5CD25-2DB9-48C3-B2D8-CB7332D95B1D} + {669FF1AD-2E1A-4FB5-9BC4-723081C43052} = {64F8E6C2-F045-4974-86B2-35E63072093D} + {B02D2602-474D-402D-BCBD-F22AD4B9C6E1} = {669FF1AD-2E1A-4FB5-9BC4-723081C43052} + {97DB76D0-A7CD-49FF-9FC9-35538F0FBFE2} = {669FF1AD-2E1A-4FB5-9BC4-723081C43052} + {1921E8C1-F02E-4013-9B9A-7835972B30E3} = {669FF1AD-2E1A-4FB5-9BC4-723081C43052} + {85F22432-8023-4245-B2A7-7191976A0C6B} = {669FF1AD-2E1A-4FB5-9BC4-723081C43052} + {39D2C7D1-D5F8-4048-A4F0-A70719336AF6} = {B02D2602-474D-402D-BCBD-F22AD4B9C6E1} + {AF9AA287-D274-4FA6-BACF-063F2A47C073} = {97DB76D0-A7CD-49FF-9FC9-35538F0FBFE2} + {B9B3630E-05CA-4A2A-B147-28298A32048E} = {1921E8C1-F02E-4013-9B9A-7835972B30E3} + {6CDD6424-BFF2-4187-A008-AF9E19B8636F} = {7C23B8CD-8B5A-4968-8383-83D26A0B1751} + {B976DBDB-BBAF-4B90-9E96-7A16292B66EE} = {7C23B8CD-8B5A-4968-8383-83D26A0B1751} + {D06CE705-E20D-4EA6-8521-134C3E14BD39} = {64F8E6C2-F045-4974-86B2-35E63072093D} + {549194DA-8CF9-4DBD-A7CF-5588F0A0253D} = {D06CE705-E20D-4EA6-8521-134C3E14BD39} + {8494341F-D5E9-44EE-B916-67E08F803F52} = {D06CE705-E20D-4EA6-8521-134C3E14BD39} + {3BEF5D17-A6AF-4D23-B159-C5C0E7F46B4A} = {D06CE705-E20D-4EA6-8521-134C3E14BD39} + {6DCCA78E-A266-4CF9-9326-CD4D5E8F2783} = {8494341F-D5E9-44EE-B916-67E08F803F52} + {9EA0DD3D-E67B-4D46-8B45-2D17CA604004} = {E5B91D44-2A62-4C5C-A16F-E7732D56AA42} + {1A8A47DE-1670-40D9-97F1-9E60EDD6AEC1} = {85F22432-8023-4245-B2A7-7191976A0C6B} + {CE7F7BB1-926A-4A87-93A7-D1B07A768F2E} = {879CD38B-1297-45D6-AAB4-88D50CDC5D70} + {1BE613F0-2B51-4A22-B312-52863501D16B} = {387CB942-5C6A-488B-9170-1F939C5CC2F1} + {16C0F9C6-0EBD-4A35-B172-138A50588B96} = {0A8FBC21-1C75-4A01-A93D-261AABF2E694} + {BB74BFF4-131B-4BAE-9345-6043C15F97F6} = {D90687B2-3CF8-4E5A-A2F2-780EB843BCBE} + {503F6D97-9DDF-44B0-A861-F532A81D3BAC} = {E50B8541-6FF2-4B56-907B-2F7584EBC3E7} + {54310E26-B264-42EE-8D53-CE490133F4FC} = {DC8302F3-1358-498E-9F91-1BFAC45026D9} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {7AC6F270-5F8A-4E0F-BF79-F0FF567D4C34} + EndGlobalSection +EndGlobal diff --git a/compose.dcproj b/compose.dcproj new file mode 100644 index 0000000..480e5b5 --- /dev/null +++ b/compose.dcproj @@ -0,0 +1,19 @@ + + + + 2.1 + Linux + False + d4488765-3902-4dba-bd41-497252fb483a + LaunchBrowser + {Scheme}://localhost:{ServicePort}/weatherforecast + vichvich.geteway + + + + docker-compose.yml + + + + + \ No newline at end of file diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 0000000..9e56755 --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,25 @@ +version: '3.4' + +services: + vichvich.geteway: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_HTTP_PORTS=8080 + - ASPNETCORE_HTTPS_PORTS=8081 + ports: + - "8080" + - "8081" + volumes: + - ${APPDATA}/Microsoft/UserSecrets:/home/app/.microsoft/usersecrets:ro + - ${APPDATA}/ASP.NET/Https:/home/app/.aspnet/https:ro + vichvich.shop.api: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_HTTP_PORTS=8080 + - ASPNETCORE_HTTPS_PORTS=8081 + ports: + - "8080" + - "8081" + volumes: + - ${APPDATA}/Microsoft/UserSecrets:/home/app/.microsoft/usersecrets:ro + - ${APPDATA}/ASP.NET/Https:/home/app/.aspnet/https:ro diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..fd0ba03 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +version: '3.4' + +services: + vichvich.geteway: + image: ${DOCKER_REGISTRY-}vichvichgeteway + build: + context: . + dockerfile: Vichvich.Geteway/Dockerfile + + vichvich.shop.api: + image: ${DOCKER_REGISTRY-}vichvichshopapi + build: + context: . + dockerfile: Vichvich.Shop.Api/Dockerfile + diff --git a/launchSettings.json b/launchSettings.json new file mode 100644 index 0000000..6e5a8aa --- /dev/null +++ b/launchSettings.json @@ -0,0 +1,12 @@ +{ + "profiles": { + "Docker Compose": { + "commandName": "DockerCompose", + "commandVersion": "1.0", + "serviceActions": { + "vichvich.geteway": "StartDebugging", + "vichvich.shop.api": "StartDebugging" + } + } + } +} \ No newline at end of file