4336 lines
184 KiB
C#
4336 lines
184 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Data;
|
||
using Microsoft.Data.SqlClient;
|
||
using System.Linq;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using XLAB2.Infrastructure;
|
||
|
||
namespace XLAB2
|
||
{
|
||
internal sealed class PsvDataService
|
||
{
|
||
public bool DocumentNumberExists(string documentNumber, string excludeDocumentNumber)
|
||
{
|
||
var normalizedNumber = NormalizeDocumentNumber(documentNumber);
|
||
if (normalizedNumber == null)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
using (var connection = CreateConnection())
|
||
using (var command = new SqlCommand(
|
||
@"
|
||
SELECT COUNT(1)
|
||
FROM dbo.EKZMK
|
||
WHERE NNZVPV = @DocumentNumber
|
||
AND (@ExcludeDocumentNumber = N'' OR NNZVPV <> @ExcludeDocumentNumber);",
|
||
connection))
|
||
{
|
||
connection.Open();
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = normalizedNumber;
|
||
command.Parameters.Add("@ExcludeDocumentNumber", SqlDbType.NVarChar, 60).Value = excludeDocumentNumber ?? string.Empty;
|
||
return Convert.ToInt32(command.ExecuteScalar()) > 0;
|
||
}
|
||
}
|
||
|
||
public async Task<bool> DocumentNumberExistsAsync(string documentNumber, string excludeDocumentNumber, CancellationToken cancellationToken = default)
|
||
{
|
||
var normalizedNumber = NormalizeDocumentNumber(documentNumber);
|
||
if (normalizedNumber == null)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
await using (var connection = await SqlServerConnectionFactory.Current.OpenConnectionAsync(cancellationToken).ConfigureAwait(false))
|
||
{
|
||
return await DocumentNumberExistsAsync(connection, null, normalizedNumber, excludeDocumentNumber, cancellationToken).ConfigureAwait(false);
|
||
}
|
||
}
|
||
|
||
public IReadOnlyList<CustomerReference> LoadCustomers()
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
z.IDFRPDV AS CustomerId,
|
||
fr.NMFRPD AS CustomerName
|
||
FROM dbo.EKZ z
|
||
JOIN dbo.FRPD fr ON fr.IDFRPD = z.IDFRPDV
|
||
WHERE z.IDFRPDV IS NOT NULL
|
||
GROUP BY z.IDFRPDV, fr.NMFRPD
|
||
ORDER BY fr.NMFRPD;";
|
||
|
||
var customers = new List<CustomerReference>();
|
||
|
||
using (var connection = CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
customers.Add(new CustomerReference
|
||
{
|
||
CustomerId = GetInt32(reader, "CustomerId"),
|
||
CustomerName = GetString(reader, "CustomerName")
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
return customers;
|
||
}
|
||
|
||
public Task<IReadOnlyList<CustomerReference>> LoadCustomersAsync(CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
z.IDFRPDV AS CustomerId,
|
||
fr.NMFRPD AS CustomerName
|
||
FROM dbo.EKZ z
|
||
JOIN dbo.FRPD fr ON fr.IDFRPD = z.IDFRPDV
|
||
WHERE z.IDFRPDV IS NOT NULL
|
||
GROUP BY z.IDFRPDV, fr.NMFRPD
|
||
ORDER BY fr.NMFRPD;";
|
||
|
||
return SqlServerConnectionFactory.Current.QueryOpenConnectionAsync(
|
||
sql,
|
||
delegate(SqlDataReader reader)
|
||
{
|
||
return new CustomerReference
|
||
{
|
||
CustomerId = GetInt32(reader, "CustomerId"),
|
||
CustomerName = GetString(reader, "CustomerName")
|
||
};
|
||
},
|
||
ConfigureCommandTimeout,
|
||
cancellationToken).ContinueWith<IReadOnlyList<CustomerReference>>(delegate(Task<List<CustomerReference>> task)
|
||
{
|
||
return task.Result;
|
||
}, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
|
||
}
|
||
|
||
public IReadOnlyList<PersonReference> LoadVerifiers()
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
p.IDPRSN AS PersonId,
|
||
p.PRFIO AS FullName
|
||
FROM dbo.PRSN p
|
||
WHERE NULLIF(LTRIM(RTRIM(p.PRFIO)), N'') IS NOT NULL
|
||
ORDER BY p.PRFIO;";
|
||
|
||
var verifiers = new List<PersonReference>();
|
||
|
||
using (var connection = CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
verifiers.Add(new PersonReference
|
||
{
|
||
PersonId = GetInt32(reader, "PersonId"),
|
||
FullName = GetString(reader, "FullName")
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
return verifiers;
|
||
}
|
||
|
||
public Task<IReadOnlyList<PersonReference>> LoadVerifiersAsync(CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
p.IDPRSN AS PersonId,
|
||
p.PRFIO AS FullName
|
||
FROM dbo.PRSN p
|
||
WHERE NULLIF(LTRIM(RTRIM(p.PRFIO)), N'') IS NOT NULL
|
||
ORDER BY p.PRFIO;";
|
||
|
||
return SqlServerConnectionFactory.Current.QueryOpenConnectionAsync(
|
||
sql,
|
||
delegate(SqlDataReader reader)
|
||
{
|
||
return new PersonReference
|
||
{
|
||
PersonId = GetInt32(reader, "PersonId"),
|
||
FullName = GetString(reader, "FullName")
|
||
};
|
||
},
|
||
ConfigureCommandTimeout,
|
||
cancellationToken).ContinueWith<IReadOnlyList<PersonReference>>(delegate(Task<List<PersonReference>> task)
|
||
{
|
||
return task.Result;
|
||
}, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
|
||
}
|
||
|
||
public IReadOnlyList<DocumentFormReference> LoadVerificationDocumentForms(bool isPassed)
|
||
{
|
||
const string sql = @"
|
||
SELECT DISTINCT
|
||
fr.IDFRDMS AS DocumentFormId,
|
||
v.IDVDODVDD AS LinkTypeId,
|
||
sp.NMVDD AS DocumentKindName,
|
||
fr.NMFRD AS DocumentFormName
|
||
FROM dbo.FRDMS fr
|
||
JOIN dbo.SPVDD sp ON sp.IDSPVDD = fr.IDSPVDD
|
||
JOIN dbo.VDODVDD v ON v.IDSPVDD = fr.IDSPVDD
|
||
WHERE v.IDSPVDOD = 2
|
||
AND fr.IDSPVDD = @DocumentTypeId
|
||
ORDER BY fr.NMFRD, v.IDVDODVDD;";
|
||
|
||
var forms = new List<DocumentFormReference>();
|
||
|
||
using (var connection = CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@DocumentTypeId", SqlDbType.Int).Value = isPassed ? 6 : 2;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
forms.Add(new DocumentFormReference
|
||
{
|
||
DocumentFormId = GetInt32(reader, "DocumentFormId"),
|
||
LinkTypeId = GetInt32(reader, "LinkTypeId"),
|
||
DocumentKindName = GetString(reader, "DocumentKindName"),
|
||
DocumentFormName = GetString(reader, "DocumentFormName")
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
return forms;
|
||
}
|
||
|
||
public Task<IReadOnlyList<DocumentFormReference>> LoadVerificationDocumentFormsAsync(bool isPassed, CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
SELECT DISTINCT
|
||
fr.IDFRDMS AS DocumentFormId,
|
||
v.IDVDODVDD AS LinkTypeId,
|
||
sp.NMVDD AS DocumentKindName,
|
||
fr.NMFRD AS DocumentFormName
|
||
FROM dbo.FRDMS fr
|
||
JOIN dbo.SPVDD sp ON sp.IDSPVDD = fr.IDSPVDD
|
||
JOIN dbo.VDODVDD v ON v.IDSPVDD = fr.IDSPVDD
|
||
WHERE v.IDSPVDOD = 2
|
||
AND fr.IDSPVDD = @DocumentTypeId
|
||
ORDER BY fr.NMFRD, v.IDVDODVDD;";
|
||
|
||
return SqlServerConnectionFactory.Current.QueryOpenConnectionAsync(
|
||
sql,
|
||
delegate(SqlDataReader reader)
|
||
{
|
||
return new DocumentFormReference
|
||
{
|
||
DocumentFormId = GetInt32(reader, "DocumentFormId"),
|
||
LinkTypeId = GetInt32(reader, "LinkTypeId"),
|
||
DocumentKindName = GetString(reader, "DocumentKindName"),
|
||
DocumentFormName = GetString(reader, "DocumentFormName")
|
||
};
|
||
},
|
||
delegate(SqlCommand command)
|
||
{
|
||
ConfigureCommandTimeout(command);
|
||
command.Parameters.Add("@DocumentTypeId", SqlDbType.Int).Value = isPassed ? 6 : 2;
|
||
},
|
||
cancellationToken).ContinueWith<IReadOnlyList<DocumentFormReference>>(delegate(Task<List<DocumentFormReference>> task)
|
||
{
|
||
return task.Result;
|
||
}, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
|
||
}
|
||
|
||
public IReadOnlyList<SpoiDirectoryItem> LoadSpoiItems()
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
s.IDSPOI AS Id,
|
||
s.KDOI AS Code,
|
||
s.NMOI AS Name
|
||
FROM dbo.SPOI s
|
||
ORDER BY s.NMOI, s.KDOI, s.IDSPOI;";
|
||
|
||
var items = new List<SpoiDirectoryItem>();
|
||
|
||
using (var connection = CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
items.Add(new SpoiDirectoryItem
|
||
{
|
||
Id = GetInt32(reader, "Id"),
|
||
Code = GetString(reader, "Code"),
|
||
Name = GetString(reader, "Name")
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
return items;
|
||
}
|
||
|
||
public Task<IReadOnlyList<SpoiDirectoryItem>> LoadSpoiItemsAsync(CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
s.IDSPOI AS Id,
|
||
s.KDOI AS Code,
|
||
s.NMOI AS Name
|
||
FROM dbo.SPOI s
|
||
ORDER BY s.NMOI, s.KDOI, s.IDSPOI;";
|
||
|
||
return SqlServerConnectionFactory.Current.QueryOpenConnectionAsync(
|
||
sql,
|
||
delegate(SqlDataReader reader)
|
||
{
|
||
return new SpoiDirectoryItem
|
||
{
|
||
Id = GetInt32(reader, "Id"),
|
||
Code = GetString(reader, "Code"),
|
||
Name = GetString(reader, "Name")
|
||
};
|
||
},
|
||
ConfigureCommandTimeout,
|
||
cancellationToken).ContinueWith<IReadOnlyList<SpoiDirectoryItem>>(delegate(Task<List<SpoiDirectoryItem>> task)
|
||
{
|
||
return task.Result;
|
||
}, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
|
||
}
|
||
|
||
public int AddSpoiItem(SpoiDirectoryItem item)
|
||
{
|
||
var normalizedItem = NormalizeSpoiItem(item);
|
||
|
||
const string sql = @"
|
||
INSERT INTO dbo.SPOI
|
||
(
|
||
KDOI,
|
||
NMOI
|
||
)
|
||
VALUES
|
||
(
|
||
@Code,
|
||
@Name
|
||
);
|
||
|
||
SELECT CAST(SCOPE_IDENTITY() AS int);";
|
||
|
||
using (var connection = CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
EnsureSpoiCodeIsUnique(connection, normalizedItem.Code, null);
|
||
EnsureSpoiNameIsUnique(connection, normalizedItem.Name, null);
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@Code", SqlDbType.VarChar, SpoiDirectoryRules.CodeMaxLength).Value = normalizedItem.Code;
|
||
command.Parameters.Add("@Name", SqlDbType.VarChar, SpoiDirectoryRules.NameMaxLength).Value = normalizedItem.Name;
|
||
|
||
try
|
||
{
|
||
return Convert.ToInt32(command.ExecuteScalar());
|
||
}
|
||
catch (SqlException ex) when (IsSpoiDuplicateCodeViolation(ex))
|
||
{
|
||
throw CreateSpoiDuplicateCodeException(normalizedItem.Code, ex);
|
||
}
|
||
catch (SqlException ex) when (IsSpoiDuplicateNameViolation(ex))
|
||
{
|
||
throw CreateSpoiDuplicateNameException(normalizedItem.Name, ex);
|
||
}
|
||
}
|
||
}
|
||
|
||
public void UpdateSpoiItem(SpoiDirectoryItem item)
|
||
{
|
||
var normalizedItem = NormalizeSpoiItem(item);
|
||
if (normalizedItem.Id <= 0)
|
||
{
|
||
throw new InvalidOperationException("Не выбрана запись SPOI для изменения.");
|
||
}
|
||
|
||
const string sql = @"
|
||
UPDATE dbo.SPOI
|
||
SET KDOI = @Code,
|
||
NMOI = @Name
|
||
WHERE IDSPOI = @Id;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
using (var connection = CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
EnsureSpoiCodeIsUnique(connection, normalizedItem.Code, normalizedItem.Id);
|
||
EnsureSpoiNameIsUnique(connection, normalizedItem.Name, normalizedItem.Id);
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@Id", SqlDbType.Int).Value = normalizedItem.Id;
|
||
command.Parameters.Add("@Code", SqlDbType.VarChar, SpoiDirectoryRules.CodeMaxLength).Value = normalizedItem.Code;
|
||
command.Parameters.Add("@Name", SqlDbType.VarChar, SpoiDirectoryRules.NameMaxLength).Value = normalizedItem.Name;
|
||
|
||
try
|
||
{
|
||
if (Convert.ToInt32(command.ExecuteScalar()) == 0)
|
||
{
|
||
throw new InvalidOperationException("Запись SPOI для изменения не найдена.");
|
||
}
|
||
}
|
||
catch (SqlException ex) when (IsSpoiDuplicateCodeViolation(ex))
|
||
{
|
||
throw CreateSpoiDuplicateCodeException(normalizedItem.Code, ex);
|
||
}
|
||
catch (SqlException ex) when (IsSpoiDuplicateNameViolation(ex))
|
||
{
|
||
throw CreateSpoiDuplicateNameException(normalizedItem.Name, ex);
|
||
}
|
||
}
|
||
}
|
||
|
||
public SpoiDeleteResult DeleteSpoiItem(int id)
|
||
{
|
||
if (id <= 0)
|
||
{
|
||
throw new InvalidOperationException("Не выбрана запись SPOI для удаления.");
|
||
}
|
||
|
||
const string sql = @"
|
||
DELETE FROM dbo.SPOI
|
||
WHERE IDSPOI = @Id;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
try
|
||
{
|
||
using (var connection = CreateConnection())
|
||
{
|
||
connection.Open();
|
||
var blockers = LoadSpoiDeleteBlockers(connection, id);
|
||
if (blockers.Count > 0)
|
||
{
|
||
return new SpoiDeleteResult
|
||
{
|
||
IsDeleted = false,
|
||
WarningMessage = CreateSpoiDeleteBlockedMessage(blockers)
|
||
};
|
||
}
|
||
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@Id", SqlDbType.Int).Value = id;
|
||
|
||
if (Convert.ToInt32(command.ExecuteScalar()) == 0)
|
||
{
|
||
throw new InvalidOperationException("Запись SPOI для удаления не найдена.");
|
||
}
|
||
}
|
||
|
||
return new SpoiDeleteResult
|
||
{
|
||
IsDeleted = true
|
||
};
|
||
}
|
||
}
|
||
catch (SqlException ex) when (ex.Number == 547)
|
||
{
|
||
return new SpoiDeleteResult
|
||
{
|
||
IsDeleted = false,
|
||
WarningMessage = CreateSpoiDeleteBlockedMessage(ex)
|
||
};
|
||
}
|
||
}
|
||
|
||
public IReadOnlyList<SpnmtpDirectoryItem> LoadSpnmtpItems()
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
s.IDSPNMTP AS Id,
|
||
s.NMTP AS Name,
|
||
s.NMTPSP AS SpecialName
|
||
FROM dbo.SPNMTP s
|
||
ORDER BY s.NMTP, s.IDSPNMTP;";
|
||
|
||
var items = new List<SpnmtpDirectoryItem>();
|
||
|
||
using (var connection = CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
items.Add(new SpnmtpDirectoryItem
|
||
{
|
||
Id = GetInt32(reader, "Id"),
|
||
Name = GetString(reader, "Name"),
|
||
SpecialName = GetString(reader, "SpecialName")
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
return items;
|
||
}
|
||
|
||
public Task<IReadOnlyList<SpnmtpDirectoryItem>> LoadSpnmtpItemsAsync(CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
s.IDSPNMTP AS Id,
|
||
s.NMTP AS Name,
|
||
s.NMTPSP AS SpecialName
|
||
FROM dbo.SPNMTP s
|
||
ORDER BY s.NMTP, s.IDSPNMTP;";
|
||
|
||
return SqlServerConnectionFactory.Current.QueryOpenConnectionAsync(
|
||
sql,
|
||
delegate(SqlDataReader reader)
|
||
{
|
||
return new SpnmtpDirectoryItem
|
||
{
|
||
Id = GetInt32(reader, "Id"),
|
||
Name = GetString(reader, "Name"),
|
||
SpecialName = GetString(reader, "SpecialName")
|
||
};
|
||
},
|
||
ConfigureCommandTimeout,
|
||
cancellationToken).ContinueWith<IReadOnlyList<SpnmtpDirectoryItem>>(delegate(Task<List<SpnmtpDirectoryItem>> task)
|
||
{
|
||
return task.Result;
|
||
}, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
|
||
}
|
||
|
||
public int AddSpnmtpItem(SpnmtpDirectoryItem item)
|
||
{
|
||
var normalizedItem = NormalizeSpnmtpItem(item);
|
||
|
||
const string sql = @"
|
||
INSERT INTO dbo.SPNMTP
|
||
(
|
||
NMTP,
|
||
NMTPSP
|
||
)
|
||
VALUES
|
||
(
|
||
@Name,
|
||
@SpecialName
|
||
);
|
||
|
||
SELECT CAST(SCOPE_IDENTITY() AS int);";
|
||
|
||
using (var connection = CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
EnsureSpnmtpNameIsUnique(connection, normalizedItem.Name, null);
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@Name", SqlDbType.NVarChar, SpnmtpDirectoryRules.NameMaxLength).Value = normalizedItem.Name;
|
||
command.Parameters.Add("@SpecialName", SqlDbType.VarChar, SpnmtpDirectoryRules.SpecialNameMaxLength).Value = (object)normalizedItem.SpecialName ?? DBNull.Value;
|
||
|
||
try
|
||
{
|
||
return Convert.ToInt32(command.ExecuteScalar());
|
||
}
|
||
catch (SqlException ex) when (IsSpnmtpDuplicateNameViolation(ex))
|
||
{
|
||
throw CreateSpnmtpDuplicateNameException(normalizedItem.Name, ex);
|
||
}
|
||
}
|
||
}
|
||
|
||
public void UpdateSpnmtpItem(SpnmtpDirectoryItem item)
|
||
{
|
||
var normalizedItem = NormalizeSpnmtpItem(item);
|
||
if (normalizedItem.Id <= 0)
|
||
{
|
||
throw new InvalidOperationException("Не выбрана запись SPNMTP для изменения.");
|
||
}
|
||
|
||
const string sql = @"
|
||
UPDATE dbo.SPNMTP
|
||
SET NMTP = @Name,
|
||
NMTPSP = @SpecialName
|
||
WHERE IDSPNMTP = @Id;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
using (var connection = CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
EnsureSpnmtpNameIsUnique(connection, normalizedItem.Name, normalizedItem.Id);
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@Id", SqlDbType.Int).Value = normalizedItem.Id;
|
||
command.Parameters.Add("@Name", SqlDbType.NVarChar, SpnmtpDirectoryRules.NameMaxLength).Value = normalizedItem.Name;
|
||
command.Parameters.Add("@SpecialName", SqlDbType.VarChar, SpnmtpDirectoryRules.SpecialNameMaxLength).Value = (object)normalizedItem.SpecialName ?? DBNull.Value;
|
||
|
||
try
|
||
{
|
||
if (Convert.ToInt32(command.ExecuteScalar()) == 0)
|
||
{
|
||
throw new InvalidOperationException("Запись SPNMTP для изменения не найдена.");
|
||
}
|
||
}
|
||
catch (SqlException ex) when (IsSpnmtpDuplicateNameViolation(ex))
|
||
{
|
||
throw CreateSpnmtpDuplicateNameException(normalizedItem.Name, ex);
|
||
}
|
||
}
|
||
}
|
||
|
||
public SpnmtpDeleteResult DeleteSpnmtpItem(int id)
|
||
{
|
||
if (id <= 0)
|
||
{
|
||
throw new InvalidOperationException("Не выбрана запись SPNMTP для удаления.");
|
||
}
|
||
|
||
const string sql = @"
|
||
DELETE FROM dbo.SPNMTP
|
||
WHERE IDSPNMTP = @Id;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
try
|
||
{
|
||
using (var connection = CreateConnection())
|
||
{
|
||
connection.Open();
|
||
var blockers = LoadSpnmtpDeleteBlockers(connection, id);
|
||
if (blockers.Count > 0)
|
||
{
|
||
return new SpnmtpDeleteResult
|
||
{
|
||
IsDeleted = false,
|
||
WarningMessage = CreateSpnmtpDeleteBlockedMessage(blockers)
|
||
};
|
||
}
|
||
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@Id", SqlDbType.Int).Value = id;
|
||
|
||
if (Convert.ToInt32(command.ExecuteScalar()) == 0)
|
||
{
|
||
throw new InvalidOperationException("Запись SPNMTP для удаления не найдена.");
|
||
}
|
||
}
|
||
|
||
return new SpnmtpDeleteResult
|
||
{
|
||
IsDeleted = true
|
||
};
|
||
}
|
||
}
|
||
catch (SqlException ex) when (ex.Number == 547)
|
||
{
|
||
return new SpnmtpDeleteResult
|
||
{
|
||
IsDeleted = false,
|
||
WarningMessage = CreateSpnmtpDeleteBlockedMessage(ex)
|
||
};
|
||
}
|
||
}
|
||
|
||
public IReadOnlyList<PsvDocumentSummary> LoadDocuments(bool loadClosedDocumentsForCurrentYear)
|
||
{
|
||
var sql = @"
|
||
SELECT
|
||
m.NNZVPV AS DocumentNumber,
|
||
MAX(m.DTPRM) AS AcceptedOn,
|
||
MAX(m.DTVDM) AS IssuedOn,
|
||
MIN(dep.NMFRPD) AS DepartmentName,
|
||
CASE WHEN COUNT(DISTINCT z.IDFRPDV) = 1 THEN MIN(z.IDFRPDV) ELSE NULL END AS CustomerId,
|
||
CASE WHEN COUNT(DISTINCT z.IDFRPDV) = 1 THEN MIN(ownerOrg.NMFRPD) ELSE N'' END AS CustomerName,
|
||
COUNT(*) AS ItemCount,
|
||
SUM(CASE WHEN m.DTVDM IS NOT NULL THEN 1 ELSE 0 END) AS IssuedCount,
|
||
SUM(CASE WHEN m.GDN = 1 THEN 1 ELSE 0 END) AS PassedCount,
|
||
SUM(CASE WHEN m.GDN = 0 THEN 1 ELSE 0 END) AS FailedCount
|
||
FROM dbo.EKZMK m
|
||
JOIN dbo.EKZ z ON z.IDEKZ = m.IDEKZ
|
||
LEFT JOIN dbo.FRPD dep ON dep.IDFRPD = m.IDFRPD
|
||
LEFT JOIN dbo.FRPD ownerOrg ON ownerOrg.IDFRPD = z.IDFRPDV
|
||
WHERE NULLIF(LTRIM(RTRIM(m.NNZVPV)), N'') IS NOT NULL
|
||
GROUP BY m.NNZVPV
|
||
HAVING " + (loadClosedDocumentsForCurrentYear
|
||
? "MAX(m.DTVDM) >= @IssuedFrom AND MAX(m.DTVDM) < @IssuedTo"
|
||
: "MAX(m.DTVDM) IS NULL") + @"
|
||
ORDER BY " + (loadClosedDocumentsForCurrentYear
|
||
? "MAX(m.DTVDM) DESC"
|
||
: "MAX(m.DTPRM) DESC") + @", m.NNZVPV DESC;";
|
||
|
||
var documents = new List<PsvDocumentSummary>();
|
||
var today = DateTime.Today;
|
||
var currentYearStart = new DateTime(today.Year, 1, 1);
|
||
var nextYearStart = currentYearStart.AddYears(1);
|
||
|
||
using (var connection = CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
if (loadClosedDocumentsForCurrentYear)
|
||
{
|
||
command.Parameters.Add("@IssuedFrom", SqlDbType.DateTime).Value = currentYearStart;
|
||
command.Parameters.Add("@IssuedTo", SqlDbType.DateTime).Value = nextYearStart;
|
||
}
|
||
|
||
connection.Open();
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
var documentNumber = GetString(reader, "DocumentNumber");
|
||
documents.Add(new PsvDocumentSummary
|
||
{
|
||
DocumentKey = documentNumber,
|
||
DocumentNumber = documentNumber,
|
||
AcceptedOn = GetNullableDateTime(reader, "AcceptedOn"),
|
||
IssuedOn = GetNullableDateTime(reader, "IssuedOn"),
|
||
DepartmentName = GetString(reader, "DepartmentName"),
|
||
CustomerId = GetNullableInt32(reader, "CustomerId"),
|
||
CustomerName = GetString(reader, "CustomerName"),
|
||
ItemCount = GetInt32(reader, "ItemCount"),
|
||
IssuedCount = GetInt32(reader, "IssuedCount"),
|
||
PassedCount = GetInt32(reader, "PassedCount"),
|
||
FailedCount = GetInt32(reader, "FailedCount"),
|
||
IsDraft = false
|
||
});
|
||
}
|
||
}
|
||
|
||
var serialNumbersByDocument = LoadDocumentSerialNumbers(connection, loadClosedDocumentsForCurrentYear, currentYearStart, nextYearStart);
|
||
foreach (var document in documents)
|
||
{
|
||
if (serialNumbersByDocument.TryGetValue(document.DocumentNumber, out var serialNumbersText))
|
||
{
|
||
document.SerialNumbersText = serialNumbersText;
|
||
}
|
||
}
|
||
}
|
||
|
||
return documents;
|
||
}
|
||
|
||
public async Task<IReadOnlyList<PsvDocumentSummary>> LoadDocumentsAsync(bool loadClosedDocumentsForCurrentYear, CancellationToken cancellationToken = default)
|
||
{
|
||
var sql = @"
|
||
SELECT
|
||
m.NNZVPV AS DocumentNumber,
|
||
MAX(m.DTPRM) AS AcceptedOn,
|
||
MAX(m.DTVDM) AS IssuedOn,
|
||
MIN(dep.NMFRPD) AS DepartmentName,
|
||
CASE WHEN COUNT(DISTINCT z.IDFRPDV) = 1 THEN MIN(z.IDFRPDV) ELSE NULL END AS CustomerId,
|
||
CASE WHEN COUNT(DISTINCT z.IDFRPDV) = 1 THEN MIN(ownerOrg.NMFRPD) ELSE N'' END AS CustomerName,
|
||
COUNT(*) AS ItemCount,
|
||
SUM(CASE WHEN m.DTVDM IS NOT NULL THEN 1 ELSE 0 END) AS IssuedCount,
|
||
SUM(CASE WHEN m.GDN = 1 THEN 1 ELSE 0 END) AS PassedCount,
|
||
SUM(CASE WHEN m.GDN = 0 THEN 1 ELSE 0 END) AS FailedCount
|
||
FROM dbo.EKZMK m
|
||
JOIN dbo.EKZ z ON z.IDEKZ = m.IDEKZ
|
||
LEFT JOIN dbo.FRPD dep ON dep.IDFRPD = m.IDFRPD
|
||
LEFT JOIN dbo.FRPD ownerOrg ON ownerOrg.IDFRPD = z.IDFRPDV
|
||
WHERE NULLIF(LTRIM(RTRIM(m.NNZVPV)), N'') IS NOT NULL
|
||
GROUP BY m.NNZVPV
|
||
HAVING " + (loadClosedDocumentsForCurrentYear
|
||
? "MAX(m.DTVDM) >= @IssuedFrom AND MAX(m.DTVDM) < @IssuedTo"
|
||
: "MAX(m.DTVDM) IS NULL") + @"
|
||
ORDER BY " + (loadClosedDocumentsForCurrentYear
|
||
? "MAX(m.DTVDM) DESC"
|
||
: "MAX(m.DTPRM) DESC") + @", m.NNZVPV DESC;";
|
||
|
||
var today = DateTime.Today;
|
||
var currentYearStart = new DateTime(today.Year, 1, 1);
|
||
var nextYearStart = currentYearStart.AddYears(1);
|
||
|
||
var documents = new List<PsvDocumentSummary>();
|
||
|
||
await using (var connection = await SqlServerConnectionFactory.Current.OpenConnectionAsync(cancellationToken).ConfigureAwait(false))
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
ConfigureCommandTimeout(command);
|
||
|
||
if (loadClosedDocumentsForCurrentYear)
|
||
{
|
||
command.Parameters.Add("@IssuedFrom", SqlDbType.DateTime).Value = currentYearStart;
|
||
command.Parameters.Add("@IssuedTo", SqlDbType.DateTime).Value = nextYearStart;
|
||
}
|
||
|
||
using (var reader = await command.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false))
|
||
{
|
||
while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
|
||
{
|
||
var documentNumber = GetString(reader, "DocumentNumber");
|
||
documents.Add(new PsvDocumentSummary
|
||
{
|
||
DocumentKey = documentNumber,
|
||
DocumentNumber = documentNumber,
|
||
AcceptedOn = GetNullableDateTime(reader, "AcceptedOn"),
|
||
IssuedOn = GetNullableDateTime(reader, "IssuedOn"),
|
||
DepartmentName = GetString(reader, "DepartmentName"),
|
||
CustomerId = GetNullableInt32(reader, "CustomerId"),
|
||
CustomerName = GetString(reader, "CustomerName"),
|
||
ItemCount = GetInt32(reader, "ItemCount"),
|
||
IssuedCount = GetInt32(reader, "IssuedCount"),
|
||
PassedCount = GetInt32(reader, "PassedCount"),
|
||
FailedCount = GetInt32(reader, "FailedCount"),
|
||
IsDraft = false
|
||
});
|
||
}
|
||
}
|
||
|
||
var serialNumbersByDocument = await LoadDocumentSerialNumbersAsync(connection, loadClosedDocumentsForCurrentYear, currentYearStart, nextYearStart, cancellationToken).ConfigureAwait(false);
|
||
foreach (var document in documents)
|
||
{
|
||
if (serialNumbersByDocument.TryGetValue(document.DocumentNumber, out var serialNumbersText))
|
||
{
|
||
document.SerialNumbersText = serialNumbersText;
|
||
}
|
||
}
|
||
}
|
||
|
||
return documents;
|
||
}
|
||
|
||
private Dictionary<string, string> LoadDocumentSerialNumbers(SqlConnection connection, bool loadClosedDocumentsForCurrentYear, DateTime currentYearStart, DateTime nextYearStart)
|
||
{
|
||
var sql = @"
|
||
WITH filteredDocuments AS
|
||
(
|
||
SELECT m.NNZVPV
|
||
FROM dbo.EKZMK m
|
||
WHERE NULLIF(LTRIM(RTRIM(m.NNZVPV)), N'') IS NOT NULL
|
||
GROUP BY m.NNZVPV
|
||
HAVING " + (loadClosedDocumentsForCurrentYear
|
||
? "MAX(m.DTVDM) >= @IssuedFrom AND MAX(m.DTVDM) < @IssuedTo"
|
||
: "MAX(m.DTVDM) IS NULL") + @"
|
||
)
|
||
SELECT
|
||
m.NNZVPV AS DocumentNumber,
|
||
z.NNZV AS SerialNumber
|
||
FROM dbo.EKZMK m
|
||
JOIN filteredDocuments documents ON documents.NNZVPV = m.NNZVPV
|
||
JOIN dbo.EKZ z ON z.IDEKZ = m.IDEKZ
|
||
WHERE NULLIF(LTRIM(RTRIM(z.NNZV)), N'') IS NOT NULL
|
||
ORDER BY m.NNZVPV, z.NNZV;";
|
||
|
||
var serialNumbersByDocument = new Dictionary<string, SortedSet<string>>(StringComparer.OrdinalIgnoreCase);
|
||
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
ConfigureCommandTimeout(command);
|
||
|
||
if (loadClosedDocumentsForCurrentYear)
|
||
{
|
||
command.Parameters.Add("@IssuedFrom", SqlDbType.DateTime).Value = currentYearStart;
|
||
command.Parameters.Add("@IssuedTo", SqlDbType.DateTime).Value = nextYearStart;
|
||
}
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
var documentNumber = GetString(reader, "DocumentNumber");
|
||
var serialNumber = GetString(reader, "SerialNumber");
|
||
if (string.IsNullOrWhiteSpace(documentNumber) || string.IsNullOrWhiteSpace(serialNumber))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
if (!serialNumbersByDocument.TryGetValue(documentNumber, out var serialNumbers))
|
||
{
|
||
serialNumbers = new SortedSet<string>(StringComparer.OrdinalIgnoreCase);
|
||
serialNumbersByDocument[documentNumber] = serialNumbers;
|
||
}
|
||
|
||
serialNumbers.Add(serialNumber.Trim());
|
||
}
|
||
}
|
||
}
|
||
|
||
return serialNumbersByDocument.ToDictionary(pair => pair.Key, pair => string.Join(", ", pair.Value), StringComparer.OrdinalIgnoreCase);
|
||
}
|
||
|
||
private async Task<Dictionary<string, string>> LoadDocumentSerialNumbersAsync(SqlConnection connection, bool loadClosedDocumentsForCurrentYear, DateTime currentYearStart, DateTime nextYearStart, CancellationToken cancellationToken)
|
||
{
|
||
var sql = @"
|
||
WITH filteredDocuments AS
|
||
(
|
||
SELECT m.NNZVPV
|
||
FROM dbo.EKZMK m
|
||
WHERE NULLIF(LTRIM(RTRIM(m.NNZVPV)), N'') IS NOT NULL
|
||
GROUP BY m.NNZVPV
|
||
HAVING " + (loadClosedDocumentsForCurrentYear
|
||
? "MAX(m.DTVDM) >= @IssuedFrom AND MAX(m.DTVDM) < @IssuedTo"
|
||
: "MAX(m.DTVDM) IS NULL") + @"
|
||
)
|
||
SELECT
|
||
m.NNZVPV AS DocumentNumber,
|
||
z.NNZV AS SerialNumber
|
||
FROM dbo.EKZMK m
|
||
JOIN filteredDocuments documents ON documents.NNZVPV = m.NNZVPV
|
||
JOIN dbo.EKZ z ON z.IDEKZ = m.IDEKZ
|
||
WHERE NULLIF(LTRIM(RTRIM(z.NNZV)), N'') IS NOT NULL
|
||
ORDER BY m.NNZVPV, z.NNZV;";
|
||
|
||
var serialNumbersByDocument = new Dictionary<string, SortedSet<string>>(StringComparer.OrdinalIgnoreCase);
|
||
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
ConfigureCommandTimeout(command);
|
||
|
||
if (loadClosedDocumentsForCurrentYear)
|
||
{
|
||
command.Parameters.Add("@IssuedFrom", SqlDbType.DateTime).Value = currentYearStart;
|
||
command.Parameters.Add("@IssuedTo", SqlDbType.DateTime).Value = nextYearStart;
|
||
}
|
||
|
||
using (var reader = await command.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false))
|
||
{
|
||
while (await reader.ReadAsync(cancellationToken).ConfigureAwait(false))
|
||
{
|
||
var documentNumber = GetString(reader, "DocumentNumber");
|
||
var serialNumber = GetString(reader, "SerialNumber");
|
||
if (string.IsNullOrWhiteSpace(documentNumber) || string.IsNullOrWhiteSpace(serialNumber))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
if (!serialNumbersByDocument.TryGetValue(documentNumber, out var serialNumbers))
|
||
{
|
||
serialNumbers = new SortedSet<string>(StringComparer.OrdinalIgnoreCase);
|
||
serialNumbersByDocument[documentNumber] = serialNumbers;
|
||
}
|
||
|
||
serialNumbers.Add(serialNumber.Trim());
|
||
}
|
||
}
|
||
}
|
||
|
||
return serialNumbersByDocument.ToDictionary(pair => pair.Key, pair => string.Join(", ", pair.Value), StringComparer.OrdinalIgnoreCase);
|
||
}
|
||
|
||
public IReadOnlyList<PsvDocumentLine> LoadDocumentLines(string documentNumber)
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
m.IDEKZMK AS CardId,
|
||
z.IDEKZ AS InstrumentId,
|
||
z.IDTPRZ AS TypeSizeId,
|
||
z.NNZV AS SerialNumber,
|
||
z.NNIN AS InventoryNumber,
|
||
ownerOrg.NMFRPD AS CustomerName,
|
||
tips.TP AS InstrumentType,
|
||
names.NMTP AS InstrumentName,
|
||
areas.NMOI AS MeasurementArea,
|
||
sizeInfo.DPZN AS RangeText,
|
||
sizeInfo.NNGSRS AS RegistryNumber,
|
||
sizeInfo.HRTC AS AccuracyText,
|
||
verificationType.NMVDMK AS VerificationType,
|
||
m.PRMK AS PeriodMonths,
|
||
m.DTPRM AS AcceptedOn,
|
||
m.DTVDM AS IssuedOn,
|
||
m.GDN AS IsPassed,
|
||
m.DTMKFK AS VerificationPerformedOn,
|
||
m.IDPRSN AS VerifierId,
|
||
verifier.PRFIO AS VerifierName,
|
||
m.NNNKL AS StickerNumber,
|
||
verificationDocument.IDFRDMS AS VerificationDocumentFormId,
|
||
verificationDocument.IDVDODVDD AS VerificationDocumentLinkTypeId,
|
||
verificationDocument.NNDMS AS VerificationDocumentNumber,
|
||
verificationDocument.DTDMS AS VerificationDocumentDate,
|
||
m.PRCHNPGDN AS RejectionReason,
|
||
m.DSEKZMK AS Notes
|
||
FROM dbo.EKZMK m
|
||
JOIN dbo.EKZ z ON z.IDEKZ = m.IDEKZ
|
||
LEFT JOIN dbo.FRPD ownerOrg ON ownerOrg.IDFRPD = z.IDFRPDV
|
||
LEFT JOIN dbo.TPRZ sizeInfo ON sizeInfo.IDTPRZ = z.IDTPRZ
|
||
LEFT JOIN dbo.TIPS tips ON tips.IDTIPS = sizeInfo.IDTIPS
|
||
LEFT JOIN dbo.SPNMTP names ON names.IDSPNMTP = tips.IDSPNMTP
|
||
LEFT JOIN dbo.SPOI areas ON areas.IDSPOI = tips.IDSPOI
|
||
LEFT JOIN dbo.SPVDMK verificationType ON verificationType.IDSPVDMK = m.IDSPVDMK
|
||
LEFT JOIN dbo.PRSN verifier ON verifier.IDPRSN = m.IDPRSN
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
d.IDFRDMS,
|
||
d.IDVDODVDD,
|
||
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.NNZVPV = @DocumentNumber
|
||
ORDER BY areas.NMOI, names.NMTP, tips.TP, z.NNZV;";
|
||
|
||
var lines = new List<PsvDocumentLine>();
|
||
|
||
using (var connection = CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
lines.Add(new PsvDocumentLine
|
||
{
|
||
CardId = GetInt32(reader, "CardId"),
|
||
InstrumentId = GetInt32(reader, "InstrumentId"),
|
||
TypeSizeId = GetInt32(reader, "TypeSizeId"),
|
||
SerialNumber = GetString(reader, "SerialNumber"),
|
||
InventoryNumber = GetString(reader, "InventoryNumber"),
|
||
CustomerName = GetString(reader, "CustomerName"),
|
||
InstrumentType = GetString(reader, "InstrumentType"),
|
||
InstrumentName = GetString(reader, "InstrumentName"),
|
||
MeasurementArea = GetString(reader, "MeasurementArea"),
|
||
RangeText = GetString(reader, "RangeText"),
|
||
RegistryNumber = GetString(reader, "RegistryNumber"),
|
||
AccuracyText = GetString(reader, "AccuracyText"),
|
||
VerificationType = GetString(reader, "VerificationType"),
|
||
PeriodMonths = GetInt32(reader, "PeriodMonths"),
|
||
AcceptedOn = GetNullableDateTime(reader, "AcceptedOn"),
|
||
IssuedOn = GetNullableDateTime(reader, "IssuedOn"),
|
||
IsPassed = GetNullableBoolean(reader, "IsPassed"),
|
||
VerificationPerformedOn = GetNullableDateTime(reader, "VerificationPerformedOn"),
|
||
VerifierId = GetNullableInt32(reader, "VerifierId"),
|
||
VerifierName = GetString(reader, "VerifierName"),
|
||
StickerNumber = GetString(reader, "StickerNumber"),
|
||
VerificationDocumentFormId = GetNullableInt32(reader, "VerificationDocumentFormId"),
|
||
VerificationDocumentLinkTypeId = GetNullableInt32(reader, "VerificationDocumentLinkTypeId"),
|
||
VerificationDocumentNumber = GetString(reader, "VerificationDocumentNumber"),
|
||
VerificationDocumentDate = GetNullableDateTime(reader, "VerificationDocumentDate"),
|
||
RejectionReason = GetString(reader, "RejectionReason"),
|
||
Notes = GetString(reader, "Notes"),
|
||
IsPendingInsert = false
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
return lines;
|
||
}
|
||
|
||
public async Task<IReadOnlyList<PsvDocumentLine>> LoadDocumentLinesAsync(string documentNumber, CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
m.IDEKZMK AS CardId,
|
||
z.IDEKZ AS InstrumentId,
|
||
z.IDTPRZ AS TypeSizeId,
|
||
z.NNZV AS SerialNumber,
|
||
z.NNIN AS InventoryNumber,
|
||
ownerOrg.NMFRPD AS CustomerName,
|
||
tips.TP AS InstrumentType,
|
||
names.NMTP AS InstrumentName,
|
||
areas.NMOI AS MeasurementArea,
|
||
sizeInfo.DPZN AS RangeText,
|
||
sizeInfo.NNGSRS AS RegistryNumber,
|
||
sizeInfo.HRTC AS AccuracyText,
|
||
verificationType.NMVDMK AS VerificationType,
|
||
m.PRMK AS PeriodMonths,
|
||
m.DTPRM AS AcceptedOn,
|
||
m.DTVDM AS IssuedOn,
|
||
m.GDN AS IsPassed,
|
||
m.DTMKFK AS VerificationPerformedOn,
|
||
m.IDPRSN AS VerifierId,
|
||
verifier.PRFIO AS VerifierName,
|
||
m.NNNKL AS StickerNumber,
|
||
verificationDocument.IDFRDMS AS VerificationDocumentFormId,
|
||
verificationDocument.IDVDODVDD AS VerificationDocumentLinkTypeId,
|
||
verificationDocument.NNDMS AS VerificationDocumentNumber,
|
||
verificationDocument.DTDMS AS VerificationDocumentDate,
|
||
m.PRCHNPGDN AS RejectionReason,
|
||
m.DSEKZMK AS Notes
|
||
FROM dbo.EKZMK m
|
||
JOIN dbo.EKZ z ON z.IDEKZ = m.IDEKZ
|
||
LEFT JOIN dbo.FRPD ownerOrg ON ownerOrg.IDFRPD = z.IDFRPDV
|
||
LEFT JOIN dbo.TPRZ sizeInfo ON sizeInfo.IDTPRZ = z.IDTPRZ
|
||
LEFT JOIN dbo.TIPS tips ON tips.IDTIPS = sizeInfo.IDTIPS
|
||
LEFT JOIN dbo.SPNMTP names ON names.IDSPNMTP = tips.IDSPNMTP
|
||
LEFT JOIN dbo.SPOI areas ON areas.IDSPOI = tips.IDSPOI
|
||
LEFT JOIN dbo.SPVDMK verificationType ON verificationType.IDSPVDMK = m.IDSPVDMK
|
||
LEFT JOIN dbo.PRSN verifier ON verifier.IDPRSN = m.IDPRSN
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
d.IDFRDMS,
|
||
d.IDVDODVDD,
|
||
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.NNZVPV = @DocumentNumber
|
||
ORDER BY areas.NMOI, names.NMTP, tips.TP, z.NNZV;";
|
||
|
||
var lines = await SqlServerConnectionFactory.Current.QueryOpenConnectionAsync(
|
||
sql,
|
||
delegate(SqlDataReader reader)
|
||
{
|
||
return new PsvDocumentLine
|
||
{
|
||
CardId = GetInt32(reader, "CardId"),
|
||
InstrumentId = GetInt32(reader, "InstrumentId"),
|
||
TypeSizeId = GetInt32(reader, "TypeSizeId"),
|
||
SerialNumber = GetString(reader, "SerialNumber"),
|
||
InventoryNumber = GetString(reader, "InventoryNumber"),
|
||
CustomerName = GetString(reader, "CustomerName"),
|
||
InstrumentType = GetString(reader, "InstrumentType"),
|
||
InstrumentName = GetString(reader, "InstrumentName"),
|
||
MeasurementArea = GetString(reader, "MeasurementArea"),
|
||
RangeText = GetString(reader, "RangeText"),
|
||
RegistryNumber = GetString(reader, "RegistryNumber"),
|
||
AccuracyText = GetString(reader, "AccuracyText"),
|
||
VerificationType = GetString(reader, "VerificationType"),
|
||
PeriodMonths = GetInt32(reader, "PeriodMonths"),
|
||
AcceptedOn = GetNullableDateTime(reader, "AcceptedOn"),
|
||
IssuedOn = GetNullableDateTime(reader, "IssuedOn"),
|
||
IsPassed = GetNullableBoolean(reader, "IsPassed"),
|
||
VerificationPerformedOn = GetNullableDateTime(reader, "VerificationPerformedOn"),
|
||
VerifierId = GetNullableInt32(reader, "VerifierId"),
|
||
VerifierName = GetString(reader, "VerifierName"),
|
||
StickerNumber = GetString(reader, "StickerNumber"),
|
||
VerificationDocumentFormId = GetNullableInt32(reader, "VerificationDocumentFormId"),
|
||
VerificationDocumentLinkTypeId = GetNullableInt32(reader, "VerificationDocumentLinkTypeId"),
|
||
VerificationDocumentNumber = GetString(reader, "VerificationDocumentNumber"),
|
||
VerificationDocumentDate = GetNullableDateTime(reader, "VerificationDocumentDate"),
|
||
RejectionReason = GetString(reader, "RejectionReason"),
|
||
Notes = GetString(reader, "Notes"),
|
||
IsPendingInsert = false
|
||
};
|
||
},
|
||
delegate(SqlCommand command)
|
||
{
|
||
ConfigureCommandTimeout(command);
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
},
|
||
cancellationToken).ConfigureAwait(false);
|
||
|
||
return lines;
|
||
}
|
||
|
||
public IReadOnlyList<AvailableInstrumentItem> LoadCustomerInstruments(int customerId)
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
z.IDEKZ AS InstrumentId,
|
||
z.IDTPRZ AS TypeSizeId,
|
||
z.NNZV AS SerialNumber,
|
||
z.NNIN AS InventoryNumber,
|
||
ownerOrg.NMFRPD AS CustomerName,
|
||
tips.TP AS InstrumentType,
|
||
names.NMTP AS InstrumentName,
|
||
areas.NMOI AS MeasurementArea,
|
||
sizeInfo.NNGSRS AS RegistryNumber,
|
||
sizeInfo.DPZN AS RangeText,
|
||
sizeInfo.HRTC AS AccuracyText,
|
||
CASE
|
||
WHEN instrumentTemplate.LastDocumentNumber IS NOT NULL
|
||
OR typeTemplate.LastDocumentNumber IS NOT NULL
|
||
OR COALESCE(periodByInstrument.PRMK, periodByType.PRMK, tips.PRMKGR) IS NOT NULL
|
||
THEN CAST(1 AS bit)
|
||
ELSE CAST(0 AS bit)
|
||
END AS HasTemplate,
|
||
COALESCE(instrumentTemplate.LastDocumentNumber, typeTemplate.LastDocumentNumber) AS LastDocumentNumber,
|
||
COALESCE(instrumentTemplate.LastAcceptedOn, typeTemplate.LastAcceptedOn) AS LastAcceptedOn,
|
||
CASE
|
||
WHEN instrumentTemplate.LastDocumentNumber IS NOT NULL THEN N'Рстория РїСЂРёР±РѕСЂР°'
|
||
WHEN typeTemplate.LastDocumentNumber IS NOT NULL THEN N'Шаблон по типоразмеру'
|
||
WHEN COALESCE(periodByInstrument.PRMK, periodByType.PRMK) IS NOT NULL THEN N'Период из TPRMCP'
|
||
WHEN tips.PRMKGR IS NOT NULL THEN N'Регистрационный период из TIPS'
|
||
ELSE N''
|
||
END AS TemplateSource
|
||
FROM dbo.EKZ z
|
||
LEFT JOIN dbo.FRPD ownerOrg ON ownerOrg.IDFRPD = z.IDFRPDV
|
||
LEFT JOIN dbo.TPRZ sizeInfo ON sizeInfo.IDTPRZ = z.IDTPRZ
|
||
LEFT JOIN dbo.TIPS tips ON tips.IDTIPS = sizeInfo.IDTIPS
|
||
LEFT JOIN dbo.SPNMTP names ON names.IDSPNMTP = tips.IDSPNMTP
|
||
LEFT JOIN dbo.SPOI areas ON areas.IDSPOI = tips.IDSPOI
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
history.NNZVPV AS LastDocumentNumber,
|
||
history.DTPRM AS LastAcceptedOn
|
||
FROM dbo.EKZMK history
|
||
WHERE history.IDEKZ = z.IDEKZ
|
||
ORDER BY ISNULL(history.DTPRM, CONVERT(datetime, '19000101', 112)) DESC, history.IDEKZMK DESC
|
||
) instrumentTemplate
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
history.NNZVPV AS LastDocumentNumber,
|
||
history.DTPRM AS LastAcceptedOn
|
||
FROM dbo.EKZMK history
|
||
JOIN dbo.EKZ instrumentOfSameType ON instrumentOfSameType.IDEKZ = history.IDEKZ
|
||
WHERE instrumentOfSameType.IDTPRZ = z.IDTPRZ
|
||
ORDER BY ISNULL(history.DTPRM, CONVERT(datetime, '19000101', 112)) DESC, history.IDEKZMK DESC
|
||
) typeTemplate
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
t.PRMK
|
||
FROM dbo.EKZMCP e
|
||
JOIN dbo.TPRMCP t ON t.IDTPRMCP = e.IDTPRMCP
|
||
WHERE e.IDEKZ = z.IDEKZ
|
||
ORDER BY e.IDEKZMCP DESC, t.IDTPRMCP DESC
|
||
) periodByInstrument
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
t.PRMK
|
||
FROM dbo.TPRMCP t
|
||
WHERE t.IDTPRZ = z.IDTPRZ
|
||
ORDER BY t.IDTPRMCP DESC
|
||
) periodByType
|
||
WHERE z.IDFRPDV = @CustomerId
|
||
ORDER BY names.NMTP, tips.TP, sizeInfo.DPZN, z.NNZV;";
|
||
|
||
var instruments = new List<AvailableInstrumentItem>();
|
||
|
||
using (var connection = CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@CustomerId", SqlDbType.Int).Value = customerId;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
instruments.Add(new AvailableInstrumentItem
|
||
{
|
||
InstrumentId = GetInt32(reader, "InstrumentId"),
|
||
TypeSizeId = GetInt32(reader, "TypeSizeId"),
|
||
SerialNumber = GetString(reader, "SerialNumber"),
|
||
InventoryNumber = GetString(reader, "InventoryNumber"),
|
||
CustomerName = GetString(reader, "CustomerName"),
|
||
InstrumentType = GetString(reader, "InstrumentType"),
|
||
InstrumentName = GetString(reader, "InstrumentName"),
|
||
MeasurementArea = GetString(reader, "MeasurementArea"),
|
||
RegistryNumber = GetString(reader, "RegistryNumber"),
|
||
RangeText = GetString(reader, "RangeText"),
|
||
AccuracyText = GetString(reader, "AccuracyText"),
|
||
HasTemplate = GetBoolean(reader, "HasTemplate"),
|
||
LastDocumentNumber = GetString(reader, "LastDocumentNumber"),
|
||
LastAcceptedOn = GetNullableDateTime(reader, "LastAcceptedOn"),
|
||
TemplateSource = GetString(reader, "TemplateSource")
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
return instruments;
|
||
}
|
||
|
||
public Task<IReadOnlyList<AvailableInstrumentItem>> LoadCustomerInstrumentsAsync(int customerId, CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
z.IDEKZ AS InstrumentId,
|
||
z.IDTPRZ AS TypeSizeId,
|
||
z.NNZV AS SerialNumber,
|
||
z.NNIN AS InventoryNumber,
|
||
ownerOrg.NMFRPD AS CustomerName,
|
||
tips.TP AS InstrumentType,
|
||
names.NMTP AS InstrumentName,
|
||
areas.NMOI AS MeasurementArea,
|
||
sizeInfo.NNGSRS AS RegistryNumber,
|
||
sizeInfo.DPZN AS RangeText,
|
||
sizeInfo.HRTC AS AccuracyText,
|
||
CASE
|
||
WHEN instrumentTemplate.LastDocumentNumber IS NOT NULL
|
||
OR typeTemplate.LastDocumentNumber IS NOT NULL
|
||
OR COALESCE(periodByInstrument.PRMK, periodByType.PRMK, tips.PRMKGR) IS NOT NULL
|
||
THEN CAST(1 AS bit)
|
||
ELSE CAST(0 AS bit)
|
||
END AS HasTemplate,
|
||
COALESCE(instrumentTemplate.LastDocumentNumber, typeTemplate.LastDocumentNumber) AS LastDocumentNumber,
|
||
COALESCE(instrumentTemplate.LastAcceptedOn, typeTemplate.LastAcceptedOn) AS LastAcceptedOn,
|
||
CASE
|
||
WHEN instrumentTemplate.LastDocumentNumber IS NOT NULL THEN N'История прибора'
|
||
WHEN typeTemplate.LastDocumentNumber IS NOT NULL THEN N'Шаблон по типоразмеру'
|
||
WHEN COALESCE(periodByInstrument.PRMK, periodByType.PRMK) IS NOT NULL THEN N'Период из TPRMCP'
|
||
WHEN tips.PRMKGR IS NOT NULL THEN N'Регистрационный период из TIPS'
|
||
ELSE N''
|
||
END AS TemplateSource
|
||
FROM dbo.EKZ z
|
||
LEFT JOIN dbo.FRPD ownerOrg ON ownerOrg.IDFRPD = z.IDFRPDV
|
||
LEFT JOIN dbo.TPRZ sizeInfo ON sizeInfo.IDTPRZ = z.IDTPRZ
|
||
LEFT JOIN dbo.TIPS tips ON tips.IDTIPS = sizeInfo.IDTIPS
|
||
LEFT JOIN dbo.SPNMTP names ON names.IDSPNMTP = tips.IDSPNMTP
|
||
LEFT JOIN dbo.SPOI areas ON areas.IDSPOI = tips.IDSPOI
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
history.NNZVPV AS LastDocumentNumber,
|
||
history.DTPRM AS LastAcceptedOn
|
||
FROM dbo.EKZMK history
|
||
WHERE history.IDEKZ = z.IDEKZ
|
||
ORDER BY ISNULL(history.DTPRM, CONVERT(datetime, '19000101', 112)) DESC, history.IDEKZMK DESC
|
||
) instrumentTemplate
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
history.NNZVPV AS LastDocumentNumber,
|
||
history.DTPRM AS LastAcceptedOn
|
||
FROM dbo.EKZMK history
|
||
JOIN dbo.EKZ instrumentOfSameType ON instrumentOfSameType.IDEKZ = history.IDEKZ
|
||
WHERE instrumentOfSameType.IDTPRZ = z.IDTPRZ
|
||
ORDER BY ISNULL(history.DTPRM, CONVERT(datetime, '19000101', 112)) DESC, history.IDEKZMK DESC
|
||
) typeTemplate
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
t.PRMK
|
||
FROM dbo.EKZMCP e
|
||
JOIN dbo.TPRMCP t ON t.IDTPRMCP = e.IDTPRMCP
|
||
WHERE e.IDEKZ = z.IDEKZ
|
||
ORDER BY e.IDEKZMCP DESC, t.IDTPRMCP DESC
|
||
) periodByInstrument
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
t.PRMK
|
||
FROM dbo.TPRMCP t
|
||
WHERE t.IDTPRZ = z.IDTPRZ
|
||
ORDER BY t.IDTPRMCP DESC
|
||
) periodByType
|
||
WHERE z.IDFRPDV = @CustomerId
|
||
ORDER BY names.NMTP, tips.TP, sizeInfo.DPZN, z.NNZV;";
|
||
|
||
return SqlServerConnectionFactory.Current.QueryOpenConnectionAsync(
|
||
sql,
|
||
delegate(SqlDataReader reader)
|
||
{
|
||
return new AvailableInstrumentItem
|
||
{
|
||
InstrumentId = GetInt32(reader, "InstrumentId"),
|
||
TypeSizeId = GetInt32(reader, "TypeSizeId"),
|
||
SerialNumber = GetString(reader, "SerialNumber"),
|
||
InventoryNumber = GetString(reader, "InventoryNumber"),
|
||
CustomerName = GetString(reader, "CustomerName"),
|
||
InstrumentType = GetString(reader, "InstrumentType"),
|
||
InstrumentName = GetString(reader, "InstrumentName"),
|
||
MeasurementArea = GetString(reader, "MeasurementArea"),
|
||
RegistryNumber = GetString(reader, "RegistryNumber"),
|
||
RangeText = GetString(reader, "RangeText"),
|
||
AccuracyText = GetString(reader, "AccuracyText"),
|
||
HasTemplate = GetBoolean(reader, "HasTemplate"),
|
||
LastDocumentNumber = GetString(reader, "LastDocumentNumber"),
|
||
LastAcceptedOn = GetNullableDateTime(reader, "LastAcceptedOn"),
|
||
TemplateSource = GetString(reader, "TemplateSource")
|
||
};
|
||
},
|
||
delegate(SqlCommand command)
|
||
{
|
||
ConfigureCommandTimeout(command);
|
||
command.Parameters.Add("@CustomerId", SqlDbType.Int).Value = customerId;
|
||
},
|
||
cancellationToken).ContinueWith<IReadOnlyList<AvailableInstrumentItem>>(delegate(Task<List<AvailableInstrumentItem>> task)
|
||
{
|
||
return task.Result;
|
||
}, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
|
||
}
|
||
|
||
public IReadOnlyList<AvailableInstrumentItem> LoadInstrumentTypes()
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
0 AS InstrumentId,
|
||
sizeInfo.IDTPRZ AS TypeSizeId,
|
||
CAST(N'' AS nvarchar(30)) AS SerialNumber,
|
||
CAST(N'' AS nvarchar(30)) AS InventoryNumber,
|
||
CAST(N'' AS nvarchar(255)) AS CustomerName,
|
||
tips.TP AS InstrumentType,
|
||
names.NMTP AS InstrumentName,
|
||
areas.NMOI AS MeasurementArea,
|
||
sizeInfo.NNGSRS AS RegistryNumber,
|
||
sizeInfo.DPZN AS RangeText,
|
||
sizeInfo.HRTC AS AccuracyText,
|
||
CASE
|
||
WHEN typeTemplate.LastDocumentNumber IS NOT NULL
|
||
OR periodByType.PRMK IS NOT NULL
|
||
OR tips.PRMKGR IS NOT NULL
|
||
THEN CAST(1 AS bit)
|
||
ELSE CAST(0 AS bit)
|
||
END AS HasTemplate,
|
||
typeTemplate.LastDocumentNumber AS LastDocumentNumber,
|
||
typeTemplate.LastAcceptedOn AS LastAcceptedOn,
|
||
CASE
|
||
WHEN typeTemplate.LastDocumentNumber IS NOT NULL THEN N'Шаблон по типоразмеру'
|
||
WHEN periodByType.PRMK IS NOT NULL THEN N'Период из TPRMCP'
|
||
WHEN tips.PRMKGR IS NOT NULL THEN N'Регистрационный период из TIPS'
|
||
ELSE N''
|
||
END AS TemplateSource
|
||
FROM dbo.TPRZ sizeInfo
|
||
LEFT JOIN dbo.TIPS tips ON tips.IDTIPS = sizeInfo.IDTIPS
|
||
LEFT JOIN dbo.SPNMTP names ON names.IDSPNMTP = tips.IDSPNMTP
|
||
LEFT JOIN dbo.SPOI areas ON areas.IDSPOI = tips.IDSPOI
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
history.NNZVPV AS LastDocumentNumber,
|
||
history.DTPRM AS LastAcceptedOn
|
||
FROM dbo.EKZMK history
|
||
JOIN dbo.EKZ instrumentOfSameType ON instrumentOfSameType.IDEKZ = history.IDEKZ
|
||
WHERE instrumentOfSameType.IDTPRZ = sizeInfo.IDTPRZ
|
||
ORDER BY ISNULL(history.DTPRM, CONVERT(datetime, '19000101', 112)) DESC, history.IDEKZMK DESC
|
||
) typeTemplate
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
t.PRMK
|
||
FROM dbo.TPRMCP t
|
||
WHERE t.IDTPRZ = sizeInfo.IDTPRZ
|
||
ORDER BY t.IDTPRMCP DESC
|
||
) periodByType
|
||
ORDER BY names.NMTP, tips.TP, sizeInfo.DPZN, sizeInfo.NNGSRS;";
|
||
|
||
var instrumentTypes = new List<AvailableInstrumentItem>();
|
||
|
||
using (var connection = CreateConnection())
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
connection.Open();
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
instrumentTypes.Add(new AvailableInstrumentItem
|
||
{
|
||
InstrumentId = GetInt32(reader, "InstrumentId"),
|
||
TypeSizeId = GetInt32(reader, "TypeSizeId"),
|
||
SerialNumber = GetString(reader, "SerialNumber"),
|
||
InventoryNumber = GetString(reader, "InventoryNumber"),
|
||
CustomerName = GetString(reader, "CustomerName"),
|
||
InstrumentType = GetString(reader, "InstrumentType"),
|
||
InstrumentName = GetString(reader, "InstrumentName"),
|
||
MeasurementArea = GetString(reader, "MeasurementArea"),
|
||
RegistryNumber = GetString(reader, "RegistryNumber"),
|
||
RangeText = GetString(reader, "RangeText"),
|
||
AccuracyText = GetString(reader, "AccuracyText"),
|
||
HasTemplate = GetBoolean(reader, "HasTemplate"),
|
||
LastDocumentNumber = GetString(reader, "LastDocumentNumber"),
|
||
LastAcceptedOn = GetNullableDateTime(reader, "LastAcceptedOn"),
|
||
TemplateSource = GetString(reader, "TemplateSource")
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
return instrumentTypes;
|
||
}
|
||
|
||
public Task<IReadOnlyList<AvailableInstrumentItem>> LoadInstrumentTypesAsync(CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
0 AS InstrumentId,
|
||
sizeInfo.IDTPRZ AS TypeSizeId,
|
||
CAST(N'' AS nvarchar(30)) AS SerialNumber,
|
||
CAST(N'' AS nvarchar(30)) AS InventoryNumber,
|
||
CAST(N'' AS nvarchar(255)) AS CustomerName,
|
||
tips.TP AS InstrumentType,
|
||
names.NMTP AS InstrumentName,
|
||
areas.NMOI AS MeasurementArea,
|
||
sizeInfo.NNGSRS AS RegistryNumber,
|
||
sizeInfo.DPZN AS RangeText,
|
||
sizeInfo.HRTC AS AccuracyText,
|
||
CASE
|
||
WHEN typeTemplate.LastDocumentNumber IS NOT NULL
|
||
OR periodByType.PRMK IS NOT NULL
|
||
OR tips.PRMKGR IS NOT NULL
|
||
THEN CAST(1 AS bit)
|
||
ELSE CAST(0 AS bit)
|
||
END AS HasTemplate,
|
||
typeTemplate.LastDocumentNumber AS LastDocumentNumber,
|
||
typeTemplate.LastAcceptedOn AS LastAcceptedOn,
|
||
CASE
|
||
WHEN typeTemplate.LastDocumentNumber IS NOT NULL THEN N'Шаблон по типоразмеру'
|
||
WHEN periodByType.PRMK IS NOT NULL THEN N'Период из TPRMCP'
|
||
WHEN tips.PRMKGR IS NOT NULL THEN N'Регистрационный период из TIPS'
|
||
ELSE N''
|
||
END AS TemplateSource
|
||
FROM dbo.TPRZ sizeInfo
|
||
LEFT JOIN dbo.TIPS tips ON tips.IDTIPS = sizeInfo.IDTIPS
|
||
LEFT JOIN dbo.SPNMTP names ON names.IDSPNMTP = tips.IDSPNMTP
|
||
LEFT JOIN dbo.SPOI areas ON areas.IDSPOI = tips.IDSPOI
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
history.NNZVPV AS LastDocumentNumber,
|
||
history.DTPRM AS LastAcceptedOn
|
||
FROM dbo.EKZMK history
|
||
JOIN dbo.EKZ instrumentOfSameType ON instrumentOfSameType.IDEKZ = history.IDEKZ
|
||
WHERE instrumentOfSameType.IDTPRZ = sizeInfo.IDTPRZ
|
||
ORDER BY ISNULL(history.DTPRM, CONVERT(datetime, '19000101', 112)) DESC, history.IDEKZMK DESC
|
||
) typeTemplate
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
t.PRMK
|
||
FROM dbo.TPRMCP t
|
||
WHERE t.IDTPRZ = sizeInfo.IDTPRZ
|
||
ORDER BY t.IDTPRMCP DESC
|
||
) periodByType
|
||
ORDER BY names.NMTP, tips.TP, sizeInfo.DPZN, sizeInfo.NNGSRS;";
|
||
|
||
return SqlServerConnectionFactory.Current.QueryOpenConnectionAsync(
|
||
sql,
|
||
delegate(SqlDataReader reader)
|
||
{
|
||
return new AvailableInstrumentItem
|
||
{
|
||
InstrumentId = GetInt32(reader, "InstrumentId"),
|
||
TypeSizeId = GetInt32(reader, "TypeSizeId"),
|
||
SerialNumber = GetString(reader, "SerialNumber"),
|
||
InventoryNumber = GetString(reader, "InventoryNumber"),
|
||
CustomerName = GetString(reader, "CustomerName"),
|
||
InstrumentType = GetString(reader, "InstrumentType"),
|
||
InstrumentName = GetString(reader, "InstrumentName"),
|
||
MeasurementArea = GetString(reader, "MeasurementArea"),
|
||
RegistryNumber = GetString(reader, "RegistryNumber"),
|
||
RangeText = GetString(reader, "RangeText"),
|
||
AccuracyText = GetString(reader, "AccuracyText"),
|
||
HasTemplate = GetBoolean(reader, "HasTemplate"),
|
||
LastDocumentNumber = GetString(reader, "LastDocumentNumber"),
|
||
LastAcceptedOn = GetNullableDateTime(reader, "LastAcceptedOn"),
|
||
TemplateSource = GetString(reader, "TemplateSource")
|
||
};
|
||
},
|
||
ConfigureCommandTimeout,
|
||
cancellationToken).ContinueWith<IReadOnlyList<AvailableInstrumentItem>>(delegate(Task<List<AvailableInstrumentItem>> task)
|
||
{
|
||
return task.Result;
|
||
}, cancellationToken, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
|
||
}
|
||
|
||
public IReadOnlyList<OpenDocumentConflictInfo> FindOpenDocumentConflicts(int customerId, string currentDocumentNumber, IEnumerable<PsvDocumentLine> candidateLines)
|
||
{
|
||
if (customerId <= 0 || candidateLines == null)
|
||
{
|
||
return new List<OpenDocumentConflictInfo>();
|
||
}
|
||
|
||
using (var connection = CreateConnection())
|
||
{
|
||
connection.Open();
|
||
return LoadOpenDocumentConflicts(connection, null, customerId, currentDocumentNumber, candidateLines);
|
||
}
|
||
}
|
||
|
||
public void ResetLineVerification(int cardId)
|
||
{
|
||
if (cardId <= 0)
|
||
{
|
||
throw new InvalidOperationException("Не выбрана строка EKZMK для отмены проверки.");
|
||
}
|
||
|
||
using (var connection = CreateConnection())
|
||
{
|
||
connection.Open();
|
||
|
||
using (var transaction = connection.BeginTransaction())
|
||
{
|
||
ClearLineVerificationCore(connection, transaction, cardId);
|
||
DeleteVerificationDocuments(connection, transaction, cardId);
|
||
transaction.Commit();
|
||
}
|
||
}
|
||
}
|
||
|
||
public async Task ResetLineVerificationAsync(int cardId, CancellationToken cancellationToken = default)
|
||
{
|
||
if (cardId <= 0)
|
||
{
|
||
throw new InvalidOperationException("Не выбрана строка EKZMK для отмены поверки.");
|
||
}
|
||
|
||
await using (var connection = await SqlServerConnectionFactory.Current.OpenConnectionAsync(cancellationToken).ConfigureAwait(false))
|
||
using (var transaction = (SqlTransaction)await connection.BeginTransactionAsync(cancellationToken).ConfigureAwait(false))
|
||
{
|
||
await ClearLineVerificationCoreAsync(connection, transaction, cardId, cancellationToken).ConfigureAwait(false);
|
||
await DeleteVerificationDocumentsAsync(connection, transaction, cardId, cancellationToken).ConfigureAwait(false);
|
||
await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
|
||
}
|
||
}
|
||
|
||
public void SaveLineVerification(int cardId, VerificationEditResult result)
|
||
{
|
||
if (cardId <= 0)
|
||
{
|
||
throw new InvalidOperationException("Не выбрана строка EKZMK для сохранения результата поверки.");
|
||
}
|
||
|
||
if (result == null)
|
||
{
|
||
throw new ArgumentNullException("result");
|
||
}
|
||
|
||
using (var connection = CreateConnection())
|
||
{
|
||
connection.Open();
|
||
|
||
using (var transaction = connection.BeginTransaction())
|
||
{
|
||
SaveLineVerificationCore(connection, transaction, cardId, result);
|
||
DeleteVerificationDocuments(connection, transaction, cardId);
|
||
|
||
if (!string.IsNullOrWhiteSpace(result.VerificationDocumentNumber))
|
||
{
|
||
if (result.DocumentFormId <= 0 || result.DocumentLinkTypeId <= 0)
|
||
{
|
||
throw new InvalidOperationException("Для документа поверки не определена форма или связь с объектом.");
|
||
}
|
||
|
||
InsertVerificationDocument(
|
||
connection,
|
||
transaction,
|
||
cardId,
|
||
result.DocumentLinkTypeId,
|
||
result.DocumentFormId,
|
||
result.VerificationDocumentNumber,
|
||
result.VerificationDate);
|
||
}
|
||
|
||
transaction.Commit();
|
||
}
|
||
}
|
||
}
|
||
|
||
public async Task SaveLineVerificationAsync(int cardId, VerificationEditResult result, CancellationToken cancellationToken = default)
|
||
{
|
||
if (cardId <= 0)
|
||
{
|
||
throw new InvalidOperationException("Не выбрана строка EKZMK для сохранения результата поверки.");
|
||
}
|
||
|
||
if (result == null)
|
||
{
|
||
throw new ArgumentNullException("result");
|
||
}
|
||
|
||
await using (var connection = await SqlServerConnectionFactory.Current.OpenConnectionAsync(cancellationToken).ConfigureAwait(false))
|
||
using (var transaction = (SqlTransaction)await connection.BeginTransactionAsync(cancellationToken).ConfigureAwait(false))
|
||
{
|
||
await SaveLineVerificationCoreAsync(connection, transaction, cardId, result, cancellationToken).ConfigureAwait(false);
|
||
await DeleteVerificationDocumentsAsync(connection, transaction, cardId, cancellationToken).ConfigureAwait(false);
|
||
|
||
if (!string.IsNullOrWhiteSpace(result.VerificationDocumentNumber))
|
||
{
|
||
if (result.DocumentFormId <= 0 || result.DocumentLinkTypeId <= 0)
|
||
{
|
||
throw new InvalidOperationException("Для документа поверки не определена форма или связь с объектом.");
|
||
}
|
||
|
||
await InsertVerificationDocumentAsync(
|
||
connection,
|
||
transaction,
|
||
cardId,
|
||
result.DocumentLinkTypeId,
|
||
result.DocumentFormId,
|
||
result.VerificationDocumentNumber,
|
||
result.VerificationDate,
|
||
cancellationToken).ConfigureAwait(false);
|
||
}
|
||
|
||
await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
|
||
}
|
||
}
|
||
|
||
public void ResetLineVerification(IEnumerable<int> cardIds)
|
||
{
|
||
var normalizedCardIds = NormalizeCardIds(
|
||
cardIds,
|
||
"Не выбрана строка EKZMK для отмены поверки.",
|
||
"Не выбрано ни одной строки EKZMK для отмены поверки.");
|
||
|
||
using (var connection = CreateConnection())
|
||
{
|
||
connection.Open();
|
||
|
||
using (var transaction = connection.BeginTransaction())
|
||
{
|
||
foreach (var cardId in normalizedCardIds)
|
||
{
|
||
ClearLineVerificationCore(connection, transaction, cardId);
|
||
DeleteVerificationDocuments(connection, transaction, cardId);
|
||
}
|
||
|
||
transaction.Commit();
|
||
}
|
||
}
|
||
}
|
||
|
||
public async Task ResetLineVerificationAsync(IEnumerable<int> cardIds, CancellationToken cancellationToken = default)
|
||
{
|
||
var normalizedCardIds = NormalizeCardIds(
|
||
cardIds,
|
||
"Не выбрана строка EKZMK для отмены поверки.",
|
||
"Не выбрано ни одной строки EKZMK для отмены поверки.");
|
||
|
||
await using (var connection = await SqlServerConnectionFactory.Current.OpenConnectionAsync(cancellationToken).ConfigureAwait(false))
|
||
using (var transaction = (SqlTransaction)await connection.BeginTransactionAsync(cancellationToken).ConfigureAwait(false))
|
||
{
|
||
foreach (var cardId in normalizedCardIds)
|
||
{
|
||
await ClearLineVerificationCoreAsync(connection, transaction, cardId, cancellationToken).ConfigureAwait(false);
|
||
await DeleteVerificationDocumentsAsync(connection, transaction, cardId, cancellationToken).ConfigureAwait(false);
|
||
}
|
||
|
||
await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
|
||
}
|
||
}
|
||
|
||
public void SaveLineVerification(IEnumerable<int> cardIds, VerificationEditResult result)
|
||
{
|
||
if (result == null)
|
||
{
|
||
throw new ArgumentNullException("result");
|
||
}
|
||
|
||
var normalizedCardIds = NormalizeCardIds(
|
||
cardIds,
|
||
"Не выбрана строка EKZMK для сохранения результата поверки.",
|
||
"Не выбрано ни одной строки EKZMK для сохранения результата поверки.");
|
||
|
||
using (var connection = CreateConnection())
|
||
{
|
||
connection.Open();
|
||
|
||
using (var transaction = connection.BeginTransaction())
|
||
{
|
||
foreach (var cardId in normalizedCardIds)
|
||
{
|
||
SaveLineVerificationCore(connection, transaction, cardId, result);
|
||
DeleteVerificationDocuments(connection, transaction, cardId);
|
||
|
||
if (!string.IsNullOrWhiteSpace(result.VerificationDocumentNumber))
|
||
{
|
||
if (result.DocumentFormId <= 0 || result.DocumentLinkTypeId <= 0)
|
||
{
|
||
throw new InvalidOperationException("Для документа поверки не определена форма или связь с объектом.");
|
||
}
|
||
|
||
InsertVerificationDocument(
|
||
connection,
|
||
transaction,
|
||
cardId,
|
||
result.DocumentLinkTypeId,
|
||
result.DocumentFormId,
|
||
result.VerificationDocumentNumber,
|
||
result.VerificationDate);
|
||
}
|
||
}
|
||
|
||
transaction.Commit();
|
||
}
|
||
}
|
||
}
|
||
|
||
public async Task SaveLineVerificationAsync(IEnumerable<int> cardIds, VerificationEditResult result, CancellationToken cancellationToken = default)
|
||
{
|
||
if (result == null)
|
||
{
|
||
throw new ArgumentNullException("result");
|
||
}
|
||
|
||
var normalizedCardIds = NormalizeCardIds(
|
||
cardIds,
|
||
"Не выбрана строка EKZMK для сохранения результата поверки.",
|
||
"Не выбрано ни одной строки EKZMK для сохранения результата поверки.");
|
||
|
||
await using (var connection = await SqlServerConnectionFactory.Current.OpenConnectionAsync(cancellationToken).ConfigureAwait(false))
|
||
using (var transaction = (SqlTransaction)await connection.BeginTransactionAsync(cancellationToken).ConfigureAwait(false))
|
||
{
|
||
foreach (var cardId in normalizedCardIds)
|
||
{
|
||
await SaveLineVerificationCoreAsync(connection, transaction, cardId, result, cancellationToken).ConfigureAwait(false);
|
||
await DeleteVerificationDocumentsAsync(connection, transaction, cardId, cancellationToken).ConfigureAwait(false);
|
||
|
||
if (!string.IsNullOrWhiteSpace(result.VerificationDocumentNumber))
|
||
{
|
||
if (result.DocumentFormId <= 0 || result.DocumentLinkTypeId <= 0)
|
||
{
|
||
throw new InvalidOperationException("Для документа поверки не определена форма или связь с объектом.");
|
||
}
|
||
|
||
await InsertVerificationDocumentAsync(
|
||
connection,
|
||
transaction,
|
||
cardId,
|
||
result.DocumentLinkTypeId,
|
||
result.DocumentFormId,
|
||
result.VerificationDocumentNumber,
|
||
result.VerificationDate,
|
||
cancellationToken).ConfigureAwait(false);
|
||
}
|
||
}
|
||
|
||
await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
|
||
}
|
||
}
|
||
|
||
public DocumentSaveResult SaveDocument(string currentDocumentNumber, DocumentEditorResult document, IEnumerable<PsvDocumentLine> pendingLines)
|
||
{
|
||
if (document == null)
|
||
{
|
||
throw new ArgumentNullException("document");
|
||
}
|
||
|
||
var normalizedNumber = NormalizeDocumentNumber(document.DocumentNumber);
|
||
if (normalizedNumber == null)
|
||
{
|
||
throw new InvalidOperationException("Номер ПСВ не заполнен.");
|
||
}
|
||
|
||
document.DocumentNumber = normalizedNumber;
|
||
|
||
var distinctPendingLines = pendingLines == null
|
||
? new List<PsvDocumentLine>()
|
||
: pendingLines
|
||
.Where(IsPendingLineReadyForSave)
|
||
.GroupBy(GetPendingLineSaveKey, StringComparer.OrdinalIgnoreCase)
|
||
.Select(delegate(IGrouping<string, PsvDocumentLine> group) { return group.First(); })
|
||
.ToList();
|
||
|
||
using (var connection = CreateConnection())
|
||
{
|
||
connection.Open();
|
||
|
||
using (var transaction = connection.BeginTransaction())
|
||
{
|
||
if (DocumentNumberExists(connection, transaction, normalizedNumber, currentDocumentNumber))
|
||
{
|
||
throw new InvalidOperationException(string.Format("ПСВ с номером \"{0}\" уже существует.", normalizedNumber));
|
||
}
|
||
|
||
if (document.CustomerId.HasValue)
|
||
{
|
||
var openDocumentConflicts = LoadOpenDocumentConflicts(
|
||
connection,
|
||
transaction,
|
||
document.CustomerId.Value,
|
||
currentDocumentNumber,
|
||
distinctPendingLines);
|
||
if (openDocumentConflicts.Count > 0)
|
||
{
|
||
throw new InvalidOperationException(BuildOpenDocumentConflictMessage(openDocumentConflicts));
|
||
}
|
||
}
|
||
|
||
var updatedEkzMkCount = 0;
|
||
if (!string.IsNullOrWhiteSpace(currentDocumentNumber))
|
||
{
|
||
updatedEkzMkCount = UpdateDocumentHeader(connection, transaction, currentDocumentNumber, document);
|
||
if (updatedEkzMkCount == 0)
|
||
{
|
||
throw new InvalidOperationException("Строки EKZMK для выбранного ПСВ не найдены.");
|
||
}
|
||
}
|
||
|
||
var insertedEkzMkCount = 0;
|
||
var skippedDuplicateCount = 0;
|
||
var skippedWithoutTemplateCount = 0;
|
||
var duplicateKeys = LoadDocumentDuplicateKeys(connection, transaction, normalizedNumber);
|
||
var verificationTypeId = 0;
|
||
var verificationTypeLoaded = false;
|
||
|
||
foreach (var pendingLine in distinctPendingLines)
|
||
{
|
||
var duplicateKey = pendingLine.DuplicateKey;
|
||
if (string.IsNullOrWhiteSpace(duplicateKey))
|
||
{
|
||
throw new InvalidOperationException("Не удалось определить ключ дубликата для строки ПСВ.");
|
||
}
|
||
|
||
var instrumentId = pendingLine.InstrumentId;
|
||
var instrumentIdentity = new InstrumentIdentityInfo
|
||
{
|
||
DuplicateKey = duplicateKey
|
||
};
|
||
if (string.IsNullOrWhiteSpace(duplicateKey))
|
||
{
|
||
throw new InvalidOperationException(string.Format("Прибор IDEKZ={0} не найден.", instrumentId));
|
||
}
|
||
|
||
if (duplicateKeys.Contains(instrumentIdentity.DuplicateKey))
|
||
{
|
||
skippedDuplicateCount++;
|
||
continue;
|
||
}
|
||
|
||
instrumentId = ResolveInstrumentIdForPendingLine(connection, transaction, document, pendingLine);
|
||
var template = LoadTemplate(connection, transaction, instrumentId);
|
||
if (template == null)
|
||
{
|
||
skippedWithoutTemplateCount++;
|
||
continue;
|
||
}
|
||
|
||
if (!verificationTypeLoaded)
|
||
{
|
||
verificationTypeId = LoadVerificationTypeId(connection, transaction);
|
||
verificationTypeLoaded = true;
|
||
}
|
||
|
||
var cardId = InsertEkzMk(connection, transaction, verificationTypeId, document, normalizedNumber, instrumentId, template, pendingLine);
|
||
if (!string.IsNullOrWhiteSpace(pendingLine.VerificationDocumentNumber))
|
||
{
|
||
if (!pendingLine.VerificationDocumentFormId.HasValue || !pendingLine.VerificationDocumentLinkTypeId.HasValue)
|
||
{
|
||
throw new InvalidOperationException("Для новой строки EKZMK не определена форма документа поверки.");
|
||
}
|
||
|
||
InsertVerificationDocument(
|
||
connection,
|
||
transaction,
|
||
cardId,
|
||
pendingLine.VerificationDocumentLinkTypeId.GetValueOrDefault(),
|
||
pendingLine.VerificationDocumentFormId.GetValueOrDefault(),
|
||
pendingLine.VerificationDocumentNumber,
|
||
pendingLine.VerificationDocumentDate ?? pendingLine.VerificationPerformedOn ?? document.AcceptedOn);
|
||
}
|
||
|
||
duplicateKeys.Add(instrumentIdentity.DuplicateKey);
|
||
insertedEkzMkCount++;
|
||
}
|
||
|
||
if (string.IsNullOrWhiteSpace(currentDocumentNumber) && insertedEkzMkCount == 0)
|
||
{
|
||
throw new InvalidOperationException("Черновик нельзя сохранить без строк EKZMK.");
|
||
}
|
||
|
||
transaction.Commit();
|
||
|
||
return new DocumentSaveResult
|
||
{
|
||
DocumentNumber = normalizedNumber,
|
||
InsertedEkzMkCount = insertedEkzMkCount,
|
||
SkippedDuplicateCount = skippedDuplicateCount,
|
||
SkippedWithoutTemplateCount = skippedWithoutTemplateCount,
|
||
UpdatedEkzMkCount = updatedEkzMkCount
|
||
};
|
||
}
|
||
}
|
||
}
|
||
|
||
public DocumentDeleteResult DeleteDocument(string documentNumber)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(documentNumber))
|
||
{
|
||
throw new InvalidOperationException("Не выбран документ для удаления.");
|
||
}
|
||
|
||
using (var connection = CreateConnection())
|
||
{
|
||
connection.Open();
|
||
|
||
using (var transaction = connection.BeginTransaction())
|
||
{
|
||
var blockers = LoadDeleteBlockers(connection, transaction, documentNumber);
|
||
if (blockers.Count > 0)
|
||
{
|
||
var details = string.Join(", ", blockers.Select(delegate(DeleteBlockerInfo blocker)
|
||
{
|
||
return string.Format("{0}: {1}", blocker.TableName, blocker.RowCount);
|
||
}));
|
||
|
||
throw new InvalidOperationException(
|
||
string.Format(
|
||
"ПСВ не может быть удалён, потому что на его строки EKZMK есть ссылки в таблицах: {0}. По вашему правилу приложение не трогает эти таблицы.",
|
||
details));
|
||
}
|
||
|
||
var deletedEkzMkFctvlCount = DeleteDocumentEkzMkFctvl(connection, transaction, documentNumber);
|
||
var deletedDmsCount = DeleteDocumentDms(connection, transaction, documentNumber);
|
||
var deletedEkzMkCount = DeleteDocumentEkzMk(connection, transaction, documentNumber);
|
||
|
||
if (deletedEkzMkCount == 0)
|
||
{
|
||
throw new InvalidOperationException("Строки EKZMK для выбранного ПСВ не найдены.");
|
||
}
|
||
|
||
transaction.Commit();
|
||
|
||
return new DocumentDeleteResult
|
||
{
|
||
DeletedEkzMkFctvlCount = deletedEkzMkFctvlCount,
|
||
DeletedDmsCount = deletedDmsCount,
|
||
DeletedEkzMkCount = deletedEkzMkCount
|
||
};
|
||
}
|
||
}
|
||
}
|
||
|
||
public async Task<DocumentDeleteResult> DeleteDocumentAsync(string documentNumber, CancellationToken cancellationToken = default)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(documentNumber))
|
||
{
|
||
throw new InvalidOperationException("Не выбран документ для удаления.");
|
||
}
|
||
|
||
await using (var connection = await SqlServerConnectionFactory.Current.OpenConnectionAsync(cancellationToken).ConfigureAwait(false))
|
||
using (var transaction = (SqlTransaction)await connection.BeginTransactionAsync(cancellationToken).ConfigureAwait(false))
|
||
{
|
||
var blockers = await LoadDeleteBlockersAsync(connection, transaction, documentNumber, cancellationToken).ConfigureAwait(false);
|
||
if (blockers.Count > 0)
|
||
{
|
||
var details = string.Join(", ", blockers.Select(delegate(DeleteBlockerInfo blocker)
|
||
{
|
||
return string.Format("{0}: {1}", blocker.TableName, blocker.RowCount);
|
||
}));
|
||
|
||
throw new InvalidOperationException(
|
||
string.Format(
|
||
"ПСВ не может быть удалён, потому что на его строки EKZMK есть ссылки в таблицах: {0}. По вашему правилу приложение не трогает эти таблицы.",
|
||
details));
|
||
}
|
||
|
||
var deletedEkzMkFctvlCount = await DeleteDocumentEkzMkFctvlAsync(connection, transaction, documentNumber, cancellationToken).ConfigureAwait(false);
|
||
var deletedDmsCount = await DeleteDocumentDmsAsync(connection, transaction, documentNumber, cancellationToken).ConfigureAwait(false);
|
||
var deletedEkzMkCount = await DeleteDocumentEkzMkAsync(connection, transaction, documentNumber, cancellationToken).ConfigureAwait(false);
|
||
|
||
if (deletedEkzMkCount == 0)
|
||
{
|
||
throw new InvalidOperationException("Строки EKZMK для выбранного ПСВ не найдены.");
|
||
}
|
||
|
||
await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
|
||
|
||
return new DocumentDeleteResult
|
||
{
|
||
DeletedEkzMkFctvlCount = deletedEkzMkFctvlCount,
|
||
DeletedDmsCount = deletedDmsCount,
|
||
DeletedEkzMkCount = deletedEkzMkCount
|
||
};
|
||
}
|
||
}
|
||
|
||
public DocumentGroupDeleteResult DeleteDocumentGroups(string documentNumber, IEnumerable<int> cardIds)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(documentNumber))
|
||
{
|
||
throw new InvalidOperationException("Р СњР Вµ выбран РґРѕРєСѓРСент для удаления РіСЂСѓРїРї.");
|
||
}
|
||
|
||
var normalizedCardIds = NormalizeCardIds(
|
||
cardIds,
|
||
"Р’ СЃРїРёСЃРєРµ удаляеРСых строк есть некорректный IDEKZMK.",
|
||
"Не выбрано ни одной строки EKZMK для удаления.");
|
||
|
||
using (var connection = CreateConnection())
|
||
{
|
||
connection.Open();
|
||
|
||
using (var transaction = connection.BeginTransaction())
|
||
{
|
||
var blockers = LoadDeleteBlockers(connection, transaction, normalizedCardIds);
|
||
if (blockers.Count > 0)
|
||
{
|
||
var details = string.Join(", ", blockers.Select(delegate(DeleteBlockerInfo blocker)
|
||
{
|
||
return string.Format("{0}: {1}", blocker.TableName, blocker.RowCount);
|
||
}));
|
||
|
||
throw new InvalidOperationException(
|
||
string.Format(
|
||
"Выбранные строки EKZMK не могут быть удалены, потому что на них есть ссылки в таблицах: {0}. По вашему правилу приложение не трогает эти таблицы.",
|
||
details));
|
||
}
|
||
|
||
var deletedEkzMkFctvlCount = 0;
|
||
var deletedDmsCount = 0;
|
||
var deletedEkzMkCount = 0;
|
||
|
||
foreach (var cardId in normalizedCardIds)
|
||
{
|
||
deletedEkzMkFctvlCount += DeleteLineEkzMkFctvl(connection, transaction, documentNumber, cardId);
|
||
deletedDmsCount += DeleteLineDms(connection, transaction, documentNumber, cardId);
|
||
deletedEkzMkCount += DeleteLineEkzMk(connection, transaction, documentNumber, cardId);
|
||
}
|
||
|
||
if (deletedEkzMkCount == 0)
|
||
{
|
||
throw new InvalidOperationException("Строки EKZMK для выбранных групп не найдены.");
|
||
}
|
||
|
||
transaction.Commit();
|
||
|
||
return new DocumentGroupDeleteResult
|
||
{
|
||
DeletedEkzMkFctvlCount = deletedEkzMkFctvlCount,
|
||
DeletedEkzMkCount = deletedEkzMkCount,
|
||
DeletedDmsCount = deletedDmsCount
|
||
};
|
||
}
|
||
}
|
||
}
|
||
|
||
public async Task<DocumentGroupDeleteResult> DeleteDocumentGroupsAsync(string documentNumber, IEnumerable<int> cardIds, CancellationToken cancellationToken = default)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(documentNumber))
|
||
{
|
||
throw new InvalidOperationException("Не выбран документ для удаления групп.");
|
||
}
|
||
|
||
var normalizedCardIds = NormalizeCardIds(
|
||
cardIds,
|
||
"В списке удаляемых строк есть некорректный IDEKZMK.",
|
||
"Не выбрано ни одной строки EKZMK для удаления.");
|
||
|
||
await using (var connection = await SqlServerConnectionFactory.Current.OpenConnectionAsync(cancellationToken).ConfigureAwait(false))
|
||
using (var transaction = (SqlTransaction)await connection.BeginTransactionAsync(cancellationToken).ConfigureAwait(false))
|
||
{
|
||
var blockers = await LoadDeleteBlockersAsync(connection, transaction, normalizedCardIds, cancellationToken).ConfigureAwait(false);
|
||
if (blockers.Count > 0)
|
||
{
|
||
var details = string.Join(", ", blockers.Select(delegate(DeleteBlockerInfo blocker)
|
||
{
|
||
return string.Format("{0}: {1}", blocker.TableName, blocker.RowCount);
|
||
}));
|
||
|
||
throw new InvalidOperationException(
|
||
string.Format(
|
||
"Выбранные строки EKZMK не могут быть удалены, потому что на них есть ссылки в таблицах: {0}. По вашему правилу приложение не трогает эти таблицы.",
|
||
details));
|
||
}
|
||
|
||
var deletedEkzMkFctvlCount = 0;
|
||
var deletedDmsCount = 0;
|
||
var deletedEkzMkCount = 0;
|
||
|
||
foreach (var cardId in normalizedCardIds)
|
||
{
|
||
deletedEkzMkFctvlCount += await DeleteLineEkzMkFctvlAsync(connection, transaction, documentNumber, cardId, cancellationToken).ConfigureAwait(false);
|
||
deletedDmsCount += await DeleteLineDmsAsync(connection, transaction, documentNumber, cardId, cancellationToken).ConfigureAwait(false);
|
||
deletedEkzMkCount += await DeleteLineEkzMkAsync(connection, transaction, documentNumber, cardId, cancellationToken).ConfigureAwait(false);
|
||
}
|
||
|
||
if (deletedEkzMkCount == 0)
|
||
{
|
||
throw new InvalidOperationException("Строки EKZMK для выбранных групп не найдены.");
|
||
}
|
||
|
||
await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
|
||
|
||
return new DocumentGroupDeleteResult
|
||
{
|
||
DeletedEkzMkFctvlCount = deletedEkzMkFctvlCount,
|
||
DeletedEkzMkCount = deletedEkzMkCount,
|
||
DeletedDmsCount = deletedDmsCount
|
||
};
|
||
}
|
||
}
|
||
|
||
private static string GetPendingLineSaveKey(PsvDocumentLine line)
|
||
{
|
||
if (line == null)
|
||
{
|
||
return string.Empty;
|
||
}
|
||
|
||
return line.InstrumentId > 0
|
||
? string.Format("ID:{0}", line.InstrumentId)
|
||
: string.Format("NEW:{0}", line.DuplicateKey ?? string.Empty);
|
||
}
|
||
|
||
private static bool IsPendingLineReadyForSave(PsvDocumentLine line)
|
||
{
|
||
return line != null
|
||
&& (line.InstrumentId > 0
|
||
|| (line.TypeSizeId > 0 && !string.IsNullOrWhiteSpace(line.SerialNumber)));
|
||
}
|
||
|
||
private static int ResolveInstrumentIdForPendingLine(SqlConnection connection, SqlTransaction transaction, DocumentEditorResult document, PsvDocumentLine pendingLine)
|
||
{
|
||
if (pendingLine == null)
|
||
{
|
||
throw new InvalidOperationException("Строка ПСВ для сохранения не задана.");
|
||
}
|
||
|
||
if (pendingLine.InstrumentId > 0)
|
||
{
|
||
return pendingLine.InstrumentId;
|
||
}
|
||
|
||
if (pendingLine.TypeSizeId <= 0)
|
||
{
|
||
throw new InvalidOperationException("Для новой строки ПСВ не указан типоразмер прибора.");
|
||
}
|
||
|
||
var serialNumber = string.IsNullOrWhiteSpace(pendingLine.SerialNumber) ? null : pendingLine.SerialNumber.Trim();
|
||
if (serialNumber == null)
|
||
{
|
||
throw new InvalidOperationException("Для новой строки ПСВ не указан заводской номер.");
|
||
}
|
||
|
||
if (!document.CustomerId.HasValue)
|
||
{
|
||
throw new InvalidOperationException("Для добавления прибора по типу должен быть выбран заказчик ПСВ.");
|
||
}
|
||
|
||
var existingInstrumentId = FindExistingInstrumentId(connection, transaction, pendingLine.TypeSizeId, document.CustomerId.Value, serialNumber);
|
||
if (existingInstrumentId.HasValue)
|
||
{
|
||
return existingInstrumentId.Value;
|
||
}
|
||
|
||
return InsertInstrument(connection, transaction, pendingLine.TypeSizeId, document.CustomerId.Value, serialNumber);
|
||
}
|
||
|
||
private static List<int> NormalizeCardIds(IEnumerable<int> cardIds, string invalidCardMessage, string emptyListMessage)
|
||
{
|
||
if (cardIds == null)
|
||
{
|
||
throw new InvalidOperationException(emptyListMessage);
|
||
}
|
||
|
||
var normalizedCardIds = cardIds.Distinct().ToList();
|
||
if (normalizedCardIds.Count == 0)
|
||
{
|
||
throw new InvalidOperationException(emptyListMessage);
|
||
}
|
||
|
||
if (normalizedCardIds.Any(delegate(int cardId) { return cardId <= 0; }))
|
||
{
|
||
throw new InvalidOperationException(invalidCardMessage);
|
||
}
|
||
|
||
return normalizedCardIds;
|
||
}
|
||
|
||
private static int? FindExistingInstrumentId(SqlConnection connection, SqlTransaction transaction, int typeSizeId, int customerId, string serialNumber)
|
||
{
|
||
const string sql = @"
|
||
SELECT TOP (1) z.IDEKZ
|
||
FROM dbo.EKZ z
|
||
WHERE z.IDTPRZ = @TypeSizeId
|
||
AND z.IDFRPDV = @CustomerId
|
||
AND z.NNZV = @SerialNumber
|
||
AND ISNULL(z.IsDeleted, 0) = 0
|
||
ORDER BY z.IDEKZ DESC;";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@TypeSizeId", SqlDbType.Int).Value = typeSizeId;
|
||
command.Parameters.Add("@CustomerId", SqlDbType.Int).Value = customerId;
|
||
command.Parameters.Add("@SerialNumber", SqlDbType.VarChar, 30).Value = serialNumber;
|
||
|
||
var result = command.ExecuteScalar();
|
||
return result == null || result == DBNull.Value ? (int?)null : Convert.ToInt32(result);
|
||
}
|
||
}
|
||
|
||
private static int InsertInstrument(SqlConnection connection, SqlTransaction transaction, int typeSizeId, int customerId, string serialNumber)
|
||
{
|
||
const string sql = @"
|
||
INSERT INTO dbo.EKZ
|
||
(
|
||
IDTPRZ,
|
||
IDFRPDV,
|
||
KLSIPR,
|
||
NNZV,
|
||
GUIDEKZ,
|
||
IsDeleted
|
||
)
|
||
VALUES
|
||
(
|
||
@TypeSizeId,
|
||
@CustomerId,
|
||
@Klsipr,
|
||
@SerialNumber,
|
||
@GuidEkz,
|
||
0
|
||
);
|
||
|
||
SELECT CAST(SCOPE_IDENTITY() AS int);";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@TypeSizeId", SqlDbType.Int).Value = typeSizeId;
|
||
command.Parameters.Add("@CustomerId", SqlDbType.Int).Value = customerId;
|
||
command.Parameters.Add("@Klsipr", SqlDbType.Int).Value = 1;
|
||
command.Parameters.Add("@SerialNumber", SqlDbType.VarChar, 30).Value = serialNumber;
|
||
command.Parameters.Add("@GuidEkz", SqlDbType.UniqueIdentifier).Value = Guid.NewGuid();
|
||
return Convert.ToInt32(command.ExecuteScalar());
|
||
}
|
||
}
|
||
|
||
private static string BuildOpenDocumentConflictMessage(IEnumerable<OpenDocumentConflictInfo> conflicts)
|
||
{
|
||
var materializedConflicts = conflicts == null
|
||
? new List<OpenDocumentConflictInfo>()
|
||
: conflicts
|
||
.Where(delegate(OpenDocumentConflictInfo conflict) { return conflict != null; })
|
||
.GroupBy(delegate(OpenDocumentConflictInfo conflict)
|
||
{
|
||
return string.Format(
|
||
"{0}|{1}|{2}",
|
||
conflict.DocumentNumber ?? string.Empty,
|
||
conflict.TypeSizeId,
|
||
conflict.SerialNumber ?? string.Empty);
|
||
}, StringComparer.OrdinalIgnoreCase)
|
||
.Select(delegate(IGrouping<string, OpenDocumentConflictInfo> group) { return group.First(); })
|
||
.OrderBy(delegate(OpenDocumentConflictInfo conflict) { return conflict.SerialNumber ?? string.Empty; })
|
||
.ThenBy(delegate(OpenDocumentConflictInfo conflict) { return conflict.DocumentNumber ?? string.Empty; })
|
||
.ToList();
|
||
|
||
if (materializedConflicts.Count == 0)
|
||
{
|
||
return "Прибор уже находится в другой открытой ПСВ этого заказчика.";
|
||
}
|
||
|
||
var preview = materializedConflicts
|
||
.Take(5)
|
||
.Select(delegate(OpenDocumentConflictInfo conflict)
|
||
{
|
||
return string.Format("зав. № {0} -> {1}", conflict.SerialNumber, conflict.DocumentNumber);
|
||
})
|
||
.ToList();
|
||
|
||
var suffix = materializedConflicts.Count > preview.Count
|
||
? string.Format(" Еще конфликтов: {0}.", materializedConflicts.Count - preview.Count)
|
||
: string.Empty;
|
||
|
||
return string.Format(
|
||
"Приборы уже находятся в других открытых ПСВ этого заказчика: {0}.{1}",
|
||
string.Join("; ", preview.ToArray()),
|
||
suffix);
|
||
}
|
||
|
||
private static List<OpenDocumentConflictInfo> LoadOpenDocumentConflicts(
|
||
SqlConnection connection,
|
||
SqlTransaction transaction,
|
||
int customerId,
|
||
string currentDocumentNumber,
|
||
IEnumerable<PsvDocumentLine> candidateLines)
|
||
{
|
||
var normalizedCandidates = candidateLines == null
|
||
? new List<PsvDocumentLine>()
|
||
: candidateLines
|
||
.Where(delegate(PsvDocumentLine line)
|
||
{
|
||
return line != null
|
||
&& line.TypeSizeId > 0
|
||
&& !string.IsNullOrWhiteSpace(line.SerialNumber);
|
||
})
|
||
.GroupBy(delegate(PsvDocumentLine line) { return line.OpenDocumentConflictKey; }, StringComparer.OrdinalIgnoreCase)
|
||
.Select(delegate(IGrouping<string, PsvDocumentLine> group) { return group.First(); })
|
||
.ToList();
|
||
|
||
if (customerId <= 0 || normalizedCandidates.Count == 0)
|
||
{
|
||
return new List<OpenDocumentConflictInfo>();
|
||
}
|
||
|
||
const string sql = @"
|
||
WITH ActiveDocuments AS
|
||
(
|
||
SELECT m.NNZVPV
|
||
FROM dbo.EKZMK m
|
||
WHERE NULLIF(LTRIM(RTRIM(m.NNZVPV)), N'') IS NOT NULL
|
||
GROUP BY m.NNZVPV
|
||
HAVING MAX(m.DTVDM) IS NULL
|
||
)
|
||
SELECT DISTINCT
|
||
m.NNZVPV AS DocumentNumber,
|
||
z.IDTPRZ AS TypeSizeId,
|
||
LTRIM(RTRIM(z.NNZV)) AS SerialNumber
|
||
FROM ActiveDocuments activeDocuments
|
||
JOIN dbo.EKZMK m ON m.NNZVPV = activeDocuments.NNZVPV
|
||
JOIN dbo.EKZ z ON z.IDEKZ = m.IDEKZ
|
||
WHERE z.IDFRPDV = @CustomerId
|
||
AND z.IDTPRZ = @TypeSizeId
|
||
AND LTRIM(RTRIM(z.NNZV)) = @SerialNumber
|
||
AND (@CurrentDocumentNumber = N'' OR m.NNZVPV <> @CurrentDocumentNumber)
|
||
ORDER BY m.NNZVPV;";
|
||
|
||
var conflicts = new List<OpenDocumentConflictInfo>();
|
||
|
||
foreach (var candidateLine in normalizedCandidates)
|
||
{
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@CustomerId", SqlDbType.Int).Value = customerId;
|
||
command.Parameters.Add("@TypeSizeId", SqlDbType.Int).Value = candidateLine.TypeSizeId;
|
||
command.Parameters.Add("@SerialNumber", SqlDbType.VarChar, 30).Value = candidateLine.SerialNumber.Trim();
|
||
command.Parameters.Add("@CurrentDocumentNumber", SqlDbType.NVarChar, 60).Value = currentDocumentNumber ?? string.Empty;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
conflicts.Add(new OpenDocumentConflictInfo
|
||
{
|
||
DocumentNumber = GetString(reader, "DocumentNumber"),
|
||
TypeSizeId = GetInt32(reader, "TypeSizeId"),
|
||
SerialNumber = GetString(reader, "SerialNumber")
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return conflicts
|
||
.GroupBy(delegate(OpenDocumentConflictInfo conflict)
|
||
{
|
||
return string.Format(
|
||
"{0}|{1}|{2}",
|
||
conflict.DocumentNumber ?? string.Empty,
|
||
conflict.TypeSizeId,
|
||
conflict.SerialNumber ?? string.Empty);
|
||
}, StringComparer.OrdinalIgnoreCase)
|
||
.Select(delegate(IGrouping<string, OpenDocumentConflictInfo> group) { return group.First(); })
|
||
.OrderBy(delegate(OpenDocumentConflictInfo conflict) { return conflict.SerialNumber ?? string.Empty; })
|
||
.ThenBy(delegate(OpenDocumentConflictInfo conflict) { return conflict.DocumentNumber ?? string.Empty; })
|
||
.ToList();
|
||
}
|
||
|
||
private static async Task<List<OpenDocumentConflictInfo>> LoadOpenDocumentConflictsAsync(
|
||
SqlConnection connection,
|
||
SqlTransaction transaction,
|
||
int customerId,
|
||
string currentDocumentNumber,
|
||
IEnumerable<PsvDocumentLine> candidateLines,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
var normalizedCandidates = candidateLines == null
|
||
? new List<PsvDocumentLine>()
|
||
: candidateLines
|
||
.Where(delegate(PsvDocumentLine line)
|
||
{
|
||
return line != null
|
||
&& line.TypeSizeId > 0
|
||
&& !string.IsNullOrWhiteSpace(line.SerialNumber);
|
||
})
|
||
.GroupBy(delegate(PsvDocumentLine line) { return line.OpenDocumentConflictKey; }, StringComparer.OrdinalIgnoreCase)
|
||
.Select(delegate(IGrouping<string, PsvDocumentLine> group) { return group.First(); })
|
||
.ToList();
|
||
|
||
if (customerId <= 0 || normalizedCandidates.Count == 0)
|
||
{
|
||
return new List<OpenDocumentConflictInfo>();
|
||
}
|
||
|
||
const string sql = @"
|
||
WITH ActiveDocuments AS
|
||
(
|
||
SELECT m.NNZVPV
|
||
FROM dbo.EKZMK m
|
||
WHERE NULLIF(LTRIM(RTRIM(m.NNZVPV)), N'') IS NOT NULL
|
||
GROUP BY m.NNZVPV
|
||
HAVING MAX(m.DTVDM) IS NULL
|
||
)
|
||
SELECT DISTINCT
|
||
m.NNZVPV AS DocumentNumber,
|
||
z.IDTPRZ AS TypeSizeId,
|
||
LTRIM(RTRIM(z.NNZV)) AS SerialNumber
|
||
FROM ActiveDocuments activeDocuments
|
||
JOIN dbo.EKZMK m ON m.NNZVPV = activeDocuments.NNZVPV
|
||
JOIN dbo.EKZ z ON z.IDEKZ = m.IDEKZ
|
||
WHERE z.IDFRPDV = @CustomerId
|
||
AND z.IDTPRZ = @TypeSizeId
|
||
AND LTRIM(RTRIM(z.NNZV)) = @SerialNumber
|
||
AND (@CurrentDocumentNumber = N'' OR m.NNZVPV <> @CurrentDocumentNumber)
|
||
ORDER BY m.NNZVPV;";
|
||
|
||
var conflicts = new List<OpenDocumentConflictInfo>();
|
||
|
||
foreach (var candidateLine in normalizedCandidates)
|
||
{
|
||
var candidateConflicts = await connection.QueryAsync(
|
||
transaction,
|
||
sql,
|
||
delegate(SqlDataReader reader)
|
||
{
|
||
return new OpenDocumentConflictInfo
|
||
{
|
||
DocumentNumber = GetString(reader, "DocumentNumber"),
|
||
TypeSizeId = GetInt32(reader, "TypeSizeId"),
|
||
SerialNumber = GetString(reader, "SerialNumber")
|
||
};
|
||
},
|
||
delegate(SqlCommand command)
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@CustomerId", SqlDbType.Int).Value = customerId;
|
||
command.Parameters.Add("@TypeSizeId", SqlDbType.Int).Value = candidateLine.TypeSizeId;
|
||
command.Parameters.Add("@SerialNumber", SqlDbType.VarChar, 30).Value = candidateLine.SerialNumber.Trim();
|
||
command.Parameters.Add("@CurrentDocumentNumber", SqlDbType.NVarChar, 60).Value = currentDocumentNumber ?? string.Empty;
|
||
},
|
||
cancellationToken).ConfigureAwait(false);
|
||
|
||
conflicts.AddRange(candidateConflicts);
|
||
}
|
||
|
||
return conflicts
|
||
.GroupBy(delegate(OpenDocumentConflictInfo conflict)
|
||
{
|
||
return string.Format(
|
||
"{0}|{1}|{2}",
|
||
conflict.DocumentNumber ?? string.Empty,
|
||
conflict.TypeSizeId,
|
||
conflict.SerialNumber ?? string.Empty);
|
||
}, StringComparer.OrdinalIgnoreCase)
|
||
.Select(delegate(IGrouping<string, OpenDocumentConflictInfo> group) { return group.First(); })
|
||
.OrderBy(delegate(OpenDocumentConflictInfo conflict) { return conflict.SerialNumber ?? string.Empty; })
|
||
.ThenBy(delegate(OpenDocumentConflictInfo conflict) { return conflict.DocumentNumber ?? string.Empty; })
|
||
.ToList();
|
||
}
|
||
|
||
private static SqlConnection CreateConnection()
|
||
{
|
||
return SqlServerConnectionFactory.Current.CreateConnection();
|
||
}
|
||
|
||
private static void ClearLineVerificationCore(SqlConnection connection, SqlTransaction transaction, int cardId)
|
||
{
|
||
const string sql = @"
|
||
UPDATE dbo.EKZMK
|
||
SET IDPRSN = NULL,
|
||
NNNKL = NULL,
|
||
GDN = NULL,
|
||
DTMKFK = NULL,
|
||
PRCHNPGDN = NULL
|
||
WHERE IDEKZMK = @CardId;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
if (Convert.ToInt32(command.ExecuteScalar()) == 0)
|
||
{
|
||
throw new InvalidOperationException("Строка EKZMK для изменения результата поверки не найдена.");
|
||
}
|
||
}
|
||
}
|
||
|
||
private static async Task ClearLineVerificationCoreAsync(SqlConnection connection, SqlTransaction transaction, int cardId, CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
UPDATE dbo.EKZMK
|
||
SET IDPRSN = NULL,
|
||
NNNKL = NULL,
|
||
GDN = NULL,
|
||
DTMKFK = NULL,
|
||
PRCHNPGDN = NULL
|
||
WHERE IDEKZMK = @CardId;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
var affectedRowCount = await connection.ExecuteScalarAsync<int>(
|
||
transaction,
|
||
sql,
|
||
delegate(SqlCommand command)
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
},
|
||
cancellationToken).ConfigureAwait(false);
|
||
|
||
if (affectedRowCount == 0)
|
||
{
|
||
throw new InvalidOperationException("Строка EKZMK для изменения результата поверки не найдена.");
|
||
}
|
||
}
|
||
|
||
private static void DeleteVerificationDocuments(SqlConnection connection, SqlTransaction transaction, int cardId)
|
||
{
|
||
const string sql = @"
|
||
DELETE d
|
||
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 = @CardId
|
||
AND vdd.IDSPVDOD = 2
|
||
AND spvdd.IDSPVDD IN (2, 6, 8);";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
command.ExecuteNonQuery();
|
||
}
|
||
}
|
||
|
||
private static Task DeleteVerificationDocumentsAsync(SqlConnection connection, SqlTransaction transaction, int cardId, CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
DELETE d
|
||
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 = @CardId
|
||
AND vdd.IDSPVDOD = 2
|
||
AND spvdd.IDSPVDD IN (2, 6, 8);";
|
||
|
||
return connection.ExecuteNonQueryAsync(
|
||
transaction,
|
||
sql,
|
||
delegate(SqlCommand command)
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
},
|
||
cancellationToken);
|
||
}
|
||
|
||
private static void InsertVerificationDocument(
|
||
SqlConnection connection,
|
||
SqlTransaction transaction,
|
||
int cardId,
|
||
int linkTypeId,
|
||
int formId,
|
||
string documentNumber,
|
||
DateTime documentDate)
|
||
{
|
||
const string sql = @"
|
||
INSERT INTO dbo.DMS
|
||
(
|
||
IDOD,
|
||
IDVDODVDD,
|
||
IDFRDMS,
|
||
NND,
|
||
DTD,
|
||
PTTXDMS,
|
||
GUIDDMS
|
||
)
|
||
VALUES
|
||
(
|
||
@CardId,
|
||
@LinkTypeId,
|
||
@FormId,
|
||
@DocumentNumber,
|
||
@DocumentDate,
|
||
NULL,
|
||
@Guid
|
||
);";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
command.Parameters.Add("@LinkTypeId", SqlDbType.Int).Value = linkTypeId;
|
||
command.Parameters.Add("@FormId", SqlDbType.Int).Value = formId;
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber.Trim();
|
||
command.Parameters.Add("@DocumentDate", SqlDbType.DateTime).Value = documentDate;
|
||
command.Parameters.Add("@Guid", SqlDbType.UniqueIdentifier).Value = Guid.NewGuid();
|
||
command.ExecuteNonQuery();
|
||
}
|
||
}
|
||
|
||
private static Task InsertVerificationDocumentAsync(
|
||
SqlConnection connection,
|
||
SqlTransaction transaction,
|
||
int cardId,
|
||
int linkTypeId,
|
||
int formId,
|
||
string documentNumber,
|
||
DateTime documentDate,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
INSERT INTO dbo.DMS
|
||
(
|
||
IDOD,
|
||
IDVDODVDD,
|
||
IDFRDMS,
|
||
NND,
|
||
DTD,
|
||
PTTXDMS,
|
||
GUIDDMS
|
||
)
|
||
VALUES
|
||
(
|
||
@CardId,
|
||
@LinkTypeId,
|
||
@FormId,
|
||
@DocumentNumber,
|
||
@DocumentDate,
|
||
NULL,
|
||
@Guid
|
||
);";
|
||
|
||
return connection.ExecuteNonQueryAsync(
|
||
transaction,
|
||
sql,
|
||
delegate(SqlCommand command)
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
command.Parameters.Add("@LinkTypeId", SqlDbType.Int).Value = linkTypeId;
|
||
command.Parameters.Add("@FormId", SqlDbType.Int).Value = formId;
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber.Trim();
|
||
command.Parameters.Add("@DocumentDate", SqlDbType.DateTime).Value = documentDate;
|
||
command.Parameters.Add("@Guid", SqlDbType.UniqueIdentifier).Value = Guid.NewGuid();
|
||
},
|
||
cancellationToken);
|
||
}
|
||
|
||
private static void SaveLineVerificationCore(SqlConnection connection, SqlTransaction transaction, int cardId, VerificationEditResult result)
|
||
{
|
||
const string sql = @"
|
||
UPDATE dbo.EKZMK
|
||
SET IDPRSN = @VerifierId,
|
||
NNNKL = @StickerNumber,
|
||
GDN = @IsPassed,
|
||
DTMKFK = @VerificationDate,
|
||
PRCHNPGDN = @RejectionReason
|
||
WHERE IDEKZMK = @CardId;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
command.Parameters.Add("@VerifierId", SqlDbType.Int).Value = result.VerifierId;
|
||
command.Parameters.Add("@StickerNumber", SqlDbType.NVarChar, 30).Value = result.IsPassed && !string.IsNullOrWhiteSpace(result.StickerNumber)
|
||
? (object)result.StickerNumber.Trim()
|
||
: DBNull.Value;
|
||
command.Parameters.Add("@IsPassed", SqlDbType.Bit).Value = result.IsPassed;
|
||
command.Parameters.Add("@VerificationDate", SqlDbType.DateTime).Value = result.VerificationDate;
|
||
command.Parameters.Add("@RejectionReason", SqlDbType.NVarChar, 1024).Value = !result.IsPassed && !string.IsNullOrWhiteSpace(result.RejectionReason)
|
||
? (object)result.RejectionReason.Trim()
|
||
: DBNull.Value;
|
||
|
||
if (Convert.ToInt32(command.ExecuteScalar()) == 0)
|
||
{
|
||
throw new InvalidOperationException("Строка EKZMK для сохранения результата поверки не найдена.");
|
||
}
|
||
}
|
||
}
|
||
|
||
private static async Task SaveLineVerificationCoreAsync(SqlConnection connection, SqlTransaction transaction, int cardId, VerificationEditResult result, CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
UPDATE dbo.EKZMK
|
||
SET IDPRSN = @VerifierId,
|
||
NNNKL = @StickerNumber,
|
||
GDN = @IsPassed,
|
||
DTMKFK = @VerificationDate,
|
||
PRCHNPGDN = @RejectionReason
|
||
WHERE IDEKZMK = @CardId;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
var affectedRowCount = await connection.ExecuteScalarAsync<int>(
|
||
transaction,
|
||
sql,
|
||
delegate(SqlCommand command)
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
command.Parameters.Add("@VerifierId", SqlDbType.Int).Value = result.VerifierId;
|
||
command.Parameters.Add("@StickerNumber", SqlDbType.NVarChar, 30).Value = result.IsPassed && !string.IsNullOrWhiteSpace(result.StickerNumber)
|
||
? (object)result.StickerNumber.Trim()
|
||
: DBNull.Value;
|
||
command.Parameters.Add("@IsPassed", SqlDbType.Bit).Value = result.IsPassed;
|
||
command.Parameters.Add("@VerificationDate", SqlDbType.DateTime).Value = result.VerificationDate;
|
||
command.Parameters.Add("@RejectionReason", SqlDbType.NVarChar, 1024).Value = !result.IsPassed && !string.IsNullOrWhiteSpace(result.RejectionReason)
|
||
? (object)result.RejectionReason.Trim()
|
||
: DBNull.Value;
|
||
},
|
||
cancellationToken).ConfigureAwait(false);
|
||
|
||
if (affectedRowCount == 0)
|
||
{
|
||
throw new InvalidOperationException("Строка EKZMK для сохранения результата поверки не найдена.");
|
||
}
|
||
}
|
||
|
||
private static int DeleteLineDms(SqlConnection connection, SqlTransaction transaction, string documentNumber, int cardId)
|
||
{
|
||
const string sql = @"
|
||
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.NNZVPV = @DocumentNumber
|
||
AND m.IDEKZMK = @CardId
|
||
AND vdd.IDSPVDOD = 2;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
return Convert.ToInt32(command.ExecuteScalar());
|
||
}
|
||
}
|
||
|
||
private static Task<int> DeleteLineDmsAsync(SqlConnection connection, SqlTransaction transaction, string documentNumber, int cardId, CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
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.NNZVPV = @DocumentNumber
|
||
AND m.IDEKZMK = @CardId
|
||
AND vdd.IDSPVDOD = 2;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
return connection.ExecuteScalarAsync<int>(
|
||
transaction,
|
||
sql,
|
||
delegate(SqlCommand command)
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
},
|
||
cancellationToken);
|
||
}
|
||
|
||
private static int DeleteLineEkzMk(SqlConnection connection, SqlTransaction transaction, string documentNumber, int cardId)
|
||
{
|
||
const string sql = @"
|
||
DELETE FROM dbo.EKZMK
|
||
WHERE NNZVPV = @DocumentNumber
|
||
AND IDEKZMK = @CardId;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
return Convert.ToInt32(command.ExecuteScalar());
|
||
}
|
||
}
|
||
|
||
private static Task<int> DeleteLineEkzMkAsync(SqlConnection connection, SqlTransaction transaction, string documentNumber, int cardId, CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
DELETE FROM dbo.EKZMK
|
||
WHERE NNZVPV = @DocumentNumber
|
||
AND IDEKZMK = @CardId;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
return connection.ExecuteScalarAsync<int>(
|
||
transaction,
|
||
sql,
|
||
delegate(SqlCommand command)
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
},
|
||
cancellationToken);
|
||
}
|
||
|
||
private static int DeleteLineEkzMkFctvl(SqlConnection connection, SqlTransaction transaction, string documentNumber, int cardId)
|
||
{
|
||
const string sql = @"
|
||
DELETE child
|
||
FROM dbo.EKZMKFCTVL child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.NNZVPV = @DocumentNumber
|
||
AND parent.IDEKZMK = @CardId;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
return Convert.ToInt32(command.ExecuteScalar());
|
||
}
|
||
}
|
||
|
||
private static Task<int> DeleteLineEkzMkFctvlAsync(SqlConnection connection, SqlTransaction transaction, string documentNumber, int cardId, CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
DELETE child
|
||
FROM dbo.EKZMKFCTVL child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.NNZVPV = @DocumentNumber
|
||
AND parent.IDEKZMK = @CardId;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
return connection.ExecuteScalarAsync<int>(
|
||
transaction,
|
||
sql,
|
||
delegate(SqlCommand command)
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
},
|
||
cancellationToken);
|
||
}
|
||
|
||
private static int DeleteDocumentDms(SqlConnection connection, SqlTransaction transaction, string documentNumber)
|
||
{
|
||
const string sql = @"
|
||
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.NNZVPV = @DocumentNumber
|
||
AND vdd.IDSPVDOD = 2;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
return Convert.ToInt32(command.ExecuteScalar());
|
||
}
|
||
}
|
||
|
||
private static Task<int> DeleteDocumentDmsAsync(SqlConnection connection, SqlTransaction transaction, string documentNumber, CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
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.NNZVPV = @DocumentNumber
|
||
AND vdd.IDSPVDOD = 2;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
return connection.ExecuteScalarAsync<int>(
|
||
transaction,
|
||
sql,
|
||
delegate(SqlCommand command)
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
},
|
||
cancellationToken);
|
||
}
|
||
|
||
private static int DeleteDocumentEkzMk(SqlConnection connection, SqlTransaction transaction, string documentNumber)
|
||
{
|
||
const string sql = @"
|
||
DELETE FROM dbo.EKZMK
|
||
WHERE NNZVPV = @DocumentNumber;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
return Convert.ToInt32(command.ExecuteScalar());
|
||
}
|
||
}
|
||
|
||
private static Task<int> DeleteDocumentEkzMkAsync(SqlConnection connection, SqlTransaction transaction, string documentNumber, CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
DELETE FROM dbo.EKZMK
|
||
WHERE NNZVPV = @DocumentNumber;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
return connection.ExecuteScalarAsync<int>(
|
||
transaction,
|
||
sql,
|
||
delegate(SqlCommand command)
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
},
|
||
cancellationToken);
|
||
}
|
||
|
||
private static int DeleteDocumentEkzMkFctvl(SqlConnection connection, SqlTransaction transaction, string documentNumber)
|
||
{
|
||
const string sql = @"
|
||
DELETE child
|
||
FROM dbo.EKZMKFCTVL child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.NNZVPV = @DocumentNumber;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
return Convert.ToInt32(command.ExecuteScalar());
|
||
}
|
||
}
|
||
|
||
private static Task<int> DeleteDocumentEkzMkFctvlAsync(SqlConnection connection, SqlTransaction transaction, string documentNumber, CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
DELETE child
|
||
FROM dbo.EKZMKFCTVL child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.NNZVPV = @DocumentNumber;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
return connection.ExecuteScalarAsync<int>(
|
||
transaction,
|
||
sql,
|
||
delegate(SqlCommand command)
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
},
|
||
cancellationToken);
|
||
}
|
||
|
||
private static bool DocumentNumberExists(SqlConnection connection, SqlTransaction transaction, string documentNumber, string excludeDocumentNumber)
|
||
{
|
||
const string sql = @"
|
||
SELECT COUNT(1)
|
||
FROM dbo.EKZMK
|
||
WHERE NNZVPV = @DocumentNumber
|
||
AND (@ExcludeDocumentNumber = N'' OR NNZVPV <> @ExcludeDocumentNumber);";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
command.Parameters.Add("@ExcludeDocumentNumber", SqlDbType.NVarChar, 60).Value = excludeDocumentNumber ?? string.Empty;
|
||
return Convert.ToInt32(command.ExecuteScalar()) > 0;
|
||
}
|
||
}
|
||
|
||
private static async Task<bool> DocumentNumberExistsAsync(SqlConnection connection, SqlTransaction transaction, string documentNumber, string excludeDocumentNumber, CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
SELECT COUNT(1)
|
||
FROM dbo.EKZMK
|
||
WHERE NNZVPV = @DocumentNumber
|
||
AND (@ExcludeDocumentNumber = N'' OR NNZVPV <> @ExcludeDocumentNumber);";
|
||
|
||
var matchCount = await connection.ExecuteScalarAsync<int>(
|
||
transaction,
|
||
sql,
|
||
delegate(SqlCommand command)
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
command.Parameters.Add("@ExcludeDocumentNumber", SqlDbType.NVarChar, 60).Value = excludeDocumentNumber ?? string.Empty;
|
||
},
|
||
cancellationToken).ConfigureAwait(false);
|
||
|
||
return matchCount > 0;
|
||
}
|
||
|
||
private static bool GetBoolean(IDataRecord record, string columnName)
|
||
{
|
||
return Convert.ToBoolean(record[columnName]);
|
||
}
|
||
|
||
private static int GetInt32(IDataRecord record, string columnName)
|
||
{
|
||
return Convert.ToInt32(record[columnName]);
|
||
}
|
||
|
||
private static string GetString(IDataRecord record, string columnName)
|
||
{
|
||
return record[columnName] == DBNull.Value ? string.Empty : Convert.ToString(record[columnName]);
|
||
}
|
||
|
||
private static DateTime? GetNullableDateTime(IDataRecord record, string columnName)
|
||
{
|
||
return record[columnName] == DBNull.Value ? (DateTime?)null : Convert.ToDateTime(record[columnName]);
|
||
}
|
||
|
||
private static decimal? GetNullableDecimal(IDataRecord record, string columnName)
|
||
{
|
||
return record[columnName] == DBNull.Value ? (decimal?)null : Convert.ToDecimal(record[columnName]);
|
||
}
|
||
|
||
private static bool? GetNullableBoolean(IDataRecord record, string columnName)
|
||
{
|
||
return record[columnName] == DBNull.Value ? (bool?)null : Convert.ToBoolean(record[columnName]);
|
||
}
|
||
|
||
private static int? GetNullableInt32(IDataRecord record, string columnName)
|
||
{
|
||
return record[columnName] == DBNull.Value ? (int?)null : Convert.ToInt32(record[columnName]);
|
||
}
|
||
|
||
private static int InsertEkzMk(
|
||
SqlConnection connection,
|
||
SqlTransaction transaction,
|
||
int verificationTypeId,
|
||
DocumentEditorResult document,
|
||
string normalizedNumber,
|
||
int instrumentId,
|
||
EkzMkTemplate template,
|
||
PsvDocumentLine pendingLine)
|
||
{
|
||
const string sql = @"
|
||
INSERT INTO dbo.EKZMK
|
||
(
|
||
IDEKZ,
|
||
IDSPMU,
|
||
IDGRSI,
|
||
IDKSPRL,
|
||
IDSPVDMK,
|
||
IDSPVDMC,
|
||
IDFRPD,
|
||
IDSPMPOB,
|
||
IDPRSN,
|
||
IDSPKMMK,
|
||
IDEKZRM,
|
||
IDSPVDKL,
|
||
IDPRSNVD,
|
||
IDEKZTO,
|
||
IDEKZOT,
|
||
NNZVPV,
|
||
SHFKL,
|
||
NNNKL,
|
||
PRMK,
|
||
DTMKFK,
|
||
DTMKPL,
|
||
DTPRM,
|
||
DTVDM,
|
||
GDN,
|
||
PZMC,
|
||
STMK,
|
||
STMKDP,
|
||
NCSRMK,
|
||
idprsnsd,
|
||
idprsnpr,
|
||
idprsnvy,
|
||
idsptsmp,
|
||
idspssmp,
|
||
GUIDEKZMK,
|
||
DSEKZMK,
|
||
DTOTM,
|
||
DTVZM,
|
||
IDPRSNOTM,
|
||
IDPRSNVZM,
|
||
NRVRMNDmp,
|
||
NRVRMmp,
|
||
VRMKFK,
|
||
IDKSP,
|
||
DPZNmp,
|
||
HRTCmp,
|
||
IDSPVDSBMK,
|
||
PRCHNPGDN,
|
||
IDEKZETL
|
||
)
|
||
VALUES
|
||
(
|
||
@IDEKZ,
|
||
@IDSPMU,
|
||
@IDGRSI,
|
||
@IDKSPRL,
|
||
@IDSPVDMK,
|
||
@IDSPVDMC,
|
||
@IDFRPD,
|
||
@IDSPMPOB,
|
||
@IDPRSN,
|
||
@IDSPKMMK,
|
||
NULL,
|
||
@IDSPVDKL,
|
||
@IDPRSNVD,
|
||
NULL,
|
||
NULL,
|
||
@NNZVPV,
|
||
NULL,
|
||
@NNNKL,
|
||
@PRMK,
|
||
@DTMKFK,
|
||
NULL,
|
||
@DTPRM,
|
||
@DTVDM,
|
||
@GDN,
|
||
NULL,
|
||
@STMK,
|
||
@STMKDP,
|
||
@NCSRMK,
|
||
@idprsnsd,
|
||
@idprsnpr,
|
||
@idprsnvy,
|
||
@idsptsmp,
|
||
@idspssmp,
|
||
@GUIDEKZMK,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
NULL,
|
||
@NRVRMNDmp,
|
||
@NRVRMmp,
|
||
@VRMKFK,
|
||
@IDKSP,
|
||
@DPZNmp,
|
||
@HRTCmp,
|
||
@IDSPVDSBMK,
|
||
@PRCHNPGDN,
|
||
@IDEKZETL
|
||
);
|
||
|
||
SELECT CAST(SCOPE_IDENTITY() AS int);";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
|
||
command.Parameters.Add("@IDEKZ", SqlDbType.Int).Value = instrumentId;
|
||
command.Parameters.Add("@IDSPMU", SqlDbType.Int).Value = (object)template.IdSpmu ?? DBNull.Value;
|
||
command.Parameters.Add("@IDGRSI", SqlDbType.Int).Value = (object)template.IdGrsi ?? DBNull.Value;
|
||
command.Parameters.Add("@IDKSPRL", SqlDbType.Int).Value = (object)template.IdKsprl ?? DBNull.Value;
|
||
command.Parameters.Add("@IDSPVDMK", SqlDbType.Int).Value = verificationTypeId;
|
||
command.Parameters.Add("@IDSPVDMC", SqlDbType.Int).Value = (object)template.IdSpvdmc ?? DBNull.Value;
|
||
command.Parameters.Add("@IDFRPD", SqlDbType.Int).Value = template.IdFrpd;
|
||
command.Parameters.Add("@IDSPMPOB", SqlDbType.Int).Value = (object)template.IdSpmpob ?? DBNull.Value;
|
||
command.Parameters.Add("@IDPRSN", SqlDbType.Int).Value = pendingLine == null ? DBNull.Value : (object)pendingLine.VerifierId ?? DBNull.Value;
|
||
command.Parameters.Add("@IDSPKMMK", SqlDbType.Int).Value = (object)template.IdSpkmmk ?? DBNull.Value;
|
||
command.Parameters.Add("@IDSPVDKL", SqlDbType.Int).Value = (object)template.IdSpvdkl ?? DBNull.Value;
|
||
command.Parameters.Add("@IDPRSNVD", SqlDbType.Int).Value = (object)template.IdPrsnvd ?? DBNull.Value;
|
||
command.Parameters.Add("@NNZVPV", SqlDbType.NVarChar, 60).Value = normalizedNumber;
|
||
command.Parameters.Add("@NNNKL", SqlDbType.NVarChar, 30).Value = pendingLine != null && pendingLine.IsPassed == true
|
||
? (object)(string.IsNullOrWhiteSpace(pendingLine.StickerNumber) ? null : pendingLine.StickerNumber.Trim())
|
||
: DBNull.Value;
|
||
command.Parameters.Add("@PRMK", SqlDbType.Int).Value = template.Prmk;
|
||
command.Parameters.Add("@DTMKFK", SqlDbType.DateTime).Value = pendingLine == null
|
||
? DBNull.Value
|
||
: (object)(pendingLine.VerificationPerformedOn ?? pendingLine.VerificationDocumentDate) ?? DBNull.Value;
|
||
command.Parameters.Add("@DTPRM", SqlDbType.DateTime).Value = document.AcceptedOn;
|
||
command.Parameters.Add("@DTVDM", SqlDbType.DateTime).Value = (object)document.IssuedOn ?? DBNull.Value;
|
||
command.Parameters.Add("@GDN", SqlDbType.Bit).Value = pendingLine == null ? DBNull.Value : (object)pendingLine.IsPassed ?? DBNull.Value;
|
||
command.Parameters.Add("@STMK", SqlDbType.Money).Value = (object)template.Stmk ?? DBNull.Value;
|
||
command.Parameters.Add("@STMKDP", SqlDbType.Money).Value = (object)template.Stmkdp ?? DBNull.Value;
|
||
command.Parameters.Add("@NCSRMK", SqlDbType.Money).Value = (object)template.NcSrmk ?? DBNull.Value;
|
||
command.Parameters.Add("@idprsnsd", SqlDbType.Int).Value = (object)template.IdPrsnsd ?? DBNull.Value;
|
||
command.Parameters.Add("@idprsnpr", SqlDbType.Int).Value = (object)template.IdPrsnpr ?? DBNull.Value;
|
||
command.Parameters.Add("@idprsnvy", SqlDbType.Int).Value = (object)template.IdPrsnvy ?? DBNull.Value;
|
||
command.Parameters.Add("@idsptsmp", SqlDbType.Int).Value = (object)template.IdSptsmp ?? DBNull.Value;
|
||
command.Parameters.Add("@idspssmp", SqlDbType.Int).Value = (object)template.IdSpssmp ?? DBNull.Value;
|
||
command.Parameters.Add("@GUIDEKZMK", SqlDbType.UniqueIdentifier).Value = Guid.NewGuid();
|
||
command.Parameters.Add("@NRVRMNDmp", SqlDbType.Decimal).Value = (object)template.Nrvrmndmp ?? DBNull.Value;
|
||
command.Parameters["@NRVRMNDmp"].Precision = 10;
|
||
command.Parameters["@NRVRMNDmp"].Scale = 2;
|
||
command.Parameters.Add("@NRVRMmp", SqlDbType.Decimal).Value = (object)template.Nrvrmmp ?? DBNull.Value;
|
||
command.Parameters["@NRVRMmp"].Precision = 10;
|
||
command.Parameters["@NRVRMmp"].Scale = 2;
|
||
command.Parameters.Add("@VRMKFK", SqlDbType.Decimal).Value = (object)template.Vrmkfk ?? DBNull.Value;
|
||
command.Parameters["@VRMKFK"].Precision = 10;
|
||
command.Parameters["@VRMKFK"].Scale = 2;
|
||
command.Parameters.Add("@IDKSP", SqlDbType.Int).Value = (object)template.IdKsp ?? DBNull.Value;
|
||
command.Parameters.Add("@DPZNmp", SqlDbType.NVarChar, 100).Value = (object)template.Dpznmp ?? DBNull.Value;
|
||
command.Parameters.Add("@HRTCmp", SqlDbType.NVarChar, 80).Value = (object)template.Hrtcmp ?? DBNull.Value;
|
||
command.Parameters.Add("@IDSPVDSBMK", SqlDbType.Int).Value = (object)template.IdSpvdsbmk ?? DBNull.Value;
|
||
command.Parameters.Add("@PRCHNPGDN", SqlDbType.NVarChar, 1024).Value = pendingLine != null && pendingLine.IsPassed == false
|
||
? (object)(string.IsNullOrWhiteSpace(pendingLine.RejectionReason) ? null : pendingLine.RejectionReason.Trim())
|
||
: DBNull.Value;
|
||
command.Parameters.Add("@IDEKZETL", SqlDbType.Int).Value = (object)template.IdEkzetl ?? DBNull.Value;
|
||
|
||
return Convert.ToInt32(command.ExecuteScalar());
|
||
}
|
||
}
|
||
|
||
private static HashSet<string> LoadDocumentDuplicateKeys(SqlConnection connection, SqlTransaction transaction, string documentNumber)
|
||
{
|
||
const string sql = @"
|
||
SELECT DISTINCT
|
||
tips.TP AS InstrumentType,
|
||
sizeInfo.DPZN AS RangeText,
|
||
sizeInfo.NNGSRS AS RegistryNumber,
|
||
z.NNZV AS SerialNumber
|
||
FROM dbo.EKZMK m
|
||
JOIN dbo.EKZ z ON z.IDEKZ = m.IDEKZ
|
||
LEFT JOIN dbo.TPRZ sizeInfo ON sizeInfo.IDTPRZ = z.IDTPRZ
|
||
LEFT JOIN dbo.TIPS tips ON tips.IDTIPS = sizeInfo.IDTIPS
|
||
WHERE m.NNZVPV = @DocumentNumber;";
|
||
|
||
var keys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
keys.Add(PsvDocumentLine.BuildDuplicateKey(
|
||
GetString(reader, "InstrumentType"),
|
||
GetString(reader, "RangeText"),
|
||
GetString(reader, "RegistryNumber"),
|
||
GetString(reader, "SerialNumber")));
|
||
}
|
||
}
|
||
}
|
||
|
||
return keys;
|
||
}
|
||
|
||
private static List<DeleteBlockerInfo> LoadDeleteBlockers(SqlConnection connection, SqlTransaction transaction, IEnumerable<int> cardIds)
|
||
{
|
||
var aggregated = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||
|
||
foreach (var cardId in cardIds)
|
||
{
|
||
foreach (var blocker in LoadDeleteBlockers(connection, transaction, cardId))
|
||
{
|
||
int currentCount;
|
||
if (!aggregated.TryGetValue(blocker.TableName, out currentCount))
|
||
{
|
||
currentCount = 0;
|
||
}
|
||
|
||
aggregated[blocker.TableName] = currentCount + blocker.RowCount;
|
||
}
|
||
}
|
||
|
||
return aggregated
|
||
.OrderBy(delegate(KeyValuePair<string, int> blocker) { return blocker.Key; })
|
||
.Select(delegate(KeyValuePair<string, int> blocker)
|
||
{
|
||
return new DeleteBlockerInfo
|
||
{
|
||
TableName = blocker.Key,
|
||
RowCount = blocker.Value
|
||
};
|
||
})
|
||
.ToList();
|
||
}
|
||
|
||
private static List<DeleteBlockerInfo> LoadDeleteBlockers(SqlConnection connection, SqlTransaction transaction, int cardId)
|
||
{
|
||
const string sql = @"
|
||
SELECT blocker.TableName, blocker.LinkCount
|
||
FROM
|
||
(
|
||
SELECT N'EKZMKDH' AS TableName, COUNT(*) AS LinkCount
|
||
FROM dbo.EKZMKDH child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZMK = @CardId
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'EKZMKEKZK', COUNT(*)
|
||
FROM dbo.EKZMKEKZK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZMK = @CardId
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'EKZMKND', COUNT(*)
|
||
FROM dbo.EKZMKND child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZMK = @CardId
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'FRPTMK', COUNT(*)
|
||
FROM dbo.FRPTMK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZMK = @CardId
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'KSPELEKZMK', COUNT(*)
|
||
FROM dbo.KSPELEKZMK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZMK = @CardId
|
||
) blocker
|
||
WHERE blocker.LinkCount > 0
|
||
ORDER BY blocker.TableName;";
|
||
|
||
var blockers = new List<DeleteBlockerInfo>();
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
blockers.Add(new DeleteBlockerInfo
|
||
{
|
||
TableName = GetString(reader, "TableName"),
|
||
RowCount = GetInt32(reader, "LinkCount")
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
return blockers;
|
||
}
|
||
|
||
private static List<DeleteBlockerInfo> LoadDeleteBlockers(SqlConnection connection, SqlTransaction transaction, string documentNumber)
|
||
{
|
||
const string sql = @"
|
||
SELECT blocker.TableName, blocker.LinkCount
|
||
FROM
|
||
(
|
||
SELECT N'EKZMKDH' AS TableName, COUNT(*) AS LinkCount
|
||
FROM dbo.EKZMKDH child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.NNZVPV = @DocumentNumber
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'EKZMKEKZK', COUNT(*)
|
||
FROM dbo.EKZMKEKZK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.NNZVPV = @DocumentNumber
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'EKZMKND', COUNT(*)
|
||
FROM dbo.EKZMKND child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.NNZVPV = @DocumentNumber
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'FRPTMK', COUNT(*)
|
||
FROM dbo.FRPTMK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.NNZVPV = @DocumentNumber
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'KSPELEKZMK', COUNT(*)
|
||
FROM dbo.KSPELEKZMK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.NNZVPV = @DocumentNumber
|
||
) blocker
|
||
WHERE blocker.LinkCount > 0
|
||
ORDER BY blocker.TableName;";
|
||
|
||
var blockers = new List<DeleteBlockerInfo>();
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
blockers.Add(new DeleteBlockerInfo
|
||
{
|
||
TableName = GetString(reader, "TableName"),
|
||
RowCount = GetInt32(reader, "LinkCount")
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
return blockers;
|
||
}
|
||
|
||
private static async Task<List<DeleteBlockerInfo>> LoadDeleteBlockersAsync(SqlConnection connection, SqlTransaction transaction, IEnumerable<int> cardIds, CancellationToken cancellationToken = default)
|
||
{
|
||
var aggregated = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||
|
||
foreach (var cardId in cardIds)
|
||
{
|
||
foreach (var blocker in await LoadDeleteBlockersAsync(connection, transaction, cardId, cancellationToken).ConfigureAwait(false))
|
||
{
|
||
int currentCount;
|
||
if (!aggregated.TryGetValue(blocker.TableName, out currentCount))
|
||
{
|
||
currentCount = 0;
|
||
}
|
||
|
||
aggregated[blocker.TableName] = currentCount + blocker.RowCount;
|
||
}
|
||
}
|
||
|
||
return aggregated
|
||
.OrderBy(delegate(KeyValuePair<string, int> blocker) { return blocker.Key; })
|
||
.Select(delegate(KeyValuePair<string, int> blocker)
|
||
{
|
||
return new DeleteBlockerInfo
|
||
{
|
||
TableName = blocker.Key,
|
||
RowCount = blocker.Value
|
||
};
|
||
})
|
||
.ToList();
|
||
}
|
||
|
||
private static Task<List<DeleteBlockerInfo>> LoadDeleteBlockersAsync(SqlConnection connection, SqlTransaction transaction, int cardId, CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
SELECT blocker.TableName, blocker.LinkCount
|
||
FROM
|
||
(
|
||
SELECT N'EKZMKDH' AS TableName, COUNT(*) AS LinkCount
|
||
FROM dbo.EKZMKDH child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZMK = @CardId
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'EKZMKEKZK', COUNT(*)
|
||
FROM dbo.EKZMKEKZK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZMK = @CardId
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'EKZMKND', COUNT(*)
|
||
FROM dbo.EKZMKND child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZMK = @CardId
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'FRPTMK', COUNT(*)
|
||
FROM dbo.FRPTMK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZMK = @CardId
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'KSPELEKZMK', COUNT(*)
|
||
FROM dbo.KSPELEKZMK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.IDEKZMK = @CardId
|
||
) blocker
|
||
WHERE blocker.LinkCount > 0
|
||
ORDER BY blocker.TableName;";
|
||
|
||
return connection.QueryAsync(
|
||
transaction,
|
||
sql,
|
||
delegate(SqlDataReader reader)
|
||
{
|
||
return new DeleteBlockerInfo
|
||
{
|
||
TableName = GetString(reader, "TableName"),
|
||
RowCount = GetInt32(reader, "LinkCount")
|
||
};
|
||
},
|
||
delegate(SqlCommand command)
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@CardId", SqlDbType.Int).Value = cardId;
|
||
},
|
||
cancellationToken);
|
||
}
|
||
|
||
private static Task<List<DeleteBlockerInfo>> LoadDeleteBlockersAsync(SqlConnection connection, SqlTransaction transaction, string documentNumber, CancellationToken cancellationToken = default)
|
||
{
|
||
const string sql = @"
|
||
SELECT blocker.TableName, blocker.LinkCount
|
||
FROM
|
||
(
|
||
SELECT N'EKZMKDH' AS TableName, COUNT(*) AS LinkCount
|
||
FROM dbo.EKZMKDH child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.NNZVPV = @DocumentNumber
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'EKZMKEKZK', COUNT(*)
|
||
FROM dbo.EKZMKEKZK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.NNZVPV = @DocumentNumber
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'EKZMKND', COUNT(*)
|
||
FROM dbo.EKZMKND child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.NNZVPV = @DocumentNumber
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'FRPTMK', COUNT(*)
|
||
FROM dbo.FRPTMK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.NNZVPV = @DocumentNumber
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'KSPELEKZMK', COUNT(*)
|
||
FROM dbo.KSPELEKZMK child
|
||
JOIN dbo.EKZMK parent ON parent.IDEKZMK = child.IDEKZMK
|
||
WHERE parent.NNZVPV = @DocumentNumber
|
||
) blocker
|
||
WHERE blocker.LinkCount > 0
|
||
ORDER BY blocker.TableName;";
|
||
|
||
return connection.QueryAsync(
|
||
transaction,
|
||
sql,
|
||
delegate(SqlDataReader reader)
|
||
{
|
||
return new DeleteBlockerInfo
|
||
{
|
||
TableName = GetString(reader, "TableName"),
|
||
RowCount = GetInt32(reader, "LinkCount")
|
||
};
|
||
},
|
||
delegate(SqlCommand command)
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@DocumentNumber", SqlDbType.NVarChar, 60).Value = documentNumber;
|
||
},
|
||
cancellationToken);
|
||
}
|
||
|
||
private static InstrumentIdentityInfo LoadInstrumentIdentity(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
const string sql = @"
|
||
SELECT
|
||
tips.TP AS InstrumentType,
|
||
sizeInfo.DPZN AS RangeText,
|
||
sizeInfo.NNGSRS AS RegistryNumber,
|
||
z.NNZV AS SerialNumber
|
||
FROM dbo.EKZ z
|
||
LEFT JOIN dbo.TPRZ sizeInfo ON sizeInfo.IDTPRZ = z.IDTPRZ
|
||
LEFT JOIN dbo.TIPS tips ON tips.IDTIPS = sizeInfo.IDTIPS
|
||
WHERE z.IDEKZ = @InstrumentId;";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.Parameters.Add("@InstrumentId", SqlDbType.Int).Value = instrumentId;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
if (!reader.Read())
|
||
{
|
||
return null;
|
||
}
|
||
|
||
return new InstrumentIdentityInfo
|
||
{
|
||
DuplicateKey = PsvDocumentLine.BuildDuplicateKey(
|
||
GetString(reader, "InstrumentType"),
|
||
GetString(reader, "RangeText"),
|
||
GetString(reader, "RegistryNumber"),
|
||
GetString(reader, "SerialNumber"))
|
||
};
|
||
}
|
||
}
|
||
}
|
||
|
||
private static int LoadVerificationTypeId(SqlConnection connection, SqlTransaction transaction)
|
||
{
|
||
const string sql = @"
|
||
SELECT TOP (1) IDSPVDMK
|
||
FROM dbo.SPVDMK
|
||
WHERE OBVDMK = N'П' OR NMVDMK = N'Поверка'
|
||
ORDER BY CASE WHEN OBVDMK = N'Рџ' THEN 0 ELSE 1 END, IDSPVDMK;";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
var result = command.ExecuteScalar();
|
||
if (result == null || result == DBNull.Value)
|
||
{
|
||
throw new InvalidOperationException("В справочнике SPVDMK не найден вид МК 'Поверка'.");
|
||
}
|
||
|
||
return Convert.ToInt32(result);
|
||
}
|
||
}
|
||
|
||
private static EkzMkTemplate LoadTemplate(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
const string sql = @"
|
||
DECLARE @TypeSizeId int;
|
||
SELECT @TypeSizeId = IDTPRZ FROM dbo.EKZ WHERE IDEKZ = @InstrumentId;
|
||
|
||
WITH TemplateCandidates AS
|
||
(
|
||
SELECT *
|
||
FROM
|
||
(
|
||
SELECT TOP (1)
|
||
1 AS Priority,
|
||
m.IDSPMU,
|
||
m.IDGRSI,
|
||
m.IDKSPRL,
|
||
m.IDSPVDMC,
|
||
m.IDFRPD,
|
||
m.IDSPMPOB,
|
||
m.IDPRSN,
|
||
m.IDSPKMMK,
|
||
m.IDSPVDKL,
|
||
m.IDPRSNVD,
|
||
m.PRMK,
|
||
m.STMK,
|
||
m.STMKDP,
|
||
m.NCSRMK,
|
||
m.idprsnsd,
|
||
m.idprsnpr,
|
||
m.idprsnvy,
|
||
m.idsptsmp,
|
||
m.idspssmp,
|
||
m.NRVRMNDmp,
|
||
m.NRVRMmp,
|
||
m.VRMKFK,
|
||
m.IDKSP,
|
||
m.DPZNmp,
|
||
m.HRTCmp,
|
||
m.IDSPVDSBMK,
|
||
m.IDEKZETL,
|
||
CAST(N'Рстория РїСЂРёР±РѕСЂР°' AS nvarchar(60)) AS SourceDescription
|
||
FROM dbo.EKZMK m
|
||
WHERE m.IDEKZ = @InstrumentId
|
||
ORDER BY ISNULL(m.DTPRM, CONVERT(datetime, '19000101', 112)) DESC, m.IDEKZMK DESC
|
||
) instrumentTemplate
|
||
UNION ALL
|
||
SELECT *
|
||
FROM
|
||
(
|
||
SELECT TOP (1)
|
||
2 AS Priority,
|
||
m.IDSPMU,
|
||
m.IDGRSI,
|
||
m.IDKSPRL,
|
||
m.IDSPVDMC,
|
||
m.IDFRPD,
|
||
m.IDSPMPOB,
|
||
m.IDPRSN,
|
||
m.IDSPKMMK,
|
||
m.IDSPVDKL,
|
||
m.IDPRSNVD,
|
||
m.PRMK,
|
||
m.STMK,
|
||
m.STMKDP,
|
||
m.NCSRMK,
|
||
m.idprsnsd,
|
||
m.idprsnpr,
|
||
m.idprsnvy,
|
||
m.idsptsmp,
|
||
m.idspssmp,
|
||
m.NRVRMNDmp,
|
||
m.NRVRMmp,
|
||
m.VRMKFK,
|
||
m.IDKSP,
|
||
m.DPZNmp,
|
||
m.HRTCmp,
|
||
m.IDSPVDSBMK,
|
||
m.IDEKZETL,
|
||
CAST(N'Шаблон по типоразмеру' AS nvarchar(60)) AS SourceDescription
|
||
FROM dbo.EKZMK m
|
||
JOIN dbo.EKZ z ON z.IDEKZ = m.IDEKZ
|
||
WHERE z.IDTPRZ = @TypeSizeId
|
||
ORDER BY ISNULL(m.DTPRM, CONVERT(datetime, '19000101', 112)) DESC, m.IDEKZMK DESC
|
||
) typeTemplate
|
||
)
|
||
SELECT TOP (1) *
|
||
FROM TemplateCandidates
|
||
ORDER BY Priority;";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.Parameters.Add("@InstrumentId", SqlDbType.Int).Value = instrumentId;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
if (reader.Read())
|
||
{
|
||
return new EkzMkTemplate
|
||
{
|
||
IdSpmu = GetNullableInt32(reader, "IDSPMU"),
|
||
IdGrsi = GetNullableInt32(reader, "IDGRSI"),
|
||
IdKsprl = GetNullableInt32(reader, "IDKSPRL"),
|
||
IdSpvdmc = GetNullableInt32(reader, "IDSPVDMC"),
|
||
IdFrpd = GetInt32(reader, "IDFRPD"),
|
||
IdSpmpob = GetNullableInt32(reader, "IDSPMPOB"),
|
||
IdPrsn = GetNullableInt32(reader, "IDPRSN"),
|
||
IdSpkmmk = GetNullableInt32(reader, "IDSPKMMK"),
|
||
IdSpvdkl = GetNullableInt32(reader, "IDSPVDKL"),
|
||
IdPrsnvd = GetNullableInt32(reader, "IDPRSNVD"),
|
||
Prmk = GetInt32(reader, "PRMK"),
|
||
Stmk = GetNullableDecimal(reader, "STMK"),
|
||
Stmkdp = GetNullableDecimal(reader, "STMKDP"),
|
||
NcSrmk = GetNullableDecimal(reader, "NCSRMK"),
|
||
IdPrsnsd = GetNullableInt32(reader, "idprsnsd"),
|
||
IdPrsnpr = GetNullableInt32(reader, "idprsnpr"),
|
||
IdPrsnvy = GetNullableInt32(reader, "idprsnvy"),
|
||
IdSptsmp = GetNullableInt32(reader, "idsptsmp"),
|
||
IdSpssmp = GetNullableInt32(reader, "idspssmp"),
|
||
Nrvrmndmp = GetNullableDecimal(reader, "NRVRMNDmp"),
|
||
Nrvrmmp = GetNullableDecimal(reader, "NRVRMmp"),
|
||
Vrmkfk = GetNullableDecimal(reader, "VRMKFK"),
|
||
IdKsp = GetNullableInt32(reader, "IDKSP"),
|
||
Dpznmp = GetString(reader, "DPZNmp"),
|
||
Hrtcmp = GetString(reader, "HRTCmp"),
|
||
IdSpvdsbmk = GetNullableInt32(reader, "IDSPVDSBMK"),
|
||
IdEkzetl = GetNullableInt32(reader, "IDEKZETL"),
|
||
SourceDescription = GetString(reader, "SourceDescription")
|
||
};
|
||
}
|
||
}
|
||
}
|
||
|
||
return LoadFallbackTemplate(connection, transaction, instrumentId);
|
||
}
|
||
|
||
private static EkzMkTemplate LoadFallbackTemplate(SqlConnection connection, SqlTransaction transaction, int instrumentId)
|
||
{
|
||
const string sql = @"
|
||
WITH DefaultLab AS
|
||
(
|
||
SELECT
|
||
CASE WHEN COUNT(DISTINCT m.IDFRPD) = 1 THEN MIN(m.IDFRPD) ELSE NULL END AS DefaultIdFrpd
|
||
FROM dbo.EKZMK m
|
||
)
|
||
SELECT TOP (1)
|
||
COALESCE(periodByInstrument.IDGRSI, periodByType.IDGRSI) AS IDGRSI,
|
||
COALESCE(periodByInstrument.IDSPVDMC, periodByType.IDSPVDMC) AS IDSPVDMC,
|
||
defaultLab.DefaultIdFrpd AS IDFRPD,
|
||
tprz.IDSPKMMK,
|
||
COALESCE(periodByInstrument.PRMK, periodByType.PRMK, tips.PRMKGR) AS PRMK,
|
||
tprz.DPZN AS DPZNmp,
|
||
tprz.HRTC AS HRTCmp,
|
||
CAST(
|
||
CASE
|
||
WHEN COALESCE(periodByInstrument.PRMK, periodByType.PRMK) IS NOT NULL THEN N'Период из TPRMCP'
|
||
WHEN tips.PRMKGR IS NOT NULL THEN N'Регистрационный период из TIPS'
|
||
ELSE N''
|
||
END AS nvarchar(60)) AS SourceDescription
|
||
FROM dbo.EKZ z
|
||
JOIN dbo.TPRZ tprz ON tprz.IDTPRZ = z.IDTPRZ
|
||
JOIN dbo.TIPS tips ON tips.IDTIPS = tprz.IDTIPS
|
||
CROSS JOIN DefaultLab defaultLab
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
t.IDGRSI,
|
||
t.IDSPVDMC,
|
||
t.PRMK
|
||
FROM dbo.EKZMCP e
|
||
JOIN dbo.TPRMCP t ON t.IDTPRMCP = e.IDTPRMCP
|
||
WHERE e.IDEKZ = z.IDEKZ
|
||
ORDER BY e.IDEKZMCP DESC, t.IDTPRMCP DESC
|
||
) periodByInstrument
|
||
OUTER APPLY
|
||
(
|
||
SELECT TOP (1)
|
||
t.IDGRSI,
|
||
t.IDSPVDMC,
|
||
t.PRMK
|
||
FROM dbo.TPRMCP t
|
||
WHERE t.IDTPRZ = z.IDTPRZ
|
||
ORDER BY t.IDTPRMCP DESC
|
||
) periodByType
|
||
WHERE z.IDEKZ = @InstrumentId
|
||
AND defaultLab.DefaultIdFrpd IS NOT NULL
|
||
AND COALESCE(periodByInstrument.PRMK, periodByType.PRMK, tips.PRMKGR) IS NOT NULL;";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.Parameters.Add("@InstrumentId", SqlDbType.Int).Value = instrumentId;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
if (!reader.Read())
|
||
{
|
||
return null;
|
||
}
|
||
|
||
return new EkzMkTemplate
|
||
{
|
||
IdSpmu = null,
|
||
IdGrsi = GetNullableInt32(reader, "IDGRSI"),
|
||
IdKsprl = null,
|
||
IdSpvdmc = GetNullableInt32(reader, "IDSPVDMC"),
|
||
IdFrpd = GetInt32(reader, "IDFRPD"),
|
||
IdSpmpob = null,
|
||
IdPrsn = null,
|
||
IdSpkmmk = GetNullableInt32(reader, "IDSPKMMK"),
|
||
IdSpvdkl = null,
|
||
IdPrsnvd = null,
|
||
Prmk = GetInt32(reader, "PRMK"),
|
||
Stmk = null,
|
||
Stmkdp = null,
|
||
NcSrmk = null,
|
||
IdPrsnsd = null,
|
||
IdPrsnpr = null,
|
||
IdPrsnvy = null,
|
||
IdSptsmp = null,
|
||
IdSpssmp = null,
|
||
Nrvrmndmp = null,
|
||
Nrvrmmp = null,
|
||
Vrmkfk = null,
|
||
IdKsp = null,
|
||
Dpznmp = GetString(reader, "DPZNmp"),
|
||
Hrtcmp = GetString(reader, "HRTCmp"),
|
||
IdSpvdsbmk = null,
|
||
IdEkzetl = null,
|
||
SourceDescription = GetString(reader, "SourceDescription")
|
||
};
|
||
}
|
||
}
|
||
}
|
||
|
||
private static string NormalizeDocumentNumber(string value)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(value))
|
||
{
|
||
return null;
|
||
}
|
||
|
||
return value.Trim();
|
||
}
|
||
|
||
private static void ConfigureCommandTimeout(SqlCommand command)
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
}
|
||
|
||
private static SpoiDirectoryItem NormalizeSpoiItem(SpoiDirectoryItem item)
|
||
{
|
||
if (item == null)
|
||
{
|
||
throw new ArgumentNullException("item");
|
||
}
|
||
|
||
var code = NormalizeRequiredSpoiValue(
|
||
item.Code,
|
||
"Код ОРне заполнен.",
|
||
SpoiDirectoryRules.CodeMaxLength,
|
||
"Код ОРпревышает допустимую длину.");
|
||
var name = NormalizeRequiredSpoiValue(
|
||
item.Name,
|
||
"Область измерений не заполнена.",
|
||
SpoiDirectoryRules.NameMaxLength,
|
||
"Область измерений превышает допустимую длину.");
|
||
|
||
return new SpoiDirectoryItem
|
||
{
|
||
Id = item.Id,
|
||
Code = code,
|
||
Name = name
|
||
};
|
||
}
|
||
|
||
private static void EnsureSpoiCodeIsUnique(SqlConnection connection, string code, int? excludeId)
|
||
{
|
||
const string sql = @"
|
||
SELECT TOP (1) IDSPOI
|
||
FROM dbo.SPOI
|
||
WHERE KDOI = @Code
|
||
AND (@ExcludeId IS NULL OR IDSPOI <> @ExcludeId);";
|
||
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@Code", SqlDbType.VarChar, SpoiDirectoryRules.CodeMaxLength).Value = code;
|
||
command.Parameters.Add("@ExcludeId", SqlDbType.Int).Value = (object)excludeId ?? DBNull.Value;
|
||
|
||
var existingId = command.ExecuteScalar();
|
||
if (existingId != null && existingId != DBNull.Value)
|
||
{
|
||
throw CreateSpoiDuplicateCodeException(code, null);
|
||
}
|
||
}
|
||
}
|
||
|
||
private static void EnsureSpoiNameIsUnique(SqlConnection connection, string name, int? excludeId)
|
||
{
|
||
const string sql = @"
|
||
SELECT TOP (1) IDSPOI
|
||
FROM dbo.SPOI
|
||
WHERE NMOI = @Name
|
||
AND (@ExcludeId IS NULL OR IDSPOI <> @ExcludeId);";
|
||
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@Name", SqlDbType.VarChar, SpoiDirectoryRules.NameMaxLength).Value = name;
|
||
command.Parameters.Add("@ExcludeId", SqlDbType.Int).Value = (object)excludeId ?? DBNull.Value;
|
||
|
||
var existingId = command.ExecuteScalar();
|
||
if (existingId != null && existingId != DBNull.Value)
|
||
{
|
||
throw CreateSpoiDuplicateNameException(name, null);
|
||
}
|
||
}
|
||
}
|
||
|
||
private static InvalidOperationException CreateSpoiDuplicateCodeException(string code, Exception innerException)
|
||
{
|
||
return new InvalidOperationException(
|
||
string.Format("Код ОР\"{0}\" уже существует в справочнике.", code),
|
||
innerException);
|
||
}
|
||
|
||
private static InvalidOperationException CreateSpoiDuplicateNameException(string name, Exception innerException)
|
||
{
|
||
return new InvalidOperationException(
|
||
string.Format("Область измерений \"{0}\" уже существует в справочнике.", name),
|
||
innerException);
|
||
}
|
||
|
||
private static List<DeleteBlockerInfo> LoadSpoiDeleteBlockers(SqlConnection connection, int id)
|
||
{
|
||
const string sql = @"
|
||
SELECT blocker.TableName, blocker.LinkCount
|
||
FROM
|
||
(
|
||
SELECT N'FRATGR' AS TableName, COUNT(*) AS LinkCount
|
||
FROM dbo.FRATGR
|
||
WHERE IDSPOI = @Id
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'PRATGR', COUNT(*)
|
||
FROM dbo.PRATGR
|
||
WHERE IDSPOI = @Id
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'PRSTOI', COUNT(*)
|
||
FROM dbo.PRSTOI
|
||
WHERE IDSPOI = @Id
|
||
|
||
UNION ALL
|
||
|
||
SELECT N'TIPS', COUNT(*)
|
||
FROM dbo.TIPS
|
||
WHERE IDSPOI = @Id
|
||
) blocker
|
||
WHERE blocker.LinkCount > 0
|
||
ORDER BY blocker.TableName;";
|
||
|
||
var blockers = new List<DeleteBlockerInfo>();
|
||
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@Id", SqlDbType.Int).Value = id;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
blockers.Add(new DeleteBlockerInfo
|
||
{
|
||
TableName = GetString(reader, "TableName"),
|
||
RowCount = GetInt32(reader, "LinkCount")
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
return blockers;
|
||
}
|
||
|
||
private static string CreateSpoiDeleteBlockedMessage(IEnumerable<DeleteBlockerInfo> blockers)
|
||
{
|
||
var blockerList = blockers == null
|
||
? new List<DeleteBlockerInfo>()
|
||
: blockers.Where(delegate(DeleteBlockerInfo blocker) { return blocker != null; }).ToList();
|
||
var details = blockerList.Count == 0
|
||
? "FRATGR, PRATGR, PRSTOI, TIPS"
|
||
: string.Join(", ", blockerList.Select(delegate(DeleteBlockerInfo blocker)
|
||
{
|
||
return string.Format("{0}: {1}", blocker.TableName, blocker.RowCount);
|
||
}));
|
||
|
||
return string.Format(
|
||
"Запись SPOI не может быть удалена, потому что на неё есть ссылки в таблицах: {0}. Подтверждённые ограничения БД: FK_FRATGR_SPOI, FK_PRATGR_SPOI, FK_PRSTOI_SPOI, FK_TIPS_SPOI.",
|
||
details);
|
||
}
|
||
|
||
private static string CreateSpoiDeleteBlockedMessage(SqlException ex)
|
||
{
|
||
if (ex != null && ex.Message.IndexOf("FK_FRATGR_SPOI", StringComparison.OrdinalIgnoreCase) >= 0)
|
||
{
|
||
return "Запись SPOI не может быть удалена, потому что на неё есть ссылки в таблице FRATGR. Ограничение БД: FK_FRATGR_SPOI (dbo.FRATGR.IDSPOI -> dbo.SPOI.IDSPOI).";
|
||
}
|
||
|
||
if (ex != null && ex.Message.IndexOf("FK_PRATGR_SPOI", StringComparison.OrdinalIgnoreCase) >= 0)
|
||
{
|
||
return "Запись SPOI не может быть удалена, потому что на неё есть ссылки в таблице PRATGR. Ограничение БД: FK_PRATGR_SPOI (dbo.PRATGR.IDSPOI -> dbo.SPOI.IDSPOI).";
|
||
}
|
||
|
||
if (ex != null && ex.Message.IndexOf("FK_PRSTOI_SPOI", StringComparison.OrdinalIgnoreCase) >= 0)
|
||
{
|
||
return "Запись SPOI не может быть удалена, потому что на неё есть ссылки в таблице PRSTOI. Ограничение БД: FK_PRSTOI_SPOI (dbo.PRSTOI.IDSPOI -> dbo.SPOI.IDSPOI).";
|
||
}
|
||
|
||
if (ex != null && ex.Message.IndexOf("FK_TIPS_SPOI", StringComparison.OrdinalIgnoreCase) >= 0)
|
||
{
|
||
return "Запись SPOI не может быть удалена, потому что на неё есть ссылки в таблице TIPS. Ограничение БД: FK_TIPS_SPOI (dbo.TIPS.IDSPOI -> dbo.SPOI.IDSPOI).";
|
||
}
|
||
|
||
return "Запись SPOI не может быть удалена из-за ограничения ссылочной целостности в БД.";
|
||
}
|
||
|
||
private static bool IsSpoiDuplicateCodeViolation(SqlException ex)
|
||
{
|
||
return ex != null
|
||
&& (ex.Number == 2601 || ex.Number == 2627)
|
||
&& ex.Message.IndexOf("XAK2SPOI", StringComparison.OrdinalIgnoreCase) >= 0;
|
||
}
|
||
|
||
private static bool IsSpoiDuplicateNameViolation(SqlException ex)
|
||
{
|
||
return ex != null
|
||
&& (ex.Number == 2601 || ex.Number == 2627)
|
||
&& ex.Message.IndexOf("XAK1SPOI", StringComparison.OrdinalIgnoreCase) >= 0;
|
||
}
|
||
|
||
private static string NormalizeRequiredSpoiValue(string value, string emptyErrorMessage, int maxLength, string tooLongErrorMessage)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(value))
|
||
{
|
||
throw new InvalidOperationException(emptyErrorMessage);
|
||
}
|
||
|
||
var normalizedValue = value.Trim();
|
||
if (normalizedValue.Length > maxLength)
|
||
{
|
||
throw new InvalidOperationException(tooLongErrorMessage);
|
||
}
|
||
|
||
return normalizedValue;
|
||
}
|
||
|
||
private static SpnmtpDirectoryItem NormalizeSpnmtpItem(SpnmtpDirectoryItem item)
|
||
{
|
||
if (item == null)
|
||
{
|
||
throw new ArgumentNullException("item");
|
||
}
|
||
|
||
var name = NormalizeRequiredSpnmtpValue(
|
||
item.Name,
|
||
"Наименование типа СРне заполнено.",
|
||
SpnmtpDirectoryRules.NameMaxLength,
|
||
"Наименование типа СРпревышает допустимую длину.");
|
||
var specialName = NormalizeOptionalSpnmtpValue(
|
||
item.SpecialName,
|
||
SpnmtpDirectoryRules.SpecialNameMaxLength,
|
||
"Специальное наименование типа превышает допустимую длину.");
|
||
|
||
return new SpnmtpDirectoryItem
|
||
{
|
||
Id = item.Id,
|
||
Name = name,
|
||
SpecialName = specialName
|
||
};
|
||
}
|
||
|
||
private static void EnsureSpnmtpNameIsUnique(SqlConnection connection, string name, int? excludeId)
|
||
{
|
||
const string sql = @"
|
||
SELECT TOP (1) IDSPNMTP
|
||
FROM dbo.SPNMTP
|
||
WHERE NMTP = @Name
|
||
AND (@ExcludeId IS NULL OR IDSPNMTP <> @ExcludeId);";
|
||
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@Name", SqlDbType.NVarChar, SpnmtpDirectoryRules.NameMaxLength).Value = name;
|
||
command.Parameters.Add("@ExcludeId", SqlDbType.Int).Value = (object)excludeId ?? DBNull.Value;
|
||
|
||
var existingId = command.ExecuteScalar();
|
||
if (existingId != null && existingId != DBNull.Value)
|
||
{
|
||
throw CreateSpnmtpDuplicateNameException(name, null);
|
||
}
|
||
}
|
||
}
|
||
|
||
private static InvalidOperationException CreateSpnmtpDuplicateNameException(string name, Exception innerException)
|
||
{
|
||
return new InvalidOperationException(
|
||
string.Format("Наименование типа СР\"{0}\" уже существует в справочнике.", name),
|
||
innerException);
|
||
}
|
||
|
||
private static List<DeleteBlockerInfo> LoadSpnmtpDeleteBlockers(SqlConnection connection, int id)
|
||
{
|
||
const string sql = @"
|
||
SELECT blocker.TableName, blocker.LinkCount
|
||
FROM
|
||
(
|
||
SELECT N'TIPS' AS TableName, COUNT(*) AS LinkCount
|
||
FROM dbo.TIPS
|
||
WHERE IDSPNMTP = @Id
|
||
) blocker
|
||
WHERE blocker.LinkCount > 0
|
||
ORDER BY blocker.TableName;";
|
||
|
||
var blockers = new List<DeleteBlockerInfo>();
|
||
|
||
using (var command = new SqlCommand(sql, connection))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@Id", SqlDbType.Int).Value = id;
|
||
|
||
using (var reader = command.ExecuteReader())
|
||
{
|
||
while (reader.Read())
|
||
{
|
||
blockers.Add(new DeleteBlockerInfo
|
||
{
|
||
TableName = GetString(reader, "TableName"),
|
||
RowCount = GetInt32(reader, "LinkCount")
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
return blockers;
|
||
}
|
||
|
||
private static string CreateSpnmtpDeleteBlockedMessage(IEnumerable<DeleteBlockerInfo> blockers)
|
||
{
|
||
var blockerList = blockers == null
|
||
? new List<DeleteBlockerInfo>()
|
||
: blockers.Where(delegate(DeleteBlockerInfo blocker) { return blocker != null; }).ToList();
|
||
var details = blockerList.Count == 0
|
||
? "TIPS"
|
||
: string.Join(", ", blockerList.Select(delegate(DeleteBlockerInfo blocker)
|
||
{
|
||
return string.Format("{0}: {1}", blocker.TableName, blocker.RowCount);
|
||
}));
|
||
|
||
return string.Format(
|
||
"Запись SPNMTP не может быть удалена, потому что на неё есть ссылки в таблицах: {0}. Подтверждённое ограничение БД: FK_TIPS_SPNMTP (dbo.TIPS.IDSPNMTP -> dbo.SPNMTP.IDSPNMTP).",
|
||
details);
|
||
}
|
||
|
||
private static string CreateSpnmtpDeleteBlockedMessage(SqlException ex)
|
||
{
|
||
if (ex != null && ex.Message.IndexOf("FK_TIPS_SPNMTP", StringComparison.OrdinalIgnoreCase) >= 0)
|
||
{
|
||
return "Запись SPNMTP не может быть удалена, потому что на неё есть ссылки в таблице TIPS. Ограничение БД: FK_TIPS_SPNMTP (dbo.TIPS.IDSPNMTP -> dbo.SPNMTP.IDSPNMTP).";
|
||
}
|
||
|
||
return "Запись SPNMTP не может быть удалена из-за ограничения ссылочной целостности в БД.";
|
||
}
|
||
|
||
private static bool IsSpnmtpDuplicateNameViolation(SqlException ex)
|
||
{
|
||
return ex != null
|
||
&& (ex.Number == 2601 || ex.Number == 2627)
|
||
&& ex.Message.IndexOf("XAK1SPNMTP", StringComparison.OrdinalIgnoreCase) >= 0;
|
||
}
|
||
|
||
private static string NormalizeRequiredSpnmtpValue(string value, string emptyErrorMessage, int maxLength, string tooLongErrorMessage)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(value))
|
||
{
|
||
throw new InvalidOperationException(emptyErrorMessage);
|
||
}
|
||
|
||
var normalizedValue = value.Trim();
|
||
if (normalizedValue.Length > maxLength)
|
||
{
|
||
throw new InvalidOperationException(tooLongErrorMessage);
|
||
}
|
||
|
||
return normalizedValue;
|
||
}
|
||
|
||
private static string NormalizeOptionalSpnmtpValue(string value, int maxLength, string tooLongErrorMessage)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(value))
|
||
{
|
||
return null;
|
||
}
|
||
|
||
var normalizedValue = value.Trim();
|
||
if (normalizedValue.Length > maxLength)
|
||
{
|
||
throw new InvalidOperationException(tooLongErrorMessage);
|
||
}
|
||
|
||
return normalizedValue;
|
||
}
|
||
|
||
private static int UpdateDocumentHeader(SqlConnection connection, SqlTransaction transaction, string currentDocumentNumber, DocumentEditorResult document)
|
||
{
|
||
const string sql = @"
|
||
UPDATE dbo.EKZMK
|
||
SET NNZVPV = @NewDocumentNumber,
|
||
DTPRM = @AcceptedOn,
|
||
DTVDM = @IssuedOn
|
||
WHERE NNZVPV = @CurrentDocumentNumber;
|
||
|
||
SELECT @@ROWCOUNT;";
|
||
|
||
using (var command = new SqlCommand(sql, connection, transaction))
|
||
{
|
||
command.CommandTimeout = SqlServerConnectionFactory.Current.Options.CommandTimeoutSeconds;
|
||
command.Parameters.Add("@NewDocumentNumber", SqlDbType.NVarChar, 60).Value = document.DocumentNumber;
|
||
command.Parameters.Add("@AcceptedOn", SqlDbType.DateTime).Value = document.AcceptedOn;
|
||
command.Parameters.Add("@IssuedOn", SqlDbType.DateTime).Value = (object)document.IssuedOn ?? DBNull.Value;
|
||
command.Parameters.Add("@CurrentDocumentNumber", SqlDbType.NVarChar, 60).Value = currentDocumentNumber;
|
||
return Convert.ToInt32(command.ExecuteScalar());
|
||
}
|
||
}
|
||
|
||
private sealed class DeleteBlockerInfo
|
||
{
|
||
public int RowCount { get; set; }
|
||
|
||
public string TableName { get; set; }
|
||
}
|
||
|
||
private sealed class InstrumentIdentityInfo
|
||
{
|
||
public string DuplicateKey { get; set; }
|
||
}
|
||
}
|
||
}
|
||
|