Browse Source

Initial Project creation

pull/79/head
Galip Tolga Erdem 5 years ago
parent
commit
ec2345c6f4
  1. 7
      services/basket/EShopOnAbp.BasketService.sln
  2. 14
      services/basket/src/EShopOnAbp.BasketService/BasketServiceAutoMapperProfile.cs
  3. 184
      services/basket/src/EShopOnAbp.BasketService/BasketServiceModule.cs
  4. 12
      services/basket/src/EShopOnAbp.BasketService/Controllers/HomeController.cs
  5. 67
      services/basket/src/EShopOnAbp.BasketService/EShopOnAbp.BasketService.csproj
  6. 77
      services/basket/src/EShopOnAbp.BasketService/Entities/Basket.cs
  7. 18
      services/basket/src/EShopOnAbp.BasketService/Entities/BasketItem.cs
  8. 7
      services/basket/src/EShopOnAbp.BasketService/Entities/BasketProductUpdatedEto.cs
  9. 23
      services/basket/src/EShopOnAbp.BasketService/Entities/BasketRepository.cs
  10. 10
      services/basket/src/EShopOnAbp.BasketService/Entities/IBasketRepository.cs
  11. 25
      services/basket/src/EShopOnAbp.BasketService/Entities/Orders/OrderPlacedEventHandler.cs
  12. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/ar.json
  13. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/cs.json
  14. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/de-DE.json
  15. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/en-GB.json
  16. 12
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/en.json
  17. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/es.json
  18. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/fi.json
  19. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/fr.json
  20. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/hi.json
  21. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/hu.json
  22. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/it.json
  23. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/nl.json
  24. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/pl-PL.json
  25. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/pt-BR.json
  26. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/ro-RO.json
  27. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/ru.json
  28. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/sk.json
  29. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/sl.json
  30. 12
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/tr.json
  31. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/vi.json
  32. 10
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/zh-Hans.json
  33. 8
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/zh-Hant.json
  34. 10
      services/basket/src/EShopOnAbp.BasketService/Localization/BasketServiceResource.cs
  35. 6
      services/basket/src/EShopOnAbp.BasketService/Program.cs
  36. 28
      services/basket/src/EShopOnAbp.BasketService/Properties/launchSettings.json
  37. 124
      services/basket/src/EShopOnAbp.BasketService/Services/BasketAppService.cs
  38. 46
      services/basket/src/EShopOnAbp.BasketService/Services/BasketProductEventHandler.cs
  39. 46
      services/basket/src/EShopOnAbp.BasketService/Services/BasketProductService.cs
  40. 13
      services/basket/src/EShopOnAbp.BasketService/Services/Dtos/AddProductDto.cs
  41. 12
      services/basket/src/EShopOnAbp.BasketService/Services/Dtos/BasketDto.cs
  42. 11
      services/basket/src/EShopOnAbp.BasketService/Services/Dtos/BasketItemDto.cs
  43. 7
      services/basket/src/EShopOnAbp.BasketService/Services/Dtos/IHasAnonymousId.cs
  44. 10
      services/basket/src/EShopOnAbp.BasketService/Services/Dtos/RemoveProductDto.cs
  45. 11
      services/basket/src/EShopOnAbp.BasketService/Services/IBasketAppService.cs
  46. 12
      services/basket/src/EShopOnAbp.BasketService/Services/IBasketProductService.cs
  47. 21
      services/basket/src/EShopOnAbp.BasketService/Services/Permissions/BasketServicePermissionDefinitionProvider.cs
  48. 10
      services/basket/src/EShopOnAbp.BasketService/Services/Permissions/BasketServicePermissions.cs
  49. 8
      services/basket/src/EShopOnAbp.BasketService/appsettings.Development.json
  50. 49
      services/basket/src/EShopOnAbp.BasketService/appsettings.json

7
services/basket/EShopOnAbp.BasketService.sln

@ -31,6 +31,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EShopOnAbp.BasketService.Ht
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EShopOnAbp.BasketService.HttpApi.Host", "src\EShopOnAbp.BasketService.HttpApi.Host\EShopOnAbp.BasketService.HttpApi.Host.csproj", "{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EShopOnAbp.BasketService", "src\EShopOnAbp.BasketService\EShopOnAbp.BasketService.csproj", "{83F0BE02-6B71-4695-B86F-18DEEE34B485}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -85,6 +87,10 @@ Global
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D}.Release|Any CPU.Build.0 = Release|Any CPU
{83F0BE02-6B71-4695-B86F-18DEEE34B485}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{83F0BE02-6B71-4695-B86F-18DEEE34B485}.Debug|Any CPU.Build.0 = Debug|Any CPU
{83F0BE02-6B71-4695-B86F-18DEEE34B485}.Release|Any CPU.ActiveCfg = Release|Any CPU
{83F0BE02-6B71-4695-B86F-18DEEE34B485}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -102,6 +108,7 @@ Global
{E512F4D9-9375-480F-A2F6-A46509F9D824} = {04DBDB01-70F4-4E06-B468-8F87850B22BE}
{EF480016-9127-4916-8735-D2466BDBC582} = {04DBDB01-70F4-4E06-B468-8F87850B22BE}
{748584B1-BA69-4F6A-81AA-F4BDE6BCE29D} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
{83F0BE02-6B71-4695-B86F-18DEEE34B485} = {CA9AC87F-097E-4F15-8393-4BC07735A5B0}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6AAFA1C6-603E-13FA-45E5-7910AA9F661D}

14
services/basket/src/EShopOnAbp.BasketService/BasketServiceAutoMapperProfile.cs

@ -0,0 +1,14 @@
using AutoMapper;
using EShopOnAbp.CatalogService.Grpc;
using EShopOnAbp.CatalogService.Products;
namespace EShopOnAbp.BasketService;
public class BasketServiceApplicationAutoMapperProfile : Profile
{
public BasketServiceApplicationAutoMapperProfile()
{
CreateMap<ProductEto, ProductDto>();
CreateMap<ProductResponse, ProductDto>();
}
}

184
services/basket/src/EShopOnAbp.BasketService/BasketServiceModule.cs

@ -0,0 +1,184 @@
using EShopOnAbp.BasketService.Entities;
using EShopOnAbp.BasketService.Localization;
using EShopOnAbp.CatalogService.Grpc;
using EShopOnAbp.Shared.Hosting.AspNetCore;
using EShopOnAbp.Shared.Hosting.Microservices;
using Microsoft.AspNetCore.Cors;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Options;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc.AntiForgery;
using Volo.Abp.AutoMapper;
using Volo.Abp.Caching;
using Volo.Abp.Http.Client;
using Volo.Abp.Localization;
using Volo.Abp.Localization.ExceptionHandling;
using Volo.Abp.Modularity;
using Volo.Abp.Validation.Localization;
using Volo.Abp.VirtualFileSystem;
namespace EShopOnAbp.BasketService
{
[DependsOn(
)]
public class BasketServiceModule : AbpModule
{
public const string RemoteServiceName = "Basket";
public override void ConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
var configuration = context.Services.GetConfiguration();
ConfigureAutoMapper();
ConfigureGrpc(context);
ConfigureDistributedCache();
ConfigureVirtualFileSystem();
ConfigureLocalization();
ConfigureHttpApiProxy(context);
ConfigureAuthentication(context, configuration);
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCorrelationId();
app.UseCors();
app.UseAbpRequestLocalization();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAbpClaimsMap();
app.UseAuthorization();
app.UseSwagger();
app.UseSwaggerUI(options =>
{
var configuration = context.ServiceProvider.GetRequiredService<IConfiguration>();
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Basket Service API");
options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]);
});
app.UseAbpSerilogEnrichers();
app.UseAuditing();
app.UseUnitOfWork();
app.UseConfiguredEndpoints();
}
private void ConfigureAuthentication(ServiceConfigurationContext context, IConfiguration configuration)
{
JwtBearerConfigurationHelper.Configure(context, "BasketService");
SwaggerWithAuthConfigurationHelper.Configure(
context: context,
authority: configuration["AuthServer:Authority"],
scopes: new
Dictionary<string, string> /* Requested scopes for authorization code request and descriptions for swagger UI only */
{
{"BasketService", "Basket Service API"}
},
apiTitle: "Basket Service API"
);
context.Services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder
.WithOrigins(
configuration["App:CorsOrigins"]
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.Trim().RemovePostFix("/"))
.ToArray()
)
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
Configure<AbpAntiForgeryOptions>(options => { options.AutoValidate = false; });
}
private void ConfigureHttpApiProxy(ServiceConfigurationContext context)
{
context.Services.AddStaticHttpClientProxies(
typeof(BasketServiceApplicationContractsModule).Assembly,
RemoteServiceName
);
}
private void ConfigureGrpc(ServiceConfigurationContext context)
{
context.Services.AddGrpcClient<ProductPublic.ProductPublicClient>((services, options) =>
{
var remoteServiceOptions = services.GetRequiredService<IOptionsMonitor<AbpRemoteServiceOptions>>().CurrentValue;
var catalogServiceConfiguration = remoteServiceOptions.RemoteServices.GetConfigurationOrDefault("Catalog");
var catalogGrpcUrl = catalogServiceConfiguration.GetOrDefault("GrpcUrl");
options.Address = new Uri(catalogGrpcUrl);
});
}
private void ConfigureAutoMapper()
{
Configure<AbpAutoMapperOptions>(options =>
{
options.AddMaps<BasketServiceApplicationModule>();
});
}
private void ConfigureDistributedCache()
{
Configure<AbpDistributedCacheOptions>(options =>
{
options.CacheConfigurators.Add(cacheName =>
{
if (cacheName == CacheNameAttribute.GetCacheName(typeof(Basket)))
{
return new DistributedCacheEntryOptions
{
SlidingExpiration = TimeSpan.FromDays(7)
};
}
return null;
});
});
}
private void ConfigureVirtualFileSystem()
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<BasketServiceModule>();
});
}
private void ConfigureLocalization()
{
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<BasketServiceResource>("en")
.AddBaseTypes(typeof(AbpValidationResource))
.AddVirtualJson("/Localization/BasketService");
options.DefaultResourceType = typeof(BasketServiceResource);
});
Configure<AbpExceptionLocalizationOptions>(options =>
{
options.MapCodeNamespace("BasketService", typeof(BasketServiceResource));
});
}
}
}

12
services/basket/src/EShopOnAbp.BasketService/Controllers/HomeController.cs

@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
namespace EShopOnAbp.BasketService.Controllers;
public class HomeController : AbpController
{
public ActionResult Index()
{
return Redirect("~/swagger");
}
}

67
services/basket/src/EShopOnAbp.BasketService/EShopOnAbp.BasketService.csproj

@ -0,0 +1,67 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<!-- DOMAIN SHARED -->
<ItemGroup>
<PackageReference Include="Volo.Abp.Validation" Version="5.1.2" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="6.0.0" />
<ProjectReference Include="..\..\..\ordering\src\EShopOnAbp.OrderingService.Domain.Shared\EShopOnAbp.OrderingService.Domain.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Localization\BasketService\*.json" />
<Content Remove="Localization\BasketService\*.json" />
</ItemGroup>
<!-- DOMAIN -->
<ItemGroup>
<ProjectReference Include="..\EShopOnAbp.BasketService.Domain.Shared\EShopOnAbp.BasketService.Domain.Shared.csproj" />
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="5.1.2" />
<PackageReference Include="Volo.Abp.Caching" Version="5.1.2" />
</ItemGroup>
<!-- APPLICATION CONTRACTS -->
<ItemGroup>
<ProjectReference Include="..\EShopOnAbp.BasketService.Domain.Shared\EShopOnAbp.BasketService.Domain.Shared.csproj" />
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" Version="5.1.2" />
<PackageReference Include="Volo.Abp.Authorization" Version="5.1.2" />
</ItemGroup>
<!-- APPLICATION -->
<ItemGroup>
<PackageReference Include="Volo.Abp.AutoMapper" Version="5.1.2" />
<PackageReference Include="Volo.Abp.Ddd.Application" Version="5.1.2" />
<PackageReference Include="Google.Protobuf" Version="3.19.3" />
<PackageReference Include="Grpc.Net.ClientFactory" Version="2.42.0" />
<PackageReference Include="Grpc.Tools" Version="2.42.0" PrivateAssets="All" />
<Protobuf Include="..\..\..\catalog\src\EShopOnAbp.CatalogService.Application.Contracts\Protos\product.proto" GrpcServices="Client" />
<ProjectReference Include="..\EShopOnAbp.BasketService.Domain\EShopOnAbp.BasketService.Domain.csproj" />
<ProjectReference Include="..\EShopOnAbp.BasketService.Application.Contracts\EShopOnAbp.BasketService.Application.Contracts.csproj" />
<ProjectReference Include="..\..\..\catalog\src\EShopOnAbp.CatalogService.HttpApi.Client\EShopOnAbp.CatalogService.HttpApi.Client.csproj" />
</ItemGroup>
<!-- HTTP API -->
<ItemGroup>
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="5.1.2" />
<ProjectReference Include="..\EShopOnAbp.BasketService.Application.Contracts\EShopOnAbp.BasketService.Application.Contracts.csproj" />
</ItemGroup>
<!-- HTTP API HOST -->
<ItemGroup>
<ProjectReference Include="..\EShopOnAbp.BasketService.Application\EShopOnAbp.BasketService.Application.csproj" />
<ProjectReference Include="..\EShopOnAbp.BasketService.HttpApi\EShopOnAbp.BasketService.HttpApi.csproj" />
<ProjectReference Include="..\..\..\..\shared\EShopOnAbp.Shared.Hosting.Microservices\EShopOnAbp.Shared.Hosting.Microservices.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Logs\**" />
<Content Remove="Logs\**" />
<EmbeddedResource Remove="Logs\**" />
<None Remove="Logs\**" />
</ItemGroup>
</Project>

77
services/basket/src/EShopOnAbp.BasketService/Entities/Basket.cs

@ -0,0 +1,77 @@
using Volo.Abp.Domain.Entities;
namespace EShopOnAbp.BasketService.Entities;
public class Basket : AggregateRoot<Guid>
{
public List<BasketItem> Items { get; set; }
private Basket()
{
}
public Basket(Guid id)
: base(id)
{
Items = new List<BasketItem>();
}
public void AddProduct(Guid productId, int count = 1)
{
if (count < 1)
{
throw new ArgumentOutOfRangeException(nameof(count), "Product count should be 1 or more!");
}
var item = Items.FirstOrDefault(x => x.ProductId == productId);
if (item == null)
{
Items.Add(new BasketItem(productId, count));
}
else
{
item.Count += count;
}
}
public void RemoveProduct(Guid productId, int? count = null)
{
if (count is < 1)
{
throw new ArgumentOutOfRangeException(nameof(count), "Product count should be null, 1 or more!");
}
var item = Items.FirstOrDefault(x => x.ProductId == productId);
if (item == null)
{
return;
}
if (count == null || item.Count <= count)
{
Items.Remove(item);
return;
}
item.Count -= count.Value;
}
public int GetProductCount(Guid productId)
{
var item = Items.FirstOrDefault(x => x.ProductId == productId);
return item?.Count ?? 0;
}
public void Clear()
{
Items.Clear();
}
public void Merge(Basket basket)
{
foreach (var item in basket.Items)
{
AddProduct(item.ProductId, item.Count);
}
}
}

18
services/basket/src/EShopOnAbp.BasketService/Entities/BasketItem.cs

@ -0,0 +1,18 @@
namespace EShopOnAbp.BasketService.Entities;
public class BasketItem
{
public Guid ProductId { get; private set; }
public int Count { get; internal set; }
private BasketItem()
{
}
public BasketItem(Guid productId, int count = 1)
{
ProductId = productId;
Count = count;
}
}

7
services/basket/src/EShopOnAbp.BasketService/Entities/BasketProductUpdatedEto.cs

@ -0,0 +1,7 @@
namespace EShopOnAbp.BasketService.Entities;
public class BasketProductUpdatedEto
{
public Guid ProductId { get; set; }
public string ProductName { get; set; }
}

23
services/basket/src/EShopOnAbp.BasketService/Entities/BasketRepository.cs

@ -0,0 +1,23 @@
using Volo.Abp.Caching;
namespace EShopOnAbp.BasketService.Entities;
public class BasketRepository : IBasketRepository
{
private readonly IDistributedCache<Basket, Guid> _cache;
public BasketRepository(IDistributedCache<Basket, Guid> cache)
{
_cache = cache;
}
public async Task<Basket> GetAsync(Guid id)
{
return await _cache.GetOrAddAsync(id, () => Task.FromResult(new Basket(id)));
}
public async Task UpdateAsync(Basket basket)
{
await _cache.SetAsync(basket.Id, basket);
}
}

10
services/basket/src/EShopOnAbp.BasketService/Entities/IBasketRepository.cs

@ -0,0 +1,10 @@
using Volo.Abp.Domain.Repositories;
namespace EShopOnAbp.BasketService.Entities;
public interface IBasketRepository : IRepository
{
Task<Basket> GetAsync(Guid id);
Task UpdateAsync(Basket basket);
}

25
services/basket/src/EShopOnAbp.BasketService/Entities/Orders/OrderPlacedEventHandler.cs

@ -0,0 +1,25 @@
using EShopOnAbp.OrderingService.Orders;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Uow;
namespace EShopOnAbp.BasketService.Entities.Orders
{
public class OrderPlacedEventHandler : IDistributedEventHandler<OrderPlacedEto>, ITransientDependency
{
private readonly IBasketRepository _basketRepository;
public OrderPlacedEventHandler(IBasketRepository basketRepository)
{
_basketRepository = basketRepository;
}
[UnitOfWork]
public async Task HandleEventAsync(OrderPlacedEto eventData)
{
var basket = await _basketRepository.GetAsync(eventData.Buyer.BuyerId.GetValueOrDefault());
basket.Clear();
await _basketRepository.UpdateAsync(basket);
}
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/ar.json

@ -0,0 +1,8 @@
{
"culture": "ar",
"texts": {
"Menu:Home": "الرئيسية",
"Welcome": "مرحبا",
"LongWelcomeMessage": "مرحبا بكم في التطبيق. هذا مشروع بدء تشغيل يعتمد على إطار عمل ABP. لمزيد من المعلومات ، يرجى زيارة abp.io."
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/cs.json

@ -0,0 +1,8 @@
{
"culture": "cs",
"texts": {
"Menu:Home": "Úvod",
"Welcome": "Vítejte",
"LongWelcomeMessage": "Vítejte v aplikaci. Toto je startovací projekt založený na ABP frameworku. Pro více informací, navštivte abp.io."
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/de-DE.json

@ -0,0 +1,8 @@
{
"culture": "de-DE",
"texts": {
"Menu:Home": "Home",
"Welcome": "Willkommen",
"LongWelcomeMessage": "Willkommen bei der Anwendung. Dies ist ein Startup-Projekt, das auf dem ABP-Framework basiert. Weitere Informationen finden Sie unter abp.io."
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/en-GB.json

@ -0,0 +1,8 @@
{
"culture": "en-GB",
"texts": {
"Menu:Home": "Home",
"Welcome": "Welcome",
"LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io."
}
}

12
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/en.json

@ -0,0 +1,12 @@
{
"culture": "en",
"texts": {
"Menu:Home": "Home",
"Welcome": "Welcome",
"LongWelcomeMessage": "Welcome to the application. This is a startup project based on the ABP framework. For more information, visit abp.io.",
"Toolbar:Cart": "My Cart",
"Toolbar:BasketNotLoaded": "Couldn't Load!",
"Toolbar:CartEmpty": "Cart is Empty!",
"ProductNotFound": "Could not find the product!"
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/es.json

@ -0,0 +1,8 @@
{
"culture": "es",
"texts": {
"Menu:Home": "Inicio",
"Welcome": "Bienvenido",
"LongWelcomeMessage": "Bienvenido a la aplicación, este es un proyecto base basado en el framework ABP. Para más información, visita abp.io."
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/fi.json

@ -0,0 +1,8 @@
{
"culture": "fi",
"texts": {
"Menu:Home": "Koti",
"Welcome": "Tervetuloa",
"LongWelcomeMessage": "Tervetuloa sovellukseen. Tämä on ABP-kehykseen perustuva käynnistysprojekti. Lisätietoja on osoitteessa abp.io."
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/fr.json

@ -0,0 +1,8 @@
{
"culture": "fr",
"texts": {
"Menu:Home": "Accueil",
"Welcome": "Bienvenue",
"LongWelcomeMessage": "Bienvenue dans l'application. Il s'agit d'un projet de démarrage basé sur le framework ABP. Pour plus d'informations, visitez abp.io."
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/hi.json

@ -0,0 +1,8 @@
{
"culture": "hi",
"texts": {
"Menu:Home": "घर",
"Welcome": "स्वागत हे",
"LongWelcomeMessage": "आवेदन करने के लिए आपका स्वागत है। यह एबीपी ढांचे पर आधारित एक स्टार्टअप परियोजना है। अधिक जानकारी के लिए, abp.io पर जाएं।"
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/hu.json

@ -0,0 +1,8 @@
{
"culture": "hu",
"texts": {
"Menu:Home": "Kezdőlap",
"Welcome": "Üdvözlöm",
"LongWelcomeMessage": "Üdvözöljük az alkalmazásban. Ez egy ABP keretrendszeren alapuló startup projekt. További információkért látogasson el az abp.io oldalra."
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/it.json

@ -0,0 +1,8 @@
{
"culture": "it",
"texts": {
"Menu:Home": "Home",
"Welcome": "Benvenuto",
"LongWelcomeMessage": "Benvenuto nell'applicazione. Questo è un progetto di avvio basato sul framework ABP. Per ulteriori informazioni, visita abp.io."
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/nl.json

@ -0,0 +1,8 @@
{
"culture": "nl",
"texts": {
"Menu:Home": "Home",
"Welcome": "Welkom",
"LongWelcomeMessage": "Welkom bij de applicatie. Dit is een startup-project gebaseerd op het ABP-framework. Bezoek abp.io voor meer informatie."
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/pl-PL.json

@ -0,0 +1,8 @@
{
"culture": "pl-PL",
"texts": {
"Menu:Home": "Home",
"Welcome": "Witaj",
"LongWelcomeMessage": "Witaj w aplikacji. To jest inicjalny projekt bazujący na ABP framework. Po więcej informacji odwiedź stronę abp.io."
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/pt-BR.json

@ -0,0 +1,8 @@
{
"culture": "pt-BR",
"texts": {
"Menu:Home": "Principal",
"Welcome": "Seja bem-vindo!",
"LongWelcomeMessage": "Bem-vindo a esta aplicação. Este é um projeto inicial baseado no ABP framework. Para mais informações, visite abp.io."
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/ro-RO.json

@ -0,0 +1,8 @@
{
"culture": "ro-RO",
"texts": {
"Menu:Home": "Acasă",
"Welcome": "Bun venit",
"LongWelcomeMessage": "Bun venit la aplicaţie. Acesta este un proiect de pornire bazat pe framework-ul ABP. Pentru mai multe informaţii, vizitaţi, visit abp.io."
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/ru.json

@ -0,0 +1,8 @@
{
"culture": "ru",
"texts": {
"Menu:Home": "Главная",
"Welcome": "Добро пожаловать",
"LongWelcomeMessage": "Добро пожаловать в приложение. Этот запущенный проект основан на фреймворке ABP. Для получения дополнительной информации посетите сайт abp.io."
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/sk.json

@ -0,0 +1,8 @@
{
"culture": "sk",
"texts": {
"Menu:Home": "Domov",
"Welcome": "Vitajte",
"LongWelcomeMessage": "Vitajte v aplikácii. Toto je štartovací projekt založený na ABP frameworku. Viac informácií nájdete na stránke abp.io."
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/sl.json

@ -0,0 +1,8 @@
{
"culture": "sl",
"texts": {
"Menu:Home": "Domov",
"Welcome": "Dobrodošli",
"LongWelcomeMessage": "Dobrodošli v aplikaciji. To je začetni projekt na osnovi okolja ABP. Za več informacij obiščite abp.io."
}
}

12
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/tr.json

@ -0,0 +1,12 @@
{
"culture": "tr",
"texts": {
"Menu:Home": "Ana sayfa",
"Welcome": "Hoşgeldiniz",
"LongWelcomeMessage": "Uygulamaya hoşgeldiniz. Bu, ABP framework'ü üzerine bina edilmiş bir başlangıç projesidir. Daha fazla bilgi için abp.io adresini ziyaret edebilirsiniz.",
"Toolbar:Cart": "Sepetim",
"Toolbar:BasketNotLoaded": "Sepet Hatası!",
"Toolbar:CartEmpty": "Sepetiniz Boş",
"ProductNotFound": "Bu ürün bulunamadı!"
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/vi.json

@ -0,0 +1,8 @@
{
"culture": "vi",
"texts": {
"Menu:Home": "Trang chủ",
"Welcome": "Chào mừng bạn",
"LongWelcomeMessage": "Chào mừng bạn đến ứng dụng. Đây là một dự án khởi nghiệp dựa trên khung ABP. Để biết thêm thông tin, hãy truy cập abp.io."
}
}

10
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/zh-Hans.json

@ -0,0 +1,10 @@
{
"culture": "zh-Hans",
"texts": {
"Menu:Home": "首页",
"Welcome": "欢迎",
"LongWelcomeMessage": "欢迎来到该应用程序. 这是一个基于ABP框架的启动项目. 有关更多信息, 请访问 abp.io.",
"Toolbar:Cart": "我的购物车",
"Toolbar:BasketNotLoaded": "无法加载!"
}
}

8
services/basket/src/EShopOnAbp.BasketService/Localization/BasketService/zh-Hant.json

@ -0,0 +1,8 @@
{
"culture": "zh-Hant",
"texts": {
"Menu:Home": "首頁",
"Welcome": "歡迎",
"LongWelcomeMessage": "歡迎來到此應用程式. 這是一個基於ABP框架的起始專案. 有關更多訊息, 請瀏覽 abp.io."
}
}

10
services/basket/src/EShopOnAbp.BasketService/Localization/BasketServiceResource.cs

@ -0,0 +1,10 @@
using Volo.Abp.Localization;
namespace EShopOnAbp.BasketService.Localization
{
[LocalizationResourceName("BasketService")]
public class BasketServiceResource
{
}
}

6
services/basket/src/EShopOnAbp.BasketService/Program.cs

@ -0,0 +1,6 @@
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();

28
services/basket/src/EShopOnAbp.BasketService/Properties/launchSettings.json

@ -0,0 +1,28 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:43756",
"sslPort": 44365
}
},
"profiles": {
"EShopOnAbp.BasketService": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7198;http://localhost:5198",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

124
services/basket/src/EShopOnAbp.BasketService/Services/BasketAppService.cs

@ -0,0 +1,124 @@
using EShopOnAbp.BasketService.Entities;
using EShopOnAbp.BasketService.Localization;
using EShopOnAbp.BasketService.Services.Dtos;
using EShopOnAbp.CatalogService.Products;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.Users;
namespace EShopOnAbp.BasketService.Services;
public class BasketAppService : ApplicationService, IBasketAppService
{
private readonly IBasketRepository _basketRepository;
private readonly IBasketProductService _basketProductService;
public BasketAppService(
IBasketRepository basketRepository,
IBasketProductService basketProductService)
{
_basketRepository = basketRepository;
_basketProductService = basketProductService;
LocalizationResource = typeof(BasketServiceResource);
}
public async Task<BasketDto> GetAsync(Guid? anonymousUserId)
{
if (anonymousUserId != null && CurrentUser.IsAuthenticated)
{
var userBasket = await _basketRepository.GetAsync(CurrentUser.GetId());
var anonymousUserBasket = await _basketRepository.GetAsync(anonymousUserId.Value);
userBasket.Merge(anonymousUserBasket);
await _basketRepository.UpdateAsync(userBasket);
anonymousUserBasket.Clear();
await _basketRepository.UpdateAsync(anonymousUserBasket);
return await GetBasketDtoAsync(userBasket);
}
if (anonymousUserId != null && !CurrentUser.IsAuthenticated)
{
return await GetBasketDtoAsync(await _basketRepository.GetAsync(anonymousUserId.Value));
}
return await GetBasketDtoAsync(await _basketRepository.GetAsync(CurrentUser.GetId()));
}
public async Task<BasketDto> AddProductAsync(AddProductDto input)
{
Guid userId = CurrentUser.IsAuthenticated ? CurrentUser.GetId() : input.AnonymousId.GetValueOrDefault();
var basket = await _basketRepository.GetAsync(userId);
var product = await _basketProductService.GetAsync(input.ProductId);
if (basket.GetProductCount(product.Id) >= product.StockCount)
{
throw new UserFriendlyException("There is not enough product in stock, sorry :(");
}
basket.AddProduct(product.Id);
await _basketRepository.UpdateAsync(basket);
return await GetBasketDtoAsync(basket);
}
public async Task<BasketDto> RemoveProductAsync(RemoveProductDto input)
{
Guid userId = CurrentUser.IsAuthenticated ? CurrentUser.GetId() : input.AnonymousId.GetValueOrDefault();
var basket = await _basketRepository.GetAsync(userId);
var product = await _basketProductService.GetAsync(input.ProductId);
basket.RemoveProduct(product.Id, input.Count);
await _basketRepository.UpdateAsync(basket);
return await GetBasketDtoAsync(basket);
}
private async Task<BasketDto> GetBasketDtoAsync(Basket basket)
{
var products = new Dictionary<Guid, ProductDto>();
var basketDto = new BasketDto();
var basketChanged = false;
foreach (var basketItem in basket.Items)
{
var productDto = products.GetOrDefault(basketItem.ProductId);
if (productDto == null)
{
productDto = await _basketProductService.GetAsync(basketItem.ProductId);
products[productDto.Id] = productDto;
}
//Removing the products if not available in the stock
if (basketItem.Count > productDto.StockCount)
{
basket.RemoveProduct(basketItem.ProductId, basketItem.Count - productDto.StockCount);
basketChanged = true;
}
basketDto.Items.Add(new BasketItemDto
{
ProductId = basketItem.ProductId,
Count = basketItem.Count,
ProductCode = productDto.Code,
ImageName = productDto.ImageName,
ProductName = productDto.Name,
TotalPrice = productDto.Price * basketItem.Count
});
}
basketDto.TotalPrice = basketDto.Items.Sum(x => x.TotalPrice);
if (basketChanged)
{
await _basketRepository.UpdateAsync(basket);
}
return basketDto;
}
}

46
services/basket/src/EShopOnAbp.BasketService/Services/BasketProductEventHandler.cs

@ -0,0 +1,46 @@
using EShopOnAbp.BasketService.Entities;
using EShopOnAbp.CatalogService.Products;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities.Events.Distributed;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.ObjectMapping;
namespace EShopOnAbp.BasketService.Services;
public class BasketProductEventHandler : IDistributedEventHandler<EntityUpdatedEto<ProductEto>>, ITransientDependency
{
private readonly IDistributedCache<ProductDto, Guid> _cache;
private readonly IObjectMapper _objectMapper;
private readonly IDistributedEventBus _distributedEventBus;
public BasketProductEventHandler(
IDistributedCache<ProductDto, Guid> cache,
IObjectMapper objectMapper,
IDistributedEventBus distributedEventBus)
{
_cache = cache;
_objectMapper = objectMapper;
_distributedEventBus = distributedEventBus;
}
public async Task HandleEventAsync(EntityUpdatedEto<ProductEto> eventData)
{
var cachedProductDto = await _cache.GetAsync(eventData.Entity.Id);
if (cachedProductDto == null)
{
return;
}
_objectMapper.Map(eventData.Entity, cachedProductDto);
await _cache.SetAsync(eventData.Entity.Id, cachedProductDto);
await _distributedEventBus.PublishAsync(
new BasketProductUpdatedEto
{
ProductId = eventData.Entity.Id,
ProductName = eventData.Entity.Name
});
}
}

46
services/basket/src/EShopOnAbp.BasketService/Services/BasketProductService.cs

@ -0,0 +1,46 @@
using EShopOnAbp.CatalogService.Grpc;
using EShopOnAbp.CatalogService.Products;
using Volo.Abp;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;
using Volo.Abp.ObjectMapping;
namespace EShopOnAbp.BasketService.Services;
public class BasketProductService : IBasketProductService, ITransientDependency
{
private readonly IDistributedCache<ProductDto, Guid> _cache;
private readonly ILogger<BasketProductService> _logger;
private readonly IObjectMapper _mapper;
private readonly ProductPublic.ProductPublicClient _productPublicGrpcClient;
public BasketProductService(
IDistributedCache<ProductDto, Guid> cache,
ILogger<BasketProductService> logger,
IObjectMapper mapper,
ProductPublic.ProductPublicClient productPublicGrpcClient)
{
_cache = cache;
_logger = logger;
_mapper = mapper;
_productPublicGrpcClient = productPublicGrpcClient;
}
public async Task<ProductDto> GetAsync(Guid productId)
{
return await _cache.GetOrAddAsync(
productId,
() => GetProductAsync(productId)
);
}
private async Task<ProductDto> GetProductAsync(Guid productId)
{
var request = new ProductRequest { Id = productId.ToString() };
_logger.LogInformation("=== GRPC request {@request}", request);
var response = await _productPublicGrpcClient.GetByIdAsync(request);
_logger.LogInformation("=== GRPC response {@response}", response);
return _mapper.Map<ProductResponse, ProductDto>(response) ??
throw new UserFriendlyException(BasketServiceDomainErrorCodes.ProductNotFound);
}
}

13
services/basket/src/EShopOnAbp.BasketService/Services/Dtos/AddProductDto.cs

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace EShopOnAbp.BasketService.Services.Dtos;
public class AddProductDto : IHasAnonymousId
{
public Guid ProductId { get; set; }
[Range(1, int.MaxValue)]
public int Count { get; set; } = 1;
public Guid? AnonymousId { get; set; }
}

12
services/basket/src/EShopOnAbp.BasketService/Services/Dtos/BasketDto.cs

@ -0,0 +1,12 @@
namespace EShopOnAbp.BasketService.Services.Dtos;
public class BasketDto
{
public float TotalPrice { get; set; }
public List<BasketItemDto> Items { get; set; }
public BasketDto()
{
Items = new List<BasketItemDto>();
}
}

11
services/basket/src/EShopOnAbp.BasketService/Services/Dtos/BasketItemDto.cs

@ -0,0 +1,11 @@
namespace EShopOnAbp.BasketService.Services.Dtos;
public class BasketItemDto
{
public Guid ProductId { get; set; }
public string ProductName { get; set; }
public string ProductCode { get; set; }
public string ImageName { get; set; }
public int Count { get; set; }
public float TotalPrice { get; set; }
}

7
services/basket/src/EShopOnAbp.BasketService/Services/Dtos/IHasAnonymousId.cs

@ -0,0 +1,7 @@
namespace EShopOnAbp.BasketService.Services.Dtos
{
public interface IHasAnonymousId
{
Guid? AnonymousId { get; }
}
}

10
services/basket/src/EShopOnAbp.BasketService/Services/Dtos/RemoveProductDto.cs

@ -0,0 +1,10 @@
namespace EShopOnAbp.BasketService.Services.Dtos;
public class RemoveProductDto : IHasAnonymousId
{
public Guid ProductId { get; set; }
public int? Count { get; set; }
public Guid? AnonymousId { get; set; }
}

11
services/basket/src/EShopOnAbp.BasketService/Services/IBasketAppService.cs

@ -0,0 +1,11 @@
using EShopOnAbp.BasketService.Services.Dtos;
using Volo.Abp.Application.Services;
namespace EShopOnAbp.BasketService.Services;
public interface IBasketAppService : IApplicationService
{
Task<BasketDto> GetAsync(Guid? anonymousUserId);
Task<BasketDto> AddProductAsync(AddProductDto input);
Task<BasketDto> RemoveProductAsync(RemoveProductDto input);
}

12
services/basket/src/EShopOnAbp.BasketService/Services/IBasketProductService.cs

@ -0,0 +1,12 @@
using System;
using System.Threading.Tasks;
using EShopOnAbp.CatalogService.Products;
using JetBrains.Annotations;
namespace EShopOnAbp.BasketService;
public interface IBasketProductService
{
[ItemNotNull]
Task<ProductDto> GetAsync(Guid productId);
}

21
services/basket/src/EShopOnAbp.BasketService/Services/Permissions/BasketServicePermissionDefinitionProvider.cs

@ -0,0 +1,21 @@
using EShopOnAbp.BasketService.Localization;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Localization;
namespace EShopOnAbp.BasketService.Services.Permissions
{
public class BasketServicePermissionDefinitionProvider : PermissionDefinitionProvider
{
public override void Define(IPermissionDefinitionContext context)
{
var myGroup = context.AddGroup(BasketServicePermissions.GroupName);
//Define your own permissions here. Example:
//myGroup.AddPermission(BasketServicePermissions.MyPermission1, L("Permission:MyPermission1"));
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<BasketServiceResource>(name);
}
}
}

10
services/basket/src/EShopOnAbp.BasketService/Services/Permissions/BasketServicePermissions.cs

@ -0,0 +1,10 @@
namespace EShopOnAbp.BasketService.Services.Permissions
{
public static class BasketServicePermissions
{
public const string GroupName = "BasketService";
//Add your own permission names. Example:
//public const string MyPermission1 = GroupName + ".MyPermission1";
}
}

8
services/basket/src/EShopOnAbp.BasketService/appsettings.Development.json

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

49
services/basket/src/EShopOnAbp.BasketService/appsettings.json

@ -0,0 +1,49 @@
{
"App": {
"SelfUrl": "https://localhost:44355",
"CorsOrigins": "https://localhost:44372,https://localhost:44373,https://localhost:44335"
},
"AuthServer": {
"Authority": "https://localhost:44330",
"RequireHttpsMetadata": "true",
"SwaggerClientId": "WebGateway_Swagger",
"SwaggerClientSecret": "1q2w3e*"
},
"RemoteServices": {
"Catalog": {
"BaseUrl": "https://localhost:44354/",
"GrpcUrl": "http://localhost:81"
}
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"AdministrationService": "User ID=postgres;Password=myPassw0rd;Host=localhost;Port=5432;Database=EShopOnAbp_Administration;Pooling=false;"
},
"StringEncryption": {
"DefaultPassPhrase": "3PfxLgcuymUUbihz"
},
"Redis": {
"Configuration": "localhost:6379"
},
"RabbitMQ": {
"Connections": {
"Default": {
"HostName": "localhost"
}
},
"EventBus": {
"ClientName": "EShopOnAbp_BasketService",
"ExchangeName": "EShopOnAbp"
}
},
"ElasticSearch": {
"Url": "http://localhost:9200"
}
}
Loading…
Cancel
Save