mirror of
https://github.com/aljazceru/BTCPayServerPlugins.git
synced 2025-12-17 15:44:26 +01:00
120 lines
3.9 KiB
C#
120 lines
3.9 KiB
C#
using System;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using BTCPayServer.Abstractions.Models;
|
|
using BTCPayServer.Client.Models;
|
|
using BTCPayServer.Data;
|
|
using BTCPayServer.Services.Reporting;
|
|
using Dapper;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Routing;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
namespace BTCPayServer.Plugins.DynamicReports;
|
|
|
|
public class PostgresReportProvider : ReportProvider
|
|
{
|
|
public string ReportName { get; set; }
|
|
public override string Name => ReportName;
|
|
public DynamicReportsSettings.DynamicReportSetting Setting { get; set; }
|
|
|
|
private readonly ApplicationDbContextFactory _dbContextFactory;
|
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
public PostgresReportProvider( ApplicationDbContextFactory dbContextFactory, IHttpContextAccessor httpContextAccessor)
|
|
{
|
|
_dbContextFactory = dbContextFactory;
|
|
_httpContextAccessor = httpContextAccessor;
|
|
}
|
|
public override bool IsAvailable()
|
|
{
|
|
return Setting.AllowForNonAdmins || _httpContextAccessor.HttpContext?.User.IsInRole(Roles.ServerAdmin) is true;
|
|
}
|
|
public override async Task Query(QueryContext queryContext, CancellationToken cancellation)
|
|
{
|
|
await ExecuteQuery(_dbContextFactory, queryContext,Setting.Sql, cancellation);
|
|
}
|
|
|
|
public static async Task ExecuteQuery(ApplicationDbContextFactory dbContextFactory, QueryContext queryContext, string sql,
|
|
CancellationToken cancellation)
|
|
{
|
|
await using var dbContext = dbContextFactory.CreateContext();
|
|
await using var connection = dbContext.Database.GetDbConnection();
|
|
await connection.OpenAsync(cancellation);
|
|
await using var transaction = await connection.BeginTransactionAsync(cancellation);
|
|
try
|
|
{
|
|
|
|
var rows = (await connection.QueryAsync(sql, new
|
|
{
|
|
queryContext.From,
|
|
queryContext.To,
|
|
queryContext.StoreId
|
|
}))?.ToArray();
|
|
if (rows?.Any() is true)
|
|
{
|
|
var firstRow = new RouteValueDictionary(rows.First());
|
|
queryContext.ViewDefinition = new ViewDefinition()
|
|
{
|
|
Fields = firstRow.Keys.Select(f => new StoreReportResponse.Field(f, ObjectToFieldType(firstRow[f])))
|
|
.ToList(),
|
|
Charts = new()
|
|
};
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
foreach (var row in rows)
|
|
{
|
|
var rowParsed = new RouteValueDictionary(row);
|
|
var data = queryContext.CreateData();
|
|
foreach (var field in queryContext.ViewDefinition.Fields)
|
|
{
|
|
var rowFieldValue = rowParsed[field.Name];
|
|
field.Type ??= ObjectToFieldType(rowFieldValue);
|
|
data.Add(rowFieldValue);
|
|
}
|
|
|
|
queryContext.Data.Add(data);
|
|
}
|
|
|
|
queryContext.ViewDefinition.Fields.Where(field => field.Type is null).ToList()
|
|
.ForEach(field => field.Type = "string");
|
|
|
|
}
|
|
finally
|
|
{
|
|
|
|
await transaction.RollbackAsync(cancellation);
|
|
}
|
|
}
|
|
|
|
private static string? ObjectToFieldType(object? value)
|
|
{
|
|
|
|
if (value is null)
|
|
return null;
|
|
if(value is string)
|
|
return "string";
|
|
if(value is DateTime)
|
|
return "datetime";
|
|
if(value is DateTimeOffset)
|
|
return "datetime";
|
|
if(value is bool)
|
|
return "boolean";
|
|
if(value is int)
|
|
return "amount";
|
|
if(value is decimal)
|
|
return "amount";
|
|
if(value is long)
|
|
return "amount";
|
|
if(value is double)
|
|
return "amount";
|
|
|
|
|
|
return "string";
|
|
}
|
|
} |