Merge branch 'marketingcampaign' into dev
This commit is contained in:
commit
1d46ba3a15
@ -95,4 +95,16 @@ services:
|
|||||||
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
||||||
- EventBusConnection=rabbitmq
|
- EventBusConnection=rabbitmq
|
||||||
ports:
|
ports:
|
||||||
- "5109:80"
|
- "5109:80"
|
||||||
|
|
||||||
|
marketing.api:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:80
|
||||||
|
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word
|
||||||
|
- EventBusConnection=rabbitmq
|
||||||
|
- MongoConnectionString=mongodb://nosql.data
|
||||||
|
- MongoDatabase=MarketingDb
|
||||||
|
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
||||||
|
ports:
|
||||||
|
- "5110:80"
|
@ -75,7 +75,19 @@ services:
|
|||||||
- BasketUrl=http://basket.api
|
- BasketUrl=http://basket.api
|
||||||
ports:
|
ports:
|
||||||
- "5100:80"
|
- "5100:80"
|
||||||
|
|
||||||
|
marketing.api:
|
||||||
|
environment:
|
||||||
|
- ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
- ASPNETCORE_URLS=http://0.0.0.0:80
|
||||||
|
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word
|
||||||
|
- EventBusConnection=rabbitmq
|
||||||
|
- MongoConnectionString=mongodb://nosql.data
|
||||||
|
- MongoDatabase=MarketingDb
|
||||||
|
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
||||||
|
ports:
|
||||||
|
- "5110:80"
|
||||||
|
|
||||||
sql.data:
|
sql.data:
|
||||||
environment:
|
environment:
|
||||||
- SA_PASSWORD=Pass@word
|
- SA_PASSWORD=Pass@word
|
||||||
|
@ -61,7 +61,19 @@ services:
|
|||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
depends_on:
|
depends_on:
|
||||||
- nosql.data
|
- nosql.data
|
||||||
|
- rabbitmq
|
||||||
|
|
||||||
|
marketing.api:
|
||||||
|
image: eshop/marketing.api
|
||||||
|
build:
|
||||||
|
context: ./src/Services/Marketing/Marketing.API
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
depends_on:
|
||||||
|
- sql.data
|
||||||
|
- nosql.data
|
||||||
|
- identity.api
|
||||||
|
- rabbitmq
|
||||||
|
|
||||||
sql.data:
|
sql.data:
|
||||||
image: microsoft/mssql-server-windows
|
image: microsoft/mssql-server-windows
|
||||||
|
|
||||||
|
@ -58,6 +58,9 @@ services:
|
|||||||
- ASPNETCORE_ENVIRONMENT=Development
|
- ASPNETCORE_ENVIRONMENT=Development
|
||||||
- ASPNETCORE_URLS=http://0.0.0.0:80
|
- ASPNETCORE_URLS=http://0.0.0.0:80
|
||||||
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word
|
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word
|
||||||
|
- MongoConnectionString=mongodb://nosql.data
|
||||||
|
- MongoDatabase=MarketingDb
|
||||||
|
- EventBusConnection=rabbitmq
|
||||||
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
||||||
ports:
|
ports:
|
||||||
- "5110:80"
|
- "5110:80"
|
||||||
|
@ -59,6 +59,9 @@ services:
|
|||||||
- ASPNETCORE_ENVIRONMENT=Production
|
- ASPNETCORE_ENVIRONMENT=Production
|
||||||
- ASPNETCORE_URLS=http://0.0.0.0:80
|
- ASPNETCORE_URLS=http://0.0.0.0:80
|
||||||
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word
|
- ConnectionString=Server=sql.data;Database=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word
|
||||||
|
- MongoConnectionString=mongodb://nosql.data
|
||||||
|
- MongoDatabase=MarketingDb
|
||||||
|
- EventBusConnection=rabbitmq
|
||||||
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
- identityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5105. at range 5100-5105.
|
||||||
ports:
|
ports:
|
||||||
- "5110:80"
|
- "5110:80"
|
||||||
|
@ -53,7 +53,9 @@ services:
|
|||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
depends_on:
|
depends_on:
|
||||||
- sql.data
|
- sql.data
|
||||||
|
- nosql.data
|
||||||
- identity.api
|
- identity.api
|
||||||
|
- rabbitmq
|
||||||
|
|
||||||
webspa:
|
webspa:
|
||||||
image: eshop/webspa
|
image: eshop/webspa
|
||||||
@ -112,3 +114,4 @@ services:
|
|||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
depends_on:
|
depends_on:
|
||||||
- nosql.data
|
- nosql.data
|
||||||
|
- rabbitmq
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26430.6
|
VisualStudioVersion = 15.0.26430.12
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{932D8224-11F6-4D07-B109-DA28AD288A63}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{932D8224-11F6-4D07-B109-DA28AD288A63}"
|
||||||
EndProject
|
EndProject
|
||||||
|
@ -41,7 +41,7 @@ namespace Locations.API.Controllers
|
|||||||
//GET api/v1/[controller]/1
|
//GET api/v1/[controller]/1
|
||||||
[Route("{locationId}")]
|
[Route("{locationId}")]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<IActionResult> GetLocation(string locationId)
|
public async Task<IActionResult> GetLocation(int locationId)
|
||||||
{
|
{
|
||||||
var location = await _locationsService.GetLocation(locationId);
|
var location = await _locationsService.GetLocation(locationId);
|
||||||
return Ok(location);
|
return Ok(location);
|
||||||
@ -54,6 +54,7 @@ namespace Locations.API.Controllers
|
|||||||
{
|
{
|
||||||
var userId = _identityService.GetUserIdentity();
|
var userId = _identityService.GetUserIdentity();
|
||||||
var result = await _locationsService.AddOrUpdateUserLocation(userId, newLocReq);
|
var result = await _locationsService.AddOrUpdateUserLocation(userId, newLocReq);
|
||||||
|
|
||||||
return result ?
|
return result ?
|
||||||
(IActionResult)Ok() :
|
(IActionResult)Ok() :
|
||||||
(IActionResult)BadRequest();
|
(IActionResult)BadRequest();
|
||||||
|
@ -32,7 +32,8 @@
|
|||||||
var us = new Locations()
|
var us = new Locations()
|
||||||
{
|
{
|
||||||
Code = "US",
|
Code = "US",
|
||||||
Description = "United States"
|
Description = "United States",
|
||||||
|
LocationId = 1
|
||||||
};
|
};
|
||||||
us.SetLocation(-101.357386, 41.650455);
|
us.SetLocation(-101.357386, 41.650455);
|
||||||
us.SetArea(GetUSPoligon());
|
us.SetArea(GetUSPoligon());
|
||||||
@ -46,7 +47,8 @@
|
|||||||
{
|
{
|
||||||
Parent_Id = parentId,
|
Parent_Id = parentId,
|
||||||
Code = "WHT",
|
Code = "WHT",
|
||||||
Description = "Washington"
|
Description = "Washington",
|
||||||
|
LocationId = 2
|
||||||
};
|
};
|
||||||
wht.SetLocation(-119.542781, 47.223652);
|
wht.SetLocation(-119.542781, 47.223652);
|
||||||
wht.SetArea(GetWashingtonPoligon());
|
wht.SetArea(GetWashingtonPoligon());
|
||||||
@ -61,7 +63,8 @@
|
|||||||
{
|
{
|
||||||
Parent_Id = parentId,
|
Parent_Id = parentId,
|
||||||
Code = "SEAT",
|
Code = "SEAT",
|
||||||
Description = "Seattle"
|
Description = "Seattle",
|
||||||
|
LocationId = 3
|
||||||
};
|
};
|
||||||
stl.SetArea(GetSeattlePoligon());
|
stl.SetArea(GetSeattlePoligon());
|
||||||
stl.SetLocation(-122.330747, 47.603111);
|
stl.SetLocation(-122.330747, 47.603111);
|
||||||
@ -74,7 +77,8 @@
|
|||||||
{
|
{
|
||||||
Parent_Id = parentId,
|
Parent_Id = parentId,
|
||||||
Code = "REDM",
|
Code = "REDM",
|
||||||
Description = "Redmond"
|
Description = "Redmond",
|
||||||
|
LocationId = 4
|
||||||
};
|
};
|
||||||
rdm.SetLocation(-122.122887, 47.674961);
|
rdm.SetLocation(-122.122887, 47.674961);
|
||||||
rdm.SetArea(GetRedmondPoligon());
|
rdm.SetArea(GetRedmondPoligon());
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
public interface ILocationsRepository
|
public interface ILocationsRepository
|
||||||
{
|
{
|
||||||
Task<Locations> GetAsync(string locationId);
|
Task<Locations> GetAsync(int locationId);
|
||||||
|
|
||||||
Task<List<Locations>> GetLocationListAsync();
|
Task<List<Locations>> GetLocationListAsync();
|
||||||
|
|
||||||
|
@ -20,9 +20,9 @@
|
|||||||
_context = new LocationsContext(settings);
|
_context = new LocationsContext(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Locations> GetAsync(string locationId)
|
public async Task<Locations> GetAsync(int locationId)
|
||||||
{
|
{
|
||||||
var filter = Builders<Locations>.Filter.Eq("Id", ObjectId.Parse(locationId));
|
var filter = Builders<Locations>.Filter.Eq("LocationId", locationId);
|
||||||
return await _context.Locations
|
return await _context.Locations
|
||||||
.Find(filter)
|
.Find(filter)
|
||||||
.FirstOrDefaultAsync();
|
.FirstOrDefaultAsync();
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
public interface ILocationsService
|
public interface ILocationsService
|
||||||
{
|
{
|
||||||
Task<Locations> GetLocation(string locationId);
|
Task<Locations> GetLocation(int locationId);
|
||||||
|
|
||||||
Task<UserLocation> GetUserLocation(string id);
|
Task<UserLocation> GetUserLocation(string id);
|
||||||
|
|
||||||
|
@ -8,29 +8,28 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Exceptions;
|
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Exceptions;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.IntegrationEvents.Events;
|
||||||
|
|
||||||
public class LocationsService : ILocationsService
|
public class LocationsService : ILocationsService
|
||||||
{
|
{
|
||||||
private ILocationsRepository _locationsRepository;
|
private readonly ILocationsRepository _locationsRepository;
|
||||||
|
private readonly IEventBus _eventBus;
|
||||||
|
|
||||||
public LocationsService(ILocationsRepository locationsRepository)
|
public LocationsService(ILocationsRepository locationsRepository, IEventBus eventBus)
|
||||||
{
|
{
|
||||||
_locationsRepository = locationsRepository ?? throw new ArgumentNullException(nameof(locationsRepository));
|
_locationsRepository = locationsRepository ?? throw new ArgumentNullException(nameof(locationsRepository));
|
||||||
|
_eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Locations> GetLocation(string locationId)
|
public async Task<Locations> GetLocation(int locationId)
|
||||||
{
|
{
|
||||||
return await _locationsRepository.GetAsync(locationId);
|
return await _locationsRepository.GetAsync(locationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<UserLocation> GetUserLocation(string id)
|
public async Task<UserLocation> GetUserLocation(string userId)
|
||||||
{
|
{
|
||||||
if (!Guid.TryParse(id, out Guid userId))
|
return await _locationsRepository.GetUserLocationAsync(userId);
|
||||||
{
|
|
||||||
throw new ArgumentException("Not valid userId");
|
|
||||||
}
|
|
||||||
|
|
||||||
return await _locationsRepository.GetUserLocationAsync(userId.ToString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<Locations>> GetAllLocation()
|
public async Task<List<Locations>> GetAllLocation()
|
||||||
@ -38,13 +37,8 @@
|
|||||||
return await _locationsRepository.GetLocationListAsync();
|
return await _locationsRepository.GetLocationListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> AddOrUpdateUserLocation(string id, LocationRequest currentPosition)
|
public async Task<bool> AddOrUpdateUserLocation(string userId, LocationRequest currentPosition)
|
||||||
{
|
{
|
||||||
if (!Guid.TryParse(id, out Guid userId))
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Not valid userId");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the list of ordered regions the user currently is within
|
// Get the list of ordered regions the user currently is within
|
||||||
var currentUserAreaLocationList = await _locationsRepository.GetCurrentUserRegionsListAsync(currentPosition);
|
var currentUserAreaLocationList = await _locationsRepository.GetCurrentUserRegionsListAsync(currentPosition);
|
||||||
|
|
||||||
@ -55,14 +49,40 @@
|
|||||||
|
|
||||||
// If current area found, then update user location
|
// If current area found, then update user location
|
||||||
var locationAncestors = new List<string>();
|
var locationAncestors = new List<string>();
|
||||||
var userLocation = await _locationsRepository.GetUserLocationAsync(userId.ToString());
|
var userLocation = await _locationsRepository.GetUserLocationAsync(userId);
|
||||||
userLocation = userLocation ?? new UserLocation();
|
userLocation = userLocation ?? new UserLocation();
|
||||||
userLocation.UserId = userId;
|
userLocation.UserId = userId;
|
||||||
userLocation.LocationId = currentUserAreaLocationList[0].Id;
|
userLocation.LocationId = currentUserAreaLocationList[0].LocationId;
|
||||||
userLocation.UpdateDate = DateTime.UtcNow;
|
userLocation.UpdateDate = DateTime.UtcNow;
|
||||||
await _locationsRepository.UpdateUserLocationAsync(userLocation);
|
await _locationsRepository.UpdateUserLocationAsync(userLocation);
|
||||||
|
|
||||||
|
// Publish integration event to update marketing read data model
|
||||||
|
// with the new locations updated
|
||||||
|
PublishNewUserLocationPositionIntegrationEvent(userId, currentUserAreaLocationList);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PublishNewUserLocationPositionIntegrationEvent(string userId, List<Locations> newLocations)
|
||||||
|
{
|
||||||
|
var newUserLocations = MapUserLocationDetails(newLocations);
|
||||||
|
var @event = new UserLocationUpdatedIntegrationEvent(userId, newUserLocations);
|
||||||
|
_eventBus.Publish(@event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<UserLocationDetails> MapUserLocationDetails(List<Locations> newLocations)
|
||||||
|
{
|
||||||
|
var result = new List<UserLocationDetails>();
|
||||||
|
newLocations.ForEach(location => {
|
||||||
|
result.Add(new UserLocationDetails()
|
||||||
|
{
|
||||||
|
LocationId = location.LocationId,
|
||||||
|
Code = location.Code,
|
||||||
|
Description = location.Description
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.IntegrationEvents.Events
|
||||||
|
{
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Model;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class UserLocationUpdatedIntegrationEvent : IntegrationEvent
|
||||||
|
{
|
||||||
|
public string UserId { get; private set; }
|
||||||
|
public List<UserLocationDetails> LocationList { get; private set; }
|
||||||
|
|
||||||
|
public UserLocationUpdatedIntegrationEvent(string userId, List<UserLocationDetails> locationList)
|
||||||
|
{
|
||||||
|
UserId = userId;
|
||||||
|
LocationList = locationList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@
|
|||||||
<Folder Include="wwwroot\" />
|
<Folder Include="wwwroot\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.1.0" />
|
||||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.2.0" />
|
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.2.0" />
|
||||||
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
|
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
|
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
|
||||||
@ -37,5 +38,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
|
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -7,8 +7,10 @@
|
|||||||
|
|
||||||
public class Locations
|
public class Locations
|
||||||
{
|
{
|
||||||
|
[BsonId]
|
||||||
[BsonRepresentation(BsonType.ObjectId)]
|
[BsonRepresentation(BsonType.ObjectId)]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
|
public int LocationId { get; set; }
|
||||||
public string Code { get; set; }
|
public string Code { get; set; }
|
||||||
[BsonRepresentation(BsonType.ObjectId)]
|
[BsonRepresentation(BsonType.ObjectId)]
|
||||||
public string Parent_Id { get; set; }
|
public string Parent_Id { get; set; }
|
||||||
|
@ -9,9 +9,8 @@
|
|||||||
[BsonIgnoreIfDefault]
|
[BsonIgnoreIfDefault]
|
||||||
[BsonRepresentation(BsonType.ObjectId)]
|
[BsonRepresentation(BsonType.ObjectId)]
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
public Guid UserId { get; set; }
|
public string UserId { get; set; }
|
||||||
[BsonRepresentation(BsonType.ObjectId)]
|
public int LocationId { get; set; }
|
||||||
public string LocationId { get; set; }
|
|
||||||
public DateTime UpdateDate { get; set; }
|
public DateTime UpdateDate { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Locations.API.Model
|
||||||
|
{
|
||||||
|
public class UserLocationDetails
|
||||||
|
{
|
||||||
|
public int LocationId { get; set; }
|
||||||
|
public string Code { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,21 @@
|
|||||||
using Microsoft.AspNetCore.Builder;
|
using Autofac;
|
||||||
|
using Autofac.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
|
||||||
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure;
|
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Filters;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using RabbitMQ.Client;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Services;
|
|
||||||
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Repositories;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.eShopOnContainers.Services.Locations.API.Infrastructure.Filters;
|
|
||||||
|
|
||||||
namespace Microsoft.eShopOnContainers.Services.Locations.API
|
namespace Microsoft.eShopOnContainers.Services.Locations.API
|
||||||
{
|
{
|
||||||
@ -37,7 +41,7 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public IServiceProvider ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
services.AddMvc(options =>
|
services.AddMvc(options =>
|
||||||
@ -46,7 +50,21 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API
|
|||||||
}).AddControllersAsServices();
|
}).AddControllersAsServices();
|
||||||
|
|
||||||
services.Configure<LocationSettings>(Configuration);
|
services.Configure<LocationSettings>(Configuration);
|
||||||
|
|
||||||
|
services.AddSingleton<IRabbitMQPersistentConnection>(sp =>
|
||||||
|
{
|
||||||
|
var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>();
|
||||||
|
|
||||||
|
var factory = new ConnectionFactory()
|
||||||
|
{
|
||||||
|
HostName = Configuration["EventBusConnection"]
|
||||||
|
};
|
||||||
|
|
||||||
|
return new DefaultRabbitMQPersistentConnection(factory, logger);
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterServiceBus(services);
|
||||||
|
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
services.AddSwaggerGen(options =>
|
services.AddSwaggerGen(options =>
|
||||||
{
|
{
|
||||||
@ -72,7 +90,13 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API
|
|||||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
services.AddTransient<IIdentityService, IdentityService>();
|
services.AddTransient<IIdentityService, IdentityService>();
|
||||||
services.AddTransient<ILocationsService, LocationsService>();
|
services.AddTransient<ILocationsService, LocationsService>();
|
||||||
services.AddTransient<ILocationsRepository, LocationsRepository>();
|
services.AddTransient<ILocationsRepository, LocationsRepository>();
|
||||||
|
|
||||||
|
//configure autofac
|
||||||
|
var container = new ContainerBuilder();
|
||||||
|
container.Populate(services);
|
||||||
|
|
||||||
|
return new AutofacServiceProvider(container.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
@ -109,5 +133,11 @@ namespace Microsoft.eShopOnContainers.Services.Locations.API
|
|||||||
RequireHttpsMetadata = false
|
RequireHttpsMetadata = false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RegisterServiceBus(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IEventBus, EventBusRabbitMQ>();
|
||||||
|
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers
|
||||||
{
|
{
|
||||||
|
using Infrastructure.Repositories;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure;
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -8,16 +9,21 @@
|
|||||||
using Microsoft.eShopOnContainers.Services.Marketing.API.Dto;
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Dto;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
[Route("api/v1/[controller]")]
|
[Route("api/v1/[controller]")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class CampaignsController : Controller
|
public class CampaignsController : Controller
|
||||||
{
|
{
|
||||||
private readonly MarketingContext _context;
|
private readonly MarketingContext _context;
|
||||||
|
private readonly IMarketingDataRepository _marketingDataRepository;
|
||||||
|
|
||||||
public CampaignsController(MarketingContext context)
|
public CampaignsController(MarketingContext context,
|
||||||
|
IMarketingDataRepository marketingDataRepository)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
|
_marketingDataRepository = marketingDataRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
@ -112,6 +118,37 @@
|
|||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("user/{userId:guid}")]
|
||||||
|
public async Task<IActionResult> GetCampaignsByUserId(Guid userId)
|
||||||
|
{
|
||||||
|
var marketingData = await _marketingDataRepository.GetAsync(userId.ToString());
|
||||||
|
|
||||||
|
if (marketingData is null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
var campaignDtoList = new List<CampaignDTO>();
|
||||||
|
|
||||||
|
//Get User Location Campaign
|
||||||
|
foreach(var userLocation in marketingData.Locations)
|
||||||
|
{
|
||||||
|
var userCampaignList = await _context.Rules
|
||||||
|
.OfType<UserLocationRule>()
|
||||||
|
.Include(c => c.Campaign)
|
||||||
|
.Where(c => c.LocationId == userLocation.LocationId)
|
||||||
|
.Select(c => c.Campaign)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
if (userCampaignList != null && userCampaignList.Any())
|
||||||
|
{
|
||||||
|
var userCampaignDtoList = MapCampaignModelListToDtoList(userCampaignList);
|
||||||
|
campaignDtoList.AddRange(userCampaignDtoList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(campaignDtoList);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private List<CampaignDTO> MapCampaignModelListToDtoList(List<Campaign> campaignList)
|
private List<CampaignDTO> MapCampaignModelListToDtoList(List<Campaign> campaignList)
|
||||||
|
@ -83,8 +83,8 @@ namespace Microsoft.eShopOnContainers.Services.Marketing.API.Controllers
|
|||||||
await _context.Rules.AddAsync(locationRule);
|
await _context.Rules.AddAsync(locationRule);
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
|
|
||||||
return CreatedAtAction(nameof(GetLocationByCampaignAndLocationRuleId),
|
return CreatedAtAction(nameof(GetLocationByCampaignAndLocationRuleId),
|
||||||
new { campaignId = campaignId, locationRuleId = locationRule.Id }, null);
|
new { campaignId = campaignId, userLocationRuleId = locationRule.Id }, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpDelete]
|
[HttpDelete]
|
||||||
|
12
src/Services/Marketing/Marketing.API/Dto/UserLocationDTO.cs
Normal file
12
src/Services/Marketing/Marketing.API/Dto/UserLocationDTO.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Dto
|
||||||
|
{
|
||||||
|
public class UserLocationDTO
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
public Guid UserId { get; set; }
|
||||||
|
public int LocationId { get; set; }
|
||||||
|
public DateTime UpdateDate { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -64,9 +64,9 @@
|
|||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
builder.HasDiscriminator<int>("RuleTypeId")
|
builder.HasDiscriminator<int>("RuleTypeId")
|
||||||
.HasValue<UserProfileRule>((int)RuleTypeEnum.UserProfileRule)
|
.HasValue<UserProfileRule>(RuleType.UserProfileRule.Id)
|
||||||
.HasValue<PurchaseHistoryRule>((int)RuleTypeEnum.PurchaseHistoryRule)
|
.HasValue<PurchaseHistoryRule>(RuleType.PurchaseHistoryRule.Id)
|
||||||
.HasValue<UserLocationRule>((int)RuleTypeEnum.UserLocationRule);
|
.HasValue<UserLocationRule>(RuleType.UserLocationRule.Id);
|
||||||
|
|
||||||
builder.Property(r => r.Description)
|
builder.Property(r => r.Description)
|
||||||
.HasColumnName("Description")
|
.HasColumnName("Description")
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
new UserLocationRule
|
new UserLocationRule
|
||||||
{
|
{
|
||||||
Description = "UserLocationRule2",
|
Description = "UserLocationRule2",
|
||||||
LocationId = 3
|
LocationId = 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure
|
||||||
|
{
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Model;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
|
||||||
|
public class MarketingReadDataContext
|
||||||
|
{
|
||||||
|
private readonly IMongoDatabase _database = null;
|
||||||
|
|
||||||
|
public MarketingReadDataContext(IOptions<MarketingSettings> settings)
|
||||||
|
{
|
||||||
|
var client = new MongoClient(settings.Value.MongoConnectionString);
|
||||||
|
if (client != null)
|
||||||
|
_database = client.GetDatabase(settings.Value.MongoDatabase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMongoCollection<MarketingData> MarketingData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _database.GetCollection<MarketingData>("MarketingReadDataModel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Repositories
|
||||||
|
{
|
||||||
|
using Model;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public interface IMarketingDataRepository
|
||||||
|
{
|
||||||
|
Task<MarketingData> GetAsync(string userId);
|
||||||
|
Task UpdateLocationAsync(MarketingData marketingData);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Model;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Repositories
|
||||||
|
{
|
||||||
|
public class MarketingDataRepository
|
||||||
|
: IMarketingDataRepository
|
||||||
|
{
|
||||||
|
private readonly MarketingReadDataContext _context;
|
||||||
|
|
||||||
|
public MarketingDataRepository(IOptions<MarketingSettings> settings)
|
||||||
|
{
|
||||||
|
_context = new MarketingReadDataContext(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<MarketingData> GetAsync(string userId)
|
||||||
|
{
|
||||||
|
var filter = Builders<MarketingData>.Filter.Eq("UserId", userId);
|
||||||
|
return await _context.MarketingData
|
||||||
|
.Find(filter)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateLocationAsync(MarketingData marketingData)
|
||||||
|
{
|
||||||
|
var filter = Builders<MarketingData>.Filter.Eq("UserId", marketingData.UserId);
|
||||||
|
var update = Builders<MarketingData>.Update
|
||||||
|
.Set("Locations", marketingData.Locations)
|
||||||
|
.CurrentDate("UpdateDate");
|
||||||
|
|
||||||
|
await _context.MarketingData
|
||||||
|
.UpdateOneAsync(filter, update, new UpdateOptions { IsUpsert = true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.IntegrationEvents.Events
|
||||||
|
{
|
||||||
|
using Model;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using BuildingBlocks.EventBus.Events;
|
||||||
|
|
||||||
|
public class UserLocationUpdatedIntegrationEvent : IntegrationEvent
|
||||||
|
{
|
||||||
|
public string UserId { get; private set; }
|
||||||
|
public List<UserLocationDetails> LocationList { get; private set; }
|
||||||
|
|
||||||
|
public UserLocationUpdatedIntegrationEvent(string userId, List<UserLocationDetails> locationList)
|
||||||
|
{
|
||||||
|
UserId = userId;
|
||||||
|
LocationList = locationList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.IntegrationEvents.Handlers
|
||||||
|
{
|
||||||
|
using BuildingBlocks.EventBus.Abstractions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Events;
|
||||||
|
using System;
|
||||||
|
using Infrastructure.Repositories;
|
||||||
|
using Model;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class UserLocationUpdatedIntegrationEventHandler
|
||||||
|
: IIntegrationEventHandler<UserLocationUpdatedIntegrationEvent>
|
||||||
|
{
|
||||||
|
private readonly IMarketingDataRepository _marketingDataRepository;
|
||||||
|
|
||||||
|
public UserLocationUpdatedIntegrationEventHandler(IMarketingDataRepository repository)
|
||||||
|
{
|
||||||
|
_marketingDataRepository = repository ?? throw new ArgumentNullException(nameof(repository));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Handle(UserLocationUpdatedIntegrationEvent @event)
|
||||||
|
{
|
||||||
|
var userMarketingData = await _marketingDataRepository.GetAsync(@event.UserId);
|
||||||
|
userMarketingData = userMarketingData ??
|
||||||
|
new MarketingData() { UserId = @event.UserId };
|
||||||
|
|
||||||
|
userMarketingData.Locations = MapUpdatedUserLocations(@event.LocationList);
|
||||||
|
await _marketingDataRepository.UpdateLocationAsync(userMarketingData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Location> MapUpdatedUserLocations(List<UserLocationDetails> newUserLocations)
|
||||||
|
{
|
||||||
|
var result = new List<Location>();
|
||||||
|
newUserLocations.ForEach(location => {
|
||||||
|
result.Add(new Location()
|
||||||
|
{
|
||||||
|
LocationId = location.LocationId,
|
||||||
|
Code = location.Code,
|
||||||
|
Description = location.Description
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -12,10 +12,9 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Infrastructure\MarketingMigrations\" />
|
<Folder Include="Infrastructure\MarketingMigrations\" />
|
||||||
<Folder Include="IntegrationEvents\EventHandling\" />
|
|
||||||
<Folder Include="IntegrationEvents\Events\" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.1.0" />
|
||||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.2.0" />
|
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.2.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
|
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
|
||||||
@ -39,6 +38,10 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.2" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="1.1.2" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.1.2" />
|
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.1.2" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="1.1.1" />
|
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="1.1.1" />
|
||||||
|
<PackageReference Include="mongocsharpdriver" Version="2.4.3" />
|
||||||
|
<PackageReference Include="MongoDB.Bson" Version="2.4.3" />
|
||||||
|
<PackageReference Include="MongoDB.Driver" Version="2.4.3" />
|
||||||
|
<PackageReference Include="MongoDB.Driver.Core" Version="2.4.3" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="1.0.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="1.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -47,4 +50,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
|
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -3,5 +3,7 @@
|
|||||||
public class MarketingSettings
|
public class MarketingSettings
|
||||||
{
|
{
|
||||||
public string ConnectionString { get; set; }
|
public string ConnectionString { get; set; }
|
||||||
|
public string MongoConnectionString { get; set; }
|
||||||
|
public string MongoDatabase { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
src/Services/Marketing/Marketing.API/Model/Location.cs
Normal file
16
src/Services/Marketing/Marketing.API/Model/Location.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Model
|
||||||
|
{
|
||||||
|
public class Location
|
||||||
|
{
|
||||||
|
public int LocationId { get; set; }
|
||||||
|
public string Code { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
}
|
||||||
|
}
|
19
src/Services/Marketing/Marketing.API/Model/MarketingData.cs
Normal file
19
src/Services/Marketing/Marketing.API/Model/MarketingData.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Model
|
||||||
|
{
|
||||||
|
public class MarketingData
|
||||||
|
{
|
||||||
|
[BsonIgnoreIfDefault]
|
||||||
|
[BsonRepresentation(BsonType.ObjectId)]
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string UserId { get; set; }
|
||||||
|
public List<Location> Locations { get; set; }
|
||||||
|
public DateTime UpdateDate { get; set; }
|
||||||
|
}
|
||||||
|
}
|
51
src/Services/Marketing/Marketing.API/Model/RuleType.cs
Normal file
51
src/Services/Marketing/Marketing.API/Model/RuleType.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Model
|
||||||
|
{
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Exceptions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
public sealed class RuleType
|
||||||
|
{
|
||||||
|
public static readonly RuleType UserProfileRule = new RuleType(1, nameof(UserProfileRule));
|
||||||
|
public static readonly RuleType PurchaseHistoryRule = new RuleType(2, nameof(UserProfileRule));
|
||||||
|
public static readonly RuleType UserLocationRule = new RuleType(3, nameof(UserProfileRule));
|
||||||
|
|
||||||
|
public readonly int Id;
|
||||||
|
public readonly string Name;
|
||||||
|
|
||||||
|
private RuleType(int id, string name)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<RuleType> List() =>
|
||||||
|
new[] { UserProfileRule, PurchaseHistoryRule, UserLocationRule };
|
||||||
|
|
||||||
|
public static RuleType FromName(string name)
|
||||||
|
{
|
||||||
|
var state = List()
|
||||||
|
.SingleOrDefault(s => String.Equals(s.Name, name, StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
|
||||||
|
if (state == null)
|
||||||
|
{
|
||||||
|
throw new MarketingDomainException($"Possible values for RuleType: {String.Join(",", List().Select(s => s.Name))}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RuleType From(int id)
|
||||||
|
{
|
||||||
|
var state = List().SingleOrDefault(s => s.Id == id);
|
||||||
|
|
||||||
|
if (state == null)
|
||||||
|
{
|
||||||
|
throw new MarketingDomainException($"Possible values for RuleType: {String.Join(",", List().Select(s => s.Name))}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +0,0 @@
|
|||||||
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Model
|
|
||||||
{
|
|
||||||
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Exceptions;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
public enum RuleTypeEnum { UserProfileRule = 1, PurchaseHistoryRule = 2, UserLocationRule = 3 }
|
|
||||||
|
|
||||||
public static class RuleType
|
|
||||||
{
|
|
||||||
public static RuleTypeEnum From(int id)
|
|
||||||
{
|
|
||||||
if (!Enum.IsDefined(typeof(RuleTypeEnum), id))
|
|
||||||
{
|
|
||||||
throw new MarketingDomainException($"Invalid value for RuleType, RuleTypeId: {id}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return (RuleTypeEnum)id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,9 @@
|
|||||||
|
namespace Microsoft.eShopOnContainers.Services.Marketing.API.Model
|
||||||
|
{
|
||||||
|
public class UserLocationDetails
|
||||||
|
{
|
||||||
|
public int LocationId { get; set; }
|
||||||
|
public string Code { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,15 @@
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Filters;
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Infrastructure.Filters;
|
||||||
|
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
|
||||||
|
using RabbitMQ.Client;
|
||||||
|
using BuildingBlocks.EventBus.Abstractions;
|
||||||
|
using BuildingBlocks.EventBus;
|
||||||
|
using IntegrationEvents.Events;
|
||||||
|
using IntegrationEvents.Handlers;
|
||||||
|
using Infrastructure.Repositories;
|
||||||
|
using Autofac;
|
||||||
|
using Autofac.Extensions.DependencyInjection;
|
||||||
|
|
||||||
public class Startup
|
public class Startup
|
||||||
{
|
{
|
||||||
@ -35,7 +44,7 @@
|
|||||||
public IConfigurationRoot Configuration { get; }
|
public IConfigurationRoot Configuration { get; }
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public IServiceProvider ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
services.AddMvc(options =>
|
services.AddMvc(options =>
|
||||||
@ -43,6 +52,8 @@
|
|||||||
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
|
options.Filters.Add(typeof(HttpGlobalExceptionFilter));
|
||||||
}).AddControllersAsServices(); //Injecting Controllers themselves thru DIFor further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services
|
}).AddControllersAsServices(); //Injecting Controllers themselves thru DIFor further info see: http://docs.autofac.org/en/latest/integration/aspnetcore.html#controllers-as-services
|
||||||
|
|
||||||
|
services.Configure<MarketingSettings>(Configuration);
|
||||||
|
|
||||||
services.AddDbContext<MarketingContext>(options =>
|
services.AddDbContext<MarketingContext>(options =>
|
||||||
{
|
{
|
||||||
options.UseSqlServer(Configuration["ConnectionString"],
|
options.UseSqlServer(Configuration["ConnectionString"],
|
||||||
@ -59,6 +70,20 @@
|
|||||||
//Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval
|
//Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddSingleton<IRabbitMQPersistentConnection>(sp =>
|
||||||
|
{
|
||||||
|
var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>();
|
||||||
|
|
||||||
|
var factory = new ConnectionFactory()
|
||||||
|
{
|
||||||
|
HostName = Configuration["EventBusConnection"]
|
||||||
|
};
|
||||||
|
|
||||||
|
return new DefaultRabbitMQPersistentConnection(factory, logger);
|
||||||
|
});
|
||||||
|
|
||||||
|
RegisterServiceBus(services);
|
||||||
|
|
||||||
// Add framework services.
|
// Add framework services.
|
||||||
services.AddSwaggerGen(options =>
|
services.AddSwaggerGen(options =>
|
||||||
{
|
{
|
||||||
@ -80,6 +105,14 @@
|
|||||||
.AllowAnyHeader()
|
.AllowAnyHeader()
|
||||||
.AllowCredentials());
|
.AllowCredentials());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddTransient<IMarketingDataRepository, MarketingDataRepository>();
|
||||||
|
|
||||||
|
//configure autofac
|
||||||
|
var container = new ContainerBuilder();
|
||||||
|
container.Populate(services);
|
||||||
|
|
||||||
|
return new AutofacServiceProvider(container.Build());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
@ -100,11 +133,12 @@
|
|||||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
|
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ConfigureEventBus(app);
|
||||||
|
|
||||||
MarketingContextSeed.SeedAsync(app, loggerFactory)
|
MarketingContextSeed.SeedAsync(app, loggerFactory)
|
||||||
.Wait();
|
.Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected virtual void ConfigureAuth(IApplicationBuilder app)
|
protected virtual void ConfigureAuth(IApplicationBuilder app)
|
||||||
{
|
{
|
||||||
var identityUrl = Configuration.GetValue<string>("IdentityUrl");
|
var identityUrl = Configuration.GetValue<string>("IdentityUrl");
|
||||||
@ -115,5 +149,22 @@
|
|||||||
RequireHttpsMetadata = false
|
RequireHttpsMetadata = false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void RegisterServiceBus(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IEventBus, EventBusRabbitMQ>();
|
||||||
|
services.AddSingleton<IEventBusSubscriptionsManager,
|
||||||
|
InMemoryEventBusSubscriptionsManager>();
|
||||||
|
|
||||||
|
services.AddTransient<IIntegrationEventHandler<UserLocationUpdatedIntegrationEvent>,
|
||||||
|
UserLocationUpdatedIntegrationEventHandler>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConfigureEventBus(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();
|
||||||
|
eventBus.Subscribe<UserLocationUpdatedIntegrationEvent,
|
||||||
|
IIntegrationEventHandler<UserLocationUpdatedIntegrationEvent>>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,5 +6,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ConnectionString": "127.0.0.1",
|
"ConnectionString": "127.0.0.1",
|
||||||
|
"MongoConnectionString": "mongodb://nosql.data",
|
||||||
|
"MongoDatabase": "MarketingDb",
|
||||||
"IdentityUrl": "http://localhost:5105"
|
"IdentityUrl": "http://localhost:5105"
|
||||||
}
|
}
|
||||||
|
@ -2,16 +2,46 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp1.1</TargetFramework>
|
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||||
|
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||||
|
<PackageTargetFallback>$(PackageTargetFallback);netstandard1.6.1;dnxcore50;portable-net451+win8</PackageTargetFallback>
|
||||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
|
||||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
|
||||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Services\Location\**" />
|
||||||
|
<Compile Remove="Services\Marketing\**" />
|
||||||
|
<EmbeddedResource Remove="Services\Location\**" />
|
||||||
|
<EmbeddedResource Remove="Services\Marketing\**" />
|
||||||
|
<None Remove="Services\Location\**" />
|
||||||
|
<None Remove="Services\Marketing\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="Services\Catalog\settings.json" />
|
<None Remove="Services\Catalog\settings.json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Services\Location\LocationsScenariosBase.cs" />
|
||||||
|
<Compile Include="Services\Location\LocationsTestsStartup.cs" />
|
||||||
|
<Compile Include="Services\Marketing\CampaignScenariosBase.cs" />
|
||||||
|
<Compile Include="Services\Marketing\UserLocationRoleScenariosBase.cs" />
|
||||||
|
<Compile Include="Services\Marketing\MarketingScenarios.cs" />
|
||||||
|
<Compile Include="Services\Marketing\MarketingScenariosBase.cs" />
|
||||||
|
<Compile Include="Services\Marketing\MarketingTestsStartup.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Services\Catalog\settings.json">
|
<Content Include="Services\Catalog\settings.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="Services\Location\appsettings.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
<Content Include="Services\Marketing\appsettings.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -25,6 +55,8 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\..\src\Services\Basket\Basket.API\Basket.API.csproj" />
|
<ProjectReference Include="..\..\..\src\Services\Basket\Basket.API\Basket.API.csproj" />
|
||||||
<ProjectReference Include="..\..\..\src\Services\Catalog\Catalog.API\Catalog.API.csproj" />
|
<ProjectReference Include="..\..\..\src\Services\Catalog\Catalog.API\Catalog.API.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\src\Services\Location\Locations.API\Locations.API.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\src\Services\Marketing\Marketing.API\Marketing.API.csproj" />
|
||||||
<ProjectReference Include="..\..\..\src\Services\Ordering\Ordering.API\Ordering.API.csproj" />
|
<ProjectReference Include="..\..\..\src\Services\Ordering\Ordering.API\Ordering.API.csproj" />
|
||||||
<ProjectReference Include="..\..\..\src\Web\WebMVC\WebMVC.csproj" />
|
<ProjectReference Include="..\..\..\src\Web\WebMVC\WebMVC.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@ -33,6 +65,9 @@
|
|||||||
<None Update="appsettings.json">
|
<None Update="appsettings.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Update="Services\Locations\appsettings.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
<None Update="Services\Ordering\settings.json">
|
<None Update="Services\Ordering\settings.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
@ -18,7 +18,7 @@ namespace FunctionalTests.Middleware
|
|||||||
public async Task Invoke(HttpContext httpContext)
|
public async Task Invoke(HttpContext httpContext)
|
||||||
{
|
{
|
||||||
var identity = new ClaimsIdentity("cookies");
|
var identity = new ClaimsIdentity("cookies");
|
||||||
identity.AddClaim(new Claim("sub", "1234"));
|
identity.AddClaim(new Claim("sub", "9e3163b9-1ae6-4652-9dc6-7898ab7b7a00"));
|
||||||
httpContext.User.AddIdentity(identity);
|
httpContext.User.AddIdentity(identity);
|
||||||
await _next.Invoke(httpContext);
|
await _next.Invoke(httpContext);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
namespace FunctionalTests.Services.Locations
|
||||||
|
{
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.TestHost;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
public class LocationsScenariosBase
|
||||||
|
{
|
||||||
|
public TestServer CreateServer()
|
||||||
|
{
|
||||||
|
var webHostBuilder = new WebHostBuilder();
|
||||||
|
webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory() + "\\Services\\Location");
|
||||||
|
webHostBuilder.UseStartup<LocationsTestsStartup>();
|
||||||
|
|
||||||
|
return new TestServer(webHostBuilder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Get
|
||||||
|
{
|
||||||
|
public static string Locations = "api/v1/locations";
|
||||||
|
|
||||||
|
public static string LocationBy(string id)
|
||||||
|
{
|
||||||
|
return $"api/v1/locations/{id}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string UserLocationBy(Guid id)
|
||||||
|
{
|
||||||
|
return $"api/v1/locations/user/{id}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Post
|
||||||
|
{
|
||||||
|
public static string AddNewLocation = "api/v1/locations/";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
namespace FunctionalTests.Services.Locations
|
||||||
|
{
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Locations.API;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
public class LocationsTestsStartup : Startup
|
||||||
|
{
|
||||||
|
public LocationsTestsStartup(IHostingEnvironment env) : base(env)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ConfigureAuth(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant())
|
||||||
|
{
|
||||||
|
app.UseMiddleware<LocationAuthorizeMiddleware>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base.ConfigureAuth(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LocationAuthorizeMiddleware
|
||||||
|
{
|
||||||
|
private readonly RequestDelegate _next;
|
||||||
|
public LocationAuthorizeMiddleware(RequestDelegate rd)
|
||||||
|
{
|
||||||
|
_next = rd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Invoke(HttpContext httpContext)
|
||||||
|
{
|
||||||
|
var identity = new ClaimsIdentity("cookies");
|
||||||
|
identity.AddClaim(new Claim("sub", "4611ce3f-380d-4db5-8d76-87a8689058ed"));
|
||||||
|
httpContext.User.AddIdentity(identity);
|
||||||
|
await _next.Invoke(httpContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"ConnectionString": "mongodb://localhost:27017",
|
||||||
|
"Database": "LocationsDb",
|
||||||
|
"ExternalCatalogBaseUrl": "http://localhost:5101",
|
||||||
|
"IdentityUrl": "http://localhost:5105",
|
||||||
|
"isTest": "true",
|
||||||
|
"EventBusConnection": "localhost"
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
namespace FunctionalTests.Services.Marketing
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
|
||||||
|
public class CampaignScenariosBase : MarketingScenariosBase
|
||||||
|
{
|
||||||
|
public static class Get
|
||||||
|
{
|
||||||
|
public static string Campaigns = CampaignsUrlBase;
|
||||||
|
|
||||||
|
public static string CampaignBy(int id)
|
||||||
|
=> $"{CampaignsUrlBase}/{id}";
|
||||||
|
|
||||||
|
public static string UserCampaignsByUserId(Guid userId)
|
||||||
|
=> $"{CampaignsUrlBase}/user/{userId}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Post
|
||||||
|
{
|
||||||
|
public static string AddNewCampaign = CampaignsUrlBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Put
|
||||||
|
{
|
||||||
|
public static string CampaignBy(int id)
|
||||||
|
=> $"{CampaignsUrlBase}/{id}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Delete
|
||||||
|
{
|
||||||
|
public static string CampaignBy(int id)
|
||||||
|
=> $"{CampaignsUrlBase}/{id}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,58 @@
|
|||||||
|
namespace FunctionalTests.Services.Marketing
|
||||||
|
{
|
||||||
|
using UserLocation = Microsoft.eShopOnContainers.Services.Locations.API.Model.UserLocation;
|
||||||
|
using LocationRequest = Microsoft.eShopOnContainers.Services.Locations.API.ViewModel.LocationRequest;
|
||||||
|
using FunctionalTests.Services.Locations;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API.Dto;
|
||||||
|
|
||||||
|
public class MarketingScenarios : MarketingScenariosBase
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task Set_new_user_location_and_get_location_campaign_by_user_id()
|
||||||
|
{
|
||||||
|
using (var locationsServer = new LocationsScenariosBase().CreateServer())
|
||||||
|
using (var marketingServer = new MarketingScenariosBase().CreateServer())
|
||||||
|
{
|
||||||
|
var location = new LocationRequest
|
||||||
|
{
|
||||||
|
Longitude = -122.315752,
|
||||||
|
Latitude = 47.604610
|
||||||
|
};
|
||||||
|
var content = new StringContent(JsonConvert.SerializeObject(location),
|
||||||
|
Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
var userId = new Guid("4611ce3f-380d-4db5-8d76-87a8689058ed");
|
||||||
|
|
||||||
|
|
||||||
|
// GIVEN a new location of user is created
|
||||||
|
var response = await locationsServer.CreateClient()
|
||||||
|
.PostAsync(LocationsScenariosBase.Post.AddNewLocation, content);
|
||||||
|
|
||||||
|
//Get location user from Location.API
|
||||||
|
var userLocationResponse = await locationsServer.CreateClient()
|
||||||
|
.GetAsync(LocationsScenariosBase.Get.UserLocationBy(userId));
|
||||||
|
|
||||||
|
var responseBody = await userLocationResponse.Content.ReadAsStringAsync();
|
||||||
|
var userLocation = JsonConvert.DeserializeObject<UserLocation>(responseBody);
|
||||||
|
|
||||||
|
await Task.Delay(300);
|
||||||
|
|
||||||
|
//Get campaing from Marketing.API given a userId
|
||||||
|
var UserLocationCampaignResponse = await marketingServer.CreateClient()
|
||||||
|
.GetAsync(CampaignScenariosBase.Get.UserCampaignsByUserId(userId));
|
||||||
|
|
||||||
|
responseBody = await UserLocationCampaignResponse.Content.ReadAsStringAsync();
|
||||||
|
var userLocationCampaigns = JsonConvert.DeserializeObject<List<CampaignDTO>>(responseBody);
|
||||||
|
|
||||||
|
Assert.True(userLocationCampaigns.Count > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
namespace FunctionalTests.Services.Marketing
|
||||||
|
{
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.TestHost;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
public class MarketingScenariosBase
|
||||||
|
{
|
||||||
|
public static string CampaignsUrlBase => "api/v1/campaigns";
|
||||||
|
|
||||||
|
public TestServer CreateServer()
|
||||||
|
{
|
||||||
|
var webHostBuilder = new WebHostBuilder();
|
||||||
|
webHostBuilder.UseContentRoot(Directory.GetCurrentDirectory() + "\\Services\\Marketing");
|
||||||
|
webHostBuilder.UseStartup<MarketingTestsStartup>();
|
||||||
|
|
||||||
|
return new TestServer(webHostBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
namespace FunctionalTests.Services.Marketing
|
||||||
|
{
|
||||||
|
using Microsoft.eShopOnContainers.Services.Marketing.API;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using FunctionalTests.Middleware;
|
||||||
|
|
||||||
|
public class MarketingTestsStartup : Startup
|
||||||
|
{
|
||||||
|
public MarketingTestsStartup(IHostingEnvironment env) : base(env)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void ConfigureAuth(IApplicationBuilder app)
|
||||||
|
{
|
||||||
|
if (Configuration["isTest"] == bool.TrueString.ToLowerInvariant())
|
||||||
|
{
|
||||||
|
app.UseMiddleware<AutoAuthorizeMiddleware>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base.ConfigureAuth(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
namespace FunctionalTests.Services.Marketing
|
||||||
|
{
|
||||||
|
public class UserLocationRoleScenariosBase : MarketingScenariosBase
|
||||||
|
{
|
||||||
|
private const string EndpointLocationName = "locations";
|
||||||
|
public static class Get
|
||||||
|
{
|
||||||
|
public static string UserLocationRulesByCampaignId(int campaignId)
|
||||||
|
=> GetUserLocationRolesUrlBase(campaignId);
|
||||||
|
|
||||||
|
public static string UserLocationRuleByCampaignAndUserLocationRuleId(int campaignId,
|
||||||
|
int userLocationRuleId)
|
||||||
|
=> $"{GetUserLocationRolesUrlBase(campaignId)}/{userLocationRuleId}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Post
|
||||||
|
{
|
||||||
|
public static string AddNewuserLocationRule(int campaignId)
|
||||||
|
=> GetUserLocationRolesUrlBase(campaignId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Put
|
||||||
|
{
|
||||||
|
public static string UserLocationRoleBy(int campaignId,
|
||||||
|
int userLocationRuleId)
|
||||||
|
=> $"{GetUserLocationRolesUrlBase(campaignId)}/{userLocationRuleId}";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Delete
|
||||||
|
{
|
||||||
|
public static string UserLocationRoleBy(int campaignId,
|
||||||
|
int userLocationRuleId)
|
||||||
|
=> $"{GetUserLocationRolesUrlBase(campaignId)}/{userLocationRuleId}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static string GetUserLocationRolesUrlBase(int campaignId)
|
||||||
|
=> $"{CampaignsUrlBase}/{campaignId}/{EndpointLocationName}";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"ConnectionString": "Server=tcp:127.0.0.1,5433;Initial Catalog=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word",
|
||||||
|
"MongoConnectionString": "mongodb://localhost:27017",
|
||||||
|
"MongoDatabase": "MarketingDb",
|
||||||
|
"IdentityUrl": "http://localhost:5105",
|
||||||
|
"isTest": "true",
|
||||||
|
"EventBusConnection": "localhost"
|
||||||
|
}
|
@ -88,7 +88,7 @@ namespace FunctionalTests.Services.Ordering
|
|||||||
|
|
||||||
string BuildBasket()
|
string BuildBasket()
|
||||||
{
|
{
|
||||||
var order = new CustomerBasket("1234");
|
var order = new CustomerBasket("9e3163b9-1ae6-4652-9dc6-7898ab7b7a00");
|
||||||
order.Items = new List<Microsoft.eShopOnContainers.Services.Basket.API.Model.BasketItem>()
|
order.Items = new List<Microsoft.eShopOnContainers.Services.Basket.API.Model.BasketItem>()
|
||||||
{
|
{
|
||||||
new Microsoft.eShopOnContainers.Services.Basket.API.Model.BasketItem()
|
new Microsoft.eShopOnContainers.Services.Basket.API.Model.BasketItem()
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp1.1</TargetFramework>
|
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||||
<AssemblyName>IntegrationTests</AssemblyName>
|
<AssemblyName>FunctionalTests</AssemblyName>
|
||||||
<PackageId>FunctionalTests</PackageId>
|
<PackageId>FunctionalTests</PackageId>
|
||||||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||||
<PackageTargetFallback>$(PackageTargetFallback);netstandard1.6.1;dnxcore50;portable-net451+win8</PackageTargetFallback>
|
<PackageTargetFallback>$(PackageTargetFallback);netstandard1.6.1;dnxcore50;portable-net451+win8</PackageTargetFallback>
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.TestHost;
|
using Microsoft.AspNetCore.TestHost;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace IntegrationTests.Services.Locations
|
namespace IntegrationTests.Services.Locations
|
||||||
{
|
{
|
||||||
@ -22,12 +19,12 @@ namespace IntegrationTests.Services.Locations
|
|||||||
{
|
{
|
||||||
public static string Locations = "api/v1/locations";
|
public static string Locations = "api/v1/locations";
|
||||||
|
|
||||||
public static string LocationBy(string id)
|
public static string LocationBy(int id)
|
||||||
{
|
{
|
||||||
return $"api/v1/locations/{id}";
|
return $"api/v1/locations/{id}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string UserLocationBy(Guid id)
|
public static string UserLocationBy(string id)
|
||||||
{
|
{
|
||||||
return $"api/v1/locations/user/{id}";
|
return $"api/v1/locations/user/{id}";
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ namespace IntegrationTests.Services.Locations
|
|||||||
{
|
{
|
||||||
using (var server = CreateServer())
|
using (var server = CreateServer())
|
||||||
{
|
{
|
||||||
var userId = new Guid("4611ce3f-380d-4db5-8d76-87a8689058ed");
|
var userId = "4611ce3f-380d-4db5-8d76-87a8689058ed";
|
||||||
var content = new StringContent(BuildLocationsRequest(-122.315752, 47.604610), UTF8Encoding.UTF8, "application/json");
|
var content = new StringContent(BuildLocationsRequest(-122.315752, 47.604610), UTF8Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
// Expected result
|
// Expected result
|
||||||
@ -51,7 +51,7 @@ namespace IntegrationTests.Services.Locations
|
|||||||
{
|
{
|
||||||
using (var server = CreateServer())
|
using (var server = CreateServer())
|
||||||
{
|
{
|
||||||
var userId = new Guid("4611ce3f-380d-4db5-8d76-87a8689058ed");
|
var userId = "4611ce3f-380d-4db5-8d76-87a8689058ed";
|
||||||
var content = new StringContent(BuildLocationsRequest(-122.119998, 47.690876), UTF8Encoding.UTF8, "application/json");
|
var content = new StringContent(BuildLocationsRequest(-122.119998, 47.690876), UTF8Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
// Expected result
|
// Expected result
|
||||||
@ -83,7 +83,7 @@ namespace IntegrationTests.Services.Locations
|
|||||||
{
|
{
|
||||||
using (var server = CreateServer())
|
using (var server = CreateServer())
|
||||||
{
|
{
|
||||||
var userId = new Guid("4611ce3f-380d-4db5-8d76-87a8689058ed");
|
var userId = "4611ce3f-380d-4db5-8d76-87a8689058ed";
|
||||||
var content = new StringContent(BuildLocationsRequest(-121.040360, 48.091631), UTF8Encoding.UTF8, "application/json");
|
var content = new StringContent(BuildLocationsRequest(-121.040360, 48.091631), UTF8Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
// Expected result
|
// Expected result
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"ConnectionString": "Server=tcp:127.0.0.1,5433;Initial Catalog=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word",
|
"ConnectionString": "Server=tcp:127.0.0.1,5433;Initial Catalog=Microsoft.eShopOnContainers.Services.MarketingDb;User Id=sa;Password=Pass@word",
|
||||||
|
"MongoConnectionString": "mongodb://localhost:27017",
|
||||||
|
"MongoDatabase": "MarketingDb",
|
||||||
"IdentityUrl": "http://localhost:5105",
|
"IdentityUrl": "http://localhost:5105",
|
||||||
"isTest": "true"
|
"isTest": "true",
|
||||||
|
"EventBusConnection": "localhost"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user