Skip to content

Commit 52c38ed

Browse files
committed
feat: Add Slug property to transaction DTOs and update import logic for enhanced data handling
1 parent 9bad46c commit 52c38ed

File tree

7 files changed

+79
-18
lines changed

7 files changed

+79
-18
lines changed

src/CryptoTracker.Client/Pages/Import.razor

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
</RadzenDataGridColumn>
5252
<RadzenDataGridColumn TItem="ImportTransactionRowDTO" Title="Coin">
5353
<Template Context="row">
54-
<CoinLink Symbol="@row.Symbol" />
54+
<CoinLink Symbol="@row.Symbol" Slug="@row.Slug" />
5555
</Template>
5656
</RadzenDataGridColumn>
5757
<RadzenDataGridColumn TItem="ImportTransactionRowDTO" Title="Menge">
@@ -75,7 +75,7 @@
7575
</RadzenDataGridColumn>
7676
<RadzenDataGridColumn TItem="ImportTransactionRowDTO" Title="Coin">
7777
<Template Context="row">
78-
<CoinLink Symbol="@row.Symbol" />
78+
<CoinLink Symbol="@row.Symbol" Slug="@row.Slug" />
7979
</Template>
8080
</RadzenDataGridColumn>
8181
<RadzenDataGridColumn TItem="ImportTransactionRowDTO" Title="Menge">
@@ -100,7 +100,7 @@
100100
<RadzenDataGridColumn TItem="ImportTradeRowDTO" Property="Side" Title="Seite" />
101101
<RadzenDataGridColumn TItem="ImportTradeRowDTO" Title="Coin">
102102
<Template Context="row">
103-
<CoinLink Symbol="@row.Symbol" />
103+
<CoinLink Symbol="@row.Symbol" Slug="@row.Slug" />
104104
</Template>
105105
</RadzenDataGridColumn>
106106
<RadzenDataGridColumn TItem="ImportTradeRowDTO" Property="OppositeSymbol" Title="Gegen-Coin" />
@@ -161,7 +161,7 @@
161161
<RadzenDataGridColumn TItem="ImportPreviewTransactionRowDTO" Property="Type" Title="Typ" />
162162
<RadzenDataGridColumn TItem="ImportPreviewTransactionRowDTO" Title="Coin">
163163
<Template Context="row">
164-
<CoinLink Symbol="@row.Coin" />
164+
<CoinLink Symbol="@row.Coin" Slug="@row.Slug" />
165165
</Template>
166166
</RadzenDataGridColumn>
167167
<RadzenDataGridColumn TItem="ImportPreviewTransactionRowDTO" Property="Amount" Title="Menge" />
@@ -202,7 +202,7 @@
202202
<RadzenDataGridColumn TItem="ImportPreviewTransactionRowDTO" Property="Type" Title="Typ" />
203203
<RadzenDataGridColumn TItem="ImportPreviewTransactionRowDTO" Title="Coin">
204204
<Template Context="row">
205-
<CoinLink Symbol="@row.Coin" />
205+
<CoinLink Symbol="@row.Coin" Slug="@row.Slug" />
206206
</Template>
207207
</RadzenDataGridColumn>
208208
<RadzenDataGridColumn TItem="ImportPreviewTransactionRowDTO" Property="Amount" Title="Menge" />

src/CryptoTracker.Client/Shared/Imports/ImportPreviewTransactionRowDTO.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ namespace CryptoTracker.Shared;
33
public record ImportPreviewTransactionRowDTO(DateTimeOffset DateTime,
44
string Type,
55
string Coin,
6+
string? Slug,
67
string? Network,
78
string Amount,
89
string Fee,

src/CryptoTracker.Client/Shared/Imports/ImportTradeRowDTO.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ namespace CryptoTracker.Shared;
33
public record ImportTradeRowDTO(DateTimeOffset DateTime,
44
string Side,
55
string Symbol,
6+
string? Slug,
67
string OppositeSymbol,
78
decimal Price,
89
decimal Quantity,

src/CryptoTracker.Client/Shared/Imports/ImportTransactionRowDTO.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ namespace CryptoTracker.Shared;
33
public record ImportTransactionRowDTO(DateTimeOffset DateTime,
44
string Type,
55
string Symbol,
6+
string? Slug,
67
decimal Amount,
78
decimal Fee,
89
string Wallet,

src/CryptoTracker/Controllers/DataImportController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public async Task<IActionResult> PreviewImport([FromForm] IFormFile file)
5858
using var memory = new MemoryStream();
5959
await file.CopyToAsync(memory);
6060
var bytes = memory.ToArray();
61-
var result = _importAutoService.Preview(() => new MemoryStream(bytes), file.FileName);
61+
var result = await _importAutoService.PreviewAsync(() => new MemoryStream(bytes), file.FileName);
6262
return Ok(result);
6363
}
6464

@@ -82,7 +82,7 @@ async Task<ImportPreviewResult> IDataImportApi.PreviewImportAsync(IBrowserFile f
8282
{
8383
using var memory = new MemoryStream();
8484
await file.OpenReadStream(MAX_REQUEST_SIZE).CopyToAsync(memory);
85-
return _importAutoService.Preview(() => new MemoryStream(memory.ToArray()), file.Name);
85+
return await _importAutoService.PreviewAsync(() => new MemoryStream(memory.ToArray()), file.Name);
8686
}
8787

8888
async Task IDataImportApi.ImportAutoAsync(string walletName, IBrowserFile file, ImportDocumentType? documentType)

src/CryptoTracker/Controllers/ImportOverviewController.cs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using CryptoTracker.Entities;
2+
using CryptoTracker.Services;
23
using CryptoTracker.Shared;
34
using Microsoft.AspNetCore.Mvc;
45
using Microsoft.EntityFrameworkCore;
@@ -10,10 +11,12 @@ namespace CryptoTracker.Controllers;
1011
public class ImportOverviewController : ControllerBase, IImportOverviewApi
1112
{
1213
private readonly CryptoTrackerDbContext _dbContext;
14+
private readonly CoinRateService _coinRateService;
1315

14-
public ImportOverviewController(CryptoTrackerDbContext dbContext)
16+
public ImportOverviewController(CryptoTrackerDbContext dbContext, CoinRateService coinRateService)
1517
{
1618
_dbContext = dbContext;
19+
_coinRateService = coinRateService;
1720
}
1821

1922
[HttpGet("GetOverview")]
@@ -36,36 +39,46 @@ private async Task<ImportOverviewDTO> LoadOverviewAsync()
3639
.Include(t => t.Wallet)
3740
.ToListAsync();
3841

42+
var symbols = transactions.Select(t => t.Symbol)
43+
.Concat(trades.Select(t => t.Symbol))
44+
.Where(s => !string.IsNullOrWhiteSpace(s))
45+
.Distinct(StringComparer.OrdinalIgnoreCase)
46+
.ToList();
47+
48+
var slugs = await _coinRateService.GetSlugsAsync(symbols);
49+
3950
var deposits = transactions
4051
.Where(t => t.TransactionType == TransactionType.Receive)
41-
.Select(MapTransaction)
52+
.Select(t => MapTransaction(t, slugs))
4253
.OrderBy(t => t.DateTime)
4354
.ToList();
4455

4556
var withdrawals = transactions
4657
.Where(t => t.TransactionType == TransactionType.Send)
47-
.Select(MapTransaction)
58+
.Select(t => MapTransaction(t, slugs))
4859
.OrderBy(t => t.DateTime)
4960
.ToList();
5061

5162
var tradeRows = trades
52-
.Select(MapTrade)
63+
.Select(t => MapTrade(t, slugs))
5364
.OrderBy(t => t.DateTime)
5465
.ToList();
5566

5667
return new ImportOverviewDTO(deposits, withdrawals, tradeRows);
5768
}
5869

59-
private static ImportTransactionRowDTO MapTransaction(CryptoTransaction transaction)
70+
private static ImportTransactionRowDTO MapTransaction(CryptoTransaction transaction, IReadOnlyDictionary<string, string?> slugs)
6071
{
6172
var type = transaction.TransactionType == TransactionType.Receive ? "Einzahlung" : "Auszahlung";
6273
var amount = transaction.TransactionType == TransactionType.Receive
6374
? transaction.QuantityAfterFee
6475
: transaction.Quantity;
76+
var slug = slugs.TryGetValue(transaction.Symbol, out var value) ? value : null;
6577

6678
return new ImportTransactionRowDTO(transaction.DateTime,
6779
type,
6880
transaction.Symbol,
81+
slug,
6982
amount,
7083
transaction.Fee,
7184
transaction.Wallet.Name,
@@ -76,12 +89,14 @@ private static ImportTransactionRowDTO MapTransaction(CryptoTransaction transact
7689
Guid.NewGuid());
7790
}
7891

79-
private static ImportTradeRowDTO MapTrade(CryptoTrade trade)
92+
private static ImportTradeRowDTO MapTrade(CryptoTrade trade, IReadOnlyDictionary<string, string?> slugs)
8093
{
8194
var side = trade.TradeType == TradeType.Buy ? "BUY" : "SELL";
95+
var slug = slugs.TryGetValue(trade.Symbol, out var value) ? value : null;
8296
return new ImportTradeRowDTO(trade.DateTime,
8397
side,
8498
trade.Symbol,
99+
slug,
85100
trade.OppositeSymbol,
86101
trade.Price,
87102
trade.Quantity,

src/CryptoTracker/Services/ImportAutoService.cs

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,19 +55,26 @@ public class ImportAutoService
5555
};
5656

5757
private readonly DataImportService _dataImportService;
58+
private readonly CoinRateService? _coinRateService;
59+
60+
public ImportAutoService(DataImportService dataImportService, CoinRateService coinRateService)
61+
{
62+
_dataImportService = dataImportService;
63+
_coinRateService = coinRateService;
64+
}
5865

5966
public ImportAutoService(DataImportService dataImportService)
6067
{
6168
_dataImportService = dataImportService;
6269
}
6370

64-
public ImportPreviewResult Preview(Func<Stream> openStream, string fileName)
71+
public async Task<ImportPreviewResult> PreviewAsync(Func<Stream> openStream, string fileName)
6572
{
6673
try
6774
{
6875
var detected = Detect(openStream, fileName);
6976
var preview = BuildPreview(openStream, fileName, detected);
70-
return preview;
77+
return await ApplyPreviewSlugsAsync(preview);
7178
}
7279
catch (Exception ex)
7380
{
@@ -77,6 +84,9 @@ public ImportPreviewResult Preview(Func<Stream> openStream, string fileName)
7784
}
7885
}
7986

87+
public ImportPreviewResult Preview(Func<Stream> openStream, string fileName)
88+
=> PreviewAsync(openStream, fileName).GetAwaiter().GetResult();
89+
8090
public async Task ImportAsync(string walletName, Func<Stream> openStream, string fileName, ImportDocumentType? documentType)
8191
{
8292
var detected = Detect(openStream, fileName);
@@ -356,6 +366,39 @@ void AddTrade(ImportPreviewTradeRowDTO row)
356366
transactions, transactionsTruncated, trades, tradesTruncated);
357367
}
358368

369+
private async Task<ImportPreviewResult> ApplyPreviewSlugsAsync(ImportPreviewResult preview)
370+
{
371+
if (_coinRateService == null || !preview.Success || preview.TransactionRows.Count == 0)
372+
{
373+
return preview;
374+
}
375+
376+
var symbols = preview.TransactionRows
377+
.Select(r => r.Coin.Trim())
378+
.Where(s => !string.IsNullOrWhiteSpace(s))
379+
.Distinct(StringComparer.OrdinalIgnoreCase)
380+
.ToList();
381+
382+
if (symbols.Count == 0)
383+
{
384+
return preview;
385+
}
386+
387+
var slugs = await _coinRateService.GetSlugsAsync(symbols);
388+
var updated = preview.TransactionRows
389+
.Select(row =>
390+
{
391+
var symbol = row.Coin.Trim();
392+
var slug = !string.IsNullOrWhiteSpace(symbol) && slugs.TryGetValue(symbol, out var value)
393+
? value
394+
: null;
395+
return row with { Slug = slug };
396+
})
397+
.ToList();
398+
399+
return preview with { TransactionRows = updated };
400+
}
401+
359402
private async Task ImportDetectedAsync(string walletName, Func<Stream> openStream, string fileName, DetectedFile detected, ImportDocumentType? documentType)
360403
{
361404
switch (detected.Variant)
@@ -998,7 +1041,7 @@ private static ImportPreviewTransactionRowDTO BuildTransactionPreview(Dictionary
9981041
string? source)
9991042
{
10001043
var date = ParseDateTimeOffset(GetValue(row, "dateutc", "datum", "timestamp", "utctime", "date", "time"));
1001-
return new ImportPreviewTransactionRowDTO(date, type, coin ?? string.Empty, network, amount ?? string.Empty,
1044+
return new ImportPreviewTransactionRowDTO(date, type, coin ?? string.Empty, null, network, amount ?? string.Empty,
10021045
fee ?? string.Empty, address, comment, source);
10031046
}
10041047

@@ -1059,7 +1102,7 @@ private static ImportPreviewTransactionRowDTO BuildBinanceTransactionPreview(Dic
10591102
{
10601103
var hasUtcHeader = HasUtcHeader(row);
10611104
var date = ParseBinanceExchangeTime(GetValue(row, "dateutc", "time"), isExcel, hasUtcHeader);
1062-
return new ImportPreviewTransactionRowDTO(date, type, coin ?? string.Empty, network, amount ?? string.Empty,
1105+
return new ImportPreviewTransactionRowDTO(date, type, coin ?? string.Empty, null, network, amount ?? string.Empty,
10631106
fee ?? string.Empty, address, comment, "Binance");
10641107
}
10651108

@@ -1074,7 +1117,7 @@ private static ImportPreviewTransactionRowDTO BuildStatementTransactionPreview(B
10741117
var amountText = FormatDecimal(Math.Abs(row.Change));
10751118
var comment = BuildOperationComment(row.Operation, row.Remark);
10761119
return new ImportPreviewTransactionRowDTO(row.Date, isDeposit ? "Einzahlung" : "Auszahlung", row.Coin ?? "UNKNOWN",
1077-
null, amountText, "0", null, comment, source);
1120+
null, null, amountText, "0", null, comment, source);
10781121
}
10791122

10801123
private static ImportPreviewTradeRowDTO BuildBinanceConvertPreview(Dictionary<string, string?> row)

0 commit comments

Comments
 (0)