This commit is contained in:
parent
6437336228
commit
1469b03c16
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
|
||||||
namespace BlueWest.Collections
|
namespace BlueWest.Collections
|
||||||
{
|
{
|
||||||
|
@ -131,6 +132,15 @@ namespace BlueWest.Collections
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts To a generic List
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">Item.</param>
|
||||||
|
public System.Collections.Immutable.ImmutableArray<T> ToList()
|
||||||
|
{
|
||||||
|
return Buffer.ToImmutableArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// if the buffer is at its max more space will be allocated to fit additionalItemCount
|
/// if the buffer is at its max more space will be allocated to fit additionalItemCount
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
#nullable enable
|
using System;
|
||||||
using System;
|
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace BlueWest.WebApi.Tools
|
namespace BlueWest.Collections
|
||||||
{
|
{
|
||||||
public static class IEnumerableExtensions
|
public static class IEnumerableExtensions
|
||||||
{
|
{
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MapTo" Version="0.9.1" />
|
<PackageReference Include="MapTo" Version="0.9.3" />
|
||||||
<PackageReference Include="MessagePack" Version="2.3.85" />
|
<PackageReference Include="MessagePack" Version="2.3.85" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="6.0.4" />
|
<PackageReference Include="Newtonsoft.Json" Version="6.0.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace BlueWest.Data
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Specifies that the annotated class can be mapped from the provided <see cref="SourceType"/>.
|
|
||||||
/// </summary>
|
|
||||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
|
|
||||||
public sealed class AAttribute : Attribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="MapFromAttribute"/> class with the specified <paramref name="sourceType"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sourceType">The type of to map from.</param>
|
|
||||||
public AAttribute(Type sourceType)
|
|
||||||
{
|
|
||||||
SourceType = sourceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the type to map from.
|
|
||||||
/// </summary>
|
|
||||||
public Type SourceType { get; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using BlueWest.Collections;
|
|
||||||
using MapTo;
|
|
||||||
using MessagePack;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace BlueWest.Data
|
|
||||||
{
|
|
||||||
[MessagePackObject]
|
|
||||||
[MapFrom(typeof(UserUpdateDto))]
|
|
||||||
public partial struct User
|
|
||||||
{
|
|
||||||
[Key(1)]public int Id { get; }
|
|
||||||
[Key(2)]public string Name { get; set; }
|
|
||||||
[Key(3)]public string Address { get; set; }
|
|
||||||
|
|
||||||
[Key(4)]public string BTCAddress { get; set; }
|
|
||||||
[Key(5)]public string LTCAddress { get; set; }
|
|
||||||
|
|
||||||
[Key(6)]public double BTCAmount { get; set; }
|
|
||||||
[Key(7)]public double LTCAmount { get; set; }
|
|
||||||
|
|
||||||
[Key(8)] public List<FinanceTransaction> FinanceTransactions { get; set; }
|
|
||||||
|
|
||||||
public User(int id, string name, string address, string btcAddress, string ltcAddress, double btcAmount, double ltcAmount, List<FinanceTransaction> financeTransactions)
|
|
||||||
{
|
|
||||||
Id = id;
|
|
||||||
Name = name;
|
|
||||||
Address = address;
|
|
||||||
BTCAddress = btcAddress;
|
|
||||||
LTCAddress = ltcAddress;
|
|
||||||
BTCAmount = btcAmount;
|
|
||||||
LTCAmount = ltcAmount;
|
|
||||||
FinanceTransactions = financeTransactions;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddTransaction(FinanceTransaction financeTransaction)
|
|
||||||
{
|
|
||||||
FinanceTransactions.Add(financeTransaction);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using BlueWest.Collections;
|
|
||||||
using MessagePack;
|
|
||||||
|
|
||||||
namespace BlueWest.Data
|
|
||||||
{
|
|
||||||
[MessagePackObject]
|
|
||||||
public class UserList: DataObject
|
|
||||||
{
|
|
||||||
[Key(9)] public List<User> Users;
|
|
||||||
|
|
||||||
public UserList(List<User> users)
|
|
||||||
{
|
|
||||||
Users = users;
|
|
||||||
}
|
|
||||||
|
|
||||||
[IgnoreMember]
|
|
||||||
public int Length => Users.Count;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace BlueWest.Data
|
||||||
|
{
|
||||||
|
class DataQueryResult { }
|
||||||
|
|
||||||
|
internal sealed class PositiveResult<T> : DataQueryResult
|
||||||
|
{
|
||||||
|
public readonly T Value;
|
||||||
|
|
||||||
|
public PositiveResult(T value)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal sealed class NegativeResult : DataQueryResult
|
||||||
|
{
|
||||||
|
public readonly string UserMessage;
|
||||||
|
public NegativeResult(string userMessage)
|
||||||
|
{
|
||||||
|
UserMessage = userMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ namespace BlueWest.Data
|
||||||
}
|
}
|
||||||
|
|
||||||
[MessagePackObject]
|
[MessagePackObject]
|
||||||
|
[MapFrom(typeof(FinanceTransactionInsertDto))]
|
||||||
public partial struct FinanceTransaction
|
public partial struct FinanceTransaction
|
||||||
{
|
{
|
||||||
[Key(1)] public int Id { get; set; }
|
[Key(1)] public int Id { get; set; }
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using MapTo;
|
||||||
|
|
||||||
|
namespace BlueWest.Data
|
||||||
|
{
|
||||||
|
[MapFrom(typeof(FinanceTransaction))]
|
||||||
|
|
||||||
|
public partial struct FinanceTransactionInsertDto
|
||||||
|
{
|
||||||
|
public int UserId { get; }
|
||||||
|
public FinanceTransactionType FinanceTransactionType { get; }
|
||||||
|
public FinanceSymbol FinanceSymbol { get; }
|
||||||
|
public double Amount { get; } // To Buy
|
||||||
|
public double Quantity { get; } // Bought
|
||||||
|
public double Fee { get; }
|
||||||
|
public DateTime DateTime { get; }
|
||||||
|
|
||||||
|
public FinanceTransactionInsertDto(
|
||||||
|
int userId,
|
||||||
|
FinanceTransactionType financeTransactionType,
|
||||||
|
FinanceSymbol financeSymbol,
|
||||||
|
double amount ,
|
||||||
|
double quantity,
|
||||||
|
double fee,
|
||||||
|
DateTime dateTime)
|
||||||
|
{
|
||||||
|
UserId = userId;
|
||||||
|
FinanceTransactionType = financeTransactionType;
|
||||||
|
FinanceSymbol = financeSymbol;
|
||||||
|
Amount = amount;
|
||||||
|
Quantity = quantity;
|
||||||
|
Fee = fee;
|
||||||
|
DateTime = dateTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Transactions;
|
||||||
|
using BlueWest.Collections;
|
||||||
|
using MapTo;
|
||||||
|
using MessagePack;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using BlueWest.Collections;
|
||||||
|
|
||||||
|
namespace BlueWest.Data
|
||||||
|
{
|
||||||
|
[MessagePackObject]
|
||||||
|
[UseUpdate]
|
||||||
|
[MapFrom(typeof(UserUpdateDto))]
|
||||||
|
public partial class User
|
||||||
|
{
|
||||||
|
[Key(1)] public int Id { get; }
|
||||||
|
[Key(2)] public string Name { get; set; }
|
||||||
|
[Key(3)] public string Address { get; set; }
|
||||||
|
|
||||||
|
[Key(4)] public string BTCAddress { get; set; }
|
||||||
|
[Key(5)] public string LTCAddress { get; set; }
|
||||||
|
|
||||||
|
[Key(6)] public double BTCAmount { get; set; }
|
||||||
|
[Key(7)] public double LTCAmount { get; set; }
|
||||||
|
|
||||||
|
[Key(8)] public FastDictionary<FinanceTransaction> FinanceTransactions { get; set; }
|
||||||
|
|
||||||
|
public User(int id, string name, string address, string btcAddress, string ltcAddress, double btcAmount, double ltcAmount, FastList<FinanceTransaction> financeTransactions)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
Name = name;
|
||||||
|
Address = address;
|
||||||
|
BTCAddress = btcAddress;
|
||||||
|
LTCAddress = ltcAddress;
|
||||||
|
BTCAmount = btcAmount;
|
||||||
|
LTCAmount = ltcAmount;
|
||||||
|
FinanceTransactions = financeTransactions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddTransaction(FinanceTransaction financeTransaction)
|
||||||
|
{
|
||||||
|
FinanceTransactions.Add(financeTransaction);
|
||||||
|
}
|
||||||
|
public void AddTransaction(FinanceTransactionInsertDto financeTransaction)
|
||||||
|
{
|
||||||
|
FinanceTransactions.Add(new FinanceTransaction(financeTransaction));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool HasTransaction(int transactionId)
|
||||||
|
{
|
||||||
|
return FinanceTransactions.Contains(transactionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Transaction GetTransactionById(int transactionId)
|
||||||
|
{
|
||||||
|
return FinanceTransactions(transactionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace BlueWest.Data
|
||||||
|
{
|
||||||
|
public static class UserExtensions
|
||||||
|
{
|
||||||
|
public static bool UserHasTransaction(this User user, int transactionId)
|
||||||
|
{
|
||||||
|
return user.FinanceTransactions.Contains(transactionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Transactions;
|
||||||
|
using BlueWest.Collections;
|
||||||
|
using MessagePack;
|
||||||
|
|
||||||
|
namespace BlueWest.Data
|
||||||
|
{
|
||||||
|
[MessagePackObject]
|
||||||
|
public class UserList: DataObject
|
||||||
|
{
|
||||||
|
[Key(9)] public readonly FastDictionary<int, User> Users;
|
||||||
|
|
||||||
|
public int Length = 0;
|
||||||
|
|
||||||
|
public UserList(FastDictionary<int, User> users)
|
||||||
|
{
|
||||||
|
Users = users;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetIndexById(int userId)
|
||||||
|
{
|
||||||
|
var keys = Users.Keys;
|
||||||
|
|
||||||
|
foreach (var key in keys)
|
||||||
|
{
|
||||||
|
if (key == userId) return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal DataQueryResult GetUserById(int id)
|
||||||
|
{
|
||||||
|
if (Users.ContainsKey(id)) return new PositiveResult<User>(Users[id]);
|
||||||
|
return new NegativeResult("Can't find a user with the provided id.");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool RemoveUser(int userId)
|
||||||
|
{
|
||||||
|
if (Users.ContainsKey(userId))
|
||||||
|
{
|
||||||
|
Users.Remove(userId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal bool HasUser(int userId)
|
||||||
|
{
|
||||||
|
return Users.Contains(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal DataQueryResult UpdateUser(int userId, UserUpdateDto userUpdate)
|
||||||
|
{
|
||||||
|
Users[userId].Update(userUpdate);
|
||||||
|
return Users[userId];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal bool UserHasTransaction(int userId, int transactionId) => HasUser(userId) && Users[userId].FinanceTransactions.Contains(transactionId);
|
||||||
|
|
||||||
|
internal DataQueryResult GetTransactionById(int userId, int transactionId)
|
||||||
|
{
|
||||||
|
if(!HasUser(userId)) return new NegativeResult("Can't find a user with the provided id.");
|
||||||
|
|
||||||
|
if (UserHasTransaction(userId, transactionId)) return new PositiveResult<Transaction>(Users[userId].FinanceTransactions[transactionId]);
|
||||||
|
|
||||||
|
return new NegativeResult("No transaction was found with the specified id");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal User AddUser(int userId, UserUpdateDto userUpdateDto)
|
||||||
|
{
|
||||||
|
if (Users.ContainsKey(userId))
|
||||||
|
{
|
||||||
|
Users[userId].Update(userUpdateDto);
|
||||||
|
return Users[userId];
|
||||||
|
}
|
||||||
|
|
||||||
|
var id = userId != -1 ? userId : Length + 1;
|
||||||
|
|
||||||
|
var newUser = new User(userUpdateDto, id, new FastList<FinanceTransaction>());
|
||||||
|
|
||||||
|
Users.Add(Length, newUser);
|
||||||
|
|
||||||
|
Length++;
|
||||||
|
|
||||||
|
return newUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
const string NoIdError = "No transaction was found with the specified id";
|
||||||
|
|
||||||
|
static NegativeResult NoIdResult = new NegativeResult(NoIdError);
|
||||||
|
internal DataQueryResult AddFinanceTransaction(int userId, FinanceTransactionInsertDto financeTransactionDto)
|
||||||
|
{
|
||||||
|
if (Users.ContainsKey(userId))
|
||||||
|
{
|
||||||
|
var financeTransaction = new FinanceTransaction(financeTransactionDto);
|
||||||
|
Users[userId].AddTransaction(financeTransaction);
|
||||||
|
return new PositiveResult<BlueWest.Data.FinanceTransaction>(financeTransaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NoIdResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal FastList<FinanceTransaction> GetUserTransactions(int userId)
|
||||||
|
{
|
||||||
|
if (Users.ContainsKey(userId))
|
||||||
|
{
|
||||||
|
return Users[userId].FinanceTransactions;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FastList<FinanceTransaction>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Grpc.Net.Client" Version="2.41.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Protobuf Include="Protos\greet.proto">
|
||||||
|
<GrpcServices>Both</GrpcServices>
|
||||||
|
<Access>Public</Access>
|
||||||
|
<ProtoCompile>True</ProtoCompile>
|
||||||
|
<CompileOutputs>True</CompileOutputs>
|
||||||
|
<OutputDir>obj\Release\net5.0-windows\</OutputDir>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Protobuf>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using Grpc.Net.Client;
|
||||||
|
|
||||||
|
namespace BlueWest.GrpcClient
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
var channel = GrpcChannel.ForAddress("https://localhost:5001");
|
||||||
|
//var client = new Greet.GreeterClient(channel);
|
||||||
|
Console.WriteLine("Hello, World!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
service Greeter {
|
||||||
|
rpc SayHello (HelloRequest) returns (HelloReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
message HelloRequest {
|
||||||
|
string name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HelloReply {
|
||||||
|
string message = 1;
|
||||||
|
}
|
|
@ -1,18 +1,23 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net5.0-windows</TargetFramework>
|
||||||
<LangVersion>9</LangVersion>
|
<LangVersion>10</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.0" />
|
<PackageReference Include="Grpc.AspNetCore" Version="2.41.0" />
|
||||||
|
<PackageReference Include="Grpc.AspNetCore.Server" Version="2.41.0" />
|
||||||
|
<PackageReference Include="Grpc.AspNetCore.Web" Version="2.41.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.12" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="6.2.3" />
|
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="6.2.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\BlueWest\BlueWest.csproj" />
|
<ProjectReference Include="..\BlueWest\BlueWest.csproj" />
|
||||||
|
<Protobuf Include="Protos\greet.proto" />
|
||||||
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using BlueWest.Data;
|
using BlueWest.Core.Tests;
|
||||||
using BlueWest.WebApi.Tools;
|
using BlueWest.Data;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using PerformanceSolution.Data;
|
using PerformanceSolution.Data;
|
||||||
|
@ -10,14 +10,15 @@ namespace BlueWest.WebApi.Controllers
|
||||||
[Route("[controller]")]
|
[Route("[controller]")]
|
||||||
public class UserController : ControllerBase
|
public class UserController : ControllerBase
|
||||||
{
|
{
|
||||||
|
private UserList _userList => MemoryData.UserList;
|
||||||
|
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public ActionResult Get()
|
public ActionResult Get()
|
||||||
{
|
{
|
||||||
if (MemoryData.UserList != null)
|
if (_userList != null)
|
||||||
{
|
{
|
||||||
return Ok(MemoryData.UserList);
|
return Ok(_userList);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,11 +31,11 @@ namespace BlueWest.WebApi.Controllers
|
||||||
[HttpGet("{userId}", Name = nameof(GetUserById))]
|
[HttpGet("{userId}", Name = nameof(GetUserById))]
|
||||||
public ActionResult GetUserById(int userId)
|
public ActionResult GetUserById(int userId)
|
||||||
{
|
{
|
||||||
User user = MemoryData.GetUserById(userId);
|
User? user = MemoryData.GetUserById(userId);
|
||||||
|
|
||||||
if (user != null)
|
if (user != null)
|
||||||
{
|
{
|
||||||
return Ok(user);
|
return Ok(user.Value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,14 +48,8 @@ namespace BlueWest.WebApi.Controllers
|
||||||
[HttpGet("{userId}/transactions")]
|
[HttpGet("{userId}/transactions")]
|
||||||
public ActionResult GetTransactions(int userId)
|
public ActionResult GetTransactions(int userId)
|
||||||
{
|
{
|
||||||
var user = MemoryData.GetUserById(userId);
|
var transactions = MemoryData.GetUserTransactions(userId);
|
||||||
var transactions = user.FinanceTransactions;
|
return OK(transactions.ToDictionary());
|
||||||
if (transactions != null)
|
|
||||||
{
|
|
||||||
return Ok(transactions);
|
|
||||||
|
|
||||||
}
|
|
||||||
return new NotFoundResult();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,7 +58,7 @@ namespace BlueWest.WebApi.Controllers
|
||||||
[HttpGet("{userId}/transactions/{transactionId}")]
|
[HttpGet("{userId}/transactions/{transactionId}")]
|
||||||
public ActionResult GetTransactionsById(int userId, int transactionId)
|
public ActionResult GetTransactionsById(int userId, int transactionId)
|
||||||
{
|
{
|
||||||
var user = MemoryData.GetUserById(userId);
|
var user = MemoryData.UserList.GetUserById(userId);
|
||||||
|
|
||||||
var transactions = user?.FinanceTransactions;
|
var transactions = user?.FinanceTransactions;
|
||||||
|
|
||||||
|
@ -91,7 +86,7 @@ namespace BlueWest.WebApi.Controllers
|
||||||
[HttpPut("{userId}")]
|
[HttpPut("{userId}")]
|
||||||
public ActionResult UpdateUser(int userId, UserUpdateDto userUpdate)
|
public ActionResult UpdateUser(int userId, UserUpdateDto userUpdate)
|
||||||
{
|
{
|
||||||
var result = MemoryData.UpdateUser(userId, userUpdate);
|
var result = MemoryData.UserList.UpdateUser(userId, userUpdate);
|
||||||
|
|
||||||
if (result != null) return Ok(result);
|
if (result != null) return Ok(result);
|
||||||
|
|
||||||
|
@ -103,8 +98,7 @@ namespace BlueWest.WebApi.Controllers
|
||||||
[HttpDelete("{id}")]
|
[HttpDelete("{id}")]
|
||||||
public ActionResult DeleteUser(int id)
|
public ActionResult DeleteUser(int id)
|
||||||
{
|
{
|
||||||
|
bool result = MemoryData.UserList.RemoveUser(id);
|
||||||
bool result = MemoryData.RemoveUser(id);
|
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
|
@ -117,9 +111,9 @@ namespace BlueWest.WebApi.Controllers
|
||||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||||
[HttpPost("{userId}/transactions")]
|
[HttpPost("{userId}/transactions")]
|
||||||
public ActionResult PostTransaction(int userId, FinanceTransaction financeTransaction)
|
public ActionResult PostTransaction(int userId, FinanceTransactionInsertDto financeTransaction)
|
||||||
{
|
{
|
||||||
FinanceTransaction? result = MemoryData.AddFinanceTransaction(userId, financeTransaction);
|
FinanceTransaction? result = MemoryData.UserList.AddFinanceTransaction(userId, financeTransaction);
|
||||||
|
|
||||||
if(result != null) return Ok(result);
|
if(result != null) return Ok(result);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
service Greeter {
|
||||||
|
rpc SayHello (HelloRequest) returns (HelloReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
message HelloRequest {
|
||||||
|
string name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HelloReply {
|
||||||
|
string message = 1;
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace BlueWest.WebApi.Service
|
||||||
|
{
|
||||||
|
public class GreeterService : Greeter.GreeterBase
|
||||||
|
{
|
||||||
|
public GreeterService(ILogger<GreeterService> logger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using BlueWest.WebApi.Service;
|
||||||
using BlueWest.WebApi.Tools;
|
using BlueWest.WebApi.Tools;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
@ -56,6 +57,8 @@ namespace BlueWest.WebApi
|
||||||
Version = "v1"
|
Version = "v1"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
services.AddGrpc();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
|
@ -79,6 +82,8 @@ namespace BlueWest.WebApi
|
||||||
app.UseEndpoints(endpoints =>
|
app.UseEndpoints(endpoints =>
|
||||||
{
|
{
|
||||||
endpoints.MapControllers();
|
endpoints.MapControllers();
|
||||||
|
endpoints.MapGrpcService<GreeterService>();
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlueWest.WebApi", "BlueWest
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlueWest.Collections", "BlueWest.Collections\BlueWest.Collections.csproj", "{F55019A2-E2A8-4AF1-8FBC-FA99476A1B1C}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlueWest.Collections", "BlueWest.Collections\BlueWest.Collections.csproj", "{F55019A2-E2A8-4AF1-8FBC-FA99476A1B1C}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlueWest.GrpcClient", "BlueWest.GrpcClient\BlueWest.GrpcClient.csproj", "{65A6A17A-EFFB-4750-8B80-3B0690CCA59F}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -33,6 +35,10 @@ Global
|
||||||
{F55019A2-E2A8-4AF1-8FBC-FA99476A1B1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{F55019A2-E2A8-4AF1-8FBC-FA99476A1B1C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{F55019A2-E2A8-4AF1-8FBC-FA99476A1B1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{F55019A2-E2A8-4AF1-8FBC-FA99476A1B1C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{F55019A2-E2A8-4AF1-8FBC-FA99476A1B1C}.Release|Any CPU.Build.0 = Release|Any CPU
|
{F55019A2-E2A8-4AF1-8FBC-FA99476A1B1C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{65A6A17A-EFFB-4750-8B80-3B0690CCA59F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{65A6A17A-EFFB-4750-8B80-3B0690CCA59F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{65A6A17A-EFFB-4750-8B80-3B0690CCA59F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{65A6A17A-EFFB-4750-8B80-3B0690CCA59F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -37,13 +37,16 @@ namespace BlueWest.Core
|
||||||
return eoDynamic;
|
return eoDynamic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
private static T DictionaryToObject<T>(IDictionary<String, Object> dictionary) where T : class
|
private static T DictionaryToObject<T>(IDictionary<String, Object> dictionary) where T : class
|
||||||
{
|
{
|
||||||
var dicToObj = DictionaryToObject(dictionary);
|
var dicToObj = DictionaryToObject(dictionary);
|
||||||
return dicToObj as T;
|
return dicToObj as T;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
public static T ToDto<T>(this object obj) where T: class
|
public static T ToDto<T>(this object obj) where T: class
|
||||||
{
|
{
|
||||||
var objDic = obj.ToDictionary();
|
var objDic = obj.ToDictionary();
|
||||||
|
@ -61,6 +64,6 @@ namespace BlueWest.Core
|
||||||
}
|
}
|
||||||
|
|
||||||
return dataInstance;
|
return dataInstance;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,9 +13,9 @@ namespace BlueWest.Core.Tests
|
||||||
private static readonly ConcurrentDictionary<Type, Func<object, IDictionary<string, object>>> Converters = new ConcurrentDictionary<Type, Func<object, IDictionary<string, object>>>();
|
private static readonly ConcurrentDictionary<Type, Func<object, IDictionary<string, object>>> Converters = new ConcurrentDictionary<Type, Func<object, IDictionary<string, object>>>();
|
||||||
private static readonly ConstructorInfo DictionaryConstructor = typeof(Dictionary<string, object>).GetConstructors().FirstOrDefault(c => c.IsPublic && !c.GetParameters().Any());
|
private static readonly ConstructorInfo DictionaryConstructor = typeof(Dictionary<string, object>).GetConstructors().FirstOrDefault(c => c.IsPublic && !c.GetParameters().Any());
|
||||||
|
|
||||||
public static IDictionary<string, object> ToDictionary(this object obj) => obj == null ? null : Converters.GetOrAdd(obj.GetType(), o =>
|
public static IDictionary<int, object> ToDictionary(this object obj) => obj == null ? null : Converters.GetOrAdd(obj.GetType(), o =>
|
||||||
{
|
{
|
||||||
var outputType = typeof(IDictionary<string, object>);
|
var outputType = typeof(IDictionary<int, object>);
|
||||||
var inputType = obj.GetType();
|
var inputType = obj.GetType();
|
||||||
var inputExpression = Expression.Parameter(typeof(object), "input");
|
var inputExpression = Expression.Parameter(typeof(object), "input");
|
||||||
var typedInputExpression = Expression.Convert(inputExpression, inputType);
|
var typedInputExpression = Expression.Convert(inputExpression, inputType);
|
||||||
|
@ -27,14 +27,14 @@ namespace BlueWest.Core.Tests
|
||||||
};
|
};
|
||||||
body.AddRange(
|
body.AddRange(
|
||||||
from prop in inputType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy)
|
from prop in inputType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy)
|
||||||
where prop.CanRead && (prop.PropertyType.IsPrimitive || prop.PropertyType == typeof(string))
|
where prop.CanRead && (prop.PropertyType.IsPrimitive || prop.PropertyType == typeof(int))
|
||||||
let getExpression = Expression.Property(typedInputExpression, prop.GetMethod)
|
let getExpression = Expression.Property(typedInputExpression, prop.GetMethod)
|
||||||
let convertExpression = Expression.Convert(getExpression, typeof(object))
|
let convertExpression = Expression.Convert(getExpression, typeof(object))
|
||||||
select Expression.Call(outputVariable, AddToDicitonaryMethod, Expression.Constant(prop.Name), convertExpression));
|
select Expression.Call(outputVariable, AddToDicitonaryMethod, Expression.Constant(prop.Name), convertExpression));
|
||||||
body.Add(Expression.Return(returnTarget, outputVariable));
|
body.Add(Expression.Return(returnTarget, outputVariable));
|
||||||
body.Add(Expression.Label(returnTarget, Expression.Constant(null, outputType)));
|
body.Add(Expression.Label(returnTarget, Expression.Constant(null, outputType)));
|
||||||
|
|
||||||
var lambdaExpression = Expression.Lambda<Func<object, IDictionary<string, object>>>(
|
var lambdaExpression = Expression.Lambda<Func<object, IDictionary<int, object>>>(
|
||||||
Expression.Block(new[] { outputVariable }, body),
|
Expression.Block(new[] { outputVariable }, body),
|
||||||
inputExpression);
|
inputExpression);
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Transactions;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using BlueWest.Collections;
|
using BlueWest.Collections;
|
||||||
using BlueWest.Core;
|
|
||||||
using BlueWest.Data;
|
using BlueWest.Data;
|
||||||
using PerformanceSolution.Tools;
|
using PerformanceSolution.Tools;
|
||||||
|
|
||||||
|
@ -11,7 +9,7 @@ namespace PerformanceSolution.Data
|
||||||
{
|
{
|
||||||
public static class MemoryData
|
public static class MemoryData
|
||||||
{
|
{
|
||||||
public static UserList UserList = new UserList(new List<User>());
|
public static UserList UserList = new UserList(new FastDictionary<int, User>());
|
||||||
|
|
||||||
private const string SavePathName = "userData";
|
private const string SavePathName = "userData";
|
||||||
|
|
||||||
|
@ -37,119 +35,44 @@ namespace PerformanceSolution.Data
|
||||||
public static void LoadUsers()
|
public static void LoadUsers()
|
||||||
{
|
{
|
||||||
UserList = SaveLoadManager.Load<UserList>(SavePathName);
|
UserList = SaveLoadManager.Load<UserList>(SavePathName);
|
||||||
UserList ??= new UserList(new List<User>());
|
UserList ??= new UserList(new FastDictionary<int, User>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static User? GetUserById(int id)
|
public static Transaction GetTransactionById(int userId, int transactionId) => UserList.GetTransactionById(userId, transactionId);
|
||||||
{
|
|
||||||
var user = UserList.Users.FirstOrDefault(user => user.Id == id);
|
|
||||||
//var d = new UserUpdateDto(user);
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool RemoveUser(int userId)
|
|
||||||
{
|
|
||||||
int index = GetIndexById(userId);
|
|
||||||
if (index == -1) return false;
|
|
||||||
UserList.Users.RemoveAt(index);
|
|
||||||
SaveUserList();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public static async Task AddUserAsync(User user) => await Task.Run(() => { AddOrModifyUser(user); });
|
|
||||||
|
|
||||||
private static int GetIndexById(int userId) => UserList.Users.FindIndex(row => row.Id == userId);
|
|
||||||
|
|
||||||
private static void SaveUserList() => SaveUserList(UserList);
|
private static void SaveUserList() => SaveUserList(UserList);
|
||||||
|
|
||||||
public static void AddOrModifyUser(User user)
|
public static User AddOrModifyUser(UserUpdateDto userUpdateDto, int userId = -1)
|
||||||
{
|
{
|
||||||
var index = GetIndexById(user.Id);
|
return UserList.AddUser(userId, userUpdateDto);
|
||||||
if (index != -1)
|
|
||||||
{
|
|
||||||
UserList.Users[index] = user;
|
|
||||||
SaveUserList();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UserList.Users.Add(user);
|
|
||||||
SaveUserList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static User? AddOrModifyUser(UserUpdateDto userUpdateDto, int userId = -1)
|
|
||||||
{
|
|
||||||
var id = userId != -1 ? userId : UserList.Length + 1;
|
|
||||||
|
|
||||||
var index = GetIndexById(userId);
|
|
||||||
|
|
||||||
User? user;
|
|
||||||
|
|
||||||
if (index != -1)
|
|
||||||
{
|
|
||||||
user = GetUserById(id);
|
|
||||||
|
|
||||||
if (user == null) return user;
|
|
||||||
|
|
||||||
UserList.Users[index] = user;
|
|
||||||
|
|
||||||
SaveUserList();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
user = new User(userUpdateDto);
|
|
||||||
|
|
||||||
UserList.Users.Add(user);
|
|
||||||
SaveUserList();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static User? UpdateUser(int userId, UserUpdateDto userUpdate)
|
|
||||||
{
|
|
||||||
var index = GetIndexById(userId);
|
|
||||||
|
|
||||||
if (index == -1) return null;
|
|
||||||
|
|
||||||
var actualUser = GetUserById(userId);
|
|
||||||
|
|
||||||
if (actualUser == null) return null;
|
|
||||||
|
|
||||||
actualUser.Update(userUpdate);
|
|
||||||
|
|
||||||
UserList.Users[index] = actualUser;
|
|
||||||
|
|
||||||
SaveUserList();
|
|
||||||
|
|
||||||
return actualUser;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static FinanceTransaction? AddFinanceTransaction(int userId, FinanceTransaction financeTransaction)
|
|
||||||
{
|
|
||||||
var user = GetUserById(userId);
|
|
||||||
|
|
||||||
if (user == null) return null;
|
|
||||||
|
|
||||||
user.AddTransaction(financeTransaction);
|
|
||||||
|
|
||||||
SaveUserList();
|
|
||||||
|
|
||||||
return financeTransaction;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UserList GenerateMockData()
|
private static UserList GenerateMockData()
|
||||||
{
|
{
|
||||||
var u = new User(1, "Rui Sousa", "Sagres", "NOADD", "NOADD", 0 , 0, new List<FinanceTransaction>()
|
|
||||||
{
|
|
||||||
new FinanceTransaction(0, 1, FinanceTransactionType.Buy, FinanceSymbol.BTC_EUR, 0, 0, 0.1, DateTime.Now)
|
var transactions = new FastList<FinanceTransaction>();
|
||||||
});
|
var financeTransaction = new FinanceTransaction(0, 1, FinanceTransactionType.Buy, FinanceSymbol.BTC_EUR, 0,
|
||||||
var list = new List<User>(10);
|
0, 0.1, DateTime.Now);
|
||||||
list.Add(u);
|
transactions.Add(financeTransaction);
|
||||||
|
|
||||||
|
var u = new User(1, "Rui Sousa", "Sagres", "NOADD", "NOADD", 0, 0, transactions);
|
||||||
|
var list = new FastDictionary<int, User>(10);
|
||||||
|
list.Add(0, u);
|
||||||
|
|
||||||
return new UserList(list);
|
return new UserList(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static User? GetUserById(int userId)
|
||||||
|
{
|
||||||
|
return UserList.GetUserById(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FastList<FinanceTransaction> GetUserTransactions(int userId)
|
||||||
|
{
|
||||||
|
return UserList.GetUserTransactions(userId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
2
MapTo
2
MapTo
|
@ -1 +1 @@
|
||||||
Subproject commit 63b2bcb3593440fb332917bed7d6c78827195dbe
|
Subproject commit 9470afb737d873f2fbbc631813eadf10032c5c6b
|
Loading…
Reference in New Issue