diff --git a/.gitea/workflows/cms-stage.yml b/.gitea/workflows/cms-stage.yml
new file mode 100644
index 0000000..856768b
--- /dev/null
+++ b/.gitea/workflows/cms-stage.yml
@@ -0,0 +1,47 @@
+
+name: Push nuget and docker image Actions Workflow
+
+on:
+ push:
+ branches:
+ - stage
+jobs:
+ Deploy:
+ runs-on: windows
+ steps:
+ - name: Checkout
+ uses: https://git.afrino.co/actions/checkout@v3
+ - name: Setup dotnet
+ uses: https://git.afrino.co/actions/setup-dotnet@v3
+ with:
+ dotnet-version: 7.0.x
+
+ - name: Remove Package Source
+ run: dotnet nuget remove source MegaBizdEx
+ continue-on-error: true
+ - name: Add Package Source
+ run: dotnet nuget add source --name MegaBizdEx --username systemuser --password BHMkDaU3uXP6euR http://88.198.47.16:7000/api/packages/MegaBizdEx/nuget/index.json --store-password-in-clear-text
+ - name: Install dependencies
+ run: dotnet restore ".\src\CMSMicroservice.Protobuf\CMSMicroservice.Protobuf.csproj"
+ - name: Build
+ run: dotnet build ".\src\CMSMicroservice.Protobuf\CMSMicroservice.Protobuf.csproj" --configuration Release --no-restore
+ - name: Test
+ run: dotnet test ".\src\CMSMicroservice.Protobuf\CMSMicroservice.Protobuf.csproj" --no-restore --verbosity normal
+ - name: Pack
+ run: dotnet pack ".\src\CMSMicroservice.Protobuf\CMSMicroservice.Protobuf.csproj" --no-build --configuration Release
+ - name: Push To Gitea Packages
+ run: dotnet nuget push **/*.nupkg --source http://88.198.47.16:7000/api/packages/megabizdex/nuget/index.json --api-key 49c6424b31442f3aaad8d5ce73401143264f8471 --skip-duplicate
+
+ - name: Build Docker Image
+ run: docker build ./src -t cmsapi:latest -f src/CMSMicroservice.WebApi/Dockerfile
+ - name: Log Out From Registry
+ run: docker logout git.afrino.co
+ - name: Log In To Registry
+ run: docker login git.afrino.co -u systemuser -p sZSA7PTiv3pUSQZ
+ - name: Tag Docker Image
+ run: docker image tag cmsapi:latest git.afrino.co/megabizdex/cmsapi:latest
+ - name: Push Docker Image
+ run: docker image push git.afrino.co/megabizdex/cmsapi:latest
+
+ - name: Deploy (Up) Services
+ run: docker-compose up -d
diff --git a/src/.dockerignore b/src/.dockerignore
new file mode 100644
index 0000000..25f68c7
--- /dev/null
+++ b/src/.dockerignore
@@ -0,0 +1,26 @@
+
+**/.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
diff --git a/src/CMS.sln b/src/CMS.sln
new file mode 100644
index 0000000..0b74488
--- /dev/null
+++ b/src/CMS.sln
@@ -0,0 +1,45 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.0.31903.59
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{43A1942F-306D-4937-8907-B9888A5449CF}") = "CMSMicroservice.Domain", "CMSMicroservice.Domain\CMSMicroservice.Domain.csproj", "{426E097F-8C77-44B2-BF9D-4280B295B366}"
+EndProject
+Project("{43A1942F-306D-4937-8907-B9888A5449CF}") = "CMSMicroservice.Application", "CMSMicroservice.Application\CMSMicroservice.Application.csproj", "{5A05B9B0-D6BB-46EB-BE8C-EEAB6F0EAC55}"
+EndProject
+Project("{43A1942F-306D-4937-8907-B9888A5449CF}") = "CMSMicroservice.Infrastructure", "CMSMicroservice.Infrastructure\CMSMicroservice.Infrastructure.csproj", "{A583B3B2-EAFB-45B7-BAA3-C17662714713}"
+EndProject
+Project("{43A1942F-306D-4937-8907-B9888A5449CF}") = "CMSMicroservice.WebApi", "CMSMicroservice.WebApi\CMSMicroservice.WebApi.csproj", "{0A56701B-A4EA-441F-A5A6-7EDD89572F9D}"
+EndProject
+Project("{43A1942F-306D-4937-8907-B9888A5449CF}") = "CMSMicroservice.Protobuf", "CMSMicroservice.Protobuf\CMSMicroservice.Protobuf.csproj", "{AC4961A7-941F-4E42-9208-B48CB352361C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {426E097F-8C77-44B2-BF9D-4280B295B366}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {426E097F-8C77-44B2-BF9D-4280B295B366}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {426E097F-8C77-44B2-BF9D-4280B295B366}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {426E097F-8C77-44B2-BF9D-4280B295B366}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5A05B9B0-D6BB-46EB-BE8C-EEAB6F0EAC55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5A05B9B0-D6BB-46EB-BE8C-EEAB6F0EAC55}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5A05B9B0-D6BB-46EB-BE8C-EEAB6F0EAC55}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5A05B9B0-D6BB-46EB-BE8C-EEAB6F0EAC55}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A583B3B2-EAFB-45B7-BAA3-C17662714713}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A583B3B2-EAFB-45B7-BAA3-C17662714713}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A583B3B2-EAFB-45B7-BAA3-C17662714713}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A583B3B2-EAFB-45B7-BAA3-C17662714713}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0A56701B-A4EA-441F-A5A6-7EDD89572F9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0A56701B-A4EA-441F-A5A6-7EDD89572F9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0A56701B-A4EA-441F-A5A6-7EDD89572F9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0A56701B-A4EA-441F-A5A6-7EDD89572F9D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AC4961A7-941F-4E42-9208-B48CB352361C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AC4961A7-941F-4E42-9208-B48CB352361C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AC4961A7-941F-4E42-9208-B48CB352361C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AC4961A7-941F-4E42-9208-B48CB352361C}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/CMSMicroservice.Application/CMSMicroservice.Application.csproj b/src/CMSMicroservice.Application/CMSMicroservice.Application.csproj
new file mode 100644
index 0000000..f292b0e
--- /dev/null
+++ b/src/CMSMicroservice.Application/CMSMicroservice.Application.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net7.0
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CMSMicroservice.Application/Common/Behaviours/LoggingBehaviour.cs b/src/CMSMicroservice.Application/Common/Behaviours/LoggingBehaviour.cs
new file mode 100644
index 0000000..951bc51
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Behaviours/LoggingBehaviour.cs
@@ -0,0 +1,24 @@
+using MediatR.Pipeline;
+using Microsoft.Extensions.Logging;
+
+namespace CMSMicroservice.Application.Common.Behaviours;
+
+public class LoggingBehaviour : IRequestPreProcessor where TRequest : notnull
+{
+ private readonly ILogger _logger;
+ private readonly ICurrentUserService _currentUserService;
+
+ public LoggingBehaviour(ILogger logger, ICurrentUserService currentUserService)
+ {
+ _logger = logger;
+ _currentUserService = currentUserService;
+ }
+
+ public async Task Process(TRequest request, CancellationToken cancellationToken)
+ {
+ var requestName = typeof(TRequest).Name;
+ var userId = _currentUserService.UserId ?? string.Empty;
+ _logger.LogInformation("Request: {Name} {@UserId} {@Request}",
+ requestName, userId, request);
+ }
+}
diff --git a/src/CMSMicroservice.Application/Common/Behaviours/PerformanceBehaviour.cs b/src/CMSMicroservice.Application/Common/Behaviours/PerformanceBehaviour.cs
new file mode 100644
index 0000000..45cd4e9
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Behaviours/PerformanceBehaviour.cs
@@ -0,0 +1,43 @@
+using System.Diagnostics;
+using MediatR;
+using Microsoft.Extensions.Logging;
+
+namespace CMSMicroservice.Application.Common.Behaviours;
+
+public class PerformanceBehaviour : IPipelineBehavior
+ where TRequest : IRequest
+{
+ private readonly Stopwatch _timer;
+ private readonly ILogger _logger;
+ private readonly ICurrentUserService _currentUserService;
+
+ public PerformanceBehaviour(ILogger logger, ICurrentUserService currentUserService)
+ {
+ _timer = new Stopwatch();
+ _logger = logger;
+ _currentUserService = currentUserService;
+ }
+
+ public async Task Handle(TRequest request, RequestHandlerDelegate next,
+ CancellationToken cancellationToken)
+ {
+ _timer.Start();
+
+ var response = await next();
+
+ _timer.Stop();
+
+ var elapsedMilliseconds = _timer.ElapsedMilliseconds;
+
+ if (elapsedMilliseconds > 500)
+ {
+ var requestName = typeof(TRequest).Name;
+ var userId = _currentUserService.UserId ?? string.Empty;
+
+ _logger.LogWarning("Long Running Request: {Name} ({ElapsedMilliseconds} milliseconds) {@UserId} {@Request}",
+ requestName, elapsedMilliseconds, userId, request);
+ }
+
+ return response;
+ }
+}
diff --git a/src/CMSMicroservice.Application/Common/Behaviours/UnhandledExceptionBehaviour.cs b/src/CMSMicroservice.Application/Common/Behaviours/UnhandledExceptionBehaviour.cs
new file mode 100644
index 0000000..12648ad
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Behaviours/UnhandledExceptionBehaviour.cs
@@ -0,0 +1,31 @@
+using Microsoft.Extensions.Logging;
+
+namespace CMSMicroservice.Application.Common.Behaviours;
+
+public class UnhandledExceptionBehaviour : IPipelineBehavior
+ where TRequest : IRequest
+{
+ private readonly ILogger _logger;
+
+ public UnhandledExceptionBehaviour(ILogger logger)
+ {
+ _logger = logger;
+ }
+
+ public async Task Handle(TRequest request, RequestHandlerDelegate next,
+ CancellationToken cancellationToken)
+ {
+ try
+ {
+ return await next();
+ }
+ catch (Exception ex)
+ {
+ var requestName = typeof(TRequest).Name;
+
+ _logger.LogError(ex, "Request: Unhandled Exception for Request {Name} {@Request}", requestName, request);
+
+ throw;
+ }
+ }
+}
diff --git a/src/CMSMicroservice.Application/Common/Behaviours/ValidationBehaviour.cs b/src/CMSMicroservice.Application/Common/Behaviours/ValidationBehaviour.cs
new file mode 100644
index 0000000..a13c783
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Behaviours/ValidationBehaviour.cs
@@ -0,0 +1,37 @@
+using ValidationException = CMSMicroservice.Application.Common.Exceptions.ValidationException;
+
+namespace CMSMicroservice.Application.Common.Behaviours;
+
+public class ValidationBehaviour : IPipelineBehavior
+ where TRequest : IRequest
+{
+ private readonly IEnumerable> _validators;
+
+ public ValidationBehaviour(IEnumerable> validators)
+ {
+ _validators = validators;
+ }
+
+ public async Task Handle(TRequest request, RequestHandlerDelegate next,
+ CancellationToken cancellationToken)
+ {
+ if (_validators.Any())
+ {
+ var context = new ValidationContext(request);
+
+ var validationResults = await Task.WhenAll(
+ _validators.Select(v =>
+ v.ValidateAsync(context, cancellationToken)));
+
+ var failures = validationResults
+ .Where(r => r.Errors.Any())
+ .SelectMany(r => r.Errors)
+ .ToList();
+
+ if (failures.Any())
+ throw new ValidationException(failures);
+ }
+
+ return await next();
+ }
+}
diff --git a/src/CMSMicroservice.Application/Common/Exceptions/DuplicateException.cs b/src/CMSMicroservice.Application/Common/Exceptions/DuplicateException.cs
new file mode 100644
index 0000000..5ccf2a1
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Exceptions/DuplicateException.cs
@@ -0,0 +1,29 @@
+namespace CMSMicroservice.Application.Common.Exceptions;
+
+public class DuplicateException : Exception
+{
+ public DuplicateException()
+ : base()
+ {
+ }
+
+ public DuplicateException(string message)
+ : base(message)
+ {
+ }
+
+ public DuplicateException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+
+ public DuplicateException(string name, object key)
+ : base($"Entity \"{name}\" ({key}) already exists.")
+ {
+ }
+
+ public DuplicateException(string name, string field, object? key)
+ : base($"Entity \"{name}\" field \"{field}\" ({key}) already exists.")
+ {
+ }
+}
diff --git a/src/CMSMicroservice.Application/Common/Exceptions/ForbiddenAccessException.cs b/src/CMSMicroservice.Application/Common/Exceptions/ForbiddenAccessException.cs
new file mode 100644
index 0000000..5809be8
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Exceptions/ForbiddenAccessException.cs
@@ -0,0 +1,8 @@
+namespace CMSMicroservice.Application.Common.Exceptions;
+
+public class ForbiddenAccessException : Exception
+{
+ public ForbiddenAccessException() : base()
+ {
+ }
+}
diff --git a/src/CMSMicroservice.Application/Common/Exceptions/NotFoundException.cs b/src/CMSMicroservice.Application/Common/Exceptions/NotFoundException.cs
new file mode 100644
index 0000000..a92a29f
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Exceptions/NotFoundException.cs
@@ -0,0 +1,24 @@
+namespace CMSMicroservice.Application.Common.Exceptions;
+
+public class NotFoundException : Exception
+{
+ public NotFoundException()
+ : base()
+ {
+ }
+
+ public NotFoundException(string message)
+ : base(message)
+ {
+ }
+
+ public NotFoundException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+
+ public NotFoundException(string name, object key)
+ : base($"Entity \"{name}\" ({key}) was not found.")
+ {
+ }
+}
diff --git a/src/CMSMicroservice.Application/Common/Exceptions/ValidationException.cs b/src/CMSMicroservice.Application/Common/Exceptions/ValidationException.cs
new file mode 100644
index 0000000..77d2d7d
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Exceptions/ValidationException.cs
@@ -0,0 +1,22 @@
+using FluentValidation.Results;
+
+namespace CMSMicroservice.Application.Common.Exceptions;
+
+public class ValidationException : Exception
+{
+ public ValidationException()
+ : base("One or more validation failures have occurred.")
+ {
+ Errors = new Dictionary();
+ }
+
+ public ValidationException(IEnumerable failures)
+ : this()
+ {
+ Errors = failures
+ .GroupBy(e => e.PropertyName, e => e.ErrorMessage)
+ .ToDictionary(failureGroup => failureGroup.Key, failureGroup => failureGroup.ToArray());
+ }
+
+ public IDictionary Errors { get; }
+}
diff --git a/src/CMSMicroservice.Application/Common/Extensions/MetaDataExtensions.cs b/src/CMSMicroservice.Application/Common/Extensions/MetaDataExtensions.cs
new file mode 100644
index 0000000..3c8ce88
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Extensions/MetaDataExtensions.cs
@@ -0,0 +1,30 @@
+namespace CMSMicroservice.Application.Common.Extensions;
+
+public static class MetaDataExtensions
+{
+ public static async Task GetMetaData(this IQueryable source, PaginationState? paginationState,
+ CancellationToken cancellationToken)
+ {
+ if (paginationState is null)
+ return new MetaData
+ {
+ TotalCount = await source.CountAsync(cancellationToken)
+ };
+
+ var pageSize = paginationState.PageSize > 0 ? paginationState.PageSize : PaginationDefaults.PageSize;
+ var pageNumber = paginationState.PageNumber > 0 ? paginationState.PageNumber : PaginationDefaults.PageNumber;
+ var totalCount = await source.CountAsync(cancellationToken);
+ var totalPageCount = (int)Math.Ceiling(totalCount / (double)pageSize);
+
+ var metaData = new MetaData
+ {
+ CurrentPage = pageNumber,
+ HasNext = pageNumber < totalPageCount,
+ HasPrevious = pageNumber > 1,
+ PageSize = pageSize,
+ TotalCount = totalCount,
+ TotalPage = totalPageCount
+ };
+ return metaData;
+ }
+}
diff --git a/src/CMSMicroservice.Application/Common/Extensions/PaginationStateExtensions.cs b/src/CMSMicroservice.Application/Common/Extensions/PaginationStateExtensions.cs
new file mode 100644
index 0000000..794a3d0
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Extensions/PaginationStateExtensions.cs
@@ -0,0 +1,25 @@
+namespace CMSMicroservice.Application.Common.Extensions;
+
+public static class PaginationStateExtensions
+{
+ public static IQueryable PaginatedListAsync(this IQueryable source,
+ PaginationState? paginationState)
+ {
+ if (paginationState is null)
+ return source;
+
+ var pageSize = paginationState.PageSize > 0 ? paginationState.PageSize : PaginationDefaults.PageSize;
+ var pageNumber = paginationState.PageNumber > 0 ? paginationState.PageNumber : PaginationDefaults.PageNumber;
+ var paginationSkip = pageSize * (pageNumber - 1);
+
+ return source.Skip(paginationSkip).Take(pageSize);
+ }
+}
+
+public static class PaginationDefaults
+{
+ public const int PageSize = 10;
+ public const int PageNumber = 1;
+ public const int Skip = 0;
+ public const int Take = PageSize;
+}
diff --git a/src/CMSMicroservice.Application/Common/Extensions/SortByExtensions.cs b/src/CMSMicroservice.Application/Common/Extensions/SortByExtensions.cs
new file mode 100644
index 0000000..3f0d9c8
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Extensions/SortByExtensions.cs
@@ -0,0 +1,23 @@
+using System.Linq.Dynamic.Core;
+using CMSMicroservice.Domain.Common;
+
+namespace CMSMicroservice.Application.Common.Extensions;
+
+public static class SortByExtensions
+{
+ public static IQueryable ApplyOrder(this IQueryable source,
+ string? sortBy) where TSource : BaseAuditableEntity
+ {
+ // default sort approach
+ if (sortBy is null or "")
+ {
+ source = source.OrderByDescending(p => p.Created);
+ return source;
+ }
+
+ // sort using dynamic linq
+ source = source.OrderBy(sortBy);
+
+ return source;
+ }
+}
diff --git a/src/CMSMicroservice.Application/Common/Interfaces/IApplicationDbContext.cs b/src/CMSMicroservice.Application/Common/Interfaces/IApplicationDbContext.cs
new file mode 100644
index 0000000..3d0f94a
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Interfaces/IApplicationDbContext.cs
@@ -0,0 +1,12 @@
+namespace CMSMicroservice.Application.Common.Interfaces;
+
+public interface IApplicationDbContext
+{
+ DbSet Users { get; }
+ DbSet UserAddresss { get; }
+ DbSet Packages { get; }
+ DbSet UserOrders { get; }
+ DbSet Roles { get; }
+ DbSet UserRoles { get; }
+ Task SaveChangesAsync(CancellationToken cancellationToken = default);
+}
\ No newline at end of file
diff --git a/src/CMSMicroservice.Application/Common/Interfaces/ICurrentUserService.cs b/src/CMSMicroservice.Application/Common/Interfaces/ICurrentUserService.cs
new file mode 100644
index 0000000..c8f2752
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Interfaces/ICurrentUserService.cs
@@ -0,0 +1,6 @@
+namespace CMSMicroservice.Application.Common.Interfaces;
+
+public interface ICurrentUserService
+{
+ string? UserId { get; }
+}
diff --git a/src/CMSMicroservice.Application/Common/Mappings/PackageProfile.cs b/src/CMSMicroservice.Application/Common/Mappings/PackageProfile.cs
new file mode 100644
index 0000000..0f077cb
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Mappings/PackageProfile.cs
@@ -0,0 +1,10 @@
+namespace CMSMicroservice.Application.Common.Mappings;
+
+public class PackageProfile : IRegister
+{
+ void IRegister.Register(TypeAdapterConfig config)
+ {
+ //config.NewConfig()
+ // .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
+ }
+}
diff --git a/src/CMSMicroservice.Application/Common/Mappings/RoleProfile.cs b/src/CMSMicroservice.Application/Common/Mappings/RoleProfile.cs
new file mode 100644
index 0000000..a061f62
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Mappings/RoleProfile.cs
@@ -0,0 +1,10 @@
+namespace CMSMicroservice.Application.Common.Mappings;
+
+public class RoleProfile : IRegister
+{
+ void IRegister.Register(TypeAdapterConfig config)
+ {
+ //config.NewConfig()
+ // .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
+ }
+}
diff --git a/src/CMSMicroservice.Application/Common/Mappings/UserAddressProfile.cs b/src/CMSMicroservice.Application/Common/Mappings/UserAddressProfile.cs
new file mode 100644
index 0000000..4347c46
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Mappings/UserAddressProfile.cs
@@ -0,0 +1,10 @@
+namespace CMSMicroservice.Application.Common.Mappings;
+
+public class UserAddressProfile : IRegister
+{
+ void IRegister.Register(TypeAdapterConfig config)
+ {
+ //config.NewConfig()
+ // .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
+ }
+}
diff --git a/src/CMSMicroservice.Application/Common/Mappings/UserOrderProfile.cs b/src/CMSMicroservice.Application/Common/Mappings/UserOrderProfile.cs
new file mode 100644
index 0000000..f9d2e63
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Mappings/UserOrderProfile.cs
@@ -0,0 +1,10 @@
+namespace CMSMicroservice.Application.Common.Mappings;
+
+public class UserOrderProfile : IRegister
+{
+ void IRegister.Register(TypeAdapterConfig config)
+ {
+ //config.NewConfig()
+ // .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
+ }
+}
diff --git a/src/CMSMicroservice.Application/Common/Mappings/UserProfile.cs b/src/CMSMicroservice.Application/Common/Mappings/UserProfile.cs
new file mode 100644
index 0000000..12f9563
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Mappings/UserProfile.cs
@@ -0,0 +1,10 @@
+namespace CMSMicroservice.Application.Common.Mappings;
+
+public class UserProfile : IRegister
+{
+ void IRegister.Register(TypeAdapterConfig config)
+ {
+ //config.NewConfig()
+ // .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
+ }
+}
diff --git a/src/CMSMicroservice.Application/Common/Mappings/UserRoleProfile.cs b/src/CMSMicroservice.Application/Common/Mappings/UserRoleProfile.cs
new file mode 100644
index 0000000..59b221d
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Mappings/UserRoleProfile.cs
@@ -0,0 +1,10 @@
+namespace CMSMicroservice.Application.Common.Mappings;
+
+public class UserRoleProfile : IRegister
+{
+ void IRegister.Register(TypeAdapterConfig config)
+ {
+ //config.NewConfig()
+ // .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
+ }
+}
diff --git a/src/CMSMicroservice.Application/Common/Models/MetaData.cs b/src/CMSMicroservice.Application/Common/Models/MetaData.cs
new file mode 100644
index 0000000..ce1184c
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Models/MetaData.cs
@@ -0,0 +1,22 @@
+namespace CMSMicroservice.Application.Common.Models;
+
+public class MetaData
+{
+ //صفحه جاری
+ public long CurrentPage { get; set; }
+
+ //تعداد کل صفحات
+ public long TotalPage { get; set; }
+
+ //تعداد در هر صفحه
+ public long PageSize { get; set; }
+
+ //تعداد کل آیتمها
+ public long TotalCount { get; set; }
+
+ //قبلی دارد؟
+ public bool HasPrevious { get; set; }
+
+ //بعدی دارد؟
+ public bool HasNext { get; set; }
+}
diff --git a/src/CMSMicroservice.Application/Common/Models/PaginationState.cs b/src/CMSMicroservice.Application/Common/Models/PaginationState.cs
new file mode 100644
index 0000000..3985c71
--- /dev/null
+++ b/src/CMSMicroservice.Application/Common/Models/PaginationState.cs
@@ -0,0 +1,10 @@
+namespace CMSMicroservice.Application.Common.Models;
+
+public class PaginationState
+{
+ //شماره صفحه
+ public int PageNumber { get; set; }
+
+ //اندازه صفحه
+ public int PageSize { get; set; }
+}
diff --git a/src/CMSMicroservice.Application/ConfigureServices.cs b/src/CMSMicroservice.Application/ConfigureServices.cs
new file mode 100644
index 0000000..2e33de9
--- /dev/null
+++ b/src/CMSMicroservice.Application/ConfigureServices.cs
@@ -0,0 +1,31 @@
+using System.Reflection;
+using CMSMicroservice.Application.Common.Behaviours;
+using MapsterMapper;
+
+namespace Microsoft.Extensions.DependencyInjection;
+
+public static class ConfigureServices
+{
+ public static IServiceCollection AddApplicationServices(this IServiceCollection services)
+ {
+ services.AddMapping();
+ services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());
+ services.AddMediatR(AppDomain.CurrentDomain.GetAssemblies());
+ services.AddTransient(typeof(IPipelineBehavior<,>), typeof(UnhandledExceptionBehaviour<,>));
+ services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehaviour<,>));
+ services.AddTransient(typeof(IPipelineBehavior<,>), typeof(PerformanceBehaviour<,>));
+
+ return services;
+ }
+
+ private static IServiceCollection AddMapping(this IServiceCollection services)
+ {
+ var typeAdapterConfig = TypeAdapterConfig.GlobalSettings;
+ // scans the assembly and gets the IRegister, adding the registration to the TypeAdapterConfig
+ typeAdapterConfig.Scan(Assembly.GetExecutingAssembly());
+ // register the mapper as Singleton service for my application
+ var mapperConfig = new Mapper(typeAdapterConfig);
+ services.AddSingleton(mapperConfig);
+ return services;
+ }
+}
diff --git a/src/CMSMicroservice.Application/GlobalUsings.cs b/src/CMSMicroservice.Application/GlobalUsings.cs
new file mode 100644
index 0000000..da6b801
--- /dev/null
+++ b/src/CMSMicroservice.Application/GlobalUsings.cs
@@ -0,0 +1,15 @@
+global using MediatR;
+global using FluentValidation;
+global using Mapster;
+
+global using CMSMicroservice.Domain.Entities;
+global using CMSMicroservice.Application.Common.Interfaces;
+global using System.Threading;
+global using System.Threading.Tasks;
+global using System;
+global using System.Collections.Generic;
+global using System.Linq;
+global using Microsoft.EntityFrameworkCore;
+global using CMSMicroservice.Application.Common.Exceptions;
+global using CMSMicroservice.Application.Common.Extensions;
+global using CMSMicroservice.Application.Common.Models;
diff --git a/src/CMSMicroservice.Application/PackageCQ/Commands/CreateNewPackage/CreateNewPackageCommand.cs b/src/CMSMicroservice.Application/PackageCQ/Commands/CreateNewPackage/CreateNewPackageCommand.cs
new file mode 100644
index 0000000..5d8b6e6
--- /dev/null
+++ b/src/CMSMicroservice.Application/PackageCQ/Commands/CreateNewPackage/CreateNewPackageCommand.cs
@@ -0,0 +1,13 @@
+namespace CMSMicroservice.Application.PackageCQ.Commands.CreateNewPackage;
+public record CreateNewPackageCommand : IRequest
+{
+ //عنوان
+ public string Title { get; init; }
+ //توضیحات
+ public string Description { get; init; }
+ //آدرس تصویر
+ public string ImagePath { get; init; }
+ //قیمت
+ public long Price { get; init; }
+
+}
\ No newline at end of file
diff --git a/src/CMSMicroservice.Application/PackageCQ/Commands/CreateNewPackage/CreateNewPackageCommandHandler.cs b/src/CMSMicroservice.Application/PackageCQ/Commands/CreateNewPackage/CreateNewPackageCommandHandler.cs
new file mode 100644
index 0000000..6ac4da7
--- /dev/null
+++ b/src/CMSMicroservice.Application/PackageCQ/Commands/CreateNewPackage/CreateNewPackageCommandHandler.cs
@@ -0,0 +1,21 @@
+using CMSMicroservice.Domain.Events;
+namespace CMSMicroservice.Application.PackageCQ.Commands.CreateNewPackage;
+public class CreateNewPackageCommandHandler : IRequestHandler
+{
+ private readonly IApplicationDbContext _context;
+
+ public CreateNewPackageCommandHandler(IApplicationDbContext context)
+ {
+ _context = context;
+ }
+
+ public async Task Handle(CreateNewPackageCommand request,
+ CancellationToken cancellationToken)
+ {
+ var entity = request.Adapt();
+ await _context.Packages.AddAsync(entity, cancellationToken);
+ entity.AddDomainEvent(new CreateNewPackageEvent(entity));
+ await _context.SaveChangesAsync(cancellationToken);
+ return entity.Adapt();
+ }
+}
diff --git a/src/CMSMicroservice.Application/PackageCQ/Commands/CreateNewPackage/CreateNewPackageCommandValidator.cs b/src/CMSMicroservice.Application/PackageCQ/Commands/CreateNewPackage/CreateNewPackageCommandValidator.cs
new file mode 100644
index 0000000..c2fb657
--- /dev/null
+++ b/src/CMSMicroservice.Application/PackageCQ/Commands/CreateNewPackage/CreateNewPackageCommandValidator.cs
@@ -0,0 +1,22 @@
+namespace CMSMicroservice.Application.PackageCQ.Commands.CreateNewPackage;
+public class CreateNewPackageCommandValidator : AbstractValidator
+{
+ public CreateNewPackageCommandValidator()
+ {
+ RuleFor(model => model.Title)
+ .NotEmpty();
+ RuleFor(model => model.Description)
+ .NotEmpty();
+ RuleFor(model => model.ImagePath)
+ .NotEmpty();
+ RuleFor(model => model.Price)
+ .NotNull();
+ }
+ public Func