Fix db and fix endpoints
This commit is contained in:
@@ -27,4 +27,5 @@ public interface IAgentSummaryRepository
|
|||||||
SortableFields sortBy,
|
SortableFields sortBy,
|
||||||
string sortOrder,
|
string sortOrder,
|
||||||
IEnumerable<string>? agentNames = null);
|
IEnumerable<string>? agentNames = null);
|
||||||
|
Task<IEnumerable<AgentSummary>> GetAllAgentWithRunningBots();
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,7 @@ public interface ITradingRepository
|
|||||||
Task InsertScenarioAsync(Scenario scenario);
|
Task InsertScenarioAsync(Scenario scenario);
|
||||||
Task InsertIndicatorAsync(IndicatorBase indicator);
|
Task InsertIndicatorAsync(IndicatorBase indicator);
|
||||||
Task<IEnumerable<Scenario>> GetScenariosAsync();
|
Task<IEnumerable<Scenario>> GetScenariosAsync();
|
||||||
|
Task<IEnumerable<Scenario>> GetScenariosByUserAsync(User user);
|
||||||
Task<IEnumerable<IndicatorBase>> GetStrategiesAsync();
|
Task<IEnumerable<IndicatorBase>> GetStrategiesAsync();
|
||||||
Task<IEnumerable<IndicatorBase>> GetIndicatorsAsync();
|
Task<IEnumerable<IndicatorBase>> GetIndicatorsAsync();
|
||||||
Task DeleteScenarioAsync(string name);
|
Task DeleteScenarioAsync(string name);
|
||||||
|
|||||||
@@ -7,6 +7,5 @@ public interface IUserRepository
|
|||||||
Task<User> GetUserByAgentNameAsync(string agentName);
|
Task<User> GetUserByAgentNameAsync(string agentName);
|
||||||
Task<User> GetUserByNameAsync(string name);
|
Task<User> GetUserByNameAsync(string name);
|
||||||
Task<IEnumerable<User>> GetAllUsersAsync();
|
Task<IEnumerable<User>> GetAllUsersAsync();
|
||||||
Task InsertUserAsync(User user);
|
Task SaveOrUpdateUserAsync(User user);
|
||||||
Task UpdateUser(User user);
|
|
||||||
}
|
}
|
||||||
@@ -13,4 +13,5 @@ public interface IAgentService
|
|||||||
Task SaveOrUpdateAgentSummary(AgentSummary agentSummary);
|
Task SaveOrUpdateAgentSummary(AgentSummary agentSummary);
|
||||||
|
|
||||||
Task<IEnumerable<AgentSummary>> GetAllAgentSummaries();
|
Task<IEnumerable<AgentSummary>> GetAllAgentSummaries();
|
||||||
|
Task<IEnumerable<string>> GetAllOnlineAgents();
|
||||||
}
|
}
|
||||||
@@ -23,6 +23,7 @@ public interface ITradingService
|
|||||||
Task InsertScenarioAsync(Scenario scenario);
|
Task InsertScenarioAsync(Scenario scenario);
|
||||||
Task InsertIndicatorAsync(IndicatorBase indicatorBase);
|
Task InsertIndicatorAsync(IndicatorBase indicatorBase);
|
||||||
Task<IEnumerable<Scenario>> GetScenariosAsync();
|
Task<IEnumerable<Scenario>> GetScenariosAsync();
|
||||||
|
Task<IEnumerable<Scenario>> GetScenariosByUserAsync(User user);
|
||||||
Task<IEnumerable<IndicatorBase>> GetIndicatorsAsync();
|
Task<IEnumerable<IndicatorBase>> GetIndicatorsAsync();
|
||||||
Task DeleteScenarioAsync(string name);
|
Task DeleteScenarioAsync(string name);
|
||||||
Task DeleteIndicatorAsync(string name);
|
Task DeleteIndicatorAsync(string name);
|
||||||
|
|||||||
@@ -35,52 +35,52 @@ public class AccountService : IAccountService
|
|||||||
_userRepository = userRepository;
|
_userRepository = userRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Account> CreateAccount(User user, Account request)
|
public async Task<Account> CreateAccount(User user, Account account)
|
||||||
{
|
{
|
||||||
var account = await _accountRepository.GetAccountByNameAsync(request.Name);
|
var a = await _accountRepository.GetAccountByNameAsync(account.Name);
|
||||||
|
|
||||||
if (account != null)
|
if (a != null)
|
||||||
{
|
{
|
||||||
throw new Exception($"Account {request.Name} alreary exist");
|
throw new Exception($"Account {account.Name} alreary exist");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
request.User = user;
|
account.User = user;
|
||||||
|
|
||||||
if (request.Exchange == TradingExchanges.Evm
|
if (account.Exchange == TradingExchanges.Evm
|
||||||
&& request.Type == AccountType.Trader)
|
&& account.Type == AccountType.Trader)
|
||||||
{
|
{
|
||||||
var keys = _evmManager.GenerateAddress();
|
var keys = _evmManager.GenerateAddress();
|
||||||
request.Key = keys.Key;
|
account.Key = keys.Key;
|
||||||
request.Secret = keys.Secret;
|
account.Secret = keys.Secret;
|
||||||
}
|
}
|
||||||
else if (request.Exchange == TradingExchanges.Evm
|
else if (account.Exchange == TradingExchanges.Evm
|
||||||
&& request.Type == AccountType.Privy)
|
&& account.Type == AccountType.Privy)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(request.Key))
|
if (string.IsNullOrEmpty(account.Key))
|
||||||
{
|
{
|
||||||
// No key provided, create new privy embedded wallet.
|
// No key provided, create new privy embedded wallet.
|
||||||
// TODO : Fix it to create privy wallet
|
// TODO : Fix it to create privy wallet
|
||||||
var privyClient = await _evmManager.CreatePrivyWallet();
|
var privyClient = await _evmManager.CreatePrivyWallet();
|
||||||
request.Key = privyClient.Address;
|
account.Key = privyClient.Address;
|
||||||
request.Secret = privyClient.Id;
|
account.Secret = privyClient.Id;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
request.Key = request.Key; // Address
|
account.Key = account.Key; // Address
|
||||||
request.Secret = request.Secret; // Privy wallet id
|
account.Secret = account.Secret; // Privy wallet id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
request.Key = request.Key;
|
account.Key = account.Key;
|
||||||
request.Secret = request.Secret;
|
account.Secret = account.Secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _accountRepository.InsertAccountAsync(request);
|
await _accountRepository.InsertAccountAsync(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
return request;
|
return account;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool DeleteAccount(User user, string name)
|
public bool DeleteAccount(User user, string name)
|
||||||
|
|||||||
@@ -114,4 +114,10 @@ public class AgentService : IAgentService
|
|||||||
{
|
{
|
||||||
return await _agentSummaryRepository.GetAllAsync();
|
return await _agentSummaryRepository.GetAllAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<string>> GetAllOnlineAgents()
|
||||||
|
{
|
||||||
|
var agentSummaries = await _agentSummaryRepository.GetAllAgentWithRunningBots();
|
||||||
|
return agentSummaries.Select(a => a.AgentName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using Managing.Application.Abstractions;
|
using Managing.Application.Abstractions.Services;
|
||||||
using Managing.Application.ManageBot.Commands;
|
using Managing.Application.ManageBot.Commands;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
|
|
||||||
@@ -9,18 +9,17 @@ namespace Managing.Application.ManageBot
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class GetOnlineAgentNamesCommandHandler : IRequestHandler<GetOnlineAgentNamesCommand, IEnumerable<string>>
|
public class GetOnlineAgentNamesCommandHandler : IRequestHandler<GetOnlineAgentNamesCommand, IEnumerable<string>>
|
||||||
{
|
{
|
||||||
private readonly IBotService _botService;
|
private readonly IAgentService _agentService;
|
||||||
|
|
||||||
public GetOnlineAgentNamesCommandHandler(IBotService botService)
|
public GetOnlineAgentNamesCommandHandler(IAgentService agentService)
|
||||||
{
|
{
|
||||||
_botService = botService;
|
_agentService = agentService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<string>> Handle(GetOnlineAgentNamesCommand request,
|
public async Task<IEnumerable<string>> Handle(GetOnlineAgentNamesCommand request,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var activeBots = await _botService.GetActiveBotsNamesAsync();
|
return await _agentService.GetAllOnlineAgents();
|
||||||
return activeBots;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,8 +116,7 @@ namespace Managing.Application.Scenarios
|
|||||||
|
|
||||||
public async Task<IEnumerable<Scenario>> GetScenariosByUserAsync(User user)
|
public async Task<IEnumerable<Scenario>> GetScenariosByUserAsync(User user)
|
||||||
{
|
{
|
||||||
var scenarios = await _tradingService.GetScenariosAsync();
|
return await _tradingService.GetScenariosByUserAsync(user);
|
||||||
return scenarios.Where(s => s.User?.Name == user.Name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Scenario> CreateScenarioForUser(User user, string name, List<string> strategies,
|
public async Task<Scenario> CreateScenarioForUser(User user, string name, List<string> strategies,
|
||||||
|
|||||||
@@ -88,6 +88,11 @@ public class TradingService : ITradingService
|
|||||||
return await _tradingRepository.GetScenariosAsync();
|
return await _tradingRepository.GetScenariosAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Scenario>> GetScenariosByUserAsync(User user)
|
||||||
|
{
|
||||||
|
return await _tradingRepository.GetScenariosByUserAsync(user);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<IndicatorBase>> GetIndicatorsAsync()
|
public async Task<IEnumerable<IndicatorBase>> GetIndicatorsAsync()
|
||||||
{
|
{
|
||||||
return await _tradingRepository.GetStrategiesAsync();
|
return await _tradingRepository.GetStrategiesAsync();
|
||||||
|
|||||||
@@ -95,15 +95,16 @@ public class UserService : IUserService
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// First login
|
// First login - create user first
|
||||||
user = new User
|
user = new User
|
||||||
{
|
{
|
||||||
Name = name
|
Name = name
|
||||||
};
|
};
|
||||||
|
|
||||||
await _userRepository.InsertUserAsync(user);
|
// Save the user first
|
||||||
|
await _userRepository.SaveOrUpdateUserAsync(user);
|
||||||
|
|
||||||
// Create embedded account to authenticate user
|
// Create embedded account to authenticate user after user is saved
|
||||||
var account = await _accountService.CreateAccount(user, new Account
|
var account = await _accountService.CreateAccount(user, new Account
|
||||||
{
|
{
|
||||||
Name = $"{name}-embedded",
|
Name = $"{name}-embedded",
|
||||||
@@ -116,9 +117,6 @@ public class UserService : IUserService
|
|||||||
{
|
{
|
||||||
account
|
account
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update user with the new account
|
|
||||||
await _userRepository.UpdateUser(user);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
@@ -165,8 +163,12 @@ public class UserService : IUserService
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
user = await GetUserByName(user.Name);
|
user = await GetUserByName(user.Name);
|
||||||
|
if (!string.IsNullOrEmpty(user.AgentName) && user.AgentName.Equals(agentName))
|
||||||
|
return user;
|
||||||
|
|
||||||
|
// Update the agent name on the provided user object
|
||||||
user.AgentName = agentName;
|
user.AgentName = agentName;
|
||||||
await _userRepository.UpdateUser(user);
|
await _userRepository.SaveOrUpdateUserAsync(user);
|
||||||
|
|
||||||
// Initialize the AgentGrain for this user
|
// Initialize the AgentGrain for this user
|
||||||
try
|
try
|
||||||
@@ -204,8 +206,12 @@ public class UserService : IUserService
|
|||||||
}
|
}
|
||||||
|
|
||||||
user = await GetUserByName(user.Name);
|
user = await GetUserByName(user.Name);
|
||||||
|
if (!string.IsNullOrEmpty(user.AvatarUrl) && user.AvatarUrl.Equals(avatarUrl))
|
||||||
|
return user;
|
||||||
|
|
||||||
|
// Update the avatar URL on the provided user object
|
||||||
user.AvatarUrl = avatarUrl;
|
user.AvatarUrl = avatarUrl;
|
||||||
await _userRepository.UpdateUser(user);
|
await _userRepository.SaveOrUpdateUserAsync(user);
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,8 +228,12 @@ public class UserService : IUserService
|
|||||||
}
|
}
|
||||||
|
|
||||||
user = await GetUserByName(user.Name);
|
user = await GetUserByName(user.Name);
|
||||||
|
if (!string.IsNullOrEmpty(user.TelegramChannel) && user.TelegramChannel.Equals(telegramChannel))
|
||||||
|
return user;
|
||||||
|
|
||||||
|
// Update the telegram channel on the provided user object
|
||||||
user.TelegramChannel = telegramChannel;
|
user.TelegramChannel = telegramChannel;
|
||||||
await _userRepository.UpdateUser(user);
|
await _userRepository.SaveOrUpdateUserAsync(user);
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,6 +257,4 @@ public class UserService : IUserService
|
|||||||
{
|
{
|
||||||
return await _userRepository.GetAllUsersAsync();
|
return await _userRepository.GetAllUsersAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -6,21 +6,15 @@ namespace Managing.Domain.Users;
|
|||||||
[GenerateSerializer]
|
[GenerateSerializer]
|
||||||
public class User
|
public class User
|
||||||
{
|
{
|
||||||
[Id(0)]
|
[Id(0)] public int Id { get; set; }
|
||||||
public int Id { get; set; }
|
|
||||||
|
|
||||||
[Id(1)]
|
[Id(1)] public string Name { get; set; }
|
||||||
public string Name { get; set; }
|
|
||||||
|
[Id(2)] public List<Account> Accounts { get; set; }
|
||||||
[Id(2)]
|
|
||||||
public List<Account> Accounts { get; set; }
|
[Id(3)] public string AgentName { get; set; } = string.Empty;
|
||||||
|
|
||||||
[Id(3)]
|
[Id(4)] public string AvatarUrl { get; set; } = string.Empty;
|
||||||
public string AgentName { get; set; }
|
|
||||||
|
[Id(5)] public string TelegramChannel { get; set; } = string.Empty;
|
||||||
[Id(4)]
|
|
||||||
public string AvatarUrl { get; set; }
|
|
||||||
|
|
||||||
[Id(5)]
|
|
||||||
public string TelegramChannel { get; set; }
|
|
||||||
}
|
}
|
||||||
1384
src/Managing.Infrastructure.Database/Migrations/20250805133422_UniqueUsername.Designer.cs
generated
Normal file
1384
src/Managing.Infrastructure.Database/Migrations/20250805133422_UniqueUsername.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Managing.Infrastructure.Databases.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class UniqueUsername : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Users_Name",
|
||||||
|
table: "Users",
|
||||||
|
column: "Name",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Users_Name",
|
||||||
|
table: "Users");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1386
src/Managing.Infrastructure.Database/Migrations/20250805135750_AccountUpdate.Designer.cs
generated
Normal file
1386
src/Managing.Infrastructure.Database/Migrations/20250805135750_AccountUpdate.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,58 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Managing.Infrastructure.Databases.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AccountUpdate : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<int>(
|
||||||
|
name: "UserId",
|
||||||
|
table: "Accounts",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0,
|
||||||
|
oldClrType: typeof(int),
|
||||||
|
oldType: "integer",
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "Key",
|
||||||
|
table: "Accounts",
|
||||||
|
type: "character varying(500)",
|
||||||
|
maxLength: 500,
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "",
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(500)",
|
||||||
|
oldMaxLength: 500,
|
||||||
|
oldNullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<int>(
|
||||||
|
name: "UserId",
|
||||||
|
table: "Accounts",
|
||||||
|
type: "integer",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(int),
|
||||||
|
oldType: "integer");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "Key",
|
||||||
|
table: "Accounts",
|
||||||
|
type: "character varying(500)",
|
||||||
|
maxLength: 500,
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(500)",
|
||||||
|
oldMaxLength: 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1422
src/Managing.Infrastructure.Database/Migrations/20250805150905_UserKeys.Designer.cs
generated
Normal file
1422
src/Managing.Infrastructure.Database/Migrations/20250805150905_UserKeys.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,425 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Managing.Infrastructure.Databases.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class UserKeys : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Signals_Identifier_Date_UserName",
|
||||||
|
table: "Signals");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Signals_UserName",
|
||||||
|
table: "Signals");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Signals_UserName_Date",
|
||||||
|
table: "Signals");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Scenarios_UserName",
|
||||||
|
table: "Scenarios");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Scenarios_UserName_Name",
|
||||||
|
table: "Scenarios");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Positions_UserName",
|
||||||
|
table: "Positions");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Positions_UserName_Identifier",
|
||||||
|
table: "Positions");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Indicators_UserName",
|
||||||
|
table: "Indicators");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Indicators_UserName_Name",
|
||||||
|
table: "Indicators");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_BundleBacktestRequests_UserName",
|
||||||
|
table: "BundleBacktestRequests");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_BundleBacktestRequests_UserName_CreatedAt",
|
||||||
|
table: "BundleBacktestRequests");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Backtests_UserName",
|
||||||
|
table: "Backtests");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Backtests_UserName_Score",
|
||||||
|
table: "Backtests");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserName",
|
||||||
|
table: "Signals");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserName",
|
||||||
|
table: "Scenarios");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserName",
|
||||||
|
table: "Positions");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserName",
|
||||||
|
table: "Indicators");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserName",
|
||||||
|
table: "BundleBacktestRequests");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserName",
|
||||||
|
table: "Backtests");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "UserId",
|
||||||
|
table: "Signals",
|
||||||
|
type: "integer",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "UserId",
|
||||||
|
table: "Scenarios",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "UserId",
|
||||||
|
table: "Positions",
|
||||||
|
type: "integer",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "UserId",
|
||||||
|
table: "Indicators",
|
||||||
|
type: "integer",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "UserId",
|
||||||
|
table: "Backtests",
|
||||||
|
type: "integer",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Signals_Identifier_Date_UserId",
|
||||||
|
table: "Signals",
|
||||||
|
columns: new[] { "Identifier", "Date", "UserId" },
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Signals_UserId",
|
||||||
|
table: "Signals",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Signals_UserId_Date",
|
||||||
|
table: "Signals",
|
||||||
|
columns: new[] { "UserId", "Date" });
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Scenarios_UserId",
|
||||||
|
table: "Scenarios",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Scenarios_UserId_Name",
|
||||||
|
table: "Scenarios",
|
||||||
|
columns: new[] { "UserId", "Name" });
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Positions_UserId",
|
||||||
|
table: "Positions",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Positions_UserId_Identifier",
|
||||||
|
table: "Positions",
|
||||||
|
columns: new[] { "UserId", "Identifier" });
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Indicators_UserId",
|
||||||
|
table: "Indicators",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Indicators_UserId_Name",
|
||||||
|
table: "Indicators",
|
||||||
|
columns: new[] { "UserId", "Name" });
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_BundleBacktestRequests_UserId_CreatedAt",
|
||||||
|
table: "BundleBacktestRequests",
|
||||||
|
columns: new[] { "UserId", "CreatedAt" });
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Backtests_UserId",
|
||||||
|
table: "Backtests",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Backtests_UserId_Score",
|
||||||
|
table: "Backtests",
|
||||||
|
columns: new[] { "UserId", "Score" });
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_Backtests_Users_UserId",
|
||||||
|
table: "Backtests",
|
||||||
|
column: "UserId",
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.SetNull);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_Indicators_Users_UserId",
|
||||||
|
table: "Indicators",
|
||||||
|
column: "UserId",
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.SetNull);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_Positions_Users_UserId",
|
||||||
|
table: "Positions",
|
||||||
|
column: "UserId",
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.SetNull);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_Scenarios_Users_UserId",
|
||||||
|
table: "Scenarios",
|
||||||
|
column: "UserId",
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.SetNull);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_Signals_Users_UserId",
|
||||||
|
table: "Signals",
|
||||||
|
column: "UserId",
|
||||||
|
principalTable: "Users",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.SetNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_Backtests_Users_UserId",
|
||||||
|
table: "Backtests");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_Indicators_Users_UserId",
|
||||||
|
table: "Indicators");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_Positions_Users_UserId",
|
||||||
|
table: "Positions");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_Scenarios_Users_UserId",
|
||||||
|
table: "Scenarios");
|
||||||
|
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_Signals_Users_UserId",
|
||||||
|
table: "Signals");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Signals_Identifier_Date_UserId",
|
||||||
|
table: "Signals");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Signals_UserId",
|
||||||
|
table: "Signals");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Signals_UserId_Date",
|
||||||
|
table: "Signals");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Scenarios_UserId",
|
||||||
|
table: "Scenarios");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Scenarios_UserId_Name",
|
||||||
|
table: "Scenarios");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Positions_UserId",
|
||||||
|
table: "Positions");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Positions_UserId_Identifier",
|
||||||
|
table: "Positions");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Indicators_UserId",
|
||||||
|
table: "Indicators");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Indicators_UserId_Name",
|
||||||
|
table: "Indicators");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_BundleBacktestRequests_UserId_CreatedAt",
|
||||||
|
table: "BundleBacktestRequests");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Backtests_UserId",
|
||||||
|
table: "Backtests");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_Backtests_UserId_Score",
|
||||||
|
table: "Backtests");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserId",
|
||||||
|
table: "Signals");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserId",
|
||||||
|
table: "Scenarios");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserId",
|
||||||
|
table: "Positions");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserId",
|
||||||
|
table: "Indicators");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "UserId",
|
||||||
|
table: "Backtests");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "UserName",
|
||||||
|
table: "Signals",
|
||||||
|
type: "character varying(255)",
|
||||||
|
maxLength: 255,
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "UserName",
|
||||||
|
table: "Scenarios",
|
||||||
|
type: "character varying(255)",
|
||||||
|
maxLength: 255,
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "UserName",
|
||||||
|
table: "Positions",
|
||||||
|
type: "character varying(255)",
|
||||||
|
maxLength: 255,
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "UserName",
|
||||||
|
table: "Indicators",
|
||||||
|
type: "character varying(255)",
|
||||||
|
maxLength: 255,
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "UserName",
|
||||||
|
table: "BundleBacktestRequests",
|
||||||
|
type: "character varying(255)",
|
||||||
|
maxLength: 255,
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "UserName",
|
||||||
|
table: "Backtests",
|
||||||
|
type: "character varying(255)",
|
||||||
|
maxLength: 255,
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Signals_Identifier_Date_UserName",
|
||||||
|
table: "Signals",
|
||||||
|
columns: new[] { "Identifier", "Date", "UserName" },
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Signals_UserName",
|
||||||
|
table: "Signals",
|
||||||
|
column: "UserName");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Signals_UserName_Date",
|
||||||
|
table: "Signals",
|
||||||
|
columns: new[] { "UserName", "Date" });
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Scenarios_UserName",
|
||||||
|
table: "Scenarios",
|
||||||
|
column: "UserName");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Scenarios_UserName_Name",
|
||||||
|
table: "Scenarios",
|
||||||
|
columns: new[] { "UserName", "Name" });
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Positions_UserName",
|
||||||
|
table: "Positions",
|
||||||
|
column: "UserName");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Positions_UserName_Identifier",
|
||||||
|
table: "Positions",
|
||||||
|
columns: new[] { "UserName", "Identifier" });
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Indicators_UserName",
|
||||||
|
table: "Indicators",
|
||||||
|
column: "UserName");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Indicators_UserName_Name",
|
||||||
|
table: "Indicators",
|
||||||
|
columns: new[] { "UserName", "Name" });
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_BundleBacktestRequests_UserName",
|
||||||
|
table: "BundleBacktestRequests",
|
||||||
|
column: "UserName");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_BundleBacktestRequests_UserName_CreatedAt",
|
||||||
|
table: "BundleBacktestRequests",
|
||||||
|
columns: new[] { "UserName", "CreatedAt" });
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Backtests_UserName",
|
||||||
|
table: "Backtests",
|
||||||
|
column: "UserName");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Backtests_UserName_Score",
|
||||||
|
table: "Backtests",
|
||||||
|
columns: new[] { "UserName", "Score" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,6 +35,7 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<string>("Key")
|
b.Property<string>("Key")
|
||||||
|
.IsRequired()
|
||||||
.HasMaxLength(500)
|
.HasMaxLength(500)
|
||||||
.HasColumnType("character varying(500)");
|
.HasColumnType("character varying(500)");
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<int?>("UserId")
|
b.Property<int>("UserId")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
@@ -192,10 +193,8 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
b.Property<DateTime>("UpdatedAt")
|
b.Property<DateTime>("UpdatedAt")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("UserName")
|
b.Property<int>("UserId")
|
||||||
.IsRequired()
|
.HasColumnType("integer");
|
||||||
.HasMaxLength(255)
|
|
||||||
.HasColumnType("character varying(255)");
|
|
||||||
|
|
||||||
b.Property<int>("WinRate")
|
b.Property<int>("WinRate")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
@@ -209,11 +208,11 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
|
|
||||||
b.HasIndex("Score");
|
b.HasIndex("Score");
|
||||||
|
|
||||||
b.HasIndex("UserName");
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
b.HasIndex("RequestId", "Score");
|
b.HasIndex("RequestId", "Score");
|
||||||
|
|
||||||
b.HasIndex("UserName", "Score");
|
b.HasIndex("UserId", "Score");
|
||||||
|
|
||||||
b.ToTable("Backtests");
|
b.ToTable("Backtests");
|
||||||
});
|
});
|
||||||
@@ -347,11 +346,6 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
b.Property<int?>("UserId")
|
b.Property<int?>("UserId")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.Property<string>("UserName")
|
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(255)
|
|
||||||
.HasColumnType("character varying(255)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("RequestId")
|
b.HasIndex("RequestId")
|
||||||
@@ -361,9 +355,7 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
|
|
||||||
b.HasIndex("UserId");
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
b.HasIndex("UserName");
|
b.HasIndex("UserId", "CreatedAt");
|
||||||
|
|
||||||
b.HasIndex("UserName", "CreatedAt");
|
|
||||||
|
|
||||||
b.ToTable("BundleBacktestRequests");
|
b.ToTable("BundleBacktestRequests");
|
||||||
});
|
});
|
||||||
@@ -593,15 +585,14 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
b.Property<DateTime>("UpdatedAt")
|
b.Property<DateTime>("UpdatedAt")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("UserName")
|
b.Property<int?>("UserId")
|
||||||
.HasMaxLength(255)
|
.HasColumnType("integer");
|
||||||
.HasColumnType("character varying(255)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("UserName");
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
b.HasIndex("UserName", "Name");
|
b.HasIndex("UserId", "Name");
|
||||||
|
|
||||||
b.ToTable("Indicators");
|
b.ToTable("Indicators");
|
||||||
});
|
});
|
||||||
@@ -715,9 +706,8 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
b.Property<DateTime>("UpdatedAt")
|
b.Property<DateTime>("UpdatedAt")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("UserName")
|
b.Property<int?>("UserId")
|
||||||
.HasMaxLength(255)
|
.HasColumnType("integer");
|
||||||
.HasColumnType("character varying(255)");
|
|
||||||
|
|
||||||
b.HasKey("Identifier");
|
b.HasKey("Identifier");
|
||||||
|
|
||||||
@@ -736,9 +726,9 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
|
|
||||||
b.HasIndex("TakeProfit2TradeId");
|
b.HasIndex("TakeProfit2TradeId");
|
||||||
|
|
||||||
b.HasIndex("UserName");
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
b.HasIndex("UserName", "Identifier");
|
b.HasIndex("UserId", "Identifier");
|
||||||
|
|
||||||
b.ToTable("Positions");
|
b.ToTable("Positions");
|
||||||
});
|
});
|
||||||
@@ -765,15 +755,14 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
b.Property<DateTime>("UpdatedAt")
|
b.Property<DateTime>("UpdatedAt")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("UserName")
|
b.Property<int>("UserId")
|
||||||
.HasMaxLength(255)
|
.HasColumnType("integer");
|
||||||
.HasColumnType("character varying(255)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("UserName");
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
b.HasIndex("UserName", "Name");
|
b.HasIndex("UserId", "Name");
|
||||||
|
|
||||||
b.ToTable("Scenarios");
|
b.ToTable("Scenarios");
|
||||||
});
|
});
|
||||||
@@ -863,9 +852,8 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
b.Property<DateTime>("UpdatedAt")
|
b.Property<DateTime>("UpdatedAt")
|
||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("UserName")
|
b.Property<int?>("UserId")
|
||||||
.HasMaxLength(255)
|
.HasColumnType("integer");
|
||||||
.HasColumnType("character varying(255)");
|
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
@@ -877,11 +865,11 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
|
|
||||||
b.HasIndex("Ticker");
|
b.HasIndex("Ticker");
|
||||||
|
|
||||||
b.HasIndex("UserName");
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
b.HasIndex("UserName", "Date");
|
b.HasIndex("UserId", "Date");
|
||||||
|
|
||||||
b.HasIndex("Identifier", "Date", "UserName")
|
b.HasIndex("Identifier", "Date", "UserId")
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
b.ToTable("Signals");
|
b.ToTable("Signals");
|
||||||
@@ -1213,6 +1201,9 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Name")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
b.ToTable("Users");
|
b.ToTable("Users");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1256,7 +1247,8 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
b.HasOne("Managing.Infrastructure.Databases.PostgreSql.Entities.UserEntity", "User")
|
b.HasOne("Managing.Infrastructure.Databases.PostgreSql.Entities.UserEntity", "User")
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("UserId")
|
.HasForeignKey("UserId")
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
.OnDelete(DeleteBehavior.SetNull)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
b.Navigation("User");
|
b.Navigation("User");
|
||||||
});
|
});
|
||||||
@@ -1272,6 +1264,17 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
b.Navigation("User");
|
b.Navigation("User");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.BacktestEntity", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Managing.Infrastructure.Databases.PostgreSql.Entities.UserEntity", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.SetNull)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.BotEntity", b =>
|
modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.BotEntity", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Managing.Infrastructure.Databases.PostgreSql.Entities.UserEntity", "User")
|
b.HasOne("Managing.Infrastructure.Databases.PostgreSql.Entities.UserEntity", "User")
|
||||||
@@ -1303,6 +1306,16 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
b.Navigation("User");
|
b.Navigation("User");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.IndicatorEntity", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Managing.Infrastructure.Databases.PostgreSql.Entities.UserEntity", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.MoneyManagementEntity", b =>
|
modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.MoneyManagementEntity", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Managing.Infrastructure.Databases.PostgreSql.Entities.UserEntity", "User")
|
b.HasOne("Managing.Infrastructure.Databases.PostgreSql.Entities.UserEntity", "User")
|
||||||
@@ -1335,6 +1348,11 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
.HasForeignKey("TakeProfit2TradeId")
|
.HasForeignKey("TakeProfit2TradeId")
|
||||||
.OnDelete(DeleteBehavior.SetNull);
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
|
b.HasOne("Managing.Infrastructure.Databases.PostgreSql.Entities.UserEntity", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
b.Navigation("OpenTrade");
|
b.Navigation("OpenTrade");
|
||||||
|
|
||||||
b.Navigation("StopLossTrade");
|
b.Navigation("StopLossTrade");
|
||||||
@@ -1342,6 +1360,19 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
b.Navigation("TakeProfit1Trade");
|
b.Navigation("TakeProfit1Trade");
|
||||||
|
|
||||||
b.Navigation("TakeProfit2Trade");
|
b.Navigation("TakeProfit2Trade");
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.ScenarioEntity", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Managing.Infrastructure.Databases.PostgreSql.Entities.UserEntity", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.SetNull)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.ScenarioIndicatorEntity", b =>
|
modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.ScenarioIndicatorEntity", b =>
|
||||||
@@ -1363,6 +1394,16 @@ namespace Managing.Infrastructure.Databases.Migrations
|
|||||||
b.Navigation("Scenario");
|
b.Navigation("Scenario");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.SignalEntity", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Managing.Infrastructure.Databases.PostgreSql.Entities.UserEntity", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.IndicatorEntity", b =>
|
modelBuilder.Entity("Managing.Infrastructure.Databases.PostgreSql.Entities.IndicatorEntity", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("ScenarioIndicators");
|
b.Navigation("ScenarioIndicators");
|
||||||
|
|||||||
@@ -229,4 +229,14 @@ public class AgentSummaryRepository : IAgentSummaryRepository
|
|||||||
User = PostgreSqlMappers.Map(entity.User)
|
User = PostgreSqlMappers.Map(entity.User)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<AgentSummary>> GetAllAgentWithRunningBots()
|
||||||
|
{
|
||||||
|
var agentSummaries = await _context.AgentSummaries
|
||||||
|
.Include(a => a.User)
|
||||||
|
.Where(a => _context.Bots.Any(b => b.UserId == a.UserId && b.Status == BotStatus.Up))
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return agentSummaries.Select(MapToDomain);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,23 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using static Managing.Common.Enums;
|
using static Managing.Common.Enums;
|
||||||
|
|
||||||
namespace Managing.Infrastructure.Databases.PostgreSql.Entities;
|
namespace Managing.Infrastructure.Databases.PostgreSql.Entities;
|
||||||
|
|
||||||
|
[Table("Accounts")]
|
||||||
public class AccountEntity
|
public class AccountEntity
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
[Key] public int Id { get; set; }
|
||||||
public string Name { get; set; }
|
[Required] public string Name { get; set; }
|
||||||
public TradingExchanges Exchange { get; set; }
|
[Required] public TradingExchanges Exchange { get; set; }
|
||||||
public AccountType Type { get; set; }
|
[Required] public AccountType Type { get; set; }
|
||||||
public string? Key { get; set; }
|
[Required] public string? Key { get; set; }
|
||||||
public string? Secret { get; set; }
|
public string? Secret { get; set; }
|
||||||
public int? UserId { get; set; }
|
[Required] public int UserId { get; set; }
|
||||||
|
|
||||||
// Navigation properties
|
// Navigation properties
|
||||||
public UserEntity? User { get; set; }
|
public UserEntity? User { get; set; }
|
||||||
|
|
||||||
// Store balances as JSON if needed, or skip them entirely
|
// Store balances as JSON if needed, or skip them entirely
|
||||||
// public string? BalancesJson { get; set; }
|
// public string? BalancesJson { get; set; }
|
||||||
}
|
}
|
||||||
@@ -56,8 +56,10 @@ public class BacktestEntity
|
|||||||
public string MoneyManagementJson { get; set; } = string.Empty;
|
public string MoneyManagementJson { get; set; } = string.Empty;
|
||||||
|
|
||||||
[Required]
|
[Required]
|
||||||
[MaxLength(255)]
|
public int UserId { get; set; }
|
||||||
public string UserName { get; set; } = string.Empty;
|
|
||||||
|
// Navigation property
|
||||||
|
public UserEntity? User { get; set; }
|
||||||
|
|
||||||
[Column(TypeName = "jsonb")]
|
[Column(TypeName = "jsonb")]
|
||||||
public string? StatisticsJson { get; set; }
|
public string? StatisticsJson { get; set; }
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class BotEntity
|
|||||||
|
|
||||||
public int UserId { get; set; }
|
public int UserId { get; set; }
|
||||||
|
|
||||||
[Required] [ForeignKey("UserId")] public required UserEntity User { get; set; }
|
[ForeignKey("UserId")] public UserEntity User { get; set; }
|
||||||
|
|
||||||
public BotStatus Status { get; set; }
|
public BotStatus Status { get; set; }
|
||||||
public DateTime CreateDate { get; set; }
|
public DateTime CreateDate { get; set; }
|
||||||
|
|||||||
@@ -15,10 +15,6 @@ public class BundleBacktestRequestEntity
|
|||||||
[MaxLength(255)]
|
[MaxLength(255)]
|
||||||
public string RequestId { get; set; } = string.Empty;
|
public string RequestId { get; set; } = string.Empty;
|
||||||
|
|
||||||
[Required]
|
|
||||||
[MaxLength(255)]
|
|
||||||
public string UserName { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
// Foreign key to User entity
|
// Foreign key to User entity
|
||||||
public int? UserId { get; set; }
|
public int? UserId { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
using static Managing.Common.Enums;
|
using static Managing.Common.Enums;
|
||||||
|
|
||||||
namespace Managing.Infrastructure.Databases.PostgreSql.Entities;
|
namespace Managing.Infrastructure.Databases.PostgreSql.Entities;
|
||||||
|
|
||||||
|
[Table("GeneticRequests")]
|
||||||
public class GeneticRequestEntity
|
public class GeneticRequestEntity
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|||||||
@@ -28,12 +28,14 @@ public class IndicatorEntity
|
|||||||
public int? SmoothPeriods { get; set; }
|
public int? SmoothPeriods { get; set; }
|
||||||
public int? CyclePeriods { get; set; }
|
public int? CyclePeriods { get; set; }
|
||||||
|
|
||||||
[MaxLength(255)]
|
public int? UserId { get; set; }
|
||||||
public string? UserName { get; set; }
|
|
||||||
|
|
||||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||||
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
||||||
|
|
||||||
|
// Navigation properties
|
||||||
|
public UserEntity? User { get; set; }
|
||||||
|
|
||||||
// Navigation property for the many-to-many relationship with scenarios
|
// Navigation property for the many-to-many relationship with scenarios
|
||||||
public virtual ICollection<ScenarioIndicatorEntity> ScenarioIndicators { get; set; } = new List<ScenarioIndicatorEntity>();
|
public virtual ICollection<ScenarioIndicatorEntity> ScenarioIndicators { get; set; } = new List<ScenarioIndicatorEntity>();
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@ public class PositionEntity
|
|||||||
|
|
||||||
[MaxLength(255)] public string AccountName { get; set; }
|
[MaxLength(255)] public string AccountName { get; set; }
|
||||||
|
|
||||||
[MaxLength(255)] public string? UserName { get; set; }
|
public int? UserId { get; set; }
|
||||||
|
|
||||||
// Foreign keys to trades
|
// Foreign keys to trades
|
||||||
public int? OpenTradeId { get; set; }
|
public int? OpenTradeId { get; set; }
|
||||||
@@ -37,6 +37,8 @@ public class PositionEntity
|
|||||||
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
||||||
|
|
||||||
// Navigation properties
|
// Navigation properties
|
||||||
|
public UserEntity? User { get; set; }
|
||||||
|
|
||||||
[ForeignKey("OpenTradeId")] public virtual TradeEntity? OpenTrade { get; set; }
|
[ForeignKey("OpenTradeId")] public virtual TradeEntity? OpenTrade { get; set; }
|
||||||
|
|
||||||
[ForeignKey("StopLossTradeId")] public virtual TradeEntity? StopLossTrade { get; set; }
|
[ForeignKey("StopLossTradeId")] public virtual TradeEntity? StopLossTrade { get; set; }
|
||||||
|
|||||||
@@ -15,12 +15,15 @@ public class ScenarioEntity
|
|||||||
|
|
||||||
public int LoopbackPeriod { get; set; }
|
public int LoopbackPeriod { get; set; }
|
||||||
|
|
||||||
[MaxLength(255)]
|
[Required]
|
||||||
public string? UserName { get; set; }
|
public int UserId { get; set; }
|
||||||
|
|
||||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||||
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
||||||
|
|
||||||
|
// Navigation properties
|
||||||
|
public UserEntity? User { get; set; }
|
||||||
|
|
||||||
// Navigation property for the many-to-many relationship with indicators
|
// Navigation property for the many-to-many relationship with indicators
|
||||||
public virtual ICollection<ScenarioIndicatorEntity> ScenarioIndicators { get; set; } = new List<ScenarioIndicatorEntity>();
|
public virtual ICollection<ScenarioIndicatorEntity> ScenarioIndicators { get; set; } = new List<ScenarioIndicatorEntity>();
|
||||||
}
|
}
|
||||||
@@ -26,8 +26,10 @@ public class SignalEntity
|
|||||||
[MaxLength(255)]
|
[MaxLength(255)]
|
||||||
public string IndicatorName { get; set; }
|
public string IndicatorName { get; set; }
|
||||||
|
|
||||||
[MaxLength(255)]
|
public int? UserId { get; set; }
|
||||||
public string? UserName { get; set; }
|
|
||||||
|
// Navigation property
|
||||||
|
public UserEntity? User { get; set; }
|
||||||
|
|
||||||
// Candle data stored as JSON
|
// Candle data stored as JSON
|
||||||
[Column(TypeName = "text")]
|
[Column(TypeName = "text")]
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace Managing.Infrastructure.Databases.PostgreSql.Entities;
|
namespace Managing.Infrastructure.Databases.PostgreSql.Entities;
|
||||||
|
|
||||||
[Table("Users")]
|
[Table("Users")]
|
||||||
|
[Index(nameof(Name), IsUnique = true)]
|
||||||
public class UserEntity
|
public class UserEntity
|
||||||
{
|
{
|
||||||
[Key] public int Id { get; set; }
|
[Key] public int Id { get; set; }
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ public class ManagingDbContext : DbContext
|
|||||||
entity.HasKey(e => e.Id);
|
entity.HasKey(e => e.Id);
|
||||||
entity.Property(e => e.Identifier).IsRequired().HasMaxLength(255);
|
entity.Property(e => e.Identifier).IsRequired().HasMaxLength(255);
|
||||||
entity.Property(e => e.RequestId).IsRequired().HasMaxLength(255);
|
entity.Property(e => e.RequestId).IsRequired().HasMaxLength(255);
|
||||||
entity.Property(e => e.UserName).IsRequired().HasMaxLength(255);
|
entity.Property(e => e.UserId).IsRequired();
|
||||||
entity.Property(e => e.FinalPnl).HasColumnType("decimal(18,8)");
|
entity.Property(e => e.FinalPnl).HasColumnType("decimal(18,8)");
|
||||||
entity.Property(e => e.GrowthPercentage).HasColumnType("decimal(18,8)");
|
entity.Property(e => e.GrowthPercentage).HasColumnType("decimal(18,8)");
|
||||||
entity.Property(e => e.HodlPercentage).HasColumnType("decimal(18,8)");
|
entity.Property(e => e.HodlPercentage).HasColumnType("decimal(18,8)");
|
||||||
@@ -143,14 +143,20 @@ public class ManagingDbContext : DbContext
|
|||||||
entity.Property(e => e.ScoreMessage).HasMaxLength(1000);
|
entity.Property(e => e.ScoreMessage).HasMaxLength(1000);
|
||||||
entity.Property(e => e.Metadata).HasColumnType("text");
|
entity.Property(e => e.Metadata).HasColumnType("text");
|
||||||
|
|
||||||
|
// Configure relationship with User
|
||||||
|
entity.HasOne(e => e.User)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(e => e.UserId)
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
// Create indexes for common queries
|
// Create indexes for common queries
|
||||||
entity.HasIndex(e => e.Identifier).IsUnique();
|
entity.HasIndex(e => e.Identifier).IsUnique();
|
||||||
entity.HasIndex(e => e.RequestId);
|
entity.HasIndex(e => e.RequestId);
|
||||||
entity.HasIndex(e => e.UserName);
|
entity.HasIndex(e => e.UserId);
|
||||||
entity.HasIndex(e => e.Score);
|
entity.HasIndex(e => e.Score);
|
||||||
|
|
||||||
// Composite indexes for efficient pagination and filtering
|
// Composite indexes for efficient pagination and filtering
|
||||||
entity.HasIndex(e => new { e.UserName, e.Score });
|
entity.HasIndex(e => new { e.UserId, e.Score });
|
||||||
entity.HasIndex(e => new { e.RequestId, e.Score });
|
entity.HasIndex(e => new { e.RequestId, e.Score });
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -159,7 +165,7 @@ public class ManagingDbContext : DbContext
|
|||||||
{
|
{
|
||||||
entity.HasKey(e => e.Id);
|
entity.HasKey(e => e.Id);
|
||||||
entity.Property(e => e.RequestId).IsRequired().HasMaxLength(255);
|
entity.Property(e => e.RequestId).IsRequired().HasMaxLength(255);
|
||||||
entity.Property(e => e.UserName).IsRequired().HasMaxLength(255);
|
entity.Property(e => e.UserId);
|
||||||
entity.Property(e => e.Name).IsRequired().HasMaxLength(255);
|
entity.Property(e => e.Name).IsRequired().HasMaxLength(255);
|
||||||
entity.Property(e => e.Status)
|
entity.Property(e => e.Status)
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
@@ -178,11 +184,11 @@ public class ManagingDbContext : DbContext
|
|||||||
|
|
||||||
// Create indexes for common queries
|
// Create indexes for common queries
|
||||||
entity.HasIndex(e => e.RequestId).IsUnique();
|
entity.HasIndex(e => e.RequestId).IsUnique();
|
||||||
entity.HasIndex(e => e.UserName);
|
entity.HasIndex(e => e.UserId);
|
||||||
entity.HasIndex(e => e.Status);
|
entity.HasIndex(e => e.Status);
|
||||||
|
|
||||||
// Composite index for user queries ordered by creation date
|
// Composite index for user queries ordered by creation date
|
||||||
entity.HasIndex(e => new { e.UserName, e.CreatedAt });
|
entity.HasIndex(e => new { e.UserId, e.CreatedAt });
|
||||||
});
|
});
|
||||||
|
|
||||||
// Configure Scenario entity
|
// Configure Scenario entity
|
||||||
@@ -190,13 +196,19 @@ public class ManagingDbContext : DbContext
|
|||||||
{
|
{
|
||||||
entity.HasKey(e => e.Id);
|
entity.HasKey(e => e.Id);
|
||||||
entity.Property(e => e.Name).IsRequired().HasMaxLength(255);
|
entity.Property(e => e.Name).IsRequired().HasMaxLength(255);
|
||||||
entity.Property(e => e.UserName).HasMaxLength(255);
|
entity.Property(e => e.UserId).IsRequired();
|
||||||
|
|
||||||
|
// Configure relationship with User
|
||||||
|
entity.HasOne(e => e.User)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(e => e.UserId)
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
// Create indexes
|
// Create indexes
|
||||||
entity.HasIndex(e => e.UserName);
|
entity.HasIndex(e => e.UserId);
|
||||||
|
|
||||||
// Composite index for user scenarios
|
// Composite index for user scenarios
|
||||||
entity.HasIndex(e => new { e.UserName, e.Name });
|
entity.HasIndex(e => new { e.UserId, e.Name });
|
||||||
});
|
});
|
||||||
|
|
||||||
// Configure Indicator entity
|
// Configure Indicator entity
|
||||||
@@ -207,13 +219,19 @@ public class ManagingDbContext : DbContext
|
|||||||
entity.Property(e => e.Type).IsRequired().HasConversion<string>();
|
entity.Property(e => e.Type).IsRequired().HasConversion<string>();
|
||||||
entity.Property(e => e.Timeframe).IsRequired().HasConversion<string>();
|
entity.Property(e => e.Timeframe).IsRequired().HasConversion<string>();
|
||||||
entity.Property(e => e.SignalType).IsRequired().HasConversion<string>();
|
entity.Property(e => e.SignalType).IsRequired().HasConversion<string>();
|
||||||
entity.Property(e => e.UserName).HasMaxLength(255);
|
entity.Property(e => e.UserId);
|
||||||
|
|
||||||
|
// Configure relationship with User
|
||||||
|
entity.HasOne(e => e.User)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(e => e.UserId)
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
// Create indexes
|
// Create indexes
|
||||||
entity.HasIndex(e => e.UserName);
|
entity.HasIndex(e => e.UserId);
|
||||||
|
|
||||||
// Composite index for user indicators
|
// Composite index for user indicators
|
||||||
entity.HasIndex(e => new { e.UserName, e.Name });
|
entity.HasIndex(e => new { e.UserId, e.Name });
|
||||||
});
|
});
|
||||||
|
|
||||||
// Configure ScenarioIndicator junction table
|
// Configure ScenarioIndicator junction table
|
||||||
@@ -249,19 +267,25 @@ public class ManagingDbContext : DbContext
|
|||||||
entity.Property(e => e.Type).IsRequired().HasConversion<string>();
|
entity.Property(e => e.Type).IsRequired().HasConversion<string>();
|
||||||
entity.Property(e => e.SignalType).IsRequired().HasConversion<string>();
|
entity.Property(e => e.SignalType).IsRequired().HasConversion<string>();
|
||||||
entity.Property(e => e.IndicatorName).IsRequired().HasMaxLength(255);
|
entity.Property(e => e.IndicatorName).IsRequired().HasMaxLength(255);
|
||||||
entity.Property(e => e.UserName).HasMaxLength(255);
|
entity.Property(e => e.UserId);
|
||||||
entity.Property(e => e.CandleJson).HasColumnType("text");
|
entity.Property(e => e.CandleJson).HasColumnType("text");
|
||||||
|
|
||||||
|
// Configure relationship with User
|
||||||
|
entity.HasOne(e => e.User)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(e => e.UserId)
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
// Create indexes
|
// Create indexes
|
||||||
entity.HasIndex(e => e.Identifier);
|
entity.HasIndex(e => e.Identifier);
|
||||||
entity.HasIndex(e => e.UserName);
|
entity.HasIndex(e => e.UserId);
|
||||||
entity.HasIndex(e => e.Date);
|
entity.HasIndex(e => e.Date);
|
||||||
entity.HasIndex(e => e.Ticker);
|
entity.HasIndex(e => e.Ticker);
|
||||||
entity.HasIndex(e => e.Status);
|
entity.HasIndex(e => e.Status);
|
||||||
|
|
||||||
// Composite indexes for common queries
|
// Composite indexes for common queries
|
||||||
entity.HasIndex(e => new { e.UserName, e.Date });
|
entity.HasIndex(e => new { e.UserId, e.Date });
|
||||||
entity.HasIndex(e => new { e.Identifier, e.Date, e.UserName }).IsUnique();
|
entity.HasIndex(e => new { e.Identifier, e.Date, e.UserId }).IsUnique();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Configure Position entity
|
// Configure Position entity
|
||||||
@@ -275,9 +299,15 @@ public class ManagingDbContext : DbContext
|
|||||||
entity.Property(e => e.Initiator).IsRequired().HasConversion<string>();
|
entity.Property(e => e.Initiator).IsRequired().HasConversion<string>();
|
||||||
entity.Property(e => e.SignalIdentifier).IsRequired().HasMaxLength(255);
|
entity.Property(e => e.SignalIdentifier).IsRequired().HasMaxLength(255);
|
||||||
entity.Property(e => e.AccountName).IsRequired().HasMaxLength(255);
|
entity.Property(e => e.AccountName).IsRequired().HasMaxLength(255);
|
||||||
entity.Property(e => e.UserName).HasMaxLength(255);
|
entity.Property(e => e.UserId);
|
||||||
entity.Property(e => e.MoneyManagementJson).HasColumnType("text");
|
entity.Property(e => e.MoneyManagementJson).HasColumnType("text");
|
||||||
|
|
||||||
|
// Configure relationship with User
|
||||||
|
entity.HasOne(e => e.User)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey(e => e.UserId)
|
||||||
|
.OnDelete(DeleteBehavior.SetNull);
|
||||||
|
|
||||||
// Configure relationships with trades
|
// Configure relationships with trades
|
||||||
entity.HasOne(e => e.OpenTrade)
|
entity.HasOne(e => e.OpenTrade)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
@@ -301,12 +331,12 @@ public class ManagingDbContext : DbContext
|
|||||||
|
|
||||||
// Create indexes
|
// Create indexes
|
||||||
entity.HasIndex(e => e.Identifier).IsUnique();
|
entity.HasIndex(e => e.Identifier).IsUnique();
|
||||||
entity.HasIndex(e => e.UserName);
|
entity.HasIndex(e => e.UserId);
|
||||||
entity.HasIndex(e => e.Status);
|
entity.HasIndex(e => e.Status);
|
||||||
entity.HasIndex(e => e.Date);
|
entity.HasIndex(e => e.Date);
|
||||||
|
|
||||||
// Composite indexes
|
// Composite indexes
|
||||||
entity.HasIndex(e => new { e.UserName, e.Identifier });
|
entity.HasIndex(e => new { e.UserId, e.Identifier });
|
||||||
});
|
});
|
||||||
|
|
||||||
// Configure Trade entity
|
// Configure Trade entity
|
||||||
|
|||||||
@@ -131,28 +131,12 @@ public class PostgreSqlAccountRepository : IAccountRepository
|
|||||||
{
|
{
|
||||||
var accountEntity = PostgreSqlMappers.Map(account);
|
var accountEntity = PostgreSqlMappers.Map(account);
|
||||||
|
|
||||||
// Handle User relationship - check if user exists or create new one
|
// Handle User relationship - user should always have an ID at this point
|
||||||
if (account.User != null)
|
if (account.User == null)
|
||||||
{
|
{
|
||||||
var existingUser = await _context.Users
|
throw new Exception($"Cannot create account {account.Name} without a user");
|
||||||
.AsTracking() // Explicitly enable tracking for this operation
|
|
||||||
.FirstOrDefaultAsync(u => u.Name == account.User.Name)
|
|
||||||
.ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (existingUser != null)
|
|
||||||
{
|
|
||||||
accountEntity.UserId = existingUser.Id;
|
|
||||||
accountEntity.User = null; // Prevent EF from trying to insert duplicate user
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Let EF handle the new user creation
|
|
||||||
accountEntity.UserId = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Balances are not stored in PostgreSQL, they remain in domain logic only
|
|
||||||
|
|
||||||
_context.Accounts.Add(accountEntity);
|
_context.Accounts.Add(accountEntity);
|
||||||
await _context.SaveChangesAsync().ConfigureAwait(false);
|
await _context.SaveChangesAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,8 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
{
|
{
|
||||||
var entities = _context.Backtests
|
var entities = _context.Backtests
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Where(b => b.UserName == user.Name)
|
.Include(b => b.User)
|
||||||
|
.Where(b => b.UserId == user.Id)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
return entities.Select(PostgreSqlMappers.Map);
|
return entities.Select(PostgreSqlMappers.Map);
|
||||||
@@ -82,7 +83,8 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
{
|
{
|
||||||
var entities = await _context.Backtests
|
var entities = await _context.Backtests
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Where(b => b.UserName == user.Name)
|
.Include(b => b.User)
|
||||||
|
.Where(b => b.UserId == user.Id)
|
||||||
.ToListAsync()
|
.ToListAsync()
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
@@ -259,7 +261,8 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
{
|
{
|
||||||
var entity = _context.Backtests
|
var entity = _context.Backtests
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.FirstOrDefault(b => b.Identifier == id && b.UserName == user.Name);
|
.Include(b => b.User)
|
||||||
|
.FirstOrDefault(b => b.Identifier == id && b.UserId == user.Id);
|
||||||
|
|
||||||
return entity != null ? PostgreSqlMappers.Map(entity) : null;
|
return entity != null ? PostgreSqlMappers.Map(entity) : null;
|
||||||
}
|
}
|
||||||
@@ -268,7 +271,8 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
{
|
{
|
||||||
var entity = await _context.Backtests
|
var entity = await _context.Backtests
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(b => b.Identifier == id && b.UserName == user.Name)
|
.Include(b => b.User)
|
||||||
|
.FirstOrDefaultAsync(b => b.Identifier == id && b.UserId == user.Id)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
return entity != null ? PostgreSqlMappers.Map(entity) : null;
|
return entity != null ? PostgreSqlMappers.Map(entity) : null;
|
||||||
@@ -278,7 +282,7 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
{
|
{
|
||||||
var entity = _context.Backtests
|
var entity = _context.Backtests
|
||||||
.AsTracking()
|
.AsTracking()
|
||||||
.FirstOrDefault(b => b.Identifier == id && b.UserName == user.Name);
|
.FirstOrDefault(b => b.Identifier == id && b.UserId == user.Id);
|
||||||
|
|
||||||
if (entity != null)
|
if (entity != null)
|
||||||
{
|
{
|
||||||
@@ -291,7 +295,7 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
{
|
{
|
||||||
var entity = await _context.Backtests
|
var entity = await _context.Backtests
|
||||||
.AsTracking()
|
.AsTracking()
|
||||||
.FirstOrDefaultAsync(b => b.Identifier == id && b.UserName == user.Name)
|
.FirstOrDefaultAsync(b => b.Identifier == id && b.UserId == user.Id)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
if (entity != null)
|
if (entity != null)
|
||||||
@@ -305,7 +309,7 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
{
|
{
|
||||||
var entities = _context.Backtests
|
var entities = _context.Backtests
|
||||||
.AsTracking()
|
.AsTracking()
|
||||||
.Where(b => b.UserName == user.Name && ids.Contains(b.Identifier))
|
.Where(b => b.UserId == user.Id && ids.Contains(b.Identifier))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (entities.Any())
|
if (entities.Any())
|
||||||
@@ -319,7 +323,7 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
{
|
{
|
||||||
var entities = await _context.Backtests
|
var entities = await _context.Backtests
|
||||||
.AsTracking()
|
.AsTracking()
|
||||||
.Where(b => b.UserName == user.Name && ids.Contains(b.Identifier))
|
.Where(b => b.UserId == user.Id && ids.Contains(b.Identifier))
|
||||||
.ToListAsync()
|
.ToListAsync()
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
@@ -334,7 +338,7 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
{
|
{
|
||||||
var entities = _context.Backtests
|
var entities = _context.Backtests
|
||||||
.AsTracking()
|
.AsTracking()
|
||||||
.Where(b => b.UserName == user.Name)
|
.Where(b => b.UserId == user.Id)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
if (entities.Any())
|
if (entities.Any())
|
||||||
@@ -380,7 +384,7 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
|
|
||||||
var baseQuery = _context.Backtests
|
var baseQuery = _context.Backtests
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Where(b => b.UserName == user.Name);
|
.Where(b => b.UserId == user.Id);
|
||||||
|
|
||||||
var afterQueryMs = stopwatch.ElapsedMilliseconds;
|
var afterQueryMs = stopwatch.ElapsedMilliseconds;
|
||||||
var totalCount = baseQuery.Count();
|
var totalCount = baseQuery.Count();
|
||||||
@@ -452,7 +456,7 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
|
|
||||||
var baseQuery = _context.Backtests
|
var baseQuery = _context.Backtests
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Where(b => b.UserName == user.Name);
|
.Where(b => b.UserId == user.Id);
|
||||||
|
|
||||||
var afterQueryMs = stopwatch.ElapsedMilliseconds;
|
var afterQueryMs = stopwatch.ElapsedMilliseconds;
|
||||||
var totalCount = await baseQuery.CountAsync().ConfigureAwait(false);
|
var totalCount = await baseQuery.CountAsync().ConfigureAwait(false);
|
||||||
@@ -556,7 +560,7 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
var entities = _context.BundleBacktestRequests
|
var entities = _context.BundleBacktestRequests
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Include(b => b.User)
|
.Include(b => b.User)
|
||||||
.Where(b => b.UserName == user.Name)
|
.Where(b => b.UserId == user.Id)
|
||||||
.OrderByDescending(b => b.CreatedAt)
|
.OrderByDescending(b => b.CreatedAt)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
@@ -568,7 +572,7 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
var entities = await _context.BundleBacktestRequests
|
var entities = await _context.BundleBacktestRequests
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Include(b => b.User)
|
.Include(b => b.User)
|
||||||
.Where(b => b.UserName == user.Name)
|
.Where(b => b.UserId == user.Id)
|
||||||
.OrderByDescending(b => b.CreatedAt)
|
.OrderByDescending(b => b.CreatedAt)
|
||||||
.ToListAsync()
|
.ToListAsync()
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
@@ -581,7 +585,7 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
var entity = _context.BundleBacktestRequests
|
var entity = _context.BundleBacktestRequests
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Include(b => b.User)
|
.Include(b => b.User)
|
||||||
.FirstOrDefault(b => b.RequestId == id && b.UserName == user.Name);
|
.FirstOrDefault(b => b.RequestId == id && b.UserId == user.Id);
|
||||||
|
|
||||||
return entity != null ? PostgreSqlMappers.Map(entity) : null;
|
return entity != null ? PostgreSqlMappers.Map(entity) : null;
|
||||||
}
|
}
|
||||||
@@ -591,7 +595,7 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
var entity = await _context.BundleBacktestRequests
|
var entity = await _context.BundleBacktestRequests
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Include(b => b.User)
|
.Include(b => b.User)
|
||||||
.FirstOrDefaultAsync(b => b.RequestId == id && b.UserName == user.Name)
|
.FirstOrDefaultAsync(b => b.RequestId == id && b.UserId == user.Id)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
return entity != null ? PostgreSqlMappers.Map(entity) : null;
|
return entity != null ? PostgreSqlMappers.Map(entity) : null;
|
||||||
@@ -682,7 +686,7 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
{
|
{
|
||||||
var entity = _context.BundleBacktestRequests
|
var entity = _context.BundleBacktestRequests
|
||||||
.AsTracking()
|
.AsTracking()
|
||||||
.FirstOrDefault(b => b.RequestId == id && b.UserName == user.Name);
|
.FirstOrDefault(b => b.RequestId == id && b.UserId == user.Id);
|
||||||
|
|
||||||
if (entity != null)
|
if (entity != null)
|
||||||
{
|
{
|
||||||
@@ -695,7 +699,7 @@ public class PostgreSqlBacktestRepository : IBacktestRepository
|
|||||||
{
|
{
|
||||||
var entity = await _context.BundleBacktestRequests
|
var entity = await _context.BundleBacktestRequests
|
||||||
.AsTracking()
|
.AsTracking()
|
||||||
.FirstOrDefaultAsync(b => b.RequestId == id && b.UserName == user.Name)
|
.FirstOrDefaultAsync(b => b.RequestId == id && b.UserId == user.Id)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
if (entity != null)
|
if (entity != null)
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public static class PostgreSqlMappers
|
|||||||
Type = account.Type,
|
Type = account.Type,
|
||||||
Key = account.Key,
|
Key = account.Key,
|
||||||
Secret = account.Secret,
|
Secret = account.Secret,
|
||||||
User = account.User != null ? Map(account.User) : null
|
UserId = account.User.Id,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,8 +88,7 @@ public static class PostgreSqlMappers
|
|||||||
StopLoss = moneyManagement.StopLoss,
|
StopLoss = moneyManagement.StopLoss,
|
||||||
TakeProfit = moneyManagement.TakeProfit,
|
TakeProfit = moneyManagement.TakeProfit,
|
||||||
Leverage = moneyManagement.Leverage,
|
Leverage = moneyManagement.Leverage,
|
||||||
UserName = moneyManagement.User?.Name,
|
UserId = moneyManagement.User?.Id ?? 0
|
||||||
User = moneyManagement.User != null ? Map(moneyManagement.User) : null
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,7 +203,7 @@ public static class PostgreSqlMappers
|
|||||||
var entity = new GeneticRequestEntity
|
var entity = new GeneticRequestEntity
|
||||||
{
|
{
|
||||||
RequestId = geneticRequest.RequestId,
|
RequestId = geneticRequest.RequestId,
|
||||||
User = geneticRequest.User != null ? Map(geneticRequest.User) : null,
|
UserId = geneticRequest.User?.Id ?? 0,
|
||||||
CreatedAt = geneticRequest.CreatedAt,
|
CreatedAt = geneticRequest.CreatedAt,
|
||||||
CompletedAt = geneticRequest.CompletedAt,
|
CompletedAt = geneticRequest.CompletedAt,
|
||||||
UpdatedAt = DateTime.UtcNow,
|
UpdatedAt = DateTime.UtcNow,
|
||||||
@@ -268,7 +267,8 @@ public static class PostgreSqlMappers
|
|||||||
var config = JsonConvert.DeserializeObject<TradingBotConfig>(entity.ConfigJson);
|
var config = JsonConvert.DeserializeObject<TradingBotConfig>(entity.ConfigJson);
|
||||||
var positionsList = JsonConvert.DeserializeObject<List<Position>>(entity.PositionsJson) ?? new List<Position>();
|
var positionsList = JsonConvert.DeserializeObject<List<Position>>(entity.PositionsJson) ?? new List<Position>();
|
||||||
var positions = positionsList.ToDictionary(p => p.Identifier, p => p);
|
var positions = positionsList.ToDictionary(p => p.Identifier, p => p);
|
||||||
var signalsList = JsonConvert.DeserializeObject<List<LightSignal>>(entity.SignalsJson) ?? new List<LightSignal>();
|
var signalsList = JsonConvert.DeserializeObject<List<LightSignal>>(entity.SignalsJson) ??
|
||||||
|
new List<LightSignal>();
|
||||||
var signals = signalsList.ToDictionary(s => s.Identifier, s => s);
|
var signals = signalsList.ToDictionary(s => s.Identifier, s => s);
|
||||||
var statistics = !string.IsNullOrEmpty(entity.StatisticsJson)
|
var statistics = !string.IsNullOrEmpty(entity.StatisticsJson)
|
||||||
? JsonConvert.DeserializeObject<PerformanceMetrics>(entity.StatisticsJson)
|
? JsonConvert.DeserializeObject<PerformanceMetrics>(entity.StatisticsJson)
|
||||||
@@ -283,7 +283,7 @@ public static class PostgreSqlMappers
|
|||||||
HodlPercentage = entity.HodlPercentage,
|
HodlPercentage = entity.HodlPercentage,
|
||||||
StartDate = entity.StartDate,
|
StartDate = entity.StartDate,
|
||||||
EndDate = entity.EndDate,
|
EndDate = entity.EndDate,
|
||||||
User = new User { Name = entity.UserName },
|
User = entity.User != null ? Map(entity.User) : null,
|
||||||
Statistics = statistics,
|
Statistics = statistics,
|
||||||
Fees = entity.Fees,
|
Fees = entity.Fees,
|
||||||
Score = entity.Score,
|
Score = entity.Score,
|
||||||
@@ -313,7 +313,7 @@ public static class PostgreSqlMappers
|
|||||||
StartDate = backtest.StartDate,
|
StartDate = backtest.StartDate,
|
||||||
EndDate = backtest.EndDate,
|
EndDate = backtest.EndDate,
|
||||||
MoneyManagementJson = JsonConvert.SerializeObject(backtest.Config?.MoneyManagement),
|
MoneyManagementJson = JsonConvert.SerializeObject(backtest.Config?.MoneyManagement),
|
||||||
UserName = backtest.User?.Name ?? string.Empty,
|
UserId = backtest.User?.Id ?? 0,
|
||||||
StatisticsJson = backtest.Statistics != null ? JsonConvert.SerializeObject(backtest.Statistics) : null,
|
StatisticsJson = backtest.Statistics != null ? JsonConvert.SerializeObject(backtest.Statistics) : null,
|
||||||
Fees = backtest.Fees,
|
Fees = backtest.Fees,
|
||||||
Score = backtest.Score,
|
Score = backtest.Score,
|
||||||
@@ -339,7 +339,7 @@ public static class PostgreSqlMappers
|
|||||||
|
|
||||||
var bundleRequest = new BundleBacktestRequest(entity.RequestId)
|
var bundleRequest = new BundleBacktestRequest(entity.RequestId)
|
||||||
{
|
{
|
||||||
User = entity.User != null ? Map(entity.User) : new User { Name = entity.UserName },
|
User = entity.User != null ? Map(entity.User) : null,
|
||||||
CreatedAt = entity.CreatedAt,
|
CreatedAt = entity.CreatedAt,
|
||||||
CompletedAt = entity.CompletedAt,
|
CompletedAt = entity.CompletedAt,
|
||||||
Status = entity.Status,
|
Status = entity.Status,
|
||||||
@@ -378,8 +378,7 @@ public static class PostgreSqlMappers
|
|||||||
var entity = new BundleBacktestRequestEntity
|
var entity = new BundleBacktestRequestEntity
|
||||||
{
|
{
|
||||||
RequestId = bundleRequest.RequestId,
|
RequestId = bundleRequest.RequestId,
|
||||||
UserName = bundleRequest.User?.Name ?? string.Empty,
|
UserId = bundleRequest.User?.Id ?? 0,
|
||||||
UserId = null, // Will be set by the repository when saving
|
|
||||||
CreatedAt = bundleRequest.CreatedAt,
|
CreatedAt = bundleRequest.CreatedAt,
|
||||||
CompletedAt = bundleRequest.CompletedAt,
|
CompletedAt = bundleRequest.CompletedAt,
|
||||||
Status = bundleRequest.Status,
|
Status = bundleRequest.Status,
|
||||||
@@ -431,7 +430,7 @@ public static class PostgreSqlMappers
|
|||||||
|
|
||||||
return new Scenario(entity.Name, entity.LoopbackPeriod)
|
return new Scenario(entity.Name, entity.LoopbackPeriod)
|
||||||
{
|
{
|
||||||
User = entity.UserName != null ? new User { Name = entity.UserName } : null,
|
User = entity.User != null ? Map(entity.User) : null,
|
||||||
Indicators = new List<IndicatorBase>() // Will be populated separately when needed
|
Indicators = new List<IndicatorBase>() // Will be populated separately when needed
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -444,7 +443,7 @@ public static class PostgreSqlMappers
|
|||||||
{
|
{
|
||||||
Name = scenario.Name,
|
Name = scenario.Name,
|
||||||
LoopbackPeriod = scenario.LoopbackPeriod ?? 1,
|
LoopbackPeriod = scenario.LoopbackPeriod ?? 1,
|
||||||
UserName = scenario.User?.Name
|
UserId = scenario.User?.Id ?? 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,7 +464,7 @@ public static class PostgreSqlMappers
|
|||||||
SmoothPeriods = entity.SmoothPeriods,
|
SmoothPeriods = entity.SmoothPeriods,
|
||||||
StochPeriods = entity.StochPeriods,
|
StochPeriods = entity.StochPeriods,
|
||||||
CyclePeriods = entity.CyclePeriods,
|
CyclePeriods = entity.CyclePeriods,
|
||||||
User = entity.UserName != null ? new User { Name = entity.UserName } : null
|
User = entity.User != null ? Map(entity.User) : null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,7 +487,7 @@ public static class PostgreSqlMappers
|
|||||||
SmoothPeriods = indicatorBase.SmoothPeriods,
|
SmoothPeriods = indicatorBase.SmoothPeriods,
|
||||||
StochPeriods = indicatorBase.StochPeriods,
|
StochPeriods = indicatorBase.StochPeriods,
|
||||||
CyclePeriods = indicatorBase.CyclePeriods,
|
CyclePeriods = indicatorBase.CyclePeriods,
|
||||||
UserName = indicatorBase.User?.Name
|
UserId = indicatorBase.User?.Id ?? 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,7 +510,7 @@ public static class PostgreSqlMappers
|
|||||||
entity.Type,
|
entity.Type,
|
||||||
entity.SignalType,
|
entity.SignalType,
|
||||||
entity.IndicatorName,
|
entity.IndicatorName,
|
||||||
entity.UserName != null ? new User { Name = entity.UserName } : null)
|
entity.User != null ? Map(entity.User) : null)
|
||||||
{
|
{
|
||||||
Status = entity.Status
|
Status = entity.Status
|
||||||
};
|
};
|
||||||
@@ -533,7 +532,7 @@ public static class PostgreSqlMappers
|
|||||||
Type = signal.IndicatorType,
|
Type = signal.IndicatorType,
|
||||||
SignalType = signal.SignalType,
|
SignalType = signal.SignalType,
|
||||||
IndicatorName = signal.IndicatorName,
|
IndicatorName = signal.IndicatorName,
|
||||||
UserName = signal.User?.Name,
|
UserId = signal.User?.Id ?? 0,
|
||||||
CandleJson = signal.Candle != null ? JsonConvert.SerializeObject(signal.Candle) : null
|
CandleJson = signal.Candle != null ? JsonConvert.SerializeObject(signal.Candle) : null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -559,7 +558,7 @@ public static class PostgreSqlMappers
|
|||||||
moneyManagement,
|
moneyManagement,
|
||||||
entity.Initiator,
|
entity.Initiator,
|
||||||
entity.Date,
|
entity.Date,
|
||||||
entity.UserName != null ? new User { Name = entity.UserName } : null)
|
entity.User != null ? Map(entity.User) : null)
|
||||||
{
|
{
|
||||||
Status = entity.Status,
|
Status = entity.Status,
|
||||||
SignalIdentifier = entity.SignalIdentifier
|
SignalIdentifier = entity.SignalIdentifier
|
||||||
@@ -596,7 +595,7 @@ public static class PostgreSqlMappers
|
|||||||
Initiator = position.Initiator,
|
Initiator = position.Initiator,
|
||||||
SignalIdentifier = position.SignalIdentifier,
|
SignalIdentifier = position.SignalIdentifier,
|
||||||
AccountName = position.AccountName,
|
AccountName = position.AccountName,
|
||||||
UserName = position.User?.Name,
|
UserId = position.User?.Id ?? 0,
|
||||||
MoneyManagementJson = position.MoneyManagement != null
|
MoneyManagementJson = position.MoneyManagement != null
|
||||||
? JsonConvert.SerializeObject(position.MoneyManagement)
|
? JsonConvert.SerializeObject(position.MoneyManagement)
|
||||||
: null
|
: null
|
||||||
@@ -703,7 +702,6 @@ public static class PostgreSqlMappers
|
|||||||
{
|
{
|
||||||
Identifier = bot.Identifier,
|
Identifier = bot.Identifier,
|
||||||
UserId = bot.User.Id,
|
UserId = bot.User.Id,
|
||||||
User = bot.User != null ? Map(bot.User) : null,
|
|
||||||
Status = bot.Status,
|
Status = bot.Status,
|
||||||
CreateDate = bot.CreateDate,
|
CreateDate = bot.CreateDate,
|
||||||
Name = bot.Name,
|
Name = bot.Name,
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ public class PostgreSqlTradingRepository : ITradingRepository
|
|||||||
{
|
{
|
||||||
var scenario = await _context.Scenarios
|
var scenario = await _context.Scenarios
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
|
.Include(s => s.User)
|
||||||
.Include(s => s.ScenarioIndicators)
|
.Include(s => s.ScenarioIndicators)
|
||||||
.ThenInclude(si => si.Indicator)
|
.ThenInclude(si => si.Indicator)
|
||||||
.FirstOrDefaultAsync(s => s.Name == name)
|
.FirstOrDefaultAsync(s => s.Name == name)
|
||||||
@@ -80,14 +81,36 @@ public class PostgreSqlTradingRepository : ITradingRepository
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<Scenario>> GetScenariosByUserAsync(User user)
|
||||||
|
{
|
||||||
|
var userId = user?.Id ?? 0;
|
||||||
|
var scenarios = await _context.Scenarios
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(s => s.User)
|
||||||
|
.Include(s => s.ScenarioIndicators)
|
||||||
|
.ThenInclude(si => si.Indicator)
|
||||||
|
.Where(s => s.UserId == userId)
|
||||||
|
.ToListAsync()
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
return scenarios.Select(scenario =>
|
||||||
|
{
|
||||||
|
var mappedScenario = PostgreSqlMappers.Map(scenario);
|
||||||
|
mappedScenario.Indicators = scenario.ScenarioIndicators
|
||||||
|
.Select(si => PostgreSqlMappers.Map(si.Indicator))
|
||||||
|
.ToList();
|
||||||
|
return mappedScenario;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public async Task InsertScenarioAsync(Scenario scenario)
|
public async Task InsertScenarioAsync(Scenario scenario)
|
||||||
{
|
{
|
||||||
|
var userId = scenario.User?.Id ?? 0;
|
||||||
|
|
||||||
// Check if scenario already exists for the same user
|
// Check if scenario already exists for the same user
|
||||||
var existingScenario = await _context.Scenarios
|
var existingScenario = await _context.Scenarios
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(s => s.Name == scenario.Name &&
|
.FirstOrDefaultAsync(s => s.Name == scenario.Name && s.UserId == userId);
|
||||||
((scenario.User == null && s.UserName == null) ||
|
|
||||||
(scenario.User != null && s.UserName == scenario.User.Name)));
|
|
||||||
|
|
||||||
if (existingScenario != null)
|
if (existingScenario != null)
|
||||||
{
|
{
|
||||||
@@ -104,11 +127,10 @@ public class PostgreSqlTradingRepository : ITradingRepository
|
|||||||
{
|
{
|
||||||
foreach (var indicator in scenario.Indicators)
|
foreach (var indicator in scenario.Indicators)
|
||||||
{
|
{
|
||||||
|
var indicatorUserId = indicator.User?.Id ?? 0;
|
||||||
var indicatorEntity = await _context.Indicators
|
var indicatorEntity = await _context.Indicators
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(i => i.Name == indicator.Name &&
|
.FirstOrDefaultAsync(i => i.Name == indicator.Name && i.UserId == indicatorUserId);
|
||||||
((indicator.User == null && i.UserName == null) ||
|
|
||||||
(indicator.User != null && i.UserName == indicator.User.Name)));
|
|
||||||
|
|
||||||
if (indicatorEntity != null)
|
if (indicatorEntity != null)
|
||||||
{
|
{
|
||||||
@@ -134,7 +156,7 @@ public class PostgreSqlTradingRepository : ITradingRepository
|
|||||||
if (entity != null)
|
if (entity != null)
|
||||||
{
|
{
|
||||||
entity.LoopbackPeriod = scenario.LoopbackPeriod ?? 1;
|
entity.LoopbackPeriod = scenario.LoopbackPeriod ?? 1;
|
||||||
entity.UserName = scenario.User?.Name;
|
entity.UserId = scenario.User?.Id ?? 0;
|
||||||
entity.UpdatedAt = DateTime.UtcNow;
|
entity.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
@@ -196,12 +218,11 @@ public class PostgreSqlTradingRepository : ITradingRepository
|
|||||||
|
|
||||||
public async Task InsertIndicatorAsync(IndicatorBase indicatorBase)
|
public async Task InsertIndicatorAsync(IndicatorBase indicatorBase)
|
||||||
{
|
{
|
||||||
|
var indicatorUserId = indicatorBase.User?.Id ?? 0;
|
||||||
// Check if indicator already exists for the same user
|
// Check if indicator already exists for the same user
|
||||||
var existingIndicator = await _context.Indicators
|
var existingIndicator = await _context.Indicators
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(i => i.Name == indicatorBase.Name &&
|
.FirstOrDefaultAsync(i => i.Name == indicatorBase.Name && i.UserId == indicatorUserId);
|
||||||
((indicatorBase.User == null && i.UserName == null) ||
|
|
||||||
(indicatorBase.User != null && i.UserName == indicatorBase.User.Name)));
|
|
||||||
|
|
||||||
if (existingIndicator != null)
|
if (existingIndicator != null)
|
||||||
{
|
{
|
||||||
@@ -233,7 +254,7 @@ public class PostgreSqlTradingRepository : ITradingRepository
|
|||||||
entity.SmoothPeriods = indicatorBase.SmoothPeriods;
|
entity.SmoothPeriods = indicatorBase.SmoothPeriods;
|
||||||
entity.StochPeriods = indicatorBase.StochPeriods;
|
entity.StochPeriods = indicatorBase.StochPeriods;
|
||||||
entity.CyclePeriods = indicatorBase.CyclePeriods;
|
entity.CyclePeriods = indicatorBase.CyclePeriods;
|
||||||
entity.UserName = indicatorBase.User?.Name;
|
entity.UserId = indicatorBase.User?.Id ?? 0;
|
||||||
entity.UpdatedAt = DateTime.UtcNow;
|
entity.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
@@ -249,6 +270,7 @@ public class PostgreSqlTradingRepository : ITradingRepository
|
|||||||
{
|
{
|
||||||
var position = await _context.Positions
|
var position = await _context.Positions
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
|
.Include(p => p.User)
|
||||||
.Include(p => p.OpenTrade)
|
.Include(p => p.OpenTrade)
|
||||||
.Include(p => p.StopLossTrade)
|
.Include(p => p.StopLossTrade)
|
||||||
.Include(p => p.TakeProfit1Trade)
|
.Include(p => p.TakeProfit1Trade)
|
||||||
@@ -268,6 +290,7 @@ public class PostgreSqlTradingRepository : ITradingRepository
|
|||||||
{
|
{
|
||||||
var positions = await _context.Positions
|
var positions = await _context.Positions
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
|
.Include(p => p.User)
|
||||||
.Include(p => p.OpenTrade)
|
.Include(p => p.OpenTrade)
|
||||||
.Include(p => p.StopLossTrade)
|
.Include(p => p.StopLossTrade)
|
||||||
.Include(p => p.TakeProfit1Trade)
|
.Include(p => p.TakeProfit1Trade)
|
||||||
@@ -288,6 +311,7 @@ public class PostgreSqlTradingRepository : ITradingRepository
|
|||||||
{
|
{
|
||||||
var positions = await _context.Positions
|
var positions = await _context.Positions
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
|
.Include(p => p.User)
|
||||||
.Include(p => p.OpenTrade)
|
.Include(p => p.OpenTrade)
|
||||||
.Include(p => p.StopLossTrade)
|
.Include(p => p.StopLossTrade)
|
||||||
.Include(p => p.TakeProfit1Trade)
|
.Include(p => p.TakeProfit1Trade)
|
||||||
@@ -301,12 +325,11 @@ public class PostgreSqlTradingRepository : ITradingRepository
|
|||||||
|
|
||||||
public async Task InsertPositionAsync(Position position)
|
public async Task InsertPositionAsync(Position position)
|
||||||
{
|
{
|
||||||
|
var positionUserId = position.User?.Id ?? 0;
|
||||||
// Check if position already exists for the same user
|
// Check if position already exists for the same user
|
||||||
var existingPosition = await _context.Positions
|
var existingPosition = await _context.Positions
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(p => p.Identifier == position.Identifier &&
|
.FirstOrDefaultAsync(p => p.Identifier == position.Identifier && p.UserId == positionUserId);
|
||||||
((position.User == null && p.UserName == null) ||
|
|
||||||
(position.User != null && p.UserName == position.User.Name)));
|
|
||||||
|
|
||||||
if (existingPosition != null)
|
if (existingPosition != null)
|
||||||
{
|
{
|
||||||
@@ -385,10 +408,11 @@ public class PostgreSqlTradingRepository : ITradingRepository
|
|||||||
|
|
||||||
public async Task<IEnumerable<Signal>> GetSignalsByUserAsync(User user)
|
public async Task<IEnumerable<Signal>> GetSignalsByUserAsync(User user)
|
||||||
{
|
{
|
||||||
|
var userId = user?.Id ?? 0;
|
||||||
var signals = await _context.Signals
|
var signals = await _context.Signals
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Where(s => (user == null && s.UserName == null) ||
|
.Include(s => s.User)
|
||||||
(user != null && s.UserName == user.Name))
|
.Where(s => s.UserId == userId)
|
||||||
.ToListAsync()
|
.ToListAsync()
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
@@ -402,11 +426,11 @@ public class PostgreSqlTradingRepository : ITradingRepository
|
|||||||
|
|
||||||
public async Task<Signal> GetSignalByIdentifierAsync(string identifier, User user = null)
|
public async Task<Signal> GetSignalByIdentifierAsync(string identifier, User user = null)
|
||||||
{
|
{
|
||||||
|
var userId = user?.Id ?? 0;
|
||||||
var signal = await _context.Signals
|
var signal = await _context.Signals
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(s => s.Identifier == identifier &&
|
.Include(s => s.User)
|
||||||
((user == null && s.UserName == null) ||
|
.FirstOrDefaultAsync(s => s.Identifier == identifier && s.UserId == userId)
|
||||||
(user != null && s.UserName == user.Name)))
|
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
return PostgreSqlMappers.Map(signal);
|
return PostgreSqlMappers.Map(signal);
|
||||||
@@ -414,13 +438,13 @@ public class PostgreSqlTradingRepository : ITradingRepository
|
|||||||
|
|
||||||
public async Task InsertSignalAsync(Signal signal)
|
public async Task InsertSignalAsync(Signal signal)
|
||||||
{
|
{
|
||||||
|
var signalUserId = signal.User?.Id ?? 0;
|
||||||
// Check if signal already exists with the same identifier, date, and user
|
// Check if signal already exists with the same identifier, date, and user
|
||||||
var existingSignal = _context.Signals
|
var existingSignal = _context.Signals
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.FirstOrDefault(s => s.Identifier == signal.Identifier &&
|
.FirstOrDefault(s => s.Identifier == signal.Identifier &&
|
||||||
s.Date == signal.Date &&
|
s.Date == signal.Date &&
|
||||||
((s.UserName == null && signal.User == null) ||
|
s.UserId == signalUserId);
|
||||||
(s.UserName != null && signal.User != null && s.UserName == signal.User.Name)));
|
|
||||||
|
|
||||||
if (existingSignal != null)
|
if (existingSignal != null)
|
||||||
{
|
{
|
||||||
@@ -435,21 +459,21 @@ public class PostgreSqlTradingRepository : ITradingRepository
|
|||||||
|
|
||||||
public async Task<IndicatorBase> GetStrategyByNameUserAsync(string name, User user)
|
public async Task<IndicatorBase> GetStrategyByNameUserAsync(string name, User user)
|
||||||
{
|
{
|
||||||
|
var userId = user?.Id ?? 0;
|
||||||
var indicator = await _context.Indicators
|
var indicator = await _context.Indicators
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(i => i.Name == name &&
|
.Include(i => i.User)
|
||||||
((user == null && i.UserName == null) ||
|
.FirstOrDefaultAsync(i => i.Name == name && i.UserId == userId);
|
||||||
(user != null && i.UserName == user.Name)));
|
|
||||||
return PostgreSqlMappers.Map(indicator);
|
return PostgreSqlMappers.Map(indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Scenario> GetScenarioByNameUserAsync(string scenarioName, User user)
|
public async Task<Scenario> GetScenarioByNameUserAsync(string scenarioName, User user)
|
||||||
{
|
{
|
||||||
|
var userId = user?.Id ?? 0;
|
||||||
var scenario = await _context.Scenarios
|
var scenario = await _context.Scenarios
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(s => s.Name == scenarioName &&
|
.Include(s => s.User)
|
||||||
((user == null && s.UserName == null) ||
|
.FirstOrDefaultAsync(s => s.Name == scenarioName && s.UserId == userId);
|
||||||
(user != null && s.UserName == user.Name)));
|
|
||||||
return PostgreSqlMappers.Map(scenario);
|
return PostgreSqlMappers.Map(scenario);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,12 +41,12 @@ public class PostgreSqlUserRepository : IUserRepository
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await EnsureConnectionOpenAsync();
|
await EnsureConnectionOpenAsync();
|
||||||
|
|
||||||
var userEntity = await _context.Users
|
var userEntity = await _context.Users
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(u => u.AgentName == agentName)
|
.FirstOrDefaultAsync(u => u.AgentName == agentName)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
return PostgreSqlMappers.Map(userEntity);
|
return PostgreSqlMappers.Map(userEntity);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@@ -62,12 +62,12 @@ public class PostgreSqlUserRepository : IUserRepository
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await EnsureConnectionOpenAsync();
|
await EnsureConnectionOpenAsync();
|
||||||
|
|
||||||
var userEntity = await _context.Users
|
var userEntity = await _context.Users
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(u => u.Name == name)
|
.FirstOrDefaultAsync(u => u.Name == name)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
return PostgreSqlMappers.Map(userEntity);
|
return PostgreSqlMappers.Map(userEntity);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@@ -78,25 +78,17 @@ public class PostgreSqlUserRepository : IUserRepository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InsertUserAsync(User user)
|
|
||||||
{
|
|
||||||
var userEntity = PostgreSqlMappers.Map(user);
|
|
||||||
|
|
||||||
_context.Users.Add(userEntity);
|
|
||||||
await _context.SaveChangesAsync().ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<IEnumerable<User>> GetAllUsersAsync()
|
public async Task<IEnumerable<User>> GetAllUsersAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await EnsureConnectionOpenAsync();
|
await EnsureConnectionOpenAsync();
|
||||||
|
|
||||||
var userEntities = await _context.Users
|
var userEntities = await _context.Users
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.ToListAsync()
|
.ToListAsync()
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
return userEntities.Select(PostgreSqlMappers.Map);
|
return userEntities.Select(PostgreSqlMappers.Map);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@@ -107,31 +99,45 @@ public class PostgreSqlUserRepository : IUserRepository
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateUser(User user)
|
public async Task SaveOrUpdateUserAsync(User user)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var userEntity = await _context.Users
|
var existingUser = await _context.Users
|
||||||
.AsTracking() // Explicitly enable tracking for update operations
|
.AsTracking()
|
||||||
.FirstOrDefaultAsync(u => u.Name == user.Name)
|
.FirstOrDefaultAsync(u => u.Name == user.Name)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
if (userEntity == null)
|
if (existingUser != null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"User with name '{user.Name}' not found");
|
// Update existing user
|
||||||
|
existingUser.AgentName = user.AgentName;
|
||||||
|
existingUser.AvatarUrl = user.AvatarUrl;
|
||||||
|
existingUser.TelegramChannel = user.TelegramChannel;
|
||||||
|
|
||||||
|
_context.Users.Update(existingUser);
|
||||||
|
|
||||||
|
// Update the user object with the existing user's ID
|
||||||
|
user.Id = existingUser.Id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Insert new user
|
||||||
|
var userEntity = PostgreSqlMappers.Map(user);
|
||||||
|
_context.Users.Add(userEntity);
|
||||||
|
|
||||||
|
// Update the user object with the database-generated ID after save
|
||||||
|
await _context.SaveChangesAsync().ConfigureAwait(false);
|
||||||
|
user.Id = userEntity.Id;
|
||||||
|
return; // Exit early since we already saved
|
||||||
}
|
}
|
||||||
|
|
||||||
userEntity.AgentName = user.AgentName;
|
|
||||||
userEntity.AvatarUrl = user.AvatarUrl;
|
|
||||||
userEntity.TelegramChannel = user.TelegramChannel;
|
|
||||||
|
|
||||||
_context.Users.Update(userEntity);
|
|
||||||
await _context.SaveChangesAsync().ConfigureAwait(false);
|
await _context.SaveChangesAsync().ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Console.WriteLine(e);
|
Console.WriteLine(e);
|
||||||
throw new Exception("Cannot update user");
|
throw new Exception("Cannot save or update user");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user