Реализована логика отмены новых запросов

parent 32596a33
......@@ -35,10 +35,7 @@
</providers>
</configProtectedData>
<connectionStrings>
<clear />
<add name="RDnLContext" connectionString="metadata=res://RnD.Model.EF/RnDConnection.csdl|res://RnD.Model.EF/RnDConnection.ssdl|res://RnD.Model.EF/RnDConnection.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=LLK-DEV\;initial catalog=OpcenterRDnL;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
<add name="RDnLContext2" connectionString="metadata=res://*/RnDConnection.csdl|res://*/RnDConnection.ssdl|res://*/RnDConnection.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=LLK-DEV\;initial catalog=OpcenterRDnL;User=RDnLAppUser;Password=pass@word1;multipleactiveresultsets=True;application name=EntityFramework&quot;" providerName="System.Data.EntityClient" />
<add name="OpcenterRDnL" connectionString="metadata=res://*/RnDConnection.csdl|res://*/RnDConnection.ssdl|res://*/RnDConnection.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=LLK-DEV\;initial catalog=OpcenterRDnL;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
</connectionStrings>
<appSettings>
<add key="Resources" value="%public%\OpcenterRDnL\Resources" />
......
......@@ -5,7 +5,7 @@ using System.Security.Claims;
using System.Text;
using System.Text.Encodings.Web;
namespace ProfitGroup.SampleNotifyService.Core.Auth
namespace ProfitGroup.NotifyService.Core.Auth
{
public class BasicAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
......
......@@ -33,12 +33,12 @@
"writeTo": "allfile"
},
{
"logger": "ProfitGroup.SampleNotifyService.*",
"logger": "ProfitGroup.NotifyService.*",
"minLevel": "Trace",
"writeTo": "requests-web"
},
{
"logger": "ProfitGroup.SampleNotifyService.Core.Auth.*",
"logger": "ProfitGroup.NotifyService.Core.Auth.*",
"minLevel": "Trace",
"writeTo": "requests-web"
}
......
......@@ -7,7 +7,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProfitGroup.SampleService.C
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProfitGroup.Rdnl.Extensions", "ProfitGroup.Rdnl.Extensions\ProfitGroup.Rdnl.Extensions.csproj", "{CE66275C-0543-46D5-8DF7-0EC58562F408}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProfitGroup.SampleNotifyService", "ProfitGroup.SampleNotifyService\ProfitGroup.SampleNotifyService.csproj", "{9CC9E1EE-03E6-44BA-A461-7C2034921970}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProfitGroup.NotifyService", "ProfitGroup.NotifyService\ProfitGroup.NotifyService.csproj", "{9CC9E1EE-03E6-44BA-A461-7C2034921970}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProfitGroup.SampleRequest", "ProfitGroup.SampleRequest\ProfitGroup.SampleRequest.csproj", "{DD05EABA-B6DA-4BE0-8B53-9D659D5CC786}"
EndProject
......
......@@ -7,8 +7,11 @@ using RnD.BusinessLayer.EF.Factory;
using RnD.BusinessLayer.EF.Interfaces;
using RnD.Model.EF;
using System;
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Web.Http;
using ProfitGroup.SampleService.Models;
using Unity;
using Unity.Injection;
using Unity.Lifetime;
......@@ -19,32 +22,39 @@ namespace ProfitGroup.SampleService
{
public static class UnityConfig
{
public static UnityContainer Container;
public static void RegisterComponents()
{
var container = new UnityContainer();
Container = new UnityContainer();
var loggerConfig = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "nlog.config");
LogManager.Setup().LoadConfigurationFromFile(loggerConfig);
LogManager.Configuration = new XmlLoggingConfiguration(loggerConfig);
container.RegisterInstance(typeof(ILogger), LogManager.GetCurrentClassLogger());
// container.RegisterInstance(typeof(RDnLManager), new RDnLManager("OpcenterRDnL", "scCreate").Initialize(), lifetimeManager: new TransientLifetimeManager());
Container.RegisterInstance(typeof(ILogger), LogManager.GetCurrentClassLogger());
container.RegisterType<RDnLManager>(
Container.RegisterType<RDnLManager>(
new TransientLifetimeManager(),
new InjectionConstructor("OpcenterRDnL", "scCreate")
);
container.RegisterType<IKSSSInfoService, KsssInfoService>();
container.RegisterType<ISampleService, Core.Services.SampleService>();
container.RegisterInstance(typeof(SampleConfirmationService));
Container.RegisterType<IKSSSInfoService, KsssInfoService>();
Container.RegisterType<ISampleService, Core.Services.SampleService>();
Container.RegisterInstance(typeof(SampleCreateState), new SampleCreateState(), new SingletonLifetimeManager());
Container.RegisterInstance(typeof(SampleConfirmationService));
Container.RegisterSingleton<QueueHandler>();
var manager = Container.Resolve<RDnLManager>();
Container.RegisterInstance(typeof(API), new API(new BusinessObjectFactory(aConnection: (ISession<RnDConnection>)manager.EventAwareObjectFactory.FactorySession)));
var manager = container.Resolve<RDnLManager>();
var queueHandler = Container.Resolve<QueueHandler>();
container.RegisterInstance(typeof(API), new API(new BusinessObjectFactory(aConnection: (ISession<RnDConnection>)manager.EventAwareObjectFactory.FactorySession)));
queueHandler.StartProcessing();
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(Container);
}
}
}
\ No newline at end of file
......@@ -16,12 +16,27 @@ using System.Xml.Serialization;
using RnD.Interspec.EF.Specification;
using ILogger = NLog.ILogger;
using ISampleService = ProfitGroup.SampleService.Core.Services.ISampleService;
using RnD.BusinessLayer.EF.Factory;
using RnD.Model.EF;
using RnD.BusinessLayer.EF.Interfaces;
using System.Collections.Concurrent;
using System.Web.Http.Results;
using RnD.BusinessLayer.Interfaces.Model;
namespace ProfitGroup.SampleService.Controllers
{
[Authorize]
public class SampleController : ApiController
{
#region Приватные свойства
private readonly ISampleService _sampleService;
private readonly Appsettings _appSettings;
private readonly RDnLManager _manager;
private readonly KsssInfoService _ksssInfoService;
private readonly API _api;
private readonly SampleCreateState _sampleCreationState;
private ILogger Logger
{
get
......@@ -34,33 +49,45 @@ namespace ProfitGroup.SampleService.Controllers
}
}
private RDnLManager _manager;
private IKSSSInfoService _ksssInfoService;
private ISampleService _sampleService;
private readonly API _api;
#endregion
#region Конструкторы
public SampleController(
RDnLManager manager,
IKSSSInfoService ksssInfoService,
ISampleService sampleService,
API api)
public SampleController(RDnLManager manager, API api, SampleCreateState sampleCreationState)
{
var loggerConfig = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "nlog.config");
LogManager.Setup().LoadConfigurationFromFile(loggerConfig);
LogManager.Configuration = new XmlLoggingConfiguration(loggerConfig);
_manager = manager;
_ksssInfoService = ksssInfoService;
_sampleService = sampleService;
_ksssInfoService = new KsssInfoService(manager, api);
_sampleService = new Core.Services.SampleService(manager, api, new SampleConfirmationService(manager, api));
_api = api;
_sampleCreationState = sampleCreationState;
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "appsettings.json");
_appSettings = JsonConvert.DeserializeObject<Appsettings>(File.ReadAllText(path));
}
#endregion
#region Контроллеры
[HttpPost]
public async Task<IHttpActionResult> Create()
{
if (_sampleCreationState.IsProcessing)
{
var messageContent = "Был получен запрос, во время создания другой пробы. Запрос был отменен.";
PushLogSeparator();
Logger.Log(LogLevel.Info, messageContent);
return BadRequest(messageContent);
}
_sampleCreationState.IsProcessing = true;
PushLogSeparator();
#region 0. Получение данных из тела запроса
MT_InspLot request = null;
......@@ -69,11 +96,14 @@ namespace ProfitGroup.SampleService.Controllers
Logger.Log(LogLevel.Info, "Тело запроса:" + content);
#endregion
if (string.IsNullOrEmpty(content))
{
const string message = теле запроса отсутствуют данные";
const string message = полученном пакете отсутствуют данные";
Logger.Error(message);
return BadRequest(message);
throw new Exception(message);
}
try
......@@ -86,36 +116,42 @@ namespace ProfitGroup.SampleService.Controllers
{
string message = "Не удалось считать данные из полученного запроса" + ex.Message;
Logger.Error(ex, message);
return BadRequest(message);
throw new Exception(message);
}
#endregion
foreach (var card in _appSettings.InfoCardSettings)
{
card.Value = null;
}
try
{
PushLogSeparator();
#region 1. Проверка данных
#region 1.1 Проверка на то, что пришли необходимые данные
if (string.IsNullOrEmpty(request.Document.Plant))
{
const string message = "Отсутствует параметр Plant (Площадка)";
Logger.Error(message);
return BadRequest(message);
const string message = "В полученном пакете данных отсутствует параметр Plant (Площадка)";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
if (string.IsNullOrEmpty(request.Document.InspectonType))
{
const string message = "Отсутствует параметр ControlType (Вид контроля)";
Logger.Error(message);
return BadRequest(message);
const string message = "В полученном пакете данных отсутствует параметр ControlType (Вид контроля)";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
if (string.IsNullOrEmpty(request.Document.Material))
{
const string message = "Отсутствует параметр ksss (Код KSSS)";
Logger.Error(message);
return BadRequest(message);
const string message =
"В полученном пакете данных отсутствует параметр ksss (Код KSSS), параметр Material";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
var customSampleCreateDto = new CustomSampleCreateDto
......@@ -127,13 +163,27 @@ namespace ProfitGroup.SampleService.Controllers
#region 1.2 Проверки на верность полученных данных
var plant = await _ksssInfoService.GetPlantByName(request.Document.Plant);
//var plant = await _ksssInfoService.GetPlantByName(request.Document.Plant);
decimal plantId = 0;
if (string.IsNullOrEmpty(request.Document.Plant) ||
decimal.TryParse(request.Document.Plant, out plantId) == false)
{
var message =
$"Не удалось считать идентификатор площадки из полученного пакета данных, полученное значение: '{request.Document.Plant}'";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
var plant = await _ksssInfoService.GetPlantById(plantId);
if (plant == null)
{
var message = $"Не удалось найти площадку с наименованием: {request.Document.Plant}";
Logger.Error(message);
return BadRequest(message);
var message =
$"Не удалось определить площадку с полученным идентификатором: '{request.Document.Plant}'";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
#endregion
......@@ -142,49 +192,62 @@ namespace ProfitGroup.SampleService.Controllers
#region 2. Поиск инфополя, со значением, соответствующему полученному KSSS коду
var ksssCodeInfoFields = await _ksssInfoService.GetInfoFieldsByKSSSCode(request.Document.Material);
if (ulong.TryParse(request.Document.Material, out ulong materialId) == false)
{
var message = $"Не удалось привести значение идентификатора в число: '{request.Document.Material}'";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
var ksssCodeInfoFields = await _ksssInfoService.GetInfoFieldsByKSSSCode(materialId.ToString());
var specificationsIDs = ksssCodeInfoFields.Select(c => c.SP).Distinct().ToList();
var groupedInfoFields = ksssCodeInfoFields.GroupBy(c => c.SP);
var activeSpecifications = await _ksssInfoService.GetActiveSpecificationsFromRange(specificationsIDs);
if (groupedInfoFields.Count() == 0)
if (activeSpecifications.Count == 0)
{
var message = $"Отсутствует спецификация с кодом KSSS: {request.Document.Material}";
Logger.Error(message);
return BadRequest(message);
var message = $"Отсутствует спецификация с кодом KSSS: '{request.Document.Material}'";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
if (groupedInfoFields.Count() > 1)
if (activeSpecifications.Count > 1)
{
var message = $"Нашлось более одного инфополя с кодом KSSS: {request.Document.Material}";
Logger.Error(message);
return BadRequest(message);
var message = $"Нашлось более одной спецификации с кодом KSSS: '{request.Document.Material}'";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
#endregion
#region 3. Получение спецификации
var specification = await _ksssInfoService.FindActiveSpecificationById(ksssCodeInfoFields[0].SP);
var specification = await _ksssInfoService.FindActiveSpecificationById(activeSpecifications[0].SP,
activeSpecifications[0].SP_VERSION);
if (specification == null)
{
var message = $"Не удалось определить спецификацию по инфополю: {ksssCodeInfoFields[0].IIVALUE}";
Logger.Error(message);
return BadRequest(message);
var message =
$"Не удалось найти активную спецификацию по коду KSSS: {ksssCodeInfoFields[0].IIVALUE}";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
#endregion
#region 4. Получение материала из спецификации
#region 4. Получение Product Code из спецификации
customSampleCreateDto.ProductCode =
_ksssInfoService.GetProductCodeFromSpecificationKSSS(specification, out decimal? frameId);
//ToDO: Проверить, что для данного продукт кода существует активная спецификация
if (string.IsNullOrEmpty(customSampleCreateDto.ProductCode))
{
var message = $"Не удалось определить тип продукта (Материал)";
Logger.Error(message);
return BadRequest(message);
var message = $"Не удалось определить код продукта у спецификации";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
#endregion
......@@ -197,18 +260,19 @@ namespace ProfitGroup.SampleService.Controllers
if (mappedControl == null)
{
var message =
$"Не удалось определить вид контроля: LO: {plant.LO}, InspectonType: {request.Document.InspectonType}, FrameId: {frameId}";
Logger.Error(message);
return BadRequest(message);
$"Не удалось определить вид контроля: Локация: {plant.LO} / {plant.SHORT_DESC}, InspectonType: {request?.Document?.InspectonType}, FrameId: {frameId}";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
var controlType = await _ksssInfoService.GetControlTypeByCode(mappedControl.ControlTypeCode);
if (controlType == null)
{
var message = $"В таблице видов контроля отсутствует вид с кодом: {mappedControl.ControlTypeCode}";
Logger.Error(message);
return BadRequest(message);
var message =
$"В таблице видов контроля отсутствует вид с кодом: '{mappedControl.ControlTypeCode}'";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
customSampleCreateDto.OperationControlName = controlType.NAME_RU;
......@@ -222,29 +286,23 @@ namespace ProfitGroup.SampleService.Controllers
// Если не входной контроль
if (controlType.CODE != "IC" && string.IsNullOrEmpty(mappedControl.Stage))
{
//Обработка частного случая //ToDo: Вынести логику обработки частного случая
//Обработка частного случая, в котором определяется упаковка, в зависимости от объема партии
if (request.Document.InspectonType == "L010")
{
if (decimal.TryParse(request.Document.InspLotSize, out var lotSize))
{
if (request.Document.InspectonType == "L010")
{
customSampleCreateDto.Package = DetectPackageServiceByRangeValue.Detect("А/Ц", "В/Ц", 50_000, lotSize);
customSampleCreateDto.Package =
DetectPackageServiceByRangeValue.Detect("А/Ц", "В/Ц", 50_000, lotSize);
}
//customSampleCreateDto.Package = request.Document.InspectonType switch
//{
// // ToDo: Убедиться что >= указано верно в пользу В/Ц
// "L010" => DetectPackageServiceByRangeValue.Detect("А/Ц", "В/Ц", 50_000, lotSize),
// _ => customSampleCreateDto.Package
//};
}
else
{
var message = $@"Для вида контроля S4 ""{request.Document.InspectonType}"" не удалось определить упаковку, не удалось получить числовое значение InspLotSize";
Logger.Error(message);
return BadRequest(message);
var message =
$@"Для вида контроля S4 ""{request.Document.InspectonType}"" не удалось определить упаковку, т.к. не удалось получить числовое значение InspLotSize, ожидалось число с плавающей точкой, фактическое значение: '{request?.Document?.InspLotSize}'";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
}
else
......@@ -253,11 +311,17 @@ namespace ProfitGroup.SampleService.Controllers
_ksssInfoService.GetPackageNameFromSpecificationKSSS(specification);
}
if (_ksssInfoService.CheckAndMapPackageName(customSampleCreateDto.Package, plant.LO,
out string opCenterPackageName) || !string.IsNullOrEmpty(opCenterPackageName))
{
customSampleCreateDto.Package = opCenterPackageName;
}
if (string.IsNullOrEmpty(customSampleCreateDto.Package) && specification.FrameId != 30)
{
var message = $"У инфокарты спецификации не заполнено инфополе: KD_Pack";
Logger.Error(message);
return BadRequest(message);
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
}
......@@ -276,9 +340,21 @@ namespace ProfitGroup.SampleService.Controllers
if (customSampleCreateDto.SampleType == null)
{
var message =
$"Не удалось определить SampleType, ProductCode: {customSampleCreateDto.ProductCode}, OperationControlName: {customSampleCreateDto.OperationControlName}, Упаковка: \"{customSampleCreateDto.Package}\", Стадия: \"{mappedControl.Stage}\"";
Logger.Error(message);
return BadRequest(message);
$"Не удалось определить SampleType, ProductCode: {customSampleCreateDto.ProductCode}, OperationControlName: {customSampleCreateDto.OperationControlName}, Упаковка: \"{customSampleCreateDto.Package}\", Стадия: \"{mappedControl.Stage}\", возможно отсутствует ";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
var sampleType =
_manager.EventAwareObjectFactory.SampleType.GetFull(customSampleCreateDto.SampleType.ST,
customSampleCreateDto.SampleType.VERSION);
if (sampleType.InfoProfiles.All(c => c.ShortDescription != "S4Integration_Probe"))
{
var message =
$"SampleType в Opcenter настроен неверно, отсутствует инфокарта S4Integration_Probe, необходимая для интеграции";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
#endregion
......@@ -286,7 +362,7 @@ namespace ProfitGroup.SampleService.Controllers
#region 8. Определение ключей создания пробы + заполнение
var taskFilterDtos = _sampleService
.GetTaskKeys(request.Document.Plant,
.GetTaskKeys(plant.SHORT_DESC,
customSampleCreateDto.OperationControlName,
customSampleCreateDto.Package ?? mappedControl.Stage
)
......@@ -296,8 +372,16 @@ namespace ProfitGroup.SampleService.Controllers
{
var message =
$"Не было задано ни одного ключа создания объекта, либо не удалось определить контекстные ключи";
Logger.Error(message);
return BadRequest(message);
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
// Проверка на то если в ключах есть "Упаковка", чтобы был заполнен соответствующий параметр
if (taskFilterDtos.Any(c => c.Field == "43@RndvStAu") &&
string.IsNullOrEmpty(customSampleCreateDto.Package))
{
throw new Exception(
$"Не удалось сопоставить наименование упаковки \"{customSampleCreateDto.Package}\" и локацией \"{plant.LO}\" ни с одной из упаковок в Opcenter!");
}
// Получаем только незаполненные параметры
......@@ -308,10 +392,10 @@ namespace ProfitGroup.SampleService.Controllers
case "SHORT_DESC@RndvSt":
taskFilter.Value = customSampleCreateDto.SampleType.SHORT_DESC;
break;
case "43@RndvStAu":
case "43@RndvStAu": // Упаковка
taskFilter.Value = customSampleCreateDto.Package.Replace(",", ".");
break;
case "38@RndvStAu":
case "38@RndvStAu": // Стадия
taskFilter.Value = mappedControl.Stage;
break;
......@@ -339,7 +423,7 @@ namespace ProfitGroup.SampleService.Controllers
#region 9. Создание пробы
var sampleFullDto = _manager.EventAwareObjectFactory.Sample.Create(
SampleFullDTO sampleFullDto = _manager.EventAwareObjectFactory.Sample.Create(
customSampleCreateDto.SampleType.ST,
customSampleCreateDto.SampleType.VERSION,
taskFilterDtos);
......@@ -350,11 +434,7 @@ namespace ProfitGroup.SampleService.Controllers
#region 10. Заполнение инфокарт
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "appsettings.json");
var appSettings = JsonConvert.DeserializeObject<Appsettings>(File.ReadAllText(path));
foreach (var card in appSettings.InfoCardSettings)
foreach (InfoCardSetting card in _appSettings.InfoCardSettings)
{
var parameter = GetPropertyValue(request.Document, card.Name);
......@@ -364,12 +444,15 @@ namespace ProfitGroup.SampleService.Controllers
}
else
{
Logger.Error(
$"Значение не было записано на инфокарту {card.Name}. Полученный запрос не имеет соответствующего поля/значения для записи");
Logger.Warn($"[{request.GuigMsgOutb}]" +
$"В полученном запросе отсутствует параметр: \"{card.Name}\". Локация: \"{card.Plant}\". Полученный запрос не имеет соответствующего поля/значения для записи");
}
}
_sampleService.FillSampleInfoCards(Convert.ToDecimal(sampleFullDto.ID), appSettings.InfoCardSettings);
var sample = new RnD.Model.Sample(sampleFullDto, _api);
_sampleService.FillSampleInfoCards(sample, _appSettings.InfoCardSettings,
plant.DESCRIPTION);
#endregion
......@@ -381,28 +464,31 @@ namespace ProfitGroup.SampleService.Controllers
#region 12. Возврат ответа на запрос
var requestMessage =
$"Запрос был обработан, позже будет выслано отдельное подтверждение с Message Guid: {request.GuigMsgOutb}";
var requestMessage = $"Запрос с Message Guid: {request.GuigMsgOutb} был успешно обработан";
Logger.Log(LogLevel.Info, requestMessage);
return Ok(new
{
Message = requestMessage
});
Logger.Log(LogLevel.Info, $"[{request.GuigMsgOutb}]" + requestMessage);
#endregion
return Ok(requestMessage);
}
catch (Exception ex)
{
Logger.Error(ex.Message + "\n\n" + ex.StackTrace);
return InternalServerError(ex);
}finally
Logger.Error($"[{request.GuigMsgOutb}]" + ex.Message + "\n\n" + ex.StackTrace);
await _sampleService.SendConfirmation(request, null, ex.Message);
return BadRequest(ex.Message);
}
finally
{
PushLogSeparator(10);
_sampleCreationState.IsProcessing = false;
}
}
#endregion
#region Приватные методы
private void PushLogSeparator(int newLineCount = 0)
{
Logger.Info($"{new string('=', 100)}{new string('\n', newLineCount)}");
......@@ -418,5 +504,7 @@ namespace ProfitGroup.SampleService.Controllers
else
return null;
}
#endregion
}
}
\ No newline at end of file
......@@ -3,55 +3,103 @@ using System.Text;
using System.Web;
using System.Net;
using System.Security.Principal;
using Microsoft.Extensions.Logging;
using NLog.Config;
using System.IO;
using NLog;
namespace ProfitGroup.SampleService.Core.Middlewares
{
/// <summary>
/// Представляет промежуточное ПО для базовой аутентификации.
/// </summary>
public class BasicAuthMiddleware : IHttpModule
{
private static NLog.ILogger Logger
{
get
{
var loggerConfig = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "nlog.config");
LogManager.Setup().LoadConfigurationFromFile(loggerConfig);
LogManager.Configuration = new XmlLoggingConfiguration(loggerConfig);
return LogManager.GetCurrentClassLogger();
}
}
//private readonly ILogger _logger;
//public BasicAuthMiddleware(ILoggerFactory loggerFactory)
//{
// _logger = loggerFactory.CreateLogger(typeof(BasicAuthMiddleware));
//}
/// <summary>
/// Инициализирует промежуточное ПО и подписывает обработчик события аутентификации запроса.
/// </summary>
public void Init(HttpApplication context)
{
context.AuthenticateRequest += OnAuthenticateRequest;
}
/// <summary>
/// Освобождает ресурсы, используемые промежуточным ПО.
/// </summary>
public void Dispose()
{
}
/// <summary>
/// Обработчик события аутентификации запроса.
/// </summary>
private void OnAuthenticateRequest(object sender, EventArgs e)
{
var context = ((HttpApplication)sender).Context;
string authHeader = context.Request.Headers["Authorization"];
var authHeader = context.Request.Headers["Authorization"];
if (!string.IsNullOrEmpty(authHeader) && authHeader.StartsWith("Basic"))
if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Basic"))
{
string encodedCredentials = authHeader.Substring("Basic".Length).Trim();
byte[] credentialsBytes = Convert.FromBase64String(encodedCredentials);
string credentials = Encoding.ASCII.GetString(credentialsBytes);
string[] usernamePassword = credentials.Split(':');
Logger.Error("Авторизация пропущена. Передан пустой Basic Auth Header");
return;
}
if (usernamePassword.Length == 2)
{
string username = usernamePassword[0];
string password = usernamePassword[1];
var encodedCredentials = authHeader.Substring("Basic".Length).Trim();
var credentialsBytes = Convert.FromBase64String(encodedCredentials);
var credentials = Encoding.ASCII.GetString(credentialsBytes);
var usernamePassword = credentials.Split(':');
if (usernamePassword.Length != 2) return;
var username = usernamePassword[0];
var password = usernamePassword[1];
if (IsUserValid(username, password))
{
Logger.Info("Успешная авторизация");
context.User = new GenericPrincipal(new GenericIdentity(username), null);
}
else
{
Logger.Error("Ошибка авторизации, неверный логин или пароль");
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
context.Response.AddHeader("WWW-Authenticate", "Basic realm=\"Your Realm\"");
context.Response.End();
}
}
}
}
/// <summary>
/// Проверяет, является ли пользователь допустимым.
/// </summary>
private bool IsUserValid(string username, string password)
{
return username == "111" && password == "111";
// ToDo: Сменить пароль при переносе решения
// APP02
return username == "S4test" && password == "Era7%agEr12#L";
// Productive
// return username == "S4test" && password == "lMxeTqMIH04R8mCE";
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Web;
using NLog;
using NLog.Config;
using ProfitGroup.Rdnl.Extensions;
using ProfitGroup.SampleService.Models;
using Unity;
namespace ProfitGroup.SampleService.Core.Middlewares
{
public class SampleMiddleware : IHttpModule
{
private readonly SampleCreateState _sampleCreateState;
private static NLog.ILogger Logger
{
get
{
var loggerConfig = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "nlog.config");
LogManager.Setup().LoadConfigurationFromFile(loggerConfig);
LogManager.Configuration = new XmlLoggingConfiguration(loggerConfig);
return LogManager.GetCurrentClassLogger();
}
}
public SampleMiddleware()
{
_sampleCreateState = UnityConfig.Container?.Resolve<SampleCreateState>();
}
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.AuthenticateRequest += OnAuthenticateRequest;
}
private void OnAuthenticateRequest(object sender, EventArgs e)
{
var context = ((HttpApplication)sender).Context;
if (_sampleCreateState != null && _sampleCreateState.IsProcessing)
{
var message = "Был получен запрос, во время создания другой пробы. Запрос был отменен.";
Logger.Error(message);
context.Response.Output.Write(message);
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
context.Response.End();
}
}
}
}
\ No newline at end of file
namespace ProfitGroup.SampleService.Core.Services
{
/// <summary>
/// Предоставляет сервис для определения упаковки по значению диапазона.
/// </summary>
public class DetectPackageServiceByRangeValue
{
/// <summary>
/// Определяет упаковку на основе переданных значений диапазона и текущего значения.
/// </summary>
/// <param name="minPackageName">Наименование упаковки для минимального значения.</param>
/// <param name="maxPackageName">Наименование упаковки для максимального значения.</param>
/// <param name="maxValue">Максимальное значение диапазона.</param>
/// <param name="currentValue">Текущее значение для определения упаковки.</param>
/// <returns>Наименование определенной упаковки.</returns>
public static string Detect(
string minPackageName,
string maxPackageName,
......
......@@ -7,22 +7,68 @@ using ProfitGroup.SampleService.Data.Database.Entities;
namespace ProfitGroup.SampleService.Core.Services
{
/// <summary>
/// Предоставляет интерфейс сервиса для работы с информацией о КССС.
/// </summary>
public interface IKSSSInfoService
{
Task<ISpecification> FindActiveSpecificationById(decimal specificationId);
/// <summary>
/// Асинхронно находит активную спецификацию по идентификатору.
/// </summary>
Task<ISpecification> FindActiveSpecificationById(decimal specificationId, decimal sP_VERSION);
/// <summary>
/// Асинхронно получает информационные поля по коду КССС.
/// </summary>
Task<List<RndvSpIi>> GetInfoFieldsByKSSSCode(string ksssCode);
/// <summary>
/// Получает код продукта из спецификации КССС и возвращает идентификатор рамы.
/// </summary>
string GetProductCodeFromSpecificationKSSS(ISpecification specification, out decimal? frameId);
/// <summary>
/// Получает наименование упаковки из спецификации КССС.
/// </summary>
string GetPackageNameFromSpecificationKSSS(ISpecification specification);
/// <summary>
/// Получает наименования местоположения из спецификации.
/// </summary>
IEnumerable<string> GetSpecificationLocationName(ISpecification specification);
/// <summary>
/// Асинхронно выполняет отображение операционного контроля для указанного местоположения, рамы и типа инспекции.
/// </summary>
Task<S4InspectionTypeMap> MapOperationControl(decimal locationId, decimal? frameId, string inspectonType);
/// <summary>
/// Получает SampleType по коду продукта, наименованию операционного контроля, упаковке, стадии и идентификатору завода.
/// </summary>
RndvSt GetSampleType(string productCode, string operationControlName, string package, string stage,
decimal plantId);
/// <summary>
/// Асинхронно получает объект завода по его наименованию.
/// </summary>
Task<RndvLo> GetPlantByName(string plant);
/// <summary>
/// Асинхронно получает тип контроля по коду контроля.
/// </summary>
Task<SiemtControlTypes> GetControlTypeByCode(string controlTypeCode);
/// <summary>
/// Асинхронно получает объект завода по его идентификатору.
/// </summary>
Task<RndvLo> GetPlantById(decimal plantId);
/// <summary>
/// Проверка на существование в системе упаковки с текущим наименованием
/// </summary>
/// <param name="package">Наименование упаковки KSSS</param>
/// <param name="opCenterPackageName">Наименвоание упаковки из Opcenter</param>
/// <returns></returns>
bool CheckAndMapPackageName(string package, decimal plantId, out string opCenterPackageName);
Task<List<RndvSp>> GetActiveSpecificationsFromRange(List<decimal> specificationSp);
}
}
using ProfitGroup.SampleService.Models;
using RnD.BusinessLayer.Interfaces.Model;
using System.Net;
using System.Threading.Tasks;
namespace ProfitGroup.SampleService.Core.Services
{
/// <summary>
/// Предоставляет интерфейс сервиса подтверждения образца, ответственного за отправку сообщений в шину SAP/S4.
/// </summary>
public interface ISampleConfirmationService
{
Task<bool> SendConfirmationToSap(MT_InspLot mtInspLot, SampleFullDTO sampleFullDto, bool isSuccessCreated);
/// <summary>
/// Асинхронно отправляет подтверждение в SAP/S4.
/// </summary>
/// <param name="mtInspLot">Экземпляр класса MT_InspLot полученное от SAP/S4.</param>
/// <param name="sampleFullDto">DTO с полной информацией об образце.</param>
/// <param name="isSuccessCreated">Флаг успешного создания образца.</param>
/// <param name="message">Дополнительное сообщение.</param>
/// <returns>True, если операция отправки подтверждения выполнена успешно, в противном случае - false.</returns>
Task<(bool isSuccess, HttpStatusCode statusCode, string message)> SendConfirmationToSap(MT_InspLot mtInspLot, SampleFullDTO sampleFullDto, bool isSuccessCreated, string message = null);
}
}
\ No newline at end of file
......@@ -2,14 +2,45 @@
using RnD.BusinessLayer.Interfaces.Model;
using System.Collections.Generic;
using System.Threading.Tasks;
using RnD.Model;
namespace ProfitGroup.SampleService.Core.Services
{
/// <summary>
/// Предоставляет интерфейс сервиса образцов.
/// </summary>
public interface ISampleService
{
/// <summary>
/// Получает ключи задач для фильтрации по наименованию завода, наименованию операционного контроля и упаковке или стадии.
/// </summary>
/// <param name="plantName">Наименование завода.</param>
/// <param name="operationControlName">Наименование операционного контроля.</param>
/// <param name="packageOrStage">Наименование упаковки или стадии.</param>
/// <returns>Перечисление ключей задач для фильтрации.</returns>
IEnumerable<TaskFilterDTO> GetTaskKeys(string plantName, string operationControlName, string packageOrStage);
void FillSampleInfoCards(decimal sampleId, List<InfoCardSetting> infoCards);
/// <summary>
/// Заполняет информационные карточки образца.
/// </summary>
/// <param name="sample">Проба</param>
/// <param name="infoCards">Список настроек информационных карточек.</param>
/// <param name="plantName">Наименование завода.</param>
void FillSampleInfoCards(Sample sample, List<InfoCardSetting> infoCards, string plantName);
/// <summary>
/// Асинхронно выполняет валидацию образца по его краткому описанию.
/// </summary>
/// <param name="shortDescription">Краткое описание образца.</param>
/// <returns>True, если образец валиден, в противном случае - false.</returns>
Task<bool> ValidateSample(string shortDescription);
Task SendConfirmation(MT_InspLot shortDescription, SampleFullDTO sampleFullDto);
/// <summary>
/// Асинхронно отправляет подтверждение образца.
/// </summary>
/// <param name="mtInspLot">Экземпляр класса MT_InspLot для отправки.</param>
/// <param name="sampleFullDto">DTO с полной информацией об образце.</param>
/// <param name="message">Дополнительное сообщение.</param>
Task SendConfirmation(MT_InspLot mtInspLot, SampleFullDTO sampleFullDto, string message = null);
}
}
......@@ -18,6 +18,8 @@ using System.Data;
using System.Data.SqlTypes;
using NLog.Config;
using System.IO;
using System.Runtime.CompilerServices;
using ProfitGroup.SampleService.Models.Entities;
namespace ProfitGroup.SampleService.Core.Services
{
......@@ -44,24 +46,26 @@ namespace ProfitGroup.SampleService.Core.Services
_databaseContext = ((ISession<RnDConnection>)manager.EventAwareObjectFactory.FactorySession).Context;
}
public async Task<ISpecification> FindActiveSpecificationById(decimal specificationId)
public async Task<ISpecification> FindActiveSpecificationById(decimal specificationId, decimal specificationVersion)
{
var activeSpecification = await _databaseContext.RndvSp.FirstAsync(c =>
c.SP == specificationId
&& c.ACTIVE_STR == "1"
);
//var activeSpecification = await _databaseContext.RndvSp.FirstOrDefaultAsync(c =>
// c.SP == specificationId
// && c.ACTIVE_STR == "1"
// );
return _api.Specification.GetSpecification(activeSpecification.SP, activeSpecification.SP_VERSION);
//if (activeSpecification == null)
// return null;
return _api.Specification.GetSpecification(specificationId, specificationVersion);
}
public Task<List<RndvSpIi>> GetInfoFieldsByKSSSCode(string ksssCode)
{
// ToDo: Вынести константу KD_KSSS в конфиг + Проверить различные сценарии, когда обновляется Frame, создается ли новая версия инфополя?
return _databaseContext.RndvSpIi.Where(c =>
c.II_SHORT_DESC_MAIN == "KD_KSSS"
&& c.IIVALUE_MAIN == ksssCode
//c.ACTIVE_STR == "1"
//&& c.ACTIVE_STR == "1"
).ToListAsync();
}
......@@ -76,11 +80,11 @@ namespace ProfitGroup.SampleService.Core.Services
var kssInfoGroup =
specification.InfoCards.FirstOrDefault(c =>
c.ShortDescription == "KSSS_Data"); //ToDo: Вынести константу в конфиг
c.ShortDescription == "KSSS_Data");
var infoField =
kssInfoGroup?.InfoFields.FirstOrDefault(c =>
c.ShortDescription == "KD_Pack"); //ToDo: Вынести константу в конфиг
c.ShortDescription == "KD_Pack");
return infoField != null ? infoField.InfoFieldValue : string.Empty;
}
......@@ -116,11 +120,11 @@ namespace ProfitGroup.SampleService.Core.Services
// Id Frame: PackagedRM
var kssInfoGroup =
specification.InfoCards.FirstOrDefault(c =>
c.ShortDescription == "KSSS_RM_SKU"); //ToDo: Вынести константу в конфиг
c.ShortDescription == "KSSS_RM_SKU");
var infoField =
kssInfoGroup?.InfoFields.FirstOrDefault(c =>
c.ShortDescription == "KSSS_RM_ID"); //ToDo: Вынести константу в конфиг
c.ShortDescription == "KSSS_RM_ID");
return infoField?.InfoFieldValue;
}
......@@ -131,11 +135,11 @@ namespace ProfitGroup.SampleService.Core.Services
var kssInfoGroup =
specification.InfoCards.FirstOrDefault(c =>
c.ShortDescription == "KSSS_SKU"); //ToDo: Вынести константу в конфиг
c.ShortDescription == "KSSS_SKU");
var infoField =
kssInfoGroup?.InfoFields.FirstOrDefault(c =>
c.ShortDescription == "SKU_KsssProductCode"); //ToDo: Вынести константу в конфиг
c.ShortDescription == "SKU_KsssProductCode");
return infoField?.InfoFieldValue;
}
......@@ -154,7 +158,7 @@ namespace ProfitGroup.SampleService.Core.Services
return Enumerable.Empty<string>();
}
public async Task<S4InspectionTypeMap> MapOperationControl(decimal locationId, decimal? frameId, string inspectonType)
public async Task<S4InspectionTypeMap> MapOperationControl(decimal locationId, decimal? frameId, string inspectionType)
{
//var sql = "SELECT * FROM [ProfIT].[S4InspectionTypeMap] " +
// "WHERE [ProfIT].[S4InspectionTypeMap].[LO] = @location " +
......@@ -193,7 +197,7 @@ namespace ProfitGroup.SampleService.Core.Services
var sqlParameters = new List<SqlParameter>
{
new SqlParameter("@location", locationId.ToString()),
new SqlParameter("@inspectonType", inspectonType)
new SqlParameter("@inspectonType", inspectionType)
};
if (frameId != null)
......@@ -244,6 +248,7 @@ namespace ProfitGroup.SampleService.Core.Services
&& (c.SampleTypeAu.VALUE_MAIN.Contains(operationControlName) || c.SampleTypeAu.VALUE_MAIN == productCode)
).ToList();
// Если указана упаковка, дополнительно сортируем по Упаковке
if (!string.IsNullOrEmpty(package))
{
sampleTypes = _databaseContext.RndvSt.Join(_databaseContext.RndvStAu,
......@@ -259,6 +264,7 @@ namespace ProfitGroup.SampleService.Core.Services
).ToList();
}
// Если указана стадия, дополнительно сортируем по Упаковке
if (!string.IsNullOrEmpty(stage))
{
sampleTypes = _databaseContext.RndvSt.Join(_databaseContext.RndvStAu,
......@@ -279,6 +285,11 @@ namespace ProfitGroup.SampleService.Core.Services
.Where(c => c.SampleType.RndvStLo.FirstOrDefault(g => g.LO == plantId) != null)
.ToList();
// Отбираем объекты, у которых нет %-SP SP_%
sampleTypes = sampleTypes
.Where(c => c.SampleType.SHORT_DESC_MAIN.EndsWith("-SP") == false && c.SampleType.SHORT_DESC_MAIN.StartsWith("SP_") == false)
.ToList();
// Проверяем, что было совпадение по двум параметрам (operationControlName и productCode)
// Или трём, если был передан упаковка или стадия
var paramsForSearchCount = string.IsNullOrEmpty(stage) && string.IsNullOrEmpty(package) ? 2 : 3;
......@@ -289,11 +300,12 @@ namespace ProfitGroup.SampleService.Core.Services
.Select(c => c.FirstOrDefault())
.ToList();
// Если мы нашли только один SampleType по количеству переданных атрибутов
if (groupingSampleTypes.Count == 1)
return groupingSampleTypes.Single().SampleType;
Logger.Error(
$"В результате получения SampleType было получено несколько возможных вариантов: {string.Join(",", sampleTypes.Select(c => $"{c.SampleType.ST} / {c.SampleType.SHORT_DESC_MAIN}"))}");
$"В результате получения SampleType было получено несколько возможных вариантов: {string.Join(",", groupingSampleTypes.Select(c => $"{c.SampleType.ST} / {c.SampleType.SHORT_DESC_MAIN}"))}");
return null;
}
......@@ -302,5 +314,56 @@ namespace ProfitGroup.SampleService.Core.Services
{
return await _databaseContext.RndvLo.FirstOrDefaultAsync(c => c.SHORT_DESC_MAIN == plant);
}
public async Task<RndvLo> GetPlantById(decimal plantId)
{
return await _databaseContext.RndvLo.FirstOrDefaultAsync(c => c.LO == plantId);
}
public bool CheckAndMapPackageName(string package, decimal plantId, out string opCenterPackageName)
{
var mappedPack = _databaseContext.Database.SqlQuery<RndtpackMapObject>("SELECT * FROM [RndSuite].[RndtpackKSSSMap] WHERE PackKSSS = @packName AND LocationId = @location", new SqlParameter("packName", package), new SqlParameter("location", plantId)).FirstOrDefault();
if (mappedPack != null)
{
opCenterPackageName = mappedPack.Pack;
return true;
#region oldCode
// var rndtPackOriginal = _databaseContext.Database.SqlQuery<Rndtpack>("SELECT * FROM [RndSuite].[Rndtpack] WHERE pack = @packName", new SqlParameter("packName", package)).FirstOrDefault();
//
// if (rndtPackOriginal == null)
// {
//
//
// opCenterPackageName = mappedPack.Pack;
//
// return true;
//
// }
// else
// {
// opCenterPackageName = rndtPackOriginal.pack;
//
// return true;
// }
// opCenterPackageName = string.Empty;
// return false;
#endregion
}
opCenterPackageName = string.Empty;
return false;
}
public Task<List<RndvSp>> GetActiveSpecificationsFromRange(List<decimal> specificationIDs)
{
return _databaseContext.RndvSp.Where(c => specificationIDs.Contains(c.SP) && c.ACTIVE_STR == "1").ToListAsync();
}
}
}
\ No newline at end of file
......@@ -83,359 +83,7 @@ namespace ProfitGroup.SampleService.Core.Services
private async Task Process(MT_InspLot request)
{
if (request.Document == null)
{
return;
}
try
{
PushLogSeparator();
#region 1. Проверка данных
#region 1.1 Проверка на то, что пришли необходимые данные
if (string.IsNullOrEmpty(request.Document.Plant))
{
const string message = "В полученном пакете данных отсутствует параметр Plant (Площадка)";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
if (string.IsNullOrEmpty(request.Document.InspectonType))
{
const string message = "В полученном пакете данных отсутствует параметр ControlType (Вид контроля)";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
if (string.IsNullOrEmpty(request.Document.Material))
{
const string message =
"В полученном пакете данных отсутствует параметр ksss (Код KSSS), параметр Material";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
var customSampleCreateDto = new CustomSampleCreateDto
{
PlantName = request.Document.Plant
};
#endregion
#region 1.2 Проверки на верность полученных данных
//var plant = await _ksssInfoService.GetPlantByName(request.Document.Plant);
decimal plantId = 0;
if (string.IsNullOrEmpty(request.Document.Plant) ||
decimal.TryParse(request.Document.Plant, out plantId) == false)
{
var message =
$"Не удалось считать идентификатор площадки из полученного пакета данных, полученное значение: '{request.Document.Plant}'";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
var plant = await _ksssInfoService.GetPlantById(plantId);
if (plant == null)
{
var message =
$"Не удалось определить площадку с полученным идентификатором: '{request.Document.Plant}'";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
#endregion
#endregion
#region 2. Поиск инфополя, со значением, соответствующему полученному KSSS коду
if (ulong.TryParse(request.Document.Material, out ulong materialId) == false)
{
var message = $"Не удалось привести значение идентификатора в число: '{request.Document.Material}'";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
var ksssCodeInfoFields = await _ksssInfoService.GetInfoFieldsByKSSSCode(materialId.ToString());
var specificationsIDs = ksssCodeInfoFields.Select(c => c.SP).Distinct().ToList();
var activeSpecifications = await _ksssInfoService.GetActiveSpecificationsFromRange(specificationsIDs);
if (activeSpecifications.Count == 0)
{
var message = $"Отсутствует спецификация с кодом KSSS: '{request.Document.Material}'";
Logger.Error([{ request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
if (activeSpecifications.Count > 1)
{
var message = $"Нашлось более одной спецификации с кодом KSSS: '{request.Document.Material}'";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
#endregion
#region 3. Получение спецификации
var specification = await _ksssInfoService.FindActiveSpecificationById(activeSpecifications[0].SP,
activeSpecifications[0].SP_VERSION);
if (specification == null)
{
var message =
$"Не удалось найти активную спецификацию по коду KSSS: {ksssCodeInfoFields[0].IIVALUE}";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
#endregion
#region 4. Получение Product Code из спецификации
customSampleCreateDto.ProductCode =
_ksssInfoService.GetProductCodeFromSpecificationKSSS(specification, out decimal? frameId);
//ToDO: Проверить, что для данного продукт кода существует активная спецификация
if (string.IsNullOrEmpty(customSampleCreateDto.ProductCode))
{
var message = $"Не удалось определить код продукта у спецификации";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
#endregion
#region 5. Маппинг вида контроля в формате OpcenterRdnL
var mappedControl =
await _ksssInfoService.MapOperationControl(plant.LO, frameId, request.Document.InspectonType);
if (mappedControl == null)
{
var message =
$"Не удалось определить вид контроля: Локация: {plant.LO} / {plant.SHORT_DESC}, InspectonType: {request?.Document?.InspectonType}, FrameId: {frameId}";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
var controlType = await _ksssInfoService.GetControlTypeByCode(mappedControl.ControlTypeCode);
if (controlType == null)
{
var message =
$"В таблице видов контроля отсутствует вид с кодом: '{mappedControl.ControlTypeCode}'";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
customSampleCreateDto.OperationControlName = controlType.NAME_RU;
#endregion
#region 6. Определение упаковки (Вида тары), у объектов, которые не имеют стадии
// customSampleCreateDto.OperationControl != OperationControl.InputControl
// Таблица: OpcenterRDnL.RndSuite.SiemtControlTypes
// Если не входной контроль
if (controlType.CODE != "IC" && string.IsNullOrEmpty(mappedControl.Stage))
{
//Обработка частного случая, в котором определяется упаковка, в зависимости от объема партии
if (request.Document.InspectonType == "L010")
{
if (decimal.TryParse(request.Document.InspLotSize, out var lotSize))
{
if (request.Document.InspectonType == "L010")
{
customSampleCreateDto.Package =
DetectPackageServiceByRangeValue.Detect("А/Ц", "В/Ц", 50_000, lotSize);
}
}
else
{
var message =
$@"Для вида контроля S4 ""{request.Document.InspectonType}"" не удалось определить упаковку, т.к. не удалось получить числовое значение InspLotSize, ожидалось число с плавающей точкой, фактическое значение: '{request?.Document?.InspLotSize}'";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
}
else
{
customSampleCreateDto.Package =
_ksssInfoService.GetPackageNameFromSpecificationKSSS(specification);
}
if (_ksssInfoService.CheckAndMapPackageName(customSampleCreateDto.Package, plant.LO,
out string opCenterPackageName) || !string.IsNullOrEmpty(opCenterPackageName))
{
customSampleCreateDto.Package = opCenterPackageName;
}
else
{
throw new Exception(
$"Не удалось сопоставить наименование упаковки \"{customSampleCreateDto.Package}\" и локацией \"{plant.LO}\" ни с одной из упаковок в Opcenter!");
}
if (string.IsNullOrEmpty(customSampleCreateDto.Package) && specification.FrameId != 30)
{
var message = $"У инфокарты спецификации не заполнено инфополе: KD_Pack";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
}
#endregion
#region 7. Определение SampleType
customSampleCreateDto.SampleType = _ksssInfoService.GetSampleType(
customSampleCreateDto.ProductCode,
customSampleCreateDto.OperationControlName,
customSampleCreateDto.Package,
mappedControl.Stage,
plant.LO
);
if (customSampleCreateDto.SampleType == null)
{
var message =
$"Не удалось определить SampleType, ProductCode: {customSampleCreateDto.ProductCode}, OperationControlName: {customSampleCreateDto.OperationControlName}, Упаковка: \"{customSampleCreateDto.Package}\", Стадия: \"{mappedControl.Stage}\", возможно отсутствует ";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
var sampleType =
_manager.EventAwareObjectFactory.SampleType.GetFull(customSampleCreateDto.SampleType.ST,
customSampleCreateDto.SampleType.VERSION);
if (sampleType.InfoProfiles.All(c => c.ShortDescription != "S4Integration_Probe"))
{
var message =
$"SampleType в Opcenter настроен неверно, отсутствует инфокарта S4Integration_Probe, необходимая для интеграции";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
#endregion
#region 8. Определение ключей создания пробы + заполнение
var taskFilterDtos = _sampleService
.GetTaskKeys(plant.SHORT_DESC,
customSampleCreateDto.OperationControlName,
customSampleCreateDto.Package ?? mappedControl.Stage
)
.ToList();
if (taskFilterDtos.Count == 0)
{
var message =
$"Не было задано ни одного ключа создания объекта, либо не удалось определить контекстные ключи";
Logger.Error($"[{request.GuigMsgOutb}]" + message);
throw new Exception(message);
}
// Получаем только незаполненные параметры
foreach (var taskFilter in taskFilterDtos.Where(taskFilter => string.IsNullOrEmpty(taskFilter.Value)))
{
switch (taskFilter.Field)
{
case "SHORT_DESC@RndvSt":
taskFilter.Value = customSampleCreateDto.SampleType.SHORT_DESC;
break;
case "43@RndvStAu": // Упаковка
taskFilter.Value = customSampleCreateDto.Package.Replace(",", ".");
break;
case "38@RndvStAu": // Стадия
taskFilter.Value = mappedControl.Stage;
break;
default:
break;
}
//taskFilter.Value = taskFilter.Field switch
//{
// // Краткое описание
// "SHORT_DESC@RndvSt" => customSampleCreateDto.SampleType.SHORT_DESC,
// // Упаковка
// "43@RndvStAu" => customSampleCreateDto.Package.Replace(",", "."),
// // Стадия
// "38@RndvStAu" => mappedControl.Stage,
// // Возвращаем значение
// _ => taskFilter.Value
//};
}
#endregion
#region 9. Создание пробы
var sampleFullDto = _manager.EventAwareObjectFactory.Sample.Create(
customSampleCreateDto.SampleType.ST,
customSampleCreateDto.SampleType.VERSION,
taskFilterDtos);
_manager.EventAwareObjectFactory.SaveChanges();
#endregion
#region 10. Заполнение инфокарт
foreach (InfoCardSetting card in _appSettings.InfoCardSettings)
{
var parameter = GetPropertyValue(request.Document, card.Name);
if (parameter != null)
{
card.Value = parameter.ToString();
}
else
{
Logger.Warn($"[{request.GuigMsgOutb}]" +
$"В полученном запросе отсутствует параметр: \"{card.Name}\". Локация: \"{card.Plant}\". Полученный запрос не имеет соответствующего поля/значения для записи");
}
}
_sampleService.FillSampleInfoCards(Convert.ToDecimal(sampleFullDto.ID), _appSettings.InfoCardSettings,
plant.DESCRIPTION);
#endregion
#region 11. Отправка Confirmation
await _sampleService.SendConfirmation(request, sampleFullDto);
#endregion
#region 12. Возврат ответа на запрос
var requestMessage = $"Запрос с Message Guid: {request.GuigMsgOutb} был успешно обработан";
Logger.Log(LogLevel.Info, $"[{request.GuigMsgOutb}]" + requestMessage);
#endregion
}
catch (Exception ex)
{
Logger.Error($"[{request.GuigMsgOutb}]" + ex.Message + "\n\n" + ex.StackTrace);
await _sampleService.SendConfirmation(request, null, ex.Message);
}
}
private void Underload()
......
......@@ -6,9 +6,12 @@ using ProfitGroup.SampleService.Models;
using RnD.API;
using RnD.BusinessLayer.Interfaces.Model;
using System;
using System.Buffers.Text;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
......@@ -38,23 +41,29 @@ namespace ProfitGroup.SampleService.Core.Services
_appSettings = JsonConvert.DeserializeObject<Appsettings>(File.ReadAllText(path));
}
public async Task<bool> SendConfirmationToSap(MT_InspLot content, SampleFullDTO sampleFullDto, bool isSuccessCreated)
public async Task<(bool isSuccess, HttpStatusCode statusCode, string message)> SendConfirmationToSap(MT_InspLot content, SampleFullDTO sampleFullDto,
bool isSuccessCreated, string message = null)
{
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = BasicAuthorization(_appSettings.ConfirmationLogin, _appSettings.ConfirmationPassword);
client.DefaultRequestHeaders.Add("SOAPAction", " http://sap.com/xi/WebService/soap1.1 ");
if (string.IsNullOrEmpty(message))
message = isSuccessCreated ? $@"Проба сформирована успешно" : "Проба не была сформирована";
client.BaseAddress = new Uri(_appSettings.ConfirmationUrl);
var dto = new Models.Confirmation.Document
{
Status = isSuccessCreated ? "S" : "E",
StatusText = isSuccessCreated ? $@"Проба сформирована успешно" : "Проба не была сформирована",
SC_VALUE = sampleFullDto.ShortDescription,
ControlPartionId = content.Document.InspectionLot,
StatusText = message,
SC_VALUE = sampleFullDto?.ID.Value.ToString() ?? string.Empty,
ControlPartionId = content?.Document?.InspectionLot,
LineId = "1",
ProbeId = sampleFullDto.ID.ToString()
ProbeId = content?.Document?.Proba
};
var data = new Models.Confirmation.Envelope
......@@ -64,6 +73,7 @@ namespace ProfitGroup.SampleService.Core.Services
MT_InspLotConf = new Models.Confirmation.MT_InspLotConf
{
Document = dto,
GuidMsgOutb = content?.GuigMsgOutb
}
}
};
......@@ -74,27 +84,53 @@ namespace ProfitGroup.SampleService.Core.Services
var serializer = new XmlSerializer(typeof(Models.Confirmation.Envelope));
using (var stringWriter = new StringWriter())
using (var stringWriter = new StringWriterUTF8())
{
serializer.Serialize(stringWriter, data, namespaces);
var xmlString = stringWriter.ToString();
if (Directory.Exists(_appSettings.XmlConfirmationDirectory) == false)
Directory.CreateDirectory(_appSettings.XmlConfirmationDirectory);
if (!string.IsNullOrEmpty(content.GuigMsgOutb))
File.WriteAllText(Path.Combine(_appSettings.XmlConfirmationDirectory, $"{content.GuigMsgOutb}.xml"), xmlString);
else
Logger.Error($"Был получен пустой Message guid");
// ToDo: Заменить ендпоинт
var request = await client.PostAsync("/XISOAPAdapter/MessageServlet?senderParty=&senderService=BSP_OPCENTER&receiverParty=&receiverService=&interface=SI_OpCenterSend_AO&interfaceNamespace=http://lukoil.ru/opcenter/ORM", new StringContent(xmlString, Encoding.UTF8));
return request.IsSuccessStatusCode;
//Dev
var request = await client.PostAsync("/XISOAPAdapter/MessageServlet?senderParty=&senderService=BSD_OPCENTER&receiverParty=&receiverService=&interface=SI_OpCenterSend_AO&interfaceNamespace=http%3A%2F%2Flukoil.ru%2Fopcenter%2FORM", new StringContent(xmlString, Encoding.UTF8, "text/xml"));
//Prod
// var request = await client.PostAsync("/XISOAPAdapter/MessageServlet?senderParty=&senderService=BSP_OPCENTER&receiverParty=&receiverService=&interface=SI_OpCenterSend_AO&interfaceNamespace=http://lukoil.ru/opcenter/ORM", new StringContent(xmlString, Encoding.UTF8, "text/xml"));
//Test
// var request = await client.PostAsync("/MessageServlet?senderParty=&senderService=BST_OPCENTER&receiverParty=&receiverService=&interface=SI_OpCenterSend_AO&interfaceNamespace=http%3A%2F%2Flukoil.ru%2Fopcenter%2FORM", new StringContent(xmlString, Encoding.UTF8, "text/xml"));
var result = await request.Content.ReadAsStringAsync();
return (request.IsSuccessStatusCode, request.StatusCode, result);
}
}
}
catch (Exception ex)
{
Logger.Error(ex);
return false;
return (false, HttpStatusCode.NoContent, string.Empty);
}
}
public AuthenticationHeaderValue BasicAuthorization(string login, string password)
{
var authenticationString = $"{login}:{password}";
var base64EncodedAuthenticationString = Convert.ToBase64String(Encoding.ASCII.GetBytes(authenticationString));
return new AuthenticationHeaderValue("Basic", base64EncodedAuthenticationString);
}
}
}
\ No newline at end of file
using NLog;
using Microsoft.Ajax.Utilities;
using NLog;
using NLog.Config;
using ProfitGroup.Rdnl.Extensions;
using ProfitGroup.SampleService.Models;
using RnD.API;
using RnD.BusinessLayer.EF.Interfaces;
using RnD.BusinessLayer.Interfaces.ExtensionMethods;
using RnD.BusinessLayer.Interfaces.InfoField;
using RnD.BusinessLayer.Interfaces.Model;
using RnD.Model.EF;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Validation;
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using RnD.Model;
namespace ProfitGroup.SampleService.Core.Services
{
......@@ -48,7 +53,6 @@ namespace ProfitGroup.SampleService.Core.Services
public IEnumerable<TaskFilterDTO> GetTaskKeys(string plantName, string operationControlName,
string packageOrStage)
{
var task = _api.BusinessObjectFactory.TaskTypes.GetAllTaskTypes()
.FirstOrDefault(c => c.Description == "Sample Creation");
......@@ -71,10 +75,15 @@ namespace ProfitGroup.SampleService.Core.Services
{
if (string.IsNullOrEmpty(packageOrStage))
{
creationTasks = creationTasks.Where(c => c.FirstOrDefault(attribute => attribute.COL_ID == "38") == null); // Ищем тот таск, у которого отсутствует стадия
}else
creationTasks =
creationTasks.Where(c =>
c.FirstOrDefault(attribute => attribute.COL_ID == "38") == null); // Ищем тот таск, у которого отсутствует стадия
}
else
{
creationTasks = creationTasks.Where(c => c.FirstOrDefault(attribute => attribute.COL_ID == "38") != null); // Ищем тот таск, у которого имеется стадия
creationTasks =
creationTasks.Where(c =>
c.FirstOrDefault(attribute => attribute.COL_ID == "38") != null); // Ищем тот таск, у которого имеется стадия
}
}
......@@ -152,20 +161,156 @@ namespace ProfitGroup.SampleService.Core.Services
//});
}
public void FillSampleInfoCards(decimal sampleId, List<InfoCardSetting> infoFieldInfoElements)
public void FillSampleInfoCards(Sample sample, List<InfoCardSetting> infoFieldInfoElements, string plantName)
{
var sample = _api.Sample.GetSample(sampleId);
var material = sample.Attributes.FirstOrDefault(c => c.ShortDescription == "Product");
var productValue = material?.Value ?? string.Empty;
foreach (var infoFieldInfo in infoFieldInfoElements)
{
var infoFields = sample.InfoCards
if (infoFieldInfo.Plant == null)
{
foreach (var infoFieldPath in infoFieldInfo.InfoFieldPaths)
{
IEnumerable<RnD.Model.IInfoField> infoFields = Enumerable.Empty<RnD.Model.IInfoField>();
if (infoFieldPath.InfoCard == null)
{
infoFields = sample.InfoCards
.SelectMany(c => c.InfoFields)
.Where(g => g.ShortDescription == infoFieldPath.InfoField);
}else
{
infoFields = sample.InfoCards
.Where(c => c.ShortDescription == infoFieldPath.InfoCard)
.SelectMany(c => c.InfoFields)
.Where(c => c.ShortDescription == infoFieldInfo.InfoField);
.Where(g => g.ShortDescription == infoFieldPath.InfoField);
}
if (infoFields.Any())
{
foreach (var infoField in infoFields)
{
// Строгая проверка (Ограничение только для даты)
if (infoFieldInfo.Name == "CreateDate")
{
if (productValue.StartsWith("FP") && infoField.ShortDescription == "S4_ProdManufDate")
{
infoField.InfoFieldValue = infoFieldInfo.Value;
continue;
}
if (productValue.StartsWith("FP") && infoField.ShortDescription == "ProdManufacturDate")
{
infoField.InfoFieldValue = infoFieldInfo.Value;
continue;
}
if (productValue.StartsWith("RM") && infoField.ShortDescription == "S4_RawMatManufDate")
{
infoField.InfoFieldValue = infoFieldInfo.Value;
continue;
}
if (productValue.StartsWith("RM") && infoField.ShortDescription == "RawMatManufactDate")
{
infoField.InfoFieldValue = infoFieldInfo.Value;
continue;
}
continue;
}
infoField.InfoFieldValue = infoFieldInfo.Value;
}
}else
{
Logger.Error(
$@"Переданный атрибут '{infoFieldInfo.Name}' не был никуда записан. Не нашлось ни одной инфокарты и соответствующего инфополя из настроек appsettings.json");
}
}
}
else if (infoFieldInfo.Plant == plantName)
{
RnD.Model.IInfoField infoField = null;
int writeCount = 0;
foreach (var infoFieldPath in infoFieldInfo.InfoFieldPaths)
{
var infoCard = sample.InfoCards
.FirstOrDefault(c => c.ShortDescription == infoFieldPath.InfoCard);
infoField = infoCard?.InfoFields
.FirstOrDefault(c => c.ShortDescription == infoFieldPath.InfoField);
if (infoField != null)
{
// Ограничение только для даты
if (infoFieldInfo.Name == "CreateDate")
{
if (productValue.StartsWith("FP") && infoField.ShortDescription == "S4_ProdManufDate")
{
infoField.InfoFieldValue = infoFieldInfo.Value;
++writeCount;
continue;
}
if (productValue.StartsWith("FP") && infoField.ShortDescription == "ProdManufacturDate")
{
infoField.InfoFieldValue = infoFieldInfo.Value;
++writeCount;
continue;
}
if (productValue.StartsWith("RM") && infoField.ShortDescription == "S4_RawMatManufDate")
{
infoField.InfoFieldValue = infoFieldInfo.Value;
++writeCount;
continue;
}
if (productValue.StartsWith("RM") && infoField.ShortDescription == "RawMatManufactDate")
{
infoField.InfoFieldValue = infoFieldInfo.Value;
++writeCount;
continue;
}
continue;
}
infoField.InfoFieldValue = infoFieldInfo.Value;
++writeCount;
}
}
if (writeCount == 0)
{
//Logger.Error($@"Переданный атрибут '{infoFieldInfo.Name}' не был никуда записан. Не нашлось ни одной инфокарты и соответствующего инфополя из настроек Appsetting.json");
continue;
}
}
}
// foreach (var infoFieldInfo in infoFieldInfoElements)
// {
// var infoFields = sample.InfoCards
// .SelectMany(c => c.InfoFields)
// .Where(c => c.ShortDescription == infoFieldInfo.InfoField);
//
// foreach (var infoField in infoFields)
// infoField.InfoFieldValue = infoFieldInfo.Value;
// }
//foreach (var infoCard in infoCards)
//{
......@@ -196,21 +341,27 @@ namespace ProfitGroup.SampleService.Core.Services
public async Task<bool> ValidateSample(string shortDescription)
{
if (string.IsNullOrEmpty(shortDescription))
return false;
var sample = await _databaseContext.RndvSc.FirstOrDefaultAsync(c => c.SC_VALUE == shortDescription);
return sample.SS == 8; // Создан
if (sample == null)
return false;
return true; // Создан
}
public async Task SendConfirmation(MT_InspLot request, SampleFullDTO sampleFullDto)
public async Task SendConfirmation(MT_InspLot request, SampleFullDTO sampleFullDto, string message = null)
{
var sampleIsCreated = await ValidateSample(sampleFullDto.ShortDescription);
var sampleIsCreated = await ValidateSample(sampleFullDto?.ShortDescription);
var sampleIsConfirmed = false;
(bool isSuccess, System.Net.HttpStatusCode statusCode, string message) sampleIsConfirmed = default;
try
{
sampleIsConfirmed = await _sampleConfirmationService
.SendConfirmationToSap(request, sampleFullDto, sampleIsCreated);
.SendConfirmationToSap(request, sampleFullDto, sampleIsCreated, message);
}
catch (Exception ex)
{
......@@ -223,9 +374,9 @@ namespace ProfitGroup.SampleService.Core.Services
? $@"Проба ""{sampleFullDto.ShortDescription}"" успешно сформирована. "
: $@"Проба не сформирована. ");
requestMessageBuilder.Append(sampleIsConfirmed
? "Был отправлен Confirmation в SAP/S4. Получен успешный HttpStatus"
: "Был отправлен Confirmation в SAP/S4. Получен ошибочный HttpStatus");
requestMessageBuilder.Append(sampleIsConfirmed.isSuccess
? $"Был отправлен Confirmation в SAP/S4. Получен успешный HttpStatus {sampleIsConfirmed.statusCode} ({(int)sampleIsConfirmed.statusCode}), \n {message}"
: $"Был отправлен Confirmation в SAP/S4. Получен ошибочный HttpStatus {sampleIsConfirmed.statusCode} ({(int)sampleIsConfirmed.statusCode}), \n {message}");
Logger.Log(LogLevel.Info, requestMessageBuilder.ToString());
}
......
using System.Collections.Generic;
using Newtonsoft.Json;
namespace ProfitGroup.SampleService.Models
{
/// <summary>
/// Представляет настройки для инфокарт, определяющие значение поля, путь и атрибуты, которые записываются в инфокарту из пакета.
/// </summary>
public class InfoCardSetting
{
public string Name { get; set; }
public string InfoCard { get; set; }
public string InfoField { get; set; }
/// <summary>
/// Получает или устанавливает имя атрибута.
/// </summary>
[JsonProperty("Name")] public string Name { get; set; }
/// <summary>
/// Получает или устанавливает значение атрибута "Plant".
/// </summary>
[JsonProperty("Plant")] public string Plant { get; set; }
/// <summary>
/// Получает или устанавливает значение атрибута "Value".
/// </summary>
public string Value { get; set; }
/// <summary>
/// Получает или устанавливает список путей к полям инфокарты.
/// </summary>
[JsonProperty("InfoFieldPaths")] public List<InfoFieldPath> InfoFieldPaths { get; set; }
}
/// <summary>
/// Представляет путь к полю инфокарты, состоящий из имени инфокарты и имени поля.
/// </summary>
public class InfoFieldPath
{
/// <summary>
/// Получает или устанавливает имя инфокарты.
/// </summary>
[JsonProperty("InfoCard")] public string InfoCard { get; set; }
/// <summary>
/// Получает или устанавливает имя поля инфокарты.
/// </summary>
[JsonProperty("InfoField")] public string InfoField { get; set; }
}
/// <summary>
/// Представляет настройки приложения, такие как URL подтверждения, логин, пароль и директория подтверждения.
/// </summary>
public class Appsettings
{
public string ConfirmationUrl { get; set; }
public List<InfoCardSetting> InfoCardSettings { get; set; }
/// <summary>
/// Получает или устанавливает URL подтверждения.
/// </summary>
[JsonProperty("ConfirmationUrl")] public string ConfirmationUrl { get; set; }
/// <summary>
/// Получает или устанавливает логин подтверждения.
/// </summary>
[JsonProperty("ConfirmationLogin")] public string ConfirmationLogin { get; set; }
/// <summary>
/// Получает или устанавливает пароль подтверждения.
/// </summary>
[JsonProperty("ConfirmationPassword")] public string ConfirmationPassword { get; set; }
/// <summary>
/// Получает или устанавливает директорию подтверждения в формате XML.
/// </summary>
[JsonProperty("XmlConfirmationDirectory")]
public string XmlConfirmationDirectory { get; set; }
/// <summary>
/// Получает или устанавливает список настроек инфокарты.
/// </summary>
[JsonProperty("InfoCardSettings")] public List<InfoCardSetting> InfoCardSettings { get; set; }
}
}
......@@ -3,31 +3,58 @@ using System.Xml.Serialization;
namespace ProfitGroup.Rdnl.Extensions.Models
{
/// <summary>
/// Представляет корневой элемент MT_Confirmation с пространством имен "http://lukoil.ru/opcenter/ORM".
/// </summary>
[XmlRoot("MT_Confirmation", Namespace = "http://lukoil.ru/opcenter/ORM")]
public class MT_Confirmation
{
/// <summary>
/// Получает или устанавливает список подтверждений.
/// </summary>
[XmlElement("Confirmation")]
public List<Confirmation> Confirmations { get; set; }
}
/// <summary>
/// Представляет элемент подтверждения с пространством имен "http://lukoil.ru/opcenter/ORM".
/// </summary>
[XmlRoot("Confirmation", Namespace = "http://lukoil.ru/opcenter/ORM")]
public class Confirmation
{
/// <summary>
/// Получает или устанавливает значение атрибута "ObjectType".
/// </summary>
[XmlAttribute]
public string ObjectType { get; set; }
/// <summary>
/// Получает или устанавливает значение атрибута "ResponseType".
/// </summary>
[XmlAttribute]
public string ResponseType { get; set; }
/// <summary>
/// Получает или устанавливает значение атрибута "ID".
/// </summary>
[XmlAttribute]
public string ID { get; set; }
/// <summary>
/// Получает или устанавливает значение атрибута "Version".
/// </summary>
[XmlAttribute]
public string Version { get; set; }
/// <summary>
/// Получает или устанавливает значение атрибута "StatusCode".
/// </summary>
[XmlAttribute]
public string StatusCode { get; set; }
/// <summary>
/// Получает или устанавливает значение атрибута "StatusText".
/// </summary>
[XmlAttribute]
public string StatusText { get; set; }
}
......

// NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
/// <remarks/>
using System;
/// <summary>
/// Представляет класс MT_InspLot с атрибутами сериализации и пространством имен "http://lukoil.ru/opcenter/ORM".
/// </summary>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://lukoil.ru/opcenter/ORM")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://lukoil.ru/opcenter/ORM", IsNullable = false)]
public partial class MT_InspLot
{
private string guigMsgOutbField;
private string systemSenderField;
private string systemReceiverField;
private MT_InspLotStatus statusField;
private Document documentField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "")]
public string GuigMsgOutb
{
get
{
return this.guigMsgOutbField;
}
set
{
this.guigMsgOutbField = value;
}
get { return this.guigMsgOutbField; }
set { this.guigMsgOutbField = value; }
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "")]
public string SystemSender
{
get
{
return this.systemSenderField;
}
set
{
this.systemSenderField = value;
}
get { return this.systemSenderField; }
set { this.systemSenderField = value; }
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "")]
public string SystemReceiver
{
get
{
return this.systemReceiverField;
get { return this.systemReceiverField; }
set { this.systemReceiverField = value; }
}
set
/// <remarks/>
public MT_InspLotStatus Status
{
this.systemReceiverField = value;
}
get { return this.statusField; }
set { this.statusField = value; }
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "")]
public Document Document
{
get
{
return this.documentField;
get { return this.documentField; }
set { this.documentField = value; }
}
set
}
/// <summary>
/// Представляет статус MT_InspLot с атрибутами сериализации и пространством имен "http://lukoil.ru/opcenter/ORM".
/// </summary>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://lukoil.ru/opcenter/ORM")]
public partial class MT_InspLotStatus
{
private string codeField;
private string textField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Code
{
this.documentField = value;
get { return this.codeField; }
set { this.codeField = value; }
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Text
{
get { return this.textField; }
set { this.textField = value; }
}
}
/// <remarks/>
/// <summary>
/// Представляет документ с атрибутами сериализации.
/// </summary>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class Document
{
private DocumentStatus[] statusField;
private string posnrField;
private string inspectionLotField;
private string inspectonTypeField;
private string inspLotSizeField;
private string materialField;
private string plantField;
private string posnrField;
private string pHYNRField;
private string inspectionLotField;
private string batchField;
private string storageField;
private string inspLotSizeField;
private string createDateField;
private string inspectonTypeField;
private string probaField;
private string unitField;
private string uOMField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Status")]
public DocumentStatus[] Status
{
get
{
return this.statusField;
}
set
{
this.statusField = value;
}
}
private string producedField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Posnr
{
get
{
return this.posnrField;
}
set
public string InspectonType
{
this.posnrField = value;
}
get { return this.inspectonTypeField; }
set { this.inspectonTypeField = value; }
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string InspectionLot
{
get
{
return this.inspectionLotField;
}
set
public string InspLotSize
{
this.inspectionLotField = value;
}
get { return this.inspLotSizeField; }
set { this.inspLotSizeField = value; }
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Material
{
get
{
return this.materialField;
}
set
{
this.materialField = value;
}
get { return this.materialField; }
set { this.materialField = value; }
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Plant
{
get
{
return this.plantField;
}
set
{
this.plantField = value;
}
get { return this.plantField; }
set { this.plantField = value; }
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Batch
{
get
{
return this.batchField;
}
set
public string Posnr
{
this.batchField = value;
}
get { return this.posnrField; }
set { this.posnrField = value; }
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Storage
{
get
public string PHYNR
{
return this.storageField;
}
set
{
this.storageField = value;
}
get { return this.pHYNRField; }
set { this.pHYNRField = value; }
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string InspLotSize
{
get
{
return this.inspLotSizeField;
}
set
public string InspectionLot
{
this.inspLotSizeField = value;
}
get { return this.inspectionLotField; }
set { this.inspectionLotField = value; }
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string CreateDate
{
get
{
return this.createDateField;
}
set
public string Batch
{
this.createDateField = value;
}
get { return this.batchField; }
set { this.batchField = value; }
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string InspectonType
{
get
public string Storage
{
return this.inspectonTypeField;
get { return this.storageField; }
set { this.storageField = value; }
}
set
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string CreateDate
{
this.inspectonTypeField = value;
}
get { return this.createDateField; }
set { this.createDateField = value; }
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Proba
{
get
{
return this.probaField;
}
set
{
this.probaField = value;
}
get { return this.probaField; }
set { this.probaField = value; }
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string UOM
{
get
public string Unit
{
return this.uOMField;
}
set
{
this.uOMField = value;
}
get { return this.unitField; }
set { this.unitField = value; }
}
}
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class DocumentStatus
{
private string codeField;
private string textField;
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Code
{
get
{
return this.codeField;
}
set
public string UOM
{
this.codeField = value;
}
get { return this.uOMField; }
set { this.uOMField = value; }
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string Text
{
get
public string Produced
{
return this.textField;
}
set
{
this.textField = value;
}
get { return this.producedField; }
set { this.producedField = value; }
}
}
......@@ -3,20 +3,56 @@ using System;
namespace ProfitGroup.SampleService.Models
{
/// <summary>
/// Представляет объект передачи данных (DTO) для создания пользовательского образца.
/// </summary>
public class CustomSampleCreateDto
{
/// <summary>
/// Получает или устанавливает наименование завода.
/// </summary>
public string PlantName { get; set; }
/// <summary>
/// Получает или устанавливает код продукта.
/// </summary>
public string ProductCode { get; set; }
/// <summary>
/// Получает или устанавливает упаковку образца.
/// </summary>
public string Package { get; set; }
/// <summary>
/// Получает или устанавливает раму спецификации.
/// </summary>
public string SpecificationFrame { get; set; }
/// <summary>
/// Получает или устанавливает наименование операции контроля.
/// </summary>
public string OperationControlName { get; set; }
/// <summary>
/// Получает или устанавливает тип образца.
/// </summary>
public RndvSt SampleType { get; set; }
}
/// <summary>
/// Представляет атрибут наименования операции контроля.
/// </summary>
public class OperationControlNameAttribute : Attribute
{
/// <summary>
/// Получает наименование операции контроля.
/// </summary>
public string Name { get; }
/// <summary>
/// Инициализирует новый экземпляр атрибута с указанным наименованием.
/// </summary>
/// <param name="name">Наименование операции контроля.</param>
public OperationControlNameAttribute(string name)
{
Name = name;
......
......@@ -13,6 +13,8 @@
//}
// NOTE: Generated code may require at least .NET Framework 4.5 or .NET Core/Standard 2.0.
/// <remarks/>
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
......@@ -86,6 +88,8 @@
private Document documentField;
private string guidMsgOutbField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Namespace = "")]
public Document Document
......@@ -99,13 +103,27 @@
this.documentField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlAttributeAttribute()]
public string GuidMsgOutb
{
get
{
return this.guidMsgOutbField;
}
set
{
this.guidMsgOutbField = value;
}
}
}
/// <remarks/>
[System.Serializable()]
[System.ComponentModel.DesignerCategory("code")]
[System.Xml.Serialization.XmlType(AnonymousType = true)]
[System.Xml.Serialization.XmlRoot(Namespace = "", IsNullable = false)]
[System.SerializableAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "", IsNullable = false)]
public partial class Document
{
......@@ -210,4 +228,5 @@
}
\ No newline at end of file
namespace ProfitGroup.SampleService.Models
{
public class SampleCreateState
{
public bool IsProcessing { get; set; }
}
}
\ No newline at end of file
......@@ -302,13 +302,21 @@
<Compile Include="Controllers\HomeController.cs" />
<Compile Include="Controllers\SampleController.cs" />
<Compile Include="Core\Middlewares\BasicAuthMiddleware.cs" />
<Compile Include="Core\Middlewares\SampleMiddleware.cs" />
<Compile Include="Core\Services\DetectPackageServiceByRangeValue.cs" />
<Compile Include="Core\Services\IKSSSInfoService.cs" />
<Compile Include="Core\Services\ISampleConfirmationService.cs" />
<Compile Include="Core\Services\ISampleService.cs" />
<Compile Include="Core\Services\KSSSInfoService.cs" />
<Compile Include="Core\Services\SampleConfirmationService.cs" />
<Compile Include="Core\Services\SampleService.cs" />
<Compile Include="Core\Services\KSSSInfoService.cs">
<DependentUpon>IKSSSInfoService.cs</DependentUpon>
</Compile>
<Compile Include="Core\Services\QueueHandler.cs" />
<Compile Include="Core\Services\SampleConfirmationService.cs">
<DependentUpon>ISampleConfirmationService.cs</DependentUpon>
</Compile>
<Compile Include="Core\Services\SampleService.cs">
<DependentUpon>ISampleService.cs</DependentUpon>
</Compile>
<Compile Include="Global.asax.cs">
<DependentUpon>Global.asax</DependentUpon>
</Compile>
......@@ -316,9 +324,12 @@
<Compile Include="Models\ConfirmationRequest.cs" />
<Compile Include="Models\CreateSampleRequestDto.cs" />
<Compile Include="Models\CustomSampleCreateDto.cs" />
<Compile Include="Models\Entities\RndtPack.cs" />
<Compile Include="Models\Entities\SiemtControlTypes.cs" />
<Compile Include="Models\S4InspectionTypeMap.cs" />
<Compile Include="Models\SampleConfirmationDto.cs" />
<Compile Include="Models\SampleCreateState.cs" />
<Compile Include="Models\StringWriterUTF8.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
......@@ -389,9 +400,6 @@
<Content Include="Views\Shared\Error.cshtml" />
<Content Include="Views\Shared\_Layout.cshtml" />
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />
</ItemGroup>
<ItemGroup>
<Content Include="Scripts\bootstrap.min.js.map" />
</ItemGroup>
......
......@@ -2,7 +2,7 @@
<section class="row" aria-labelledby="aspnetTitle">
<h1 id="aspnetTitle">PROF-IT Group | Sample Service</h1>
<p class="lead">Сервис по созданию проб в RDnL Opcenter</p>
<p><a href="https://localhost:44395/Help" class="btn btn-primary btn-md">Перейти к документации API &raquo;</a></p>
<p><a href="/Help" class="btn btn-primary btn-md">Перейти к документации API &raquo;</a></p>
</section>
</main>
\ No newline at end of file
......@@ -77,6 +77,7 @@
</handlers>
<modules>
<add name="BasicAuthMiddleware" type="ProfitGroup.SampleService.Core.Middlewares.BasicAuthMiddleware"/>
<add name="SampleMiddleware" type="ProfitGroup.SampleService.Core.Middlewares.SampleMiddleware"/>
</modules>
</system.webServer>
<runtime>
......
{
"ConfirmationUrl": "http://sapx64.srv.lukoil.com",
"ConfirmationUrl": "http://sapx62cidb.srv.lukoil.com",
"ConfirmationLogin": "",
"ConfirmationPassword": "",
"XmlConfirmationDirectory": "C:\\Logs\\S4ScCreateConfirmations",
"InfoCardSettings": [
{
"Name": "Material",
"InfoCard": "S4Integration",
"Plant": null,
"InfoFieldPaths": [
{
"InfoCard": "S4Integration_Probe",
"InfoField": "Ksss"
}
]
},
{
"Name": "Produced",
"Plant": null,
"InfoFieldPaths": [
{
"InfoCard": "S4Integration_Probe",
"InfoField": "S4_Produced"
}
]
},
{
"Name": "InspLotSize",
"Plant": null,
"InfoFieldPaths": [
{
"InfoCard": "S4Integration_Probe",
"InfoField": "S4_ProductWeight"
}
]
},
{
"Name": "UOM",
"Plant": null,
"InfoFieldPaths": [
{
"InfoCard": "S4Integration_Probe",
"InfoField": "S4_UnitsMeasure"
}
]
},
{
"Name": "CreateDate",
"Plant": null,
"InfoFieldPaths": [
{
"InfoCard": "S4Integration_Probe",
"InfoField": "S4_ProdManufDate"
}
]
},
{
"Name": "CreateDate",
"Plant": null,
"InfoFieldPaths": [
{
"InfoCard": "S4Integration_Probe",
"InfoField": "S4_RawMatManufDate"
}
]
},
{
"Name": "InspectionLot",
"InfoCard": "S4Integration",
"Plant": null,
"InfoFieldPaths": [
{
"InfoCard": "S4Integration_Probe",
"InfoField": "S4_InspectionLot"
}
]
},
{
"Name": "Proba",
"InfoCard": "S4Integration",
"Plant": null,
"InfoFieldPaths": [
{
"InfoCard": "S4Integration_Probe",
"InfoField": "S4_PHYNR"
}
]
},
{
"Name": "Produced",
"Plant": "Tyumen",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleAC",
"InfoField": "Produced"
}
]
},
{
"Name": "Produced",
"Plant": "Perm",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleAC-PTPP",
"InfoField": "Produced"
}
]
},
{
"Name": "Produced",
"Plant": "Volgograd",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleAC-VTPP",
"InfoField": "Produced"
}
]
},
{
"Name": "Produced",
"Plant": "Torzhok",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleAC-TK",
"InfoField": "Produced"
}
]
},
{
"Name": "Batch",
"Plant": null,
"InfoFieldPaths": [
{
"InfoCard": "S4Integration_Probe",
"InfoField": "S4_BatchNumber"
}
]
},
{
"Name": "Batch",
"InfoCard": "S4Integration",
"Plant": "Tyumen",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleIC",
"InfoField": "BatchNumber"
},
{
"InfoCard": "ICSampleOCAC",
"InfoField": "BatchNumber"
},
{
"Name": "Storage",
"InfoCard": "S4Integration",
"InfoField": "S4_Storage"
"InfoCard": "ICSampleAC",
"InfoField": "BatchNumber"
},
{
"InfoCard": "ICSampleOCRW",
"InfoField": "BatchNumber"
},
{
"InfoCard": "ICSampleOCAdditSol",
"InfoField": "BatchNumber"
}
]
},
{
"Name": "Batch",
"Plant": "Perm",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleIC-PTPP",
"InfoField": "BatchNumber"
},
{
"InfoCard": "ICSampleOCAC-PTPP",
"InfoField": "BatchNumber"
},
{
"InfoCard": "ICSampleAC-PTPP",
"InfoField": "BatchNumber"
},
{
"InfoCard": "ICSampleIC-PTPP+TF",
"InfoField": "BatchNumber"
}
]
},
{
"Name": "Batch",
"Plant": "Volgograd",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleIC-VTPP",
"InfoField": "BatchNumber"
},
{
"InfoCard": "ICSampleOCAC-VTPP",
"InfoField": "BatchNumber"
},
{
"InfoCard": "ICSampleAC-VTPP",
"InfoField": "BatchNumber"
}
]
},
{
"Name": "Batch",
"Plant": "Torzhok",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleIC-TK",
"InfoField": "BatchNumber"
},
{
"InfoCard": "ICSampleOCAC-TK",
"InfoField": "BatchNumber"
},
{
"InfoCard": "ICSampleAC-TK",
"InfoField": "BatchNumber"
}
]
},
{
"Name": "InspLotSize",
"InfoCard": "S4Integration",
"Plant": "Tyumen",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleIC",
"InfoField": "ProductWeight"
},
{
"Name": "CreateDate",
"InfoCard": "S4Integration",
"InfoField": "ProdManufacturDate"
"InfoCard": "ICSampleOCAC",
"InfoField": "ProductWeight"
},
{
"InfoCard": "ICSampleAC",
"InfoField": "ProductWeight"
},
{
"InfoCard": "ICSampleOCRW",
"InfoField": "ProductWeight"
},
{
"InfoCard": "ICSampleOCAdditSol",
"InfoField": "ProductWeight"
}
]
},
{
"Name": "InspLotSize",
"Plant": "Perm",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleIC-PTPP",
"InfoField": "ProductWeight"
},
{
"InfoCard": "ICSampleOCAC-PTPP",
"InfoField": "ProductWeight"
},
{
"InfoCard": "ICSampleAC-PTPP",
"InfoField": "ProductWeight"
},
{
"InfoCard": "ICSampleIC-PTPP+TF",
"InfoField": "ProductWeight"
}
]
},
{
"Name": "InspLotSize",
"Plant": "Volgograd",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleIC-VTPP",
"InfoField": "ProductWeight"
},
{
"InfoCard": "ICSampleOCAC-VTPP",
"InfoField": "ProductWeight"
},
{
"InfoCard": "ICSampleAC-VTPP",
"InfoField": "ProductWeight"
}
]
},
{
"Name": "InspLotSize",
"Plant": "Torzhok",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleAC-TK",
"InfoField": "ProductWeight"
},
{
"InfoCard": "ICSampleOCAC-TK",
"InfoField": "ProductWeight"
},
{
"InfoCard": "ICSampleIC-TK",
"InfoField": "ProductWeight"
}
]
},
{
"Name": "UOM",
"Plant": "Tyumen",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleIC",
"InfoField": "UnitsMeasure"
},
{
"InfoCard": "ICSampleOCAC",
"InfoField": "UnitsMeasure"
},
{
"InfoCard": "ICSampleAC",
"InfoField": "UnitsMeasure"
},
{
"InfoCard": "ICSampleOCRW",
"InfoField": "UnitsMeasure"
},
{
"InfoCard": "ICSampleOCAdditSol",
"InfoField": "UnitsMeasure"
}
]
},
{
"Name": "UOM",
"Plant": "Perm",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleIC-PTPP",
"InfoField": "UnitsMeasure"
},
{
"InfoCard": "ICSampleOCAC-PTPP",
"InfoField": "UnitsMeasure"
},
{
"InfoCard": "ICSampleAC-PTPP",
"InfoField": "UnitsMeasure"
},
{
"InfoCard": "ICSampleIC-PTPP+TF",
"InfoField": "UnitsMeasure"
}
]
},
{
"Name": "UOM",
"Plant": "Volgograd",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleIC-VTPP",
"InfoField": "UnitsMeasure"
},
{
"InfoCard": "ICSampleOCAC-VTPP",
"InfoField": "UnitsMeasure"
},
{
"InfoCard": "ICSampleAC-VTPP",
"InfoField": "UnitsMeasure"
}
]
},
{
"Name": "UOM",
"InfoCard": "S4Integration",
"Plant": "Torzhok",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleAC-TK",
"InfoField": "UnitsMeasure"
},
{
"InfoCard": "ICSampleOCAC-TK",
"InfoField": "UnitsMeasure"
},
{
"InfoCard": "ICSampleIC-TK",
"InfoField": "UnitsMeasure"
}
]
},
{
"Name": "CreateDate",
"Plant": "Tyumen",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleOCAC",
"InfoField": "ProdManufacturDate"
}
]
},
{
"Name": "CreateDate",
"Plant": "Perm",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleOCAC-PTPP",
"InfoField": "ProdManufacturDate"
}
]
},
{
"Name": "CreateDate",
"Plant": "Volgograd",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleOCAC-VTPP",
"InfoField": "ProdManufacturDate"
}
]
},
{
"Name": "CreateDate",
"Plant": "Torzhok",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleOCAC-TK",
"InfoField": "ProdManufacturDate"
}
]
},
{
"Name": "CreateDate",
"Plant": "Tyumen",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleIC",
"InfoField": "RawMatManufactDate"
}
]
},
{
"Name": "CreateDate",
"Plant": "Perm",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleIC-PTPP",
"InfoField": "RawMatManufactDate"
}
]
},
{
"Name": "CreateDate",
"Plant": "Volgograd",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleIC-VTPP",
"InfoField": "RawMatManufactDate"
}
]
},
{
"Name": "CreateDate",
"Plant": "Torzhok",
"InfoFieldPaths": [
{
"InfoCard": "ICSampleIC-TK",
"InfoField": "RawMatManufactDate"
}
]
}
]
}
\ No newline at end of file
......@@ -3,18 +3,21 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
internalLogLevel="Warn"
internalLogFile="C:\111\temp\sample-service\${shortdate}\internal-nlog.txt">
internalLogFile="C:\Logs\S4ScCreateIn\internal-nlog.txt">
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<targets>
<target xsi:type="File" name="sampleService" fileName="C:\111\temp\sample-service\${shortdate}\requests.log"
<target xsi:type="File" name="sampleService" fileName="C:\Logs\S4ScCreateIn\${shortdate}\requests.log"
layout="${longdate}|${event-properties:item=EventId_Id}|${logger}|${level:uppercase=true}|${message} ${exception:format=tostring}" />
<target xsi:type="File" name="queueHandler" fileName="C:\Logs\S4ScCreateIn\${shortdate}\CreateSample.log"
layout="${longdate}|${event-properties:item=EventId_Id}|${logger}|${level:uppercase=true}|${message} ${exception:format=tostring}" />
</targets>
<rules>
<logger name="ProfitGroup.SampleService.*" minlevel="Trace" writeTo="sampleService" />
<logger name="ProfitGroup.SampleService.Core.Services.QueueHandler" minlevel="Trace" writeTo="queueHandler" />
<logger name="ProfitGroup.SampleService.*" minlevel="Trace" writeTo="sampleService" final="true"/>
</rules>
</nlog>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment