162 lines
5.6 KiB
C#
162 lines
5.6 KiB
C#
using Microsoft.AspNetCore.Components.Authorization;
|
|
using Raven.Client.Documents;
|
|
using ZahlenAnalyse.Web.Models;
|
|
using ExcelDataReader;
|
|
using System.Data;
|
|
|
|
namespace ZahlenAnalyse.Web.Services;
|
|
|
|
public class WorkspaceService
|
|
{
|
|
private readonly IDocumentStore _store;
|
|
private readonly AuthenticationStateProvider _authStateProvider;
|
|
|
|
// Den AuthStateProvider injizieren
|
|
public WorkspaceService(IDocumentStore store, AuthenticationStateProvider authStateProvider)
|
|
{
|
|
_store = store;
|
|
_authStateProvider = authStateProvider;
|
|
}
|
|
|
|
private async Task<string> GetUserIdAsync()
|
|
{
|
|
var authState = await _authStateProvider.GetAuthenticationStateAsync();
|
|
var user = authState.User;
|
|
var userid = user.FindFirst(c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")?.Value
|
|
?? user.FindFirst("sub")?.Value
|
|
?? string.Empty;
|
|
return userid;
|
|
}
|
|
|
|
// --- Die Magie passiert hier ---
|
|
private async Task EnrichWithAuditDataAsync(object entity)
|
|
{
|
|
// Wenn das Objekt weder IOwnedEntity noch IAuditableEntity ist, können wir abbrechen
|
|
if (entity is not IOwnedEntity and not IAuditableEntity)
|
|
return;
|
|
|
|
var authState = await _authStateProvider.GetAuthenticationStateAsync();
|
|
var user = authState.User;
|
|
|
|
if (entity is IOwnedEntity ownedEntity)
|
|
{
|
|
var userid = await GetUserIdAsync();
|
|
|
|
// Setzt bei JEDEM Speichern sicherheitshalber den aktuellen User als Owner
|
|
ownedEntity.OwnerId = userid;
|
|
}
|
|
|
|
if (entity is IAuditableEntity auditableEntity)
|
|
{
|
|
// WICHTIG: Wir setzen CreatedBy und CreatedAt NUR, wenn sie noch leer sind.
|
|
// Sonst würden wir bei einem Update (z.B. Namensänderung des Workspaces)
|
|
// das ursprüngliche Erstellungsdatum und den ursprünglichen Ersteller überschreiben!
|
|
if (string.IsNullOrWhiteSpace(auditableEntity.CreatedBy))
|
|
{
|
|
auditableEntity.CreatedBy = user.FindFirst("name")?.Value ?? user.Identity?.Name ?? "Unbekannt";
|
|
auditableEntity.CreatedAt = DateTime.UtcNow;
|
|
}
|
|
}
|
|
}
|
|
|
|
public async Task SaveWorkspaceAsync(Workspace workspace)
|
|
{
|
|
// 1. Audit-Daten automatisch befüllen
|
|
await EnrichWithAuditDataAsync(workspace);
|
|
|
|
// 2. Speichern
|
|
using var session = _store.OpenAsyncSession();
|
|
await session.StoreAsync(workspace);
|
|
await session.SaveChangesAsync();
|
|
}
|
|
|
|
public async Task<List<Workspace>> GetWorkspacesForUserAsync()
|
|
{
|
|
|
|
var authState = await _authStateProvider.GetAuthenticationStateAsync();
|
|
var ownerId = await GetUserIdAsync();
|
|
|
|
using var session = _store.OpenAsyncSession();
|
|
return await session.Query<Workspace>()
|
|
.Where(w => w.OwnerId == ownerId)
|
|
.ToListAsync();
|
|
}
|
|
|
|
public async Task<Workspace?> GetWorkspaceAsync(string id)
|
|
{
|
|
var authState = await _authStateProvider.GetAuthenticationStateAsync();
|
|
var currentUserId = await GetUserIdAsync();
|
|
|
|
using var session = _store.OpenAsyncSession();
|
|
var workspace = await session.LoadAsync<Workspace>(id);
|
|
|
|
|
|
if (workspace != null && workspace.OwnerId != currentUserId)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return workspace;
|
|
}
|
|
|
|
public async Task SaveFaktAsync(AnalysisFakt fakt)
|
|
{
|
|
// Unsere elegante Hilfsmethode von vorhin füllt OwnerId, CreatedBy und CreatedAt!
|
|
await EnrichWithAuditDataAsync(fakt);
|
|
|
|
using var session = _store.OpenAsyncSession();
|
|
await session.StoreAsync(fakt);
|
|
await session.SaveChangesAsync();
|
|
}
|
|
|
|
public async Task<List<AnalysisFakt>> GetFaktenForWorkspaceAsync(string workspaceId)
|
|
{
|
|
using var session = _store.OpenAsyncSession();
|
|
var ownerId = await GetUserIdAsync();
|
|
|
|
|
|
return await session.Query<AnalysisFakt>()
|
|
.Where(f => f.WorkspaceId == workspaceId && f.OwnerId == ownerId)
|
|
.OrderByDescending(f => f.Date)
|
|
.ToListAsync();
|
|
}
|
|
|
|
public async Task ImportFromExcelAsync(string workspaceId, Stream fileStream)
|
|
{
|
|
// Encoding für deutsche Excel-Dateien
|
|
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
|
|
|
|
using var reader = ExcelReaderFactory.CreateReader(fileStream);
|
|
var result = reader.AsDataSet(new ExcelDataSetConfiguration() {
|
|
ConfigureDataTable = (_) => new ExcelDataTableConfiguration() { UseHeaderRow = true }
|
|
});
|
|
|
|
var dataTable = result.Tables[0];
|
|
|
|
using var session = _store.OpenAsyncSession();
|
|
|
|
foreach (DataRow row in dataTable.Rows)
|
|
{
|
|
var fakt = new AnalysisFakt
|
|
{
|
|
WorkspaceId = workspaceId,
|
|
Date = Convert.ToDateTime(row["Datum"]),
|
|
Amount = Convert.ToDecimal(row["Betrag"]),
|
|
// Hier mappen wir dynamisch die Dimensionen
|
|
Dimensions = new Dictionary<string, string>()
|
|
};
|
|
|
|
// Wir gehen davon aus, dass deine Excel-Spaltennamen
|
|
// den Dimensions-Namen entsprechen
|
|
foreach (var col in dataTable.Columns.Cast<DataColumn>().Skip(2)) // Datum/Betrag überspringen
|
|
{
|
|
fakt.Dimensions[col.ColumnName] = row[col.ColumnName].ToString() ?? "";
|
|
}
|
|
|
|
await EnrichWithAuditDataAsync(fakt);
|
|
await session.StoreAsync(fakt);
|
|
}
|
|
|
|
await session.SaveChangesAsync();
|
|
}
|
|
} |