Update account/position and platform summary

This commit is contained in:
2025-09-26 01:18:59 +07:00
parent b2e38811ed
commit bcfeb693ce
32 changed files with 3301 additions and 151 deletions

View File

@@ -0,0 +1,63 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Managing.Infrastructure.Databases.Migrations
{
/// <inheritdoc />
public partial class RemoveAccountNameFromPositions : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Fee",
table: "Trades");
migrationBuilder.DropColumn(
name: "AccountName",
table: "Positions");
migrationBuilder.AddColumn<decimal>(
name: "GasFees",
table: "Positions",
type: "numeric(18,8)",
nullable: false,
defaultValue: 0m);
migrationBuilder.AddColumn<decimal>(
name: "UiFees",
table: "Positions",
type: "numeric(18,8)",
nullable: false,
defaultValue: 0m);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "GasFees",
table: "Positions");
migrationBuilder.DropColumn(
name: "UiFees",
table: "Positions");
migrationBuilder.AddColumn<decimal>(
name: "Fee",
table: "Trades",
type: "numeric(18,8)",
nullable: false,
defaultValue: 0m);
migrationBuilder.AddColumn<string>(
name: "AccountName",
table: "Positions",
type: "character varying(255)",
maxLength: 255,
nullable: false,
defaultValue: "");
}
}
}

View File

@@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Managing.Infrastructure.Databases.Migrations
{
/// <inheritdoc />
public partial class AddAccountIdToPositions : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "AccountId",
table: "Positions",
type: "integer",
nullable: false,
defaultValue: 0);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "AccountId",
table: "Positions");
}
}
}

View File

@@ -666,10 +666,8 @@ namespace Managing.Infrastructure.Databases.Migrations
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<string>("AccountName")
.IsRequired()
.HasMaxLength(255)
.HasColumnType("character varying(255)");
b.Property<int>("AccountId")
.HasColumnType("integer");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");
@@ -677,6 +675,9 @@ namespace Managing.Infrastructure.Databases.Migrations
b.Property<DateTime>("Date")
.HasColumnType("timestamp with time zone");
b.Property<decimal>("GasFees")
.HasColumnType("decimal(18,8)");
b.Property<string>("Initiator")
.IsRequired()
.HasColumnType("text");
@@ -719,6 +720,9 @@ namespace Managing.Infrastructure.Databases.Migrations
.IsRequired()
.HasColumnType("text");
b.Property<decimal>("UiFees")
.HasColumnType("decimal(18,8)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("timestamp with time zone");
@@ -1083,9 +1087,6 @@ namespace Managing.Infrastructure.Databases.Migrations
.HasMaxLength(255)
.HasColumnType("character varying(255)");
b.Property<decimal>("Fee")
.HasColumnType("decimal(18,8)");
b.Property<decimal>("Leverage")
.HasColumnType("decimal(18,8)");

View File

@@ -11,16 +11,20 @@ public class PositionEntity
public DateTime Date { get; set; }
[Required] public int AccountId { get; set; }
[Column(TypeName = "decimal(18,8)")] public decimal ProfitAndLoss { get; set; }
[Column(TypeName = "decimal(18,8)")] public decimal UiFees { get; set; }
[Column(TypeName = "decimal(18,8)")] public decimal GasFees { get; set; }
public TradeDirection OriginDirection { get; set; }
public PositionStatus Status { get; set; }
public Ticker Ticker { get; set; }
public PositionInitiator Initiator { get; set; }
[MaxLength(255)] public string SignalIdentifier { get; set; }
[MaxLength(255)] public string AccountName { get; set; }
[MaxLength(255)] public string? SignalIdentifier { get; set; }
public int? UserId { get; set; }

View File

@@ -16,9 +16,6 @@ public class TradeEntity
public TradeType TradeType { get; set; }
public Ticker Ticker { get; set; }
[Column(TypeName = "decimal(18,8)")]
public decimal Fee { get; set; }
[Column(TypeName = "decimal(18,8)")]
public decimal Quantity { get; set; }

View File

@@ -301,7 +301,6 @@ public class ManagingDbContext : DbContext
entity.Property(e => e.Ticker).IsRequired().HasConversion<string>();
entity.Property(e => e.Initiator).IsRequired().HasConversion<string>();
entity.Property(e => e.SignalIdentifier).IsRequired().HasMaxLength(255);
entity.Property(e => e.AccountName).IsRequired().HasMaxLength(255);
entity.Property(e => e.UserId);
entity.Property(e => e.InitiatorIdentifier).IsRequired();
entity.Property(e => e.MoneyManagementJson).HasColumnType("text");
@@ -351,7 +350,6 @@ public class ManagingDbContext : DbContext
entity.Property(e => e.Status).IsRequired().HasConversion<string>();
entity.Property(e => e.TradeType).IsRequired().HasConversion<string>();
entity.Property(e => e.Ticker).IsRequired().HasConversion<string>();
entity.Property(e => e.Fee).HasColumnType("decimal(18,8)");
entity.Property(e => e.Quantity).HasColumnType("decimal(18,8)");
entity.Property(e => e.Price).HasColumnType("decimal(18,8)");
entity.Property(e => e.Leverage).HasColumnType("decimal(18,8)");
@@ -561,8 +559,6 @@ public class ManagingDbContext : DbContext
.HasForeignKey(e => e.UserId)
.OnDelete(DeleteBehavior.Cascade);
});
}
/// <summary>
@@ -575,7 +571,7 @@ public class ManagingDbContext : DbContext
// when using AdoNetClustering and AdoNetReminderService.
// This method serves as a verification point and can be extended
// for custom Orleans table management if needed.
// For now, we just ensure the database is accessible
await Database.CanConnectAsync();
}
@@ -587,12 +583,12 @@ public class ManagingDbContext : DbContext
public async Task<Dictionary<string, long>> GetOrleansTableStatsAsync()
{
var stats = new Dictionary<string, long>();
// Orleans table names
var orleansTables = new[]
{
"orleansmembershiptable",
"orleansmembershipversiontable",
"orleansmembershipversiontable",
"orleansquery",
"orleansreminderstable",
"orleansstorage"
@@ -630,7 +626,7 @@ public class ManagingDbContext : DbContext
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
// Add any additional configuration here if needed
}
}

View File

@@ -82,6 +82,27 @@ public class PostgreSqlAccountRepository : IAccountRepository
}
}
public async Task<Account> GetAccountByIdAsync(int id)
{
try
{
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
var accountEntity = await _context.Accounts
.AsNoTracking()
.Include(a => a.User)
.FirstOrDefaultAsync(a => a.Id == id)
.ConfigureAwait(false);
return PostgreSqlMappers.Map(accountEntity);
}
finally
{
// Always ensure the connection is closed after the operation
await PostgreSqlConnectionHelper.SafeCloseConnectionAsync(_context);
}
}
public async Task<IEnumerable<Account>> GetAccountsAsync()
{
try

View File

@@ -28,6 +28,7 @@ public static class PostgreSqlMappers
return new Account
{
Id = entity.Id,
Name = entity.Name,
Exchange = entity.Exchange,
Type = entity.Type,
@@ -45,6 +46,7 @@ public static class PostgreSqlMappers
return new AccountEntity
{
Id = account.Id,
Name = account.Name,
Exchange = account.Exchange,
Type = account.Type,
@@ -554,7 +556,7 @@ public static class PostgreSqlMappers
var position = new Position(
entity.Identifier,
entity.AccountName,
entity.AccountId,
entity.OriginDirection,
entity.Ticker,
moneyManagement,
@@ -569,6 +571,10 @@ public static class PostgreSqlMappers
// Set ProfitAndLoss with proper type
position.ProfitAndLoss = new ProfitAndLoss { Realized = entity.ProfitAndLoss };
// Set fee properties
position.UiFees = entity.UiFees;
position.GasFees = entity.GasFees;
// Map related trades
if (entity.OpenTrade != null)
@@ -591,13 +597,15 @@ public static class PostgreSqlMappers
{
Identifier = position.Identifier,
Date = position.Date,
AccountId = position.AccountId,
ProfitAndLoss = position.ProfitAndLoss?.Realized ?? 0,
UiFees = position.UiFees,
GasFees = position.GasFees,
OriginDirection = position.OriginDirection,
Status = position.Status,
Ticker = position.Ticker,
Initiator = position.Initiator,
SignalIdentifier = position.SignalIdentifier,
AccountName = position.AccountName,
UserId = position.User?.Id ?? 0,
InitiatorIdentifier = position.InitiatorIdentifier,
MoneyManagementJson = position.MoneyManagement != null
@@ -621,10 +629,7 @@ public static class PostgreSqlMappers
entity.Price,
entity.Leverage,
entity.ExchangeOrderId,
entity.Message)
{
Fee = entity.Fee
};
entity.Message);
}
public static TradeEntity Map(Trade trade)
@@ -638,7 +643,6 @@ public static class PostgreSqlMappers
Status = trade.Status,
TradeType = trade.TradeType,
Ticker = trade.Ticker,
Fee = trade.Fee,
Quantity = trade.Quantity,
Price = trade.Price,
Leverage = trade.Leverage,

View File

@@ -106,7 +106,7 @@ public class PostgreSqlTradingRepository : ITradingRepository
public async Task InsertScenarioAsync(Scenario scenario)
{
var userId = scenario.User?.Id ?? 0;
// Check if scenario already exists for the same user
var existingScenario = await _context.Scenarios
.AsNoTracking()
@@ -271,7 +271,7 @@ public class PostgreSqlTradingRepository : ITradingRepository
try
{
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
var position = await _context.Positions
.AsNoTracking()
.Include(p => p.User)
@@ -395,6 +395,8 @@ public class PostgreSqlTradingRepository : ITradingRepository
{
entity.Date = position.Date;
entity.ProfitAndLoss = position.ProfitAndLoss?.Realized ?? 0;
entity.UiFees = position.UiFees;
entity.GasFees = position.GasFees;
entity.Status = position.Status;
entity.SignalIdentifier = position.SignalIdentifier;
entity.MoneyManagementJson = position.MoneyManagement != null
@@ -440,7 +442,6 @@ public class PostgreSqlTradingRepository : ITradingRepository
entity.Status = trade.Status;
entity.TradeType = trade.TradeType;
entity.Ticker = trade.Ticker;
entity.Fee = trade.Fee;
entity.Quantity = trade.Quantity;
entity.Price = trade.Price;
entity.Leverage = trade.Leverage;
@@ -468,7 +469,8 @@ public class PostgreSqlTradingRepository : ITradingRepository
return PostgreSqlMappers.Map(positions);
}
public async Task<IEnumerable<Position>> GetPositionsByInitiatorIdentifiersAsync(IEnumerable<Guid> initiatorIdentifiers)
public async Task<IEnumerable<Position>> GetPositionsByInitiatorIdentifiersAsync(
IEnumerable<Guid> initiatorIdentifiers)
{
var identifiersList = initiatorIdentifiers.ToList();
if (!identifiersList.Any())
@@ -510,7 +512,7 @@ public class PostgreSqlTradingRepository : ITradingRepository
try
{
await PostgreSqlConnectionHelper.EnsureConnectionOpenAsync(_context);
// Calculate total PnL from all finished positions (closed positions)
// Only include positions that are Finished or Flipped (closed positions)
var totalPnL = await _context.Positions