laatzen/LaaProductionWeb/LaaProduction.Services/ProtocolService.cs
2024-09-18 15:36:12 +02:00

306 lines
15 KiB
C#

namespace LaaProduction.Services
{
using LaaPackages.SqlClient;
using LaaProduction.Services.Interfaces;
using LaaProduction.Services.Models;
using LaaProduction.Services.Models.Reports;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
public class ProtocolService : IProtocolService
{
private const String PROTOCOL = "PROTOCOL";
private readonly SqlConnection sqlConnection;
public ProtocolService(SqlConnection sqlConnection)
=> this.sqlConnection = sqlConnection;
public Boolean DeleteFile(Int32 fileId)
=> this.sqlConnection
.CreateCommand($@"
DELETE FROM [File]
WHERE [FileId] = @{nameof(fileId)};
DELETE FROM [FilesOrders]
OUTPUT [Deleted].[FileId]
WHERE [FileId] = @{nameof(fileId)};")
.SetParameter(nameof(fileId), fileId)
.ExecuteScalar(x => x.GetValue<Int32>(0)) > 0;
public String FileContent(Int32? fileId)
{
var fileContent = this.sqlConnection
.CreateCommand($@"
SELECT [dbo].[File].[FileContent]
FROM [dbo].[File]
WHERE [dbo].[File].[FileId] = @{nameof(fileId)}")
.SetParameter(nameof(fileId), fileId)
.FirstOrDefault(reader => reader.GetValue<Byte[]>(0))
?? Array.Empty<Byte>();
return String.Format("data:application/pdf;base64,{0}", Convert.ToBase64String(fileContent));
}
public OrderClientModel FindOrder(Int32 orderId)
{
/// Für ungültige auftrag nummer einfach leere objekt zurück geben.
if (orderId <= 0)
{
return new OrderClientModel();
}
/// Abfragen der algemeinen auftrag daten
var model = this.sqlConnection
.CreateCommand($@"
SELECT [APG].[AuftragNr]
, [K].[KundenNr]
, [K].[Name]
FROM [AuftragPosition_Gesamt] AS [APG]
JOIN [Auftrag_Gesamt] AS [AG]
ON [AG].[AuftragNr] = [APG].[AuftragNr]
JOIN [IdentNr] AS [IN]
ON [IN].[IdentNr] = [APG].[Identnr]
AND [IN].[Typ] = 'GNS'
JOIN [Kunde] AS [K]
ON [K].[KundenNr] = [AG].[KundenNr]
WHERE [APG].[AuftragNr] = @{nameof(orderId)}")
.SetParameter(nameof(orderId), orderId)
.FirstOrDefault(reader => new OrderClientModel
{
OrderId = reader.GetValue<Int32>(0),
ClientId = reader.GetValue<Int32>(1),
ClientName = reader.GetValue<String>(2)
});
/// Wenn auftrag nicht gefunden ist einfach leere objekt zurück geben.
if (model is null)
{
return new OrderClientModel();
}
model.Results = this.LoadTestResults(orderId);
model.Positions = model
.Results
.GroupBy(x => x.PosNr)
.Where(x => x.Key > 0)
.OrderBy(x => x.Key)
.ToDictionary(x => x.Key, x => x.All(r => r.Succeeded));
/// Abfragen bestähende protokolle.
model.Files = this.sqlConnection
.CreateCommand($@"
SELECT COUNT([FileId])
FROM [FilesOrders]
WHERE [OrderId] = @{nameof(orderId)}
AND [Usage] = '{PROTOCOL}'")
.SetParameter(nameof(orderId), orderId)
.FirstOrDefault(x => x.GetValue<Int32>(0));
return model;
}
public IEnumerable<KeyValuePair<Int32, String>> FindOrdersById(Int32 orderno)
=> this.sqlConnection
.CreateCommand($@"
SELECT DISTINCT
[APG].[AuftragNr]
, [K].[Name]
FROM [AuftragPosition_Gesamt] AS [APG]
JOIN [Auftrag_Gesamt] AS [AG]
ON [AG].[AuftragNr] = [APG].[AuftragNr]
JOIN [IdentNr] AS [IN]
ON [IN].[IdentNr] = [APG].[Identnr]
AND [IN].[Typ] = 'GNS'
JOIN [Kunde] AS [K]
ON [K].[KundenNr] = [AG].[KundenNr]
WHERE [APG].[AuftragNr] LIKE @{nameof(orderno)}")
.SetParameter(nameof(orderno), $"%{orderno}%")
.ExecuteReader(reader => new KeyValuePair<Int32, String>(
key: reader.GetValue<Int32>(0),
value: reader.GetValue<String>(1)));
public IEnumerable<KeyValuePair<Int32, String>> FindOrdersByClient(String clientName)
=> this.sqlConnection
.CreateCommand($@"
SELECT DISTINCT
[APG].[AuftragNr]
, [K].[Name]
FROM [AuftragPosition_Gesamt] AS [APG]
JOIN [Auftrag_Gesamt] AS [AG]
ON [AG].[AuftragNr] = [APG].[AuftragNr]
JOIN [IdentNr] AS [IN]
ON [IN].[IdentNr] = [APG].[Identnr]
AND [IN].[Typ] = 'GNS'
JOIN [Kunde] AS [K]
ON [K].[KundenNr] = [AG].[KundenNr]
WHERE [K].[Name] LIKE @{nameof(clientName)}")
.SetParameter(nameof(clientName), $"%{clientName}%")
.ExecuteReader(reader => new KeyValuePair<Int32, String>(
key: reader.GetValue<Int32>(0),
value: reader.GetValue<String>(1)));
public IDictionary<Int32, String> GetFiles(Int32 orderId)
{
var files = this.sqlConnection
.CreateCommand($@"
SELECT [FileId]
, [FileContent]
FROM [File]
WHERE [FileId] IN (SELECT [FileId] FROM [FilesOrders] WHERE [OrderId] = @{nameof(orderId)})
ORDER BY [FileId] ASC")
.SetParameter(nameof(orderId), orderId)
.ExecuteReader(x => new
{
Key = x.GetValue<Int32>(0),
Value = String.Format("data:application/pdf;base64,{0}", Convert.ToBase64String(x.GetValue<Byte[]>(1)))
})
?.ToDictionary(x => x.Key, x => x.Value)
?? new Dictionary<Int32, String>();
return files;
}
public IEnumerable<TestStatus> LoadTestResults(Int32 orderId)
=> this.sqlConnection
.CreateCommand($@"
SELECT DISTINCT
[APS].[PositionNr] AS [PosNr] -- 0
, ISNULL([APS].[KundeneigeneSerienNr], [APS].[SerienNr]) AS [SerialNr] -- 1
, [CPT].[CordonelPressureTest_Valid] AS [3TightnessTest] -- 2
, [DP].[Dicht] AS [4PressureAndTightness] -- 3
, MAX([APS].[StatusFertigung]) AS [5Metrologicaltesting] -- 4
, [CRRH].[Result] AS [6ConfigComparisonAndRadiotest] -- 5
FROM [AuftragPositionSerienNr] AS [APS]
LEFT JOIN [Genesis_Meter] AS [GM] ON [GM].[Seriennummer] = [APS].[SerienNr]
LEFT JOIN [MapPcbIdToSerialNumber] AS [PCB] ON [PCB].[MapPcbIdToSerialNumber_SerialNumber] = [GM].[Seriennummer]
LEFT JOIN [Cordonel_Radio_RSSI_History] AS [CRRH] ON [CRRH].[RadioAdress] = [GM].[Adresse] - 10000000000
AND [CRRH].[IsLast] = 1
AND [CRRH].[Result] = 1
LEFT JOIN [Druckpruefung] AS [DP] ON [DP].[FabNr] = [PCB].[MapPcbIdToSerialNumber_PcbId]
AND [DP].[Dicht] = 1
LEFT JOIN [Cordonel_PressureTest] AS [CPT] ON [CPT].[CordonelPressureTest_PcbId] = [PCB].[MapPcbIdToSerialNumber_PcbId]
AND [CPT].[CordonelPressureTest_Valid] = 1
WHERE [APS].[AuftragNr] = @{nameof(orderId)}
GROUP BY [APS].[PositionNr]
, [APS].[SerienNr]
, [APS].[KundeneigeneSerienNr]
, [CPT].[CordonelPressureTest_Valid]
, [DP].[Dicht]
, [CRRH].[Result]
ORDER BY [APS].[PositionNr]
, ISNULL([APS].[KundeneigeneSerienNr], [APS].[SerienNr])")
.SetParameter(nameof(orderId), orderId)
.ExecuteReader(reader => new TestStatus
{
PosNr = reader.GetValue<Int16>(0),
SerialNr = reader.GetValue<String>(1),
HeliumTest = reader.GetValue<Boolean?>(2),
PressureTest = reader.GetValue<Boolean?>(3),
MetroTest = this.MetrologicalValue(reader.GetValue<Byte?>(4)),
RadioTest = reader.GetValue<Boolean?>(5),
})
.OrderBy(x => !x.Succeeded)
.ThenBy(x => x.PosNr);
public Boolean OrderCompleted(Int32 orderId)
{
var sumResults = this.sqlConnection
.CreateCommand($@"
SELECT CAST(CASE WHEN ISNULL([CPT].[CordonelPressureTest_Valid], 1) = 1 THEN 0 ELSE 1 END AS INT)
+ CAST(CASE WHEN ISNULL([DP].[Dicht], 1) = 1 THEN 0 ELSE 1 END AS INT)
+ ISNULL(MAX([APS].[StatusFertigung]) - 30, 0)
+ CAST(CASE WHEN ISNULL([CRRH].[Result], 1) = 1 THEN 0 ELSE 1 END AS INT)
FROM [AuftragPositionSerienNr] AS [APS]
LEFT JOIN [Genesis_Meter] AS [GM] ON [GM].[Seriennummer] = [APS].[SerienNr]
LEFT JOIN [MapPcbIdToSerialNumber] AS [PCB] ON [PCB].[MapPcbIdToSerialNumber_SerialNumber] = [GM].[Seriennummer]
LEFT JOIN [Cordonel_Radio_RSSI_History] AS [CRRH] ON [CRRH].[RadioAdress] = [GM].[Adresse] - 10000000000
AND [CRRH].[IsLast] = 1
AND [CRRH].[Result] = 1
LEFT JOIN [Druckpruefung] AS [DP] ON [DP].[FabNr] = [PCB].[MapPcbIdToSerialNumber_PcbId]
AND [DP].[Dicht] = 1
LEFT JOIN [Cordonel_PressureTest] AS [CPT] ON [CPT].[CordonelPressureTest_PcbId] = [PCB].[MapPcbIdToSerialNumber_PcbId]
AND [CPT].[CordonelPressureTest_Valid] = 1
WHERE [APS].[AuftragNr] = @{nameof(orderId)}
GROUP BY [APS].[PositionNr]
, [APS].[SerienNr]
, [APS].[KundeneigeneSerienNr]
, [CPT].[CordonelPressureTest_Valid]
, [DP].[Dicht]
, [CRRH].[Result]")
.SetParameter(nameof(orderId), orderId)
.ExecuteReader(reader => reader.GetValue<Int32>(0))
.Sum(x => x);
return sumResults == 0;
}
public Int32 SaveFile(Stream fileStream, Int32 clientId, Int32 orderId)
{
var fileName = $"{clientId}_{orderId}.pdf";
var fileContent = this.GetBuffer(fileStream);
var fileMD5Buffer = MD5.Create().ComputeHash(fileContent);
var fileMD5 = BitConverter
.ToString(fileMD5Buffer)
.Replace("-", String.Empty)
.ToLower();
var length = fileMD5?.Length;
var exists = this.sqlConnection
.CreateCommand($@"
SELECT COUNT(1)
FROM [FilesOrders]
WHERE [Hash] = @{nameof(fileMD5)}")
.SetParameter(nameof(fileMD5), fileMD5)
.FirstOrDefault(x => x.GetValue<Int32>(0)) > 0;
if (exists)
{
return -1;
}
return this.sqlConnection
.CreateCommand($@"
INSERT INTO [dbo].[File] (
[FileName]
, [FileContent])
OUTPUT @{nameof(orderId)}, [Inserted].[FileId], '{PROTOCOL}', @{nameof(fileMD5)}
INTO [FilesOrders]([OrderId], [FileId], [Usage], [Hash])
OUTPUT [Inserted].[FileId]
VALUES (@{nameof(fileName)}
, @{nameof(fileContent)})")
.SetParameter(nameof(orderId), orderId)
.SetParameter(nameof(fileName), fileName)
.SetParameter(nameof(fileContent), fileContent)
.SetParameter(nameof(fileMD5), fileMD5)
.ExecuteScalar(x => x.GetValue<Int32>(0));
}
private Byte[] GetBuffer(Stream fileStream)
{
var fileContent = new Byte[fileStream.Length];
using (var memoryStream = new MemoryStream())
{
fileStream.CopyTo(memoryStream);
fileContent = memoryStream.ToArray();
}
return fileContent;
}
private Boolean? MetrologicalValue(Byte? value)
{
if (value is null)
{
return null;
}
return value == 30;
}
}
}