|
|
@@ -5,6 +5,8 @@ namespace TrafagSalesExporter.Services;
|
|
|
|
|
|
|
|
|
|
|
|
public class HanaQueryService : IHanaQueryService
|
|
|
|
public class HanaQueryService : IHanaQueryService
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
private const string TscParameterName = "tsc";
|
|
|
|
|
|
|
|
private const string DateFilterParameterName = "dateFilter";
|
|
|
|
private readonly IAppEventLogService _appEventLogService;
|
|
|
|
private readonly IAppEventLogService _appEventLogService;
|
|
|
|
|
|
|
|
|
|
|
|
public HanaQueryService(IAppEventLogService appEventLogService)
|
|
|
|
public HanaQueryService(IAppEventLogService appEventLogService)
|
|
|
@@ -12,39 +14,42 @@ public class HanaQueryService : IHanaQueryService
|
|
|
|
_appEventLogService = appEventLogService;
|
|
|
|
_appEventLogService = appEventLogService;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public List<SalesRecord> GetSalesRecords(HanaServer server,
|
|
|
|
public async Task<List<SalesRecord>> GetSalesRecordsAsync(HanaServer server,
|
|
|
|
string schema, string tsc, string land, string dateFilter)
|
|
|
|
string schema, string tsc, string land, string dateFilter, CancellationToken cancellationToken = default)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var connectionString = server.BuildConnectionString();
|
|
|
|
var connectionString = server.BuildConnectionString();
|
|
|
|
var result = new List<SalesRecord>();
|
|
|
|
var result = new List<SalesRecord>();
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
try
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_appEventLogService.WriteAsync("HANA", "Verbindungsaufbau gestartet", land: land,
|
|
|
|
await _appEventLogService.WriteAsync("HANA", "Verbindungsaufbau gestartet", land: land,
|
|
|
|
details: $"Server={server.GetConnectionStringPreview()} | Schema={schema} | TSC={tsc}").GetAwaiter().GetResult();
|
|
|
|
details: $"Server={server.GetConnectionStringPreview()} | Schema={schema} | TSC={tsc}");
|
|
|
|
|
|
|
|
|
|
|
|
using var connection = new HanaConnection(connectionString);
|
|
|
|
using var connection = new HanaConnection(connectionString);
|
|
|
|
connection.Open();
|
|
|
|
await connection.OpenAsync(cancellationToken);
|
|
|
|
|
|
|
|
|
|
|
|
_appEventLogService.WriteAsync("HANA", "Verbindung erfolgreich", land: land,
|
|
|
|
await _appEventLogService.WriteAsync("HANA", "Verbindung erfolgreich", land: land,
|
|
|
|
details: $"Schema={schema} | TSC={tsc}").GetAwaiter().GetResult();
|
|
|
|
details: $"Schema={schema} | TSC={tsc}");
|
|
|
|
|
|
|
|
|
|
|
|
var invoiceQuery = GetInvoiceQuery(schema, tsc, dateFilter);
|
|
|
|
var invoiceQuery = GetInvoiceQuery(schema);
|
|
|
|
var creditNoteQuery = GetCreditNoteQuery(schema, tsc, dateFilter);
|
|
|
|
var creditNoteQuery = GetCreditNoteQuery(schema);
|
|
|
|
|
|
|
|
var parsedDateFilter = ParseDateFilter(dateFilter);
|
|
|
|
|
|
|
|
|
|
|
|
_appEventLogService.WriteAsync("HANA", "Invoice-Query gestartet", land: land, details: invoiceQuery).GetAwaiter().GetResult();
|
|
|
|
await _appEventLogService.WriteAsync("HANA", "Invoice-Query gestartet", land: land,
|
|
|
|
var invoiceRecords = ReadRecords(connection, invoiceQuery, land, "Invoice");
|
|
|
|
details: BuildQueryLogDetails(invoiceQuery, schema, tsc, parsedDateFilter));
|
|
|
|
|
|
|
|
var invoiceRecords = await ReadRecordsAsync(connection, invoiceQuery, tsc, parsedDateFilter, land, "Invoice", cancellationToken);
|
|
|
|
result.AddRange(invoiceRecords);
|
|
|
|
result.AddRange(invoiceRecords);
|
|
|
|
_appEventLogService.WriteAsync("HANA", "Invoice-Query beendet", land: land, details: $"Zeilen={invoiceRecords.Count}").GetAwaiter().GetResult();
|
|
|
|
await _appEventLogService.WriteAsync("HANA", "Invoice-Query beendet", land: land, details: $"Zeilen={invoiceRecords.Count}");
|
|
|
|
|
|
|
|
|
|
|
|
_appEventLogService.WriteAsync("HANA", "Credit-Query gestartet", land: land, details: creditNoteQuery).GetAwaiter().GetResult();
|
|
|
|
await _appEventLogService.WriteAsync("HANA", "Credit-Query gestartet", land: land,
|
|
|
|
var creditRecords = ReadRecords(connection, creditNoteQuery, land, "Credit");
|
|
|
|
details: BuildQueryLogDetails(creditNoteQuery, schema, tsc, parsedDateFilter));
|
|
|
|
|
|
|
|
var creditRecords = await ReadRecordsAsync(connection, creditNoteQuery, tsc, parsedDateFilter, land, "Credit", cancellationToken);
|
|
|
|
result.AddRange(creditRecords);
|
|
|
|
result.AddRange(creditRecords);
|
|
|
|
_appEventLogService.WriteAsync("HANA", "Credit-Query beendet", land: land, details: $"Zeilen={creditRecords.Count}").GetAwaiter().GetResult();
|
|
|
|
await _appEventLogService.WriteAsync("HANA", "Credit-Query beendet", land: land, details: $"Zeilen={creditRecords.Count}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_appEventLogService.WriteAsync("HANA", "HANA-Abfrage fehlgeschlagen", "Error", land: land, details: ex.ToString()).GetAwaiter().GetResult();
|
|
|
|
await _appEventLogService.WriteAsync("HANA", "HANA-Abfrage fehlgeschlagen", "Error", land: land, details: ex.ToString());
|
|
|
|
throw;
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@@ -60,7 +65,7 @@ public class HanaQueryService : IHanaQueryService
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public ConnectionTestResult TestConnectionDetailed(HanaServer server)
|
|
|
|
public async Task<ConnectionTestResult> TestConnectionDetailedAsync(HanaServer server, CancellationToken cancellationToken = default)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var testResult = new ConnectionTestResult
|
|
|
|
var testResult = new ConnectionTestResult
|
|
|
|
{
|
|
|
|
{
|
|
|
@@ -71,20 +76,20 @@ public class HanaQueryService : IHanaQueryService
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
try
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_appEventLogService.WriteAsync("HANA", "Verbindungstest gestartet",
|
|
|
|
await _appEventLogService.WriteAsync("HANA", "Verbindungstest gestartet",
|
|
|
|
details: testResult.ConnectionStringPreview).GetAwaiter().GetResult();
|
|
|
|
details: testResult.ConnectionStringPreview);
|
|
|
|
var connectionString = server.BuildConnectionString();
|
|
|
|
var connectionString = server.BuildConnectionString();
|
|
|
|
using var connection = new HanaConnection(connectionString);
|
|
|
|
using var connection = new HanaConnection(connectionString);
|
|
|
|
connection.Open();
|
|
|
|
await connection.OpenAsync(cancellationToken);
|
|
|
|
|
|
|
|
|
|
|
|
testResult.Stage = "Ping-Query";
|
|
|
|
testResult.Stage = "Ping-Query";
|
|
|
|
using var command = new HanaCommand("SELECT 1 FROM DUMMY", connection);
|
|
|
|
using var command = new HanaCommand("SELECT 1 FROM DUMMY", connection);
|
|
|
|
command.ExecuteScalar();
|
|
|
|
await command.ExecuteScalarAsync(cancellationToken);
|
|
|
|
|
|
|
|
|
|
|
|
testResult.Success = true;
|
|
|
|
testResult.Success = true;
|
|
|
|
testResult.Stage = "OK";
|
|
|
|
testResult.Stage = "OK";
|
|
|
|
_appEventLogService.WriteAsync("HANA", "Verbindungstest erfolgreich",
|
|
|
|
await _appEventLogService.WriteAsync("HANA", "Verbindungstest erfolgreich",
|
|
|
|
details: testResult.ConnectionStringPreview).GetAwaiter().GetResult();
|
|
|
|
details: testResult.ConnectionStringPreview);
|
|
|
|
return testResult;
|
|
|
|
return testResult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
catch (Exception ex)
|
|
|
@@ -92,24 +97,24 @@ public class HanaQueryService : IHanaQueryService
|
|
|
|
testResult.Success = false;
|
|
|
|
testResult.Success = false;
|
|
|
|
testResult.ErrorMessage = ex.Message;
|
|
|
|
testResult.ErrorMessage = ex.Message;
|
|
|
|
testResult.ExceptionType = ex.GetType().Name;
|
|
|
|
testResult.ExceptionType = ex.GetType().Name;
|
|
|
|
_appEventLogService.WriteAsync("HANA", "Verbindungstest fehlgeschlagen", "Error",
|
|
|
|
await _appEventLogService.WriteAsync("HANA", "Verbindungstest fehlgeschlagen", "Error",
|
|
|
|
details: $"{testResult.ConnectionStringPreview}{Environment.NewLine}{ex}").GetAwaiter().GetResult();
|
|
|
|
details: $"{testResult.ConnectionStringPreview}{Environment.NewLine}{ex}");
|
|
|
|
return testResult;
|
|
|
|
return testResult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void TestConnection(HanaServer server)
|
|
|
|
public async Task TestConnectionAsync(HanaServer server, CancellationToken cancellationToken = default)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var connectionString = server.BuildConnectionString();
|
|
|
|
var connectionString = server.BuildConnectionString();
|
|
|
|
using var connection = new HanaConnection(connectionString);
|
|
|
|
using var connection = new HanaConnection(connectionString);
|
|
|
|
connection.Open();
|
|
|
|
await connection.OpenAsync(cancellationToken);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public List<string> GetAvailableSchemas(HanaServer server)
|
|
|
|
public async Task<List<string>> GetAvailableSchemasAsync(HanaServer server, CancellationToken cancellationToken = default)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var connectionString = server.BuildConnectionString();
|
|
|
|
var connectionString = server.BuildConnectionString();
|
|
|
|
using var connection = new HanaConnection(connectionString);
|
|
|
|
using var connection = new HanaConnection(connectionString);
|
|
|
|
connection.Open();
|
|
|
|
await connection.OpenAsync(cancellationToken);
|
|
|
|
|
|
|
|
|
|
|
|
const string query = """
|
|
|
|
const string query = """
|
|
|
|
SELECT schema_name
|
|
|
|
SELECT schema_name
|
|
|
@@ -124,10 +129,10 @@ public class HanaQueryService : IHanaQueryService
|
|
|
|
""";
|
|
|
|
""";
|
|
|
|
|
|
|
|
|
|
|
|
using var command = new HanaCommand(query, connection);
|
|
|
|
using var command = new HanaCommand(query, connection);
|
|
|
|
using var reader = command.ExecuteReader();
|
|
|
|
using var reader = await command.ExecuteReaderAsync(cancellationToken);
|
|
|
|
|
|
|
|
|
|
|
|
var schemas = new List<string>();
|
|
|
|
var schemas = new List<string>();
|
|
|
|
while (reader.Read())
|
|
|
|
while (await reader.ReadAsync(cancellationToken))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var schema = reader["schema_name"]?.ToString()?.Trim();
|
|
|
|
var schema = reader["schema_name"]?.ToString()?.Trim();
|
|
|
|
if (!string.IsNullOrWhiteSpace(schema))
|
|
|
|
if (!string.IsNullOrWhiteSpace(schema))
|
|
|
@@ -137,15 +142,17 @@ public class HanaQueryService : IHanaQueryService
|
|
|
|
return schemas;
|
|
|
|
return schemas;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private List<SalesRecord> ReadRecords(HanaConnection connection, string query, string land, string queryName)
|
|
|
|
private async Task<List<SalesRecord>> ReadRecordsAsync(HanaConnection connection, string query, string tsc, DateTime dateFilter, string land, string queryName, CancellationToken cancellationToken)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var records = new List<SalesRecord>();
|
|
|
|
var records = new List<SalesRecord>();
|
|
|
|
|
|
|
|
|
|
|
|
using var command = new HanaCommand(query, connection);
|
|
|
|
using var command = new HanaCommand(query, connection);
|
|
|
|
using var reader = command.ExecuteReader();
|
|
|
|
command.Parameters.Add(new HanaParameter(TscParameterName, HanaDbType.NVarChar) { Value = tsc });
|
|
|
|
|
|
|
|
command.Parameters.Add(new HanaParameter(DateFilterParameterName, HanaDbType.Date) { Value = dateFilter.Date });
|
|
|
|
|
|
|
|
using var reader = await command.ExecuteReaderAsync(cancellationToken);
|
|
|
|
var counter = 0;
|
|
|
|
var counter = 0;
|
|
|
|
|
|
|
|
|
|
|
|
while (reader.Read())
|
|
|
|
while (await reader.ReadAsync(cancellationToken))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
records.Add(new SalesRecord
|
|
|
|
records.Add(new SalesRecord
|
|
|
|
{
|
|
|
|
{
|
|
|
@@ -180,18 +187,21 @@ public class HanaQueryService : IHanaQueryService
|
|
|
|
counter++;
|
|
|
|
counter++;
|
|
|
|
if (counter % 250 == 0)
|
|
|
|
if (counter % 250 == 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_appEventLogService.WriteDebugAsync("HANA", $"{queryName}-Query liest Daten", land: land,
|
|
|
|
await _appEventLogService.WriteDebugAsync("HANA", $"{queryName}-Query liest Daten", land: land,
|
|
|
|
details: $"Bisher gelesene Zeilen={counter}").GetAwaiter().GetResult();
|
|
|
|
details: $"Bisher gelesene Zeilen={counter}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return records;
|
|
|
|
return records;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static string GetInvoiceQuery(string schema, string tsc, string dateFilter) => $@"
|
|
|
|
private static string GetInvoiceQuery(string schema)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var quotedSchema = QuoteIdentifier(schema);
|
|
|
|
|
|
|
|
return $@"
|
|
|
|
SELECT
|
|
|
|
SELECT
|
|
|
|
CURRENT_TIMESTAMP AS extraction_date,
|
|
|
|
CURRENT_TIMESTAMP AS extraction_date,
|
|
|
|
'{tsc}' AS tsc,
|
|
|
|
:{TscParameterName} AS tsc,
|
|
|
|
h.""DocNum"" AS invoice_number,
|
|
|
|
h.""DocNum"" AS invoice_number,
|
|
|
|
p.""LineNum"" AS invoice_position,
|
|
|
|
p.""LineNum"" AS invoice_position,
|
|
|
|
h.""DocDate"" AS invoice_date,
|
|
|
|
h.""DocDate"" AS invoice_date,
|
|
|
@@ -216,30 +226,34 @@ SELECT
|
|
|
|
'' AS incoterms_2020,
|
|
|
|
'' AS incoterms_2020,
|
|
|
|
COALESCE(emp.""SlpName"", '') AS sales_responsible,
|
|
|
|
COALESCE(emp.""SlpName"", '') AS sales_responsible,
|
|
|
|
CASE WHEN p.""BaseType"" = 17
|
|
|
|
CASE WHEN p.""BaseType"" = 17
|
|
|
|
THEN (SELECT o.""DocDate"" FROM {schema}.""ORDR"" o
|
|
|
|
THEN (SELECT o.""DocDate"" FROM {quotedSchema}.""ORDR"" o
|
|
|
|
WHERE o.""DocEntry"" = p.""BaseEntry"")
|
|
|
|
WHERE o.""DocEntry"" = p.""BaseEntry"")
|
|
|
|
ELSE NULL END AS order_date,
|
|
|
|
ELSE NULL END AS order_date,
|
|
|
|
'INV' AS doc_type
|
|
|
|
'INV' AS doc_type
|
|
|
|
FROM {schema}.""OINV"" h
|
|
|
|
FROM {quotedSchema}.""OINV"" h
|
|
|
|
INNER JOIN {schema}.""INV1"" p ON h.""DocEntry"" = p.""DocEntry""
|
|
|
|
INNER JOIN {quotedSchema}.""INV1"" p ON h.""DocEntry"" = p.""DocEntry""
|
|
|
|
LEFT JOIN {schema}.""OITM"" itm ON p.""ItemCode"" = itm.""ItemCode""
|
|
|
|
LEFT JOIN {quotedSchema}.""OITM"" itm ON p.""ItemCode"" = itm.""ItemCode""
|
|
|
|
LEFT JOIN {schema}.""OITB"" grp ON itm.""ItmsGrpCod"" = grp.""ItmsGrpCod""
|
|
|
|
LEFT JOIN {quotedSchema}.""OITB"" grp ON itm.""ItmsGrpCod"" = grp.""ItmsGrpCod""
|
|
|
|
LEFT JOIN {schema}.""OCRD"" cust ON h.""CardCode"" = cust.""CardCode""
|
|
|
|
LEFT JOIN {quotedSchema}.""OCRD"" cust ON h.""CardCode"" = cust.""CardCode""
|
|
|
|
LEFT JOIN {schema}.""CRD1"" cust_adr ON h.""CardCode"" = cust_adr.""CardCode""
|
|
|
|
LEFT JOIN {quotedSchema}.""CRD1"" cust_adr ON h.""CardCode"" = cust_adr.""CardCode""
|
|
|
|
AND cust_adr.""AdresType"" = 'B' AND cust_adr.""Address"" = h.""PayToCode""
|
|
|
|
AND cust_adr.""AdresType"" = 'B' AND cust_adr.""Address"" = h.""PayToCode""
|
|
|
|
LEFT JOIN {schema}.""OOND"" ind ON cust.""IndustryC"" = ind.""IndCode""
|
|
|
|
LEFT JOIN {quotedSchema}.""OOND"" ind ON cust.""IndustryC"" = ind.""IndCode""
|
|
|
|
LEFT JOIN {schema}.""OCRD"" sup ON itm.""CardCode"" = sup.""CardCode""
|
|
|
|
LEFT JOIN {quotedSchema}.""OCRD"" sup ON itm.""CardCode"" = sup.""CardCode""
|
|
|
|
AND sup.""CardType"" = 'S'
|
|
|
|
AND sup.""CardType"" = 'S'
|
|
|
|
LEFT JOIN {schema}.""CRD1"" sup_adr ON itm.""CardCode"" = sup_adr.""CardCode""
|
|
|
|
LEFT JOIN {quotedSchema}.""CRD1"" sup_adr ON itm.""CardCode"" = sup_adr.""CardCode""
|
|
|
|
AND sup_adr.""AdresType"" = 'B'
|
|
|
|
AND sup_adr.""AdresType"" = 'B'
|
|
|
|
LEFT JOIN {schema}.""OSLP"" emp ON h.""SlpCode"" = emp.""SlpCode""
|
|
|
|
LEFT JOIN {quotedSchema}.""OSLP"" emp ON h.""SlpCode"" = emp.""SlpCode""
|
|
|
|
WHERE h.""CANCELED"" = 'N' AND h.""DocDate"" >= '{dateFilter}'
|
|
|
|
WHERE h.""CANCELED"" = 'N' AND h.""DocDate"" >= :{DateFilterParameterName}
|
|
|
|
ORDER BY h.""DocDate"" DESC, h.""DocNum"", p.""LineNum""";
|
|
|
|
ORDER BY h.""DocDate"" DESC, h.""DocNum"", p.""LineNum""";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static string GetCreditNoteQuery(string schema, string tsc, string dateFilter) => $@"
|
|
|
|
private static string GetCreditNoteQuery(string schema)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var quotedSchema = QuoteIdentifier(schema);
|
|
|
|
|
|
|
|
return $@"
|
|
|
|
SELECT
|
|
|
|
SELECT
|
|
|
|
CURRENT_TIMESTAMP AS extraction_date,
|
|
|
|
CURRENT_TIMESTAMP AS extraction_date,
|
|
|
|
'{tsc}' AS tsc,
|
|
|
|
:{TscParameterName} AS tsc,
|
|
|
|
h.""DocNum"" AS invoice_number,
|
|
|
|
h.""DocNum"" AS invoice_number,
|
|
|
|
p.""LineNum"" AS invoice_position,
|
|
|
|
p.""LineNum"" AS invoice_position,
|
|
|
|
h.""DocDate"" AS invoice_date,
|
|
|
|
h.""DocDate"" AS invoice_date,
|
|
|
@@ -263,21 +277,48 @@ SELECT
|
|
|
|
COALESCE(emp.""SlpName"", '') AS sales_responsible,
|
|
|
|
COALESCE(emp.""SlpName"", '') AS sales_responsible,
|
|
|
|
NULL AS order_date,
|
|
|
|
NULL AS order_date,
|
|
|
|
'CRN' AS doc_type
|
|
|
|
'CRN' AS doc_type
|
|
|
|
FROM {schema}.""ORIN"" h
|
|
|
|
FROM {quotedSchema}.""ORIN"" h
|
|
|
|
INNER JOIN {schema}.""RIN1"" p ON h.""DocEntry"" = p.""DocEntry""
|
|
|
|
INNER JOIN {quotedSchema}.""RIN1"" p ON h.""DocEntry"" = p.""DocEntry""
|
|
|
|
LEFT JOIN {schema}.""OITM"" itm ON p.""ItemCode"" = itm.""ItemCode""
|
|
|
|
LEFT JOIN {quotedSchema}.""OITM"" itm ON p.""ItemCode"" = itm.""ItemCode""
|
|
|
|
LEFT JOIN {schema}.""OITB"" grp ON itm.""ItmsGrpCod"" = grp.""ItmsGrpCod""
|
|
|
|
LEFT JOIN {quotedSchema}.""OITB"" grp ON itm.""ItmsGrpCod"" = grp.""ItmsGrpCod""
|
|
|
|
LEFT JOIN {schema}.""OCRD"" cust ON h.""CardCode"" = cust.""CardCode""
|
|
|
|
LEFT JOIN {quotedSchema}.""OCRD"" cust ON h.""CardCode"" = cust.""CardCode""
|
|
|
|
LEFT JOIN {schema}.""CRD1"" cust_adr ON h.""CardCode"" = cust_adr.""CardCode""
|
|
|
|
LEFT JOIN {quotedSchema}.""CRD1"" cust_adr ON h.""CardCode"" = cust_adr.""CardCode""
|
|
|
|
AND cust_adr.""AdresType"" = 'B' AND cust_adr.""Address"" = h.""PayToCode""
|
|
|
|
AND cust_adr.""AdresType"" = 'B' AND cust_adr.""Address"" = h.""PayToCode""
|
|
|
|
LEFT JOIN {schema}.""OOND"" ind ON cust.""IndustryC"" = ind.""IndCode""
|
|
|
|
LEFT JOIN {quotedSchema}.""OOND"" ind ON cust.""IndustryC"" = ind.""IndCode""
|
|
|
|
LEFT JOIN {schema}.""OCRD"" sup ON itm.""CardCode"" = sup.""CardCode""
|
|
|
|
LEFT JOIN {quotedSchema}.""OCRD"" sup ON itm.""CardCode"" = sup.""CardCode""
|
|
|
|
AND sup.""CardType"" = 'S'
|
|
|
|
AND sup.""CardType"" = 'S'
|
|
|
|
LEFT JOIN {schema}.""CRD1"" sup_adr ON itm.""CardCode"" = sup_adr.""CardCode""
|
|
|
|
LEFT JOIN {quotedSchema}.""CRD1"" sup_adr ON itm.""CardCode"" = sup_adr.""CardCode""
|
|
|
|
AND sup_adr.""AdresType"" = 'B'
|
|
|
|
AND sup_adr.""AdresType"" = 'B'
|
|
|
|
LEFT JOIN {schema}.""OSLP"" emp ON h.""SlpCode"" = emp.""SlpCode""
|
|
|
|
LEFT JOIN {quotedSchema}.""OSLP"" emp ON h.""SlpCode"" = emp.""SlpCode""
|
|
|
|
WHERE h.""CANCELED"" = 'N' AND h.""DocDate"" >= '{dateFilter}'
|
|
|
|
WHERE h.""CANCELED"" = 'N' AND h.""DocDate"" >= :{DateFilterParameterName}
|
|
|
|
ORDER BY h.""DocDate"" DESC, h.""DocNum"", p.""LineNum""";
|
|
|
|
ORDER BY h.""DocDate"" DESC, h.""DocNum"", p.""LineNum""";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static DateTime ParseDateFilter(string dateFilter)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (DateTime.TryParse(dateFilter, out var parsed))
|
|
|
|
|
|
|
|
return parsed.Date;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
throw new InvalidOperationException($"Ungueltiger HANA-DateFilter: '{dateFilter}'. Erwartet wird ein parsebares Datum.");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static string BuildQueryLogDetails(string query, string schema, string tsc, DateTime dateFilter)
|
|
|
|
|
|
|
|
=> $"{query}{Environment.NewLine}-- schema={schema}; tsc={tsc}; dateFilter={dateFilter:yyyy-MM-dd}";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static string QuoteIdentifier(string identifier)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var value = identifier?.Trim() ?? string.Empty;
|
|
|
|
|
|
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
|
|
|
|
|
|
throw new InvalidOperationException("HANA-Schema darf nicht leer sein.");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var ch in value)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!(char.IsLetterOrDigit(ch) || ch == '_'))
|
|
|
|
|
|
|
|
throw new InvalidOperationException($"Ungueltiger HANA-Identifier: '{identifier}'.");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return $@"""{value}""";
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class ConnectionTestResult
|
|
|
|
public class ConnectionTestResult
|
|
|
|