859 lines
37 KiB
C#
859 lines
37 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Data;
|
||
using System.Linq;
|
||
using System.Data.SqlClient;
|
||
|
||
namespace XLAB
|
||
{
|
||
internal sealed class EkzDirectoryService
|
||
{
|
||
private static readonly string[] CascadingEkzChildTables = { "EKZMK", "EKZMCP" };
|
||
|
||
private static readonly string[] CascadingEkzMkChildTables = { "EKZMKFCTVL", "EKZMKDH", "EKZMKEKZK", "EKZMKND", "KSPELEKZMK" };
|
||
|
||
public int AddEkzItem(EkzDirectoryItem item)
|
||
{
|
||
var normalizedItem = NormalizeEkzItem(item);
|
||
|
||
const string sql = @"
|
||
INSERT INTO dbo.EKZ
|
||
(
|
||
IDTPRZ,
|
||
IDFRPDV,
|
||
KLSIPR,
|
||
NNZV,
|
||
NNIN,
|
||
DSEKZ,
|
||
GUIDEKZ,
|
||
IsDeleted
|
||
)
|
||
VALUES
|
||
(
|
||
@TypeSizeId,
|
||
@OwnerOrganizationId,
|
||
1,
|
||
@SerialNumber,
|
||
@InventoryNumber,
|
||
@Notes,
|
||
@Guid,
|
||
0
|
||
);
|
||
|
||
SELECT CAST(SCOPE_IDENTITY() AS int);";
|
||
|
||
using (var connection = ReferenceDirectorySqlHelpers.CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
EnsureEkzIsUnique(connection, normalizedItem.TypeSizeId, normalizedItem.OwnerOrganizationId, normalizedItem.SerialNumber, null);
|
||
|
||
command.CommandTimeout = ReferenceDirectorySqlHelpers.GetCommandTimeoutSeconds();
|
||
command.Parameters.Add("@TypeSizeId", SqlDbType.Int).Value = normalizedItem.TypeSizeId;
|
||
command.Parameters.Add("@OwnerOrganizationId", SqlDbType.Int).Value = normalizedItem.OwnerOrganizationId;
|
||
command.Parameters.Add("@SerialNumber", SqlDbType.VarChar, EkzDirectoryRules.SerialNumberMaxLength).Value = normalizedItem.SerialNumber;
|
||
ReferenceDirectorySqlHelpers.AddNullableStringParameter(command, "@InventoryNumber", SqlDbType.VarChar, EkzDirectoryRules.InventoryNumberMaxLength, normalizedItem.InventoryNumber);
|
||
ReferenceDirectorySqlHelpers.AddNullableStringParameter(command, "@Notes", SqlDbType.VarChar, EkzDirectoryRules.NotesMaxLength, normalizedItem.Notes);
|
||
command.Parameters.Add("@Guid", SqlDbType.UniqueIdentifier).Value = Guid.NewGuid();
|
||
|
||
return Convert.ToInt32(command.ExecuteScalar());
|
||
}
|
||
}
|
||
|
||
public EkzDeletePreview GetEkzDeletePreview(int id)
|
||
{
|
||
if (id <= 0)
|
||
{
|
||
return new EkzDeletePreview
|
||
{
|
||
CanDelete = false,
|
||
ImpactItems = Array.Empty<EkzDeleteImpactItem>(),
|
||
WarningMessage = "Не выбрана запись EKZ для удаления."
|
||
};
|
||
}
|
||
|
||
using (var connection = ReferenceDirectorySqlHelpers.CreateConnection())
|
||
{
|
||
connection.Open();
|
||
return BuildEkzDeletePreview(connection, null, id);
|
||
}
|
||
}
|
||
|
||
public EkzDeleteResult DeleteEkzItem(int id)
|
||
{
|
||
if (id <= 0)
|
||
{
|
||
throw new InvalidOperationException("Не выбрана запись EKZ для удаления.");
|
||
}
|
||
|
||
try
|
||
{
|
||
using (var connection = ReferenceDirectorySqlHelpers.CreateConnection())
|
||
{
|
||
connection.Open();
|
||
|
||
using (var transaction = connection.BeginTransaction())
|
||
{
|
||
var preview = BuildEkzDeletePreview(connection, transaction, id);
|
||
if (!preview.CanDelete)
|
||
{
|
||
transaction.Rollback();
|
||
return new EkzDeleteResult
|
||
{
|
||
IsDeleted = false,
|
||
ImpactItems = preview.ImpactItems ?? Array.Empty<EkzDeleteImpactItem>(),
|
||
WarningMessage = preview.WarningMessage
|
||
};
|
||
}
|
||
|
||
var impactItems = new List<EkzDeleteImpactItem>();
|
||
AddImpactItem(impactItems, "EKZMKFCTVL", DeleteEkzMkFctvl(connection, transaction, id));
|
||
AddImpactItem(impactItems, "EKZMKDH", DeleteEkzMkDh(connection, transaction, id));
|
||
AddImpactItem(impactItems, "EKZMKEKZK", DeleteEkzMkEkzk(connection, transaction, id));
|
||
AddImpactItem(impactItems, "EKZMKND", DeleteEkzMkNd(connection, transaction, id));
|
||
AddImpactItem(impactItems, "KSPELEKZMK", DeleteKspelEkzMk(connection, transaction, id));
|
||
AddImpactItem(impactItems, "DMS", DeleteEkzDms(connection, transaction, id));
|
||
AddImpactItem(impactItems, "EKZMK", DeleteEkzMk(connection, transaction, id));
|
||
AddImpactItem(impactItems, "EKZMCP", DeleteEkzMcp(connection, transaction, id));
|
||
|
||
var deletedEkzCount = DeleteEkz(connection, transaction, id);
|
||
if (deletedEkzCount == 0)
|
||
{
|
||
transaction.Rollback();
|
||
return new EkzDeleteResult
|
||
{
|
||
IsDeleted = false,
|
||
ImpactItems = Array.Empty<EkzDeleteImpactItem>(),
|
||
WarningMessage = "Запись EKZ для удаления не найдена."
|
||
};
|
||
}
|
||
|
||
AddImpactItem(impactItems, "EKZ", deletedEkzCount);
|
||
transaction.Commit();
|
||
|
||
return new EkzDeleteResult
|
||
{
|
||
IsDeleted = true,
|
||
ImpactItems = OrderImpactItems(impactItems)
|
||
};
|
||
}
|
||
}
|
||
}
|
||
catch (SqlException ex) when (ex.Number == 547)
|
||
{
|
||
return new EkzDeleteResult
|
||
{
|
||
IsDeleted = false,
|
||
ImpactItems = Array.Empty<EkzDeleteImpactItem>(),
|
||
WarningMessage = CreateEkzDeleteFailedMessage(ex)
|
||
};
|
||
}
|
||
}
|
||
|
||
public IReadOnlyList<EkzDirectoryItem> LoadEkzItems()
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
z.IDEKZ AS Id,
|
||
z.IDTPRZ AS TypeSizeId,
|
||
areas.NMOI AS MeasurementAreaName,
|
||
names.NMTP AS InstrumentName,
|
||
tips.TP AS TypeName,
|
||
tprz.DPZN AS RangeText,
|
||
tprz.HRTC AS AccuracyText,
|
||
tprz.NNGSRS AS RegistryNumber,
|
||
z.IDFRPDV AS OwnerOrganizationId,
|
||
ownerOrg.NMFRPD AS OwnerOrganizationName,
|
||
z.NNZV AS SerialNumber,
|
||
z.NNIN AS InventoryNumber,
|
||
stickers.StickerNumbers AS StickerNumbers,
|
||
CAST(z.DSEKZ AS nvarchar(max)) AS Notes
|
||
FROM dbo.EKZ z
|
||
JOIN dbo.TPRZ tprz ON tprz.IDTPRZ = z.IDTPRZ
|
||
JOIN dbo.TIPS tips ON tips.IDTIPS = tprz.IDTIPS
|
||
JOIN dbo.SPNMTP names ON names.IDSPNMTP = tips.IDSPNMTP
|
||
JOIN dbo.SPOI areas ON areas.IDSPOI = tips.IDSPOI
|
||
JOIN dbo.FRPD ownerOrg ON ownerOrg.IDFRPD = z.IDFRPDV
|
||
OUTER APPLY
|
||
(
|
||
SELECT STUFF(
|
||
(
|
||
SELECT N' ' + sticker.StickerNumber
|
||
FROM
|
||
(
|
||
SELECT DISTINCT LTRIM(RTRIM(m.NNNKL)) AS StickerNumber
|
||
FROM dbo.EKZMK m
|
||
WHERE m.IDEKZ = z.IDEKZ
|
||
AND NULLIF(LTRIM(RTRIM(m.NNNKL)), N'') IS NOT NULL
|
||
) sticker
|
||
ORDER BY sticker.StickerNumber
|
||
FOR XML PATH(''), TYPE
|
||
).value('.', 'nvarchar(max)'),
|
||
1,
|
||
1,
|
||
N'') AS StickerNumbers
|
||
) stickers
|
||
WHERE ISNULL(z.IsDeleted, 0) = 0
|
||
ORDER BY ownerOrg.NMFRPD, areas.NMOI, names.NMTP, tips.TP, tprz.DPZN, z.NNZV, z.IDEKZ;";
|
||
|
||
var items = new List<EkzDirectoryItem>();
|
||
|
||
using (var connection = ReferenceDirectorySqlHelpers.CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
command.CommandTimeout = ReferenceDirectorySqlHelpers.GetCommandTimeoutSeconds();
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
items.Add(new EkzDirectoryItem
|
||
{
|
||
Id = ReferenceDirectorySqlHelpers.GetInt32(reader, "Id"),
|
||
TypeSizeId = ReferenceDirectorySqlHelpers.GetInt32(reader, "TypeSizeId"),
|
||
MeasurementAreaName = ReferenceDirectorySqlHelpers.GetString(reader, "MeasurementAreaName"),
|
||
InstrumentName = ReferenceDirectorySqlHelpers.GetString(reader, "InstrumentName"),
|
||
TypeName = ReferenceDirectorySqlHelpers.GetString(reader, "TypeName"),
|
||
RangeText = ReferenceDirectorySqlHelpers.GetString(reader, "RangeText"),
|
||
AccuracyText = ReferenceDirectorySqlHelpers.GetString(reader, "AccuracyText"),
|
||
RegistryNumber = ReferenceDirectorySqlHelpers.GetString(reader, "RegistryNumber"),
|
||
OwnerOrganizationId = ReferenceDirectorySqlHelpers.GetInt32(reader, "OwnerOrganizationId"),
|
||
OwnerOrganizationName = ReferenceDirectorySqlHelpers.GetString(reader, "OwnerOrganizationName"),
|
||
SerialNumber = ReferenceDirectorySqlHelpers.GetString(reader, "SerialNumber"),
|
||
InventoryNumber = ReferenceDirectorySqlHelpers.GetString(reader, "InventoryNumber"),
|
||
StickerNumbers = ReferenceDirectorySqlHelpers.GetString(reader, "StickerNumbers"),
|
||
Notes = ReferenceDirectorySqlHelpers.GetString(reader, "Notes")
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
return items;
|
||
}
|
||
|
||
public IReadOnlyList<EkzMkDirectoryItem> LoadEkzMkItems(int instrumentId)
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
m.IDEKZMK AS CardId,
|
||
m.IDEKZ AS InstrumentId,
|
||
verificationType.NMVDMK AS VerificationTypeName,
|
||
organization.NMFRPD AS VerificationOrganizationName,
|
||
m.NNZVPV AS DocumentNumber,
|
||
verificationDocument.NNDMS AS VerificationDocumentNumber,
|
||
verificationDocument.DTDMS AS VerificationDocumentDate,
|
||
m.NNNKL AS StickerNumber,
|
||
verifier.PRFIO AS VerifierName,
|
||
m.PRMK AS PeriodMonths,
|
||
m.DTPRM AS AcceptedOn,
|
||
m.DTMKPL AS PlannedOn,
|
||
m.DTMKFK AS PerformedOn,
|
||
m.DTVDM AS IssuedOn,
|
||
m.GDN AS IsPassed,
|
||
CAST(m.DSEKZMK AS nvarchar(max)) AS Notes
|
||
FROM dbo.EKZMK m
|
||
LEFT JOIN dbo.SPVDMK verificationType ON verificationType.IDSPVDMK = m.IDSPVDMK
|
||
LEFT JOIN dbo.FRPD organization ON organization.IDFRPD = m.IDFRPD
|
||
LEFT JOIN dbo.PRSN verifier ON verifier.IDPRSN = m.IDPRSN
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
d.NND AS NNDMS,
|
||
d.DTD AS DTDMS
|
||
FROM dbo.DMS d
|
||
JOIN dbo.VDODVDD vdd ON vdd.IDVDODVDD = d.IDVDODVDD
|
||
JOIN dbo.FRDMS frdms ON frdms.IDFRDMS = d.IDFRDMS
|
||
JOIN dbo.SPVDD spvdd ON spvdd.IDSPVDD = frdms.IDSPVDD
|
||
WHERE d.IDOD = m.IDEKZMK
|
||
AND vdd.IDSPVDOD = 2
|
||
AND spvdd.IDSPVDD IN (2, 6, 8)
|
||
ORDER BY d.DTD DESC
|
||
) verificationDocument
|
||
WHERE m.IDEKZ = @InstrumentId
|
||
ORDER BY ISNULL(m.DTPRM, CONVERT(datetime, '19000101', 112)) DESC, m.IDEKZMK DESC;";
|
||
|
||
var items = new List<EkzMkDirectoryItem>();
|
||
|
||
using (var connection = ReferenceDirectorySqlHelpers.CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
command.CommandTimeout = ReferenceDirectorySqlHelpers.GetCommandTimeoutSeconds();
|
||
command.Parameters.Add("@InstrumentId", SqlDbType.Int).Value = instrumentId;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
items.Add(new EkzMkDirectoryItem
|
||
{
|
||
CardId = ReferenceDirectorySqlHelpers.GetInt32(reader, "CardId"),
|
||
InstrumentId = ReferenceDirectorySqlHelpers.GetInt32(reader, "InstrumentId"),
|
||
VerificationTypeName = ReferenceDirectorySqlHelpers.GetString(reader, "VerificationTypeName"),
|
||
VerificationOrganizationName = ReferenceDirectorySqlHelpers.GetString(reader, "VerificationOrganizationName"),
|
||
DocumentNumber = ReferenceDirectorySqlHelpers.GetString(reader, "DocumentNumber"),
|
||
VerificationDocumentNumber = ReferenceDirectorySqlHelpers.GetString(reader, "VerificationDocumentNumber"),
|
||
VerificationDocumentDate = ReferenceDirectorySqlHelpers.GetNullableDateTime(reader, "VerificationDocumentDate"),
|
||
StickerNumber = ReferenceDirectorySqlHelpers.GetString(reader, "StickerNumber"),
|
||
VerifierName = ReferenceDirectorySqlHelpers.GetString(reader, "VerifierName"),
|
||
PeriodMonths = ReferenceDirectorySqlHelpers.GetInt32(reader, "PeriodMonths"),
|
||
AcceptedOn = ReferenceDirectorySqlHelpers.GetNullableDateTime(reader, "AcceptedOn"),
|
||
PlannedOn = ReferenceDirectorySqlHelpers.GetNullableDateTime(reader, "PlannedOn"),
|
||
PerformedOn = ReferenceDirectorySqlHelpers.GetNullableDateTime(reader, "PerformedOn"),
|
||
IssuedOn = ReferenceDirectorySqlHelpers.GetNullableDateTime(reader, "IssuedOn"),
|
||
IsPassed = ReferenceDirectorySqlHelpers.GetNullableBoolean(reader, "IsPassed"),
|
||
Notes = ReferenceDirectorySqlHelpers.GetString(reader, "Notes")
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
return items;
|
||
}
|
||
|
||
public IReadOnlyList<DirectoryLookupItem> LoadFrpdReferences()
|
||
{
|
||
return ReferenceDirectorySqlHelpers.LoadLookupItems(@"
|
||
SELECT
|
||
fr.IDFRPD AS Id,
|
||
fr.NMFRPD AS Name
|
||
FROM dbo.FRPD fr
|
||
WHERE NULLIF(LTRIM(RTRIM(fr.NMFRPD)), '') IS NOT NULL
|
||
ORDER BY fr.NMFRPD, fr.IDFRPD;");
|
||
}
|
||
|
||
public IReadOnlyList<DirectoryLookupItem> LoadTypeSizeReferences()
|
||
{
|
||
return ReferenceDirectorySqlHelpers.LoadLookupItems(@"
|
||
SELECT
|
||
tprz.IDTPRZ AS Id,
|
||
LTRIM(RTRIM(
|
||
COALESCE(NULLIF(areas.NMOI, N'') + N' / ', N'')
|
||
+ COALESCE(NULLIF(names.NMTP, N'') + N' / ', N'')
|
||
+ COALESCE(NULLIF(tips.TP, N''), N'')
|
||
+ CASE WHEN NULLIF(LTRIM(RTRIM(tprz.DPZN)), N'') IS NULL THEN N'' ELSE N' / ' + tprz.DPZN END
|
||
+ CASE
|
||
WHEN NULLIF(LTRIM(RTRIM(CONVERT(nvarchar(50), tprz.NNGSRS))), N'') IS NULL THEN N''
|
||
ELSE N' / № ГР ' + CONVERT(nvarchar(50), tprz.NNGSRS)
|
||
END
|
||
)) AS Name
|
||
FROM dbo.TPRZ tprz
|
||
JOIN dbo.TIPS tips ON tips.IDTIPS = tprz.IDTIPS
|
||
JOIN dbo.SPNMTP names ON names.IDSPNMTP = tips.IDSPNMTP
|
||
JOIN dbo.SPOI areas ON areas.IDSPOI = tips.IDSPOI
|
||
ORDER BY areas.NMOI, names.NMTP, tips.TP, tprz.DPZN, tprz.IDTPRZ;");
|
||
}
|
||
|
||
public void UpdateEkzItem(EkzDirectoryItem item)
|
||
{
|
||
var normalizedItem = NormalizeEkzItem(item);
|
||
if (normalizedItem.Id <= 0)
|
||
{
|
||
throw new InvalidOperationException("Не выбрана запись EKZ для изменения.");
|
||
}
|
||
|
||
const string sql = @"
|
||
UPDATE dbo.EKZ
|
||
SET IDTPRZ = @TypeSizeId,
|
||
IDFRPDV = @OwnerOrganizationId,
|
||
NNZV = @SerialNumber,
|
||
NNIN = @InventoryNumber,
|
||
DSEKZ = @Notes
|
||
WHERE IDEKZ = @Id;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
using (var connection = ReferenceDirectorySqlHelpers.CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
EnsureEkzIsUnique(connection, normalizedItem.TypeSizeId, normalizedItem.OwnerOrganizationId, normalizedItem.SerialNumber, normalizedItem.Id);
|
||
|
||
command.CommandTimeout = ReferenceDirectorySqlHelpers.GetCommandTimeoutSeconds();
|
||
command.Parameters.Add("@Id", SqlDbType.Int).Value = normalizedItem.Id;
|
||
command.Parameters.Add("@TypeSizeId", SqlDbType.Int).Value = normalizedItem.TypeSizeId;
|
||
command.Parameters.Add("@OwnerOrganizationId", SqlDbType.Int).Value = normalizedItem.OwnerOrganizationId;
|
||
command.Parameters.Add("@SerialNumber", SqlDbType.VarChar, EkzDirectoryRules.SerialNumberMaxLength).Value = normalizedItem.SerialNumber;
|
||
ReferenceDirectorySqlHelpers.AddNullableStringParameter(command, "@InventoryNumber", SqlDbType.VarChar, EkzDirectoryRules.InventoryNumberMaxLength, normalizedItem.InventoryNumber);
|
||
ReferenceDirectorySqlHelpers.AddNullableStringParameter(command, "@Notes", SqlDbType.VarChar, EkzDirectoryRules.NotesMaxLength, normalizedItem.Notes);
|
||
|
||
if (Convert.ToInt32(command.ExecuteScalar()) == 0)
|
||
{
|
||
throw new InvalidOperationException("Запись EKZ для изменения не найдена.");
|
||
}
|
||
}
|
||
}
|
||
|
||
private static EkzDeletePreview BuildEkzDeletePreview(SqlConnection connection, SqlTransaction transaction, int id)
|
||
{
|
||
if (!EkzExists(connection, transaction, id))
|
||
{
|
||
return new EkzDeletePreview
|
||
{
|
||
CanDelete = false,
|
||
ImpactItems = Array.Empty<EkzDeleteImpactItem>(),
|
||
WarningMessage = "Запись EKZ для удаления не найдена."
|
||
};
|
||
}
|
||
|
||
var cardIds = LoadEkzMkCardIds(connection, transaction, id);
|
||
var blockers = new List<DeleteBlockerInfo>();
|
||
blockers.AddRange(ReferenceDirectorySqlHelpers.LoadDeleteBlockersFromForeignKeys(connection, transaction, "EKZ", id, CascadingEkzChildTables));
|
||
blockers.AddRange(LoadUnhandledDeleteBlockers(connection, transaction, "EKZMK", cardIds, CascadingEkzMkChildTables));
|
||
|
||
var impactItems = BuildImpactItems(connection, transaction, id, cardIds);
|
||
var mergedBlockers = MergeBlockers(blockers);
|
||
if (mergedBlockers.Count > 0)
|
||
{
|
||
return new EkzDeletePreview
|
||
{
|
||
CanDelete = false,
|
||
ImpactItems = impactItems,
|
||
WarningMessage = CreateEkzCascadeBlockedMessage(mergedBlockers)
|
||
};
|
||
}
|
||
|
||
return new EkzDeletePreview
|
||
{
|
||
CanDelete = true,
|
||
ImpactItems = impactItems,
|
||
ConfirmationMessage = CreateEkzDeleteConfirmationMessage(impactItems)
|
||
};
|
||
}
|
||
|
||
private static IReadOnlyList<EkzDeleteImpactItem> BuildImpactItems(SqlConnection connection, SqlTransaction transaction, int instrumentId, IReadOnlyCollection<int> cardIds)
|
||
{
|
||
var impactItems = new List<EkzDeleteImpactItem>();
|
||
AddImpactItem(impactItems, "EKZ", 1);
|
||
AddImpactItem(impactItems, "EKZMK", cardIds == null ? 0 : cardIds.Count);
|
||
AddImpactItem(impactItems, "DMS", CountEkzDms(connection, transaction, instrumentId));
|
||
AddImpactItem(impactItems, "EKZMKFCTVL", CountEkzMkFctvl(connection, transaction, instrumentId));
|
||
AddImpactItem(impactItems, "EKZMKDH", CountEkzMkDh(connection, transaction, instrumentId));
|
||
AddImpactItem(impactItems, "EKZMKEKZK", CountEkzMkEkzk(connection, transaction, instrumentId));
|
||
AddImpactItem(impactItems, "EKZMKND", CountEkzMkNd(connection, transaction, instrumentId));
|
||
AddImpactItem(impactItems, "KSPELEKZMK", CountKspelEkzMk(connection, transaction, instrumentId));
|
||
AddImpactItem(impactItems, "EKZMCP", CountEkzMcp(connection, transaction, instrumentId));
|
||
return OrderImpactItems(impactItems);
|
||
}
|
||
|
||
private static IReadOnlyList<EkzDeleteImpactItem> OrderImpactItems(IEnumerable<EkzDeleteImpactItem> impactItems)
|
||
{
|
||
var order = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
|
||
{
|
||
{ "EKZ", 1 },
|
||
{ "EKZMK", 2 },
|
||
{ "DMS", 3 },
|
||
{ "EKZMKFCTVL", 4 },
|
||
{ "EKZMKDH", 5 },
|
||
{ "EKZMKEKZK", 6 },
|
||
{ "EKZMKND", 7 },
|
||
{ "KSPELEKZMK", 8 },
|
||
{ "EKZMCP", 9 }
|
||
};
|
||
|
||
return (impactItems ?? Enumerable.Empty<EkzDeleteImpactItem>())
|
||
.Where(delegate(EkzDeleteImpactItem item) { return item != null && item.RowCount > 0; })
|
||
.OrderBy(delegate(EkzDeleteImpactItem item)
|
||
{
|
||
int value;
|
||
return order.TryGetValue(item.TableName ?? string.Empty, out value) ? value : int.MaxValue;
|
||
})
|
||
.ThenBy(delegate(EkzDeleteImpactItem item) { return item.TableName; }, StringComparer.OrdinalIgnoreCase)
|
||
.ToList();
|
||
}
|
||
|
||
private static void AddImpactItem(ICollection<EkzDeleteImpactItem> impactItems, string tableName, int rowCount)
|
||
{
|
||
if (impactItems == null || string.IsNullOrWhiteSpace(tableName) || rowCount <= 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
impactItems.Add(new EkzDeleteImpactItem
|
||
{
|
||
TableName = tableName,
|
||
RowCount = rowCount
|
||
});
|
||
}
|
||
|
||
private static string CreateEkzDeleteConfirmationMessage(IEnumerable<EkzDeleteImpactItem> impactItems)
|
||
{
|
||
var items = OrderImpactItems(impactItems).ToList();
|
||
var lines = new List<string>();
|
||
if (items.Count == 0)
|
||
{
|
||
lines.Add("Будет физически удалена только запись EKZ.");
|
||
}
|
||
else
|
||
{
|
||
lines.Add("Будут физически удалены записи:");
|
||
foreach (var item in items)
|
||
{
|
||
lines.Add(string.Format("{0}: {1}", item.TableName, item.RowCount));
|
||
}
|
||
}
|
||
|
||
lines.Add(string.Empty);
|
||
lines.Add("Продолжить?");
|
||
return string.Join(Environment.NewLine, lines.ToArray());
|
||
}
|
||
|
||
private static string CreateEkzCascadeBlockedMessage(IEnumerable<DeleteBlockerInfo> blockers)
|
||
{
|
||
return string.Format(
|
||
"Экземпляр не может быть удалён автоматически. Есть связанные записи в таблицах, которые не входят в каскад удаления: {0}.",
|
||
FormatBlockerDetails(blockers));
|
||
}
|
||
|
||
private static string CreateEkzDeleteFailedMessage(SqlException ex)
|
||
{
|
||
var suffix = ex == null || string.IsNullOrWhiteSpace(ex.Message)
|
||
? string.Empty
|
||
: " " + ex.Message.Trim();
|
||
|
||
return "Экземпляр не может быть удалён из-за ограничений ссылочной целостности БД." + suffix;
|
||
}
|
||
|
||
private static string FormatBlockerDetails(IEnumerable<DeleteBlockerInfo> blockers)
|
||
{
|
||
var details = string.Join(", ", (blockers ?? Enumerable.Empty<DeleteBlockerInfo>())
|
||
.Where(delegate(DeleteBlockerInfo blocker) { return blocker != null && blocker.RowCount > 0; })
|
||
.OrderBy(delegate(DeleteBlockerInfo blocker) { return blocker.TableName; }, StringComparer.OrdinalIgnoreCase)
|
||
.Select(delegate(DeleteBlockerInfo blocker) { return string.Format("{0}: {1}", blocker.TableName, blocker.RowCount); }));
|
||
|
||
return string.IsNullOrWhiteSpace(details) ? "связанные данные" : details;
|
||
}
|
||
|
||
private static List<DeleteBlockerInfo> MergeBlockers(IEnumerable<DeleteBlockerInfo> blockers)
|
||
{
|
||
return (blockers ?? Enumerable.Empty<DeleteBlockerInfo>())
|
||
.Where(delegate(DeleteBlockerInfo blocker) { return blocker != null && blocker.RowCount > 0 && !string.IsNullOrWhiteSpace(blocker.TableName); })
|
||
.GroupBy(delegate(DeleteBlockerInfo blocker) { return blocker.TableName; }, StringComparer.OrdinalIgnoreCase)
|
||
.Select(delegate(IGrouping<string, DeleteBlockerInfo> group)
|
||
{
|
||
return new DeleteBlockerInfo
|
||
{
|
||
TableName = group.Key,
|
||
RowCount = group.Sum(delegate(DeleteBlockerInfo blocker) { return blocker.RowCount; })
|
||
};
|
||
})
|
||
.OrderBy(delegate(DeleteBlockerInfo blocker) { return blocker.TableName; }, StringComparer.OrdinalIgnoreCase)
|
||
.ToList();
|
||
}
|
||
|
||
private static List<DeleteBlockerInfo> LoadUnhandledDeleteBlockers(SqlConnection connection, SqlTransaction transaction, string parentTableName, IEnumerable<int> ids, IEnumerable<string> excludedChildTables)
|
||
{
|
||
var blockers = new List<DeleteBlockerInfo>();
|
||
foreach (var id in (ids ?? Enumerable.Empty<int>()).Where(delegate(int value) { return value > 0; }).Distinct())
|
||
{
|
||
blockers.AddRange(ReferenceDirectorySqlHelpers.LoadDeleteBlockersFromForeignKeys(connection, transaction, parentTableName, id, excludedChildTables));
|
||
}
|
||
|
||
return MergeBlockers(blockers);
|
||
}
|
||
|
||
private static bool EkzExists(SqlConnection connection, SqlTransaction transaction, int id)
|
||
{
|
||
const string sql = @"
|
||
SELECT COUNT(1)
|
||
FROM dbo.EKZ
|
||
WHERE IDEKZ = @Id;";
|
||
|
||
return ExecuteScalarForId(connection, transaction, sql, id) > 0;
|
||
}
|
||
|
||
private static List<int> LoadEkzMkCardIds(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
const string sql = @"
|
||
SELECT IDEKZMK
|
||
FROM dbo.EKZMK
|
||
WHERE IDEKZ = @InstrumentId
|
||
ORDER BY IDEKZMK;";
|
||
|
||
return ExecuteIdList(connection, transaction, sql, "@InstrumentId", instrumentId);
|
||
}
|
||
|
||
private static int CountEkzMcp(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
return ExecuteScalarForInstrument(connection, transaction, @"
|
||
SELECT COUNT(*)
|
||
FROM dbo.EKZMCP
|
||
WHERE IDEKZ = @InstrumentId;", instrumentId);
|
||
}
|
||
|
||
private static int CountEkzMkFctvl(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
return ExecuteScalarForInstrument(connection, transaction, @"
|
||
SELECT COUNT(*)
|
||
FROM dbo.EKZMKFCTVL child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZ = @InstrumentId;", instrumentId);
|
||
}
|
||
|
||
private static int CountEkzMkDh(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
return ExecuteScalarForInstrument(connection, transaction, @"
|
||
SELECT COUNT(*)
|
||
FROM dbo.EKZMKDH child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZ = @InstrumentId;", instrumentId);
|
||
}
|
||
|
||
private static int CountEkzMkEkzk(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
return ExecuteScalarForInstrument(connection, transaction, @"
|
||
SELECT COUNT(*)
|
||
FROM dbo.EKZMKEKZK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZ = @InstrumentId;", instrumentId);
|
||
}
|
||
|
||
private static int CountEkzMkNd(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
return ExecuteScalarForInstrument(connection, transaction, @"
|
||
SELECT COUNT(*)
|
||
FROM dbo.EKZMKND child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZ = @InstrumentId;", instrumentId);
|
||
}
|
||
|
||
private static int CountKspelEkzMk(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
return ExecuteScalarForInstrument(connection, transaction, @"
|
||
SELECT COUNT(*)
|
||
FROM dbo.KSPELEKZMK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZ = @InstrumentId;", instrumentId);
|
||
}
|
||
|
||
private static int CountEkzDms(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
return ExecuteScalarForInstrument(connection, transaction, @"
|
||
SELECT COUNT(*)
|
||
FROM dbo.DMS d
|
||
JOIN dbo.VDODVDD vdd ON vdd.IDVDODVDD = d.IDVDODVDD
|
||
JOIN dbo.EKZMK m ON m.IDEKZMK = d.IDOD
|
||
WHERE m.IDEKZ = @InstrumentId
|
||
AND vdd.IDSPVDOD = 2;", instrumentId);
|
||
}
|
||
|
||
private static int DeleteEkzMcp(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
return ExecuteScalarForInstrument(connection, transaction, @"
|
||
DELETE FROM dbo.EKZMCP
|
||
WHERE IDEKZ = @InstrumentId;
|
||
|
||
SELECT @@ROWCOUNT;", instrumentId);
|
||
}
|
||
|
||
private static int DeleteEkzMkFctvl(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
return ExecuteScalarForInstrument(connection, transaction, @"
|
||
DELETE child
|
||
FROM dbo.EKZMKFCTVL child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZ = @InstrumentId;
|
||
|
||
SELECT @@ROWCOUNT;", instrumentId);
|
||
}
|
||
|
||
private static int DeleteEkzMkDh(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
return ExecuteScalarForInstrument(connection, transaction, @"
|
||
DELETE child
|
||
FROM dbo.EKZMKDH child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZ = @InstrumentId;
|
||
|
||
SELECT @@ROWCOUNT;", instrumentId);
|
||
}
|
||
|
||
private static int DeleteEkzMkEkzk(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
return ExecuteScalarForInstrument(connection, transaction, @"
|
||
DELETE child
|
||
FROM dbo.EKZMKEKZK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZ = @InstrumentId;
|
||
|
||
SELECT @@ROWCOUNT;", instrumentId);
|
||
}
|
||
|
||
private static int DeleteEkzMkNd(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
return ExecuteScalarForInstrument(connection, transaction, @"
|
||
DELETE child
|
||
FROM dbo.EKZMKND child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZ = @InstrumentId;
|
||
|
||
SELECT @@ROWCOUNT;", instrumentId);
|
||
}
|
||
|
||
private static int DeleteKspelEkzMk(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
return ExecuteScalarForInstrument(connection, transaction, @"
|
||
DELETE child
|
||
FROM dbo.KSPELEKZMK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZ = @InstrumentId;
|
||
|
||
SELECT @@ROWCOUNT;", instrumentId);
|
||
}
|
||
|
||
private static int DeleteEkzDms(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
return ExecuteScalarForInstrument(connection, transaction, @"
|
||
DELETE d
|
||
FROM dbo.DMS d
|
||
JOIN dbo.VDODVDD vdd ON vdd.IDVDODVDD = d.IDVDODVDD
|
||
JOIN dbo.EKZMK m ON m.IDEKZMK = d.IDOD
|
||
WHERE m.IDEKZ = @InstrumentId
|
||
AND vdd.IDSPVDOD = 2;
|
||
|
||
SELECT @@ROWCOUNT;", instrumentId);
|
||
}
|
||
|
||
private static int DeleteEkzMk(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
return ExecuteScalarForInstrument(connection, transaction, @"
|
||
DELETE FROM dbo.EKZMK
|
||
WHERE IDEKZ = @InstrumentId;
|
||
|
||
SELECT @@ROWCOUNT;", instrumentId);
|
||
}
|
||
|
||
private static int DeleteEkz(SqlConnection connection, SqlTransaction transaction, int id)
|
||
{
|
||
return ExecuteScalarForId(connection, transaction, @"
|
||
DELETE FROM dbo.EKZ
|
||
WHERE IDEKZ = @Id;
|
||
|
||
SELECT @@ROWCOUNT;", id);
|
||
}
|
||
|
||
private static int ExecuteScalarForInstrument(SqlConnection connection, SqlTransaction transaction, string sql, int instrumentId)
|
||
{
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.CommandTimeout = ReferenceDirectorySqlHelpers.GetCommandTimeoutSeconds();
|
||
command.Parameters.Add("@InstrumentId", SqlDbType.Int).Value = instrumentId;
|
||
return Convert.ToInt32(command.ExecuteScalar());
|
||
}
|
||
}
|
||
|
||
private static int ExecuteScalarForId(SqlConnection connection, SqlTransaction transaction, string sql, int id)
|
||
{
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.CommandTimeout = ReferenceDirectorySqlHelpers.GetCommandTimeoutSeconds();
|
||
command.Parameters.Add("@Id", SqlDbType.Int).Value = id;
|
||
return Convert.ToInt32(command.ExecuteScalar());
|
||
}
|
||
}
|
||
|
||
private static List<int> ExecuteIdList(SqlConnection connection, SqlTransaction transaction, string sql, string parameterName, int parameterValue)
|
||
{
|
||
var result = new List<int>();
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.CommandTimeout = ReferenceDirectorySqlHelpers.GetCommandTimeoutSeconds();
|
||
command.Parameters.Add(parameterName, SqlDbType.Int).Value = parameterValue;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
result.Add(reader.GetInt32(0));
|
||
}
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
private static string NormalizeOptional(string value)
|
||
{
|
||
return string.IsNullOrWhiteSpace(value) ? null : value.Trim();
|
||
}
|
||
|
||
private static EkzDirectoryItem NormalizeEkzItem(EkzDirectoryItem item)
|
||
{
|
||
if (item == null)
|
||
{
|
||
throw new InvalidOperationException("Не переданы данные записи EKZ.");
|
||
}
|
||
|
||
var normalizedItem = new EkzDirectoryItem
|
||
{
|
||
Id = item.Id,
|
||
TypeSizeId = item.TypeSizeId,
|
||
OwnerOrganizationId = item.OwnerOrganizationId,
|
||
SerialNumber = NormalizeOptional(item.SerialNumber),
|
||
InventoryNumber = NormalizeOptional(item.InventoryNumber),
|
||
Notes = NormalizeOptional(item.Notes)
|
||
};
|
||
|
||
if (normalizedItem.TypeSizeId <= 0)
|
||
{
|
||
throw new InvalidOperationException("Не указан типоразмер СИ.");
|
||
}
|
||
|
||
if (normalizedItem.OwnerOrganizationId <= 0)
|
||
{
|
||
throw new InvalidOperationException("Не указана организация-владелец.");
|
||
}
|
||
|
||
if (string.IsNullOrWhiteSpace(normalizedItem.SerialNumber))
|
||
{
|
||
throw new InvalidOperationException("Не указан заводской номер.");
|
||
}
|
||
|
||
if (normalizedItem.SerialNumber.Length > EkzDirectoryRules.SerialNumberMaxLength)
|
||
{
|
||
throw new InvalidOperationException(string.Format("Заводской номер не должен превышать {0} символов.", EkzDirectoryRules.SerialNumberMaxLength));
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(normalizedItem.InventoryNumber) && normalizedItem.InventoryNumber.Length > EkzDirectoryRules.InventoryNumberMaxLength)
|
||
{
|
||
throw new InvalidOperationException(string.Format("Инвентарный номер не должен превышать {0} символов.", EkzDirectoryRules.InventoryNumberMaxLength));
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(normalizedItem.Notes) && normalizedItem.Notes.Length > EkzDirectoryRules.NotesMaxLength)
|
||
{
|
||
throw new InvalidOperationException(string.Format("Примечание не должно превышать {0} символов.", EkzDirectoryRules.NotesMaxLength));
|
||
}
|
||
|
||
return normalizedItem;
|
||
}
|
||
|
||
private static void EnsureEkzIsUnique(SqlConnection connection, int typeSizeId, int ownerOrganizationId, string serialNumber, int? excludeId)
|
||
{
|
||
const string sql = @"
|
||
SELECT TOP (1) z.IDEKZ
|
||
FROM dbo.EKZ z
|
||
WHERE z.IDTPRZ = @TypeSizeId
|
||
AND z.IDFRPDV = @OwnerOrganizationId
|
||
AND z.NNZV = @SerialNumber
|
||
AND ISNULL(z.IsDeleted, 0) = 0
|
||
AND (@ExcludeId IS NULL OR z.IDEKZ <> @ExcludeId)
|
||
ORDER BY z.IDEKZ DESC;";
|
||
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
command.CommandTimeout = ReferenceDirectorySqlHelpers.GetCommandTimeoutSeconds();
|
||
command.Parameters.Add("@TypeSizeId", SqlDbType.Int).Value = typeSizeId;
|
||
command.Parameters.Add("@OwnerOrganizationId", SqlDbType.Int).Value = ownerOrganizationId;
|
||
command.Parameters.Add("@SerialNumber", SqlDbType.VarChar, EkzDirectoryRules.SerialNumberMaxLength).Value = serialNumber;
|
||
ReferenceDirectorySqlHelpers.AddNullableIntParameter(command, "@ExcludeId", excludeId);
|
||
|
||
if (command.ExecuteScalar() != null)
|
||
{
|
||
throw new InvalidOperationException("Экземпляр с таким типоразмером, владельцем и заводским номером уже существует.");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|