From 7df93dc822448b7bee2002adf1fd57c08df99442 Mon Sep 17 00:00:00 2001 From: AnboevDD Date: Tue, 25 Feb 2025 10:06:21 +0500 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D1=8C=D1=82?= =?UTF-8?q?=D0=B5=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D0=B5=D0=BA=D1=82=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 1CDataBus.sln | 25 ++++++ 1CDataBus/1CDataBus.csproj | 24 ++++++ 1CDataBus/1CDataBus.http | 6 ++ 1CDataBus/Controllers/ContractsController.cs | 72 ++++++++++++++++++ .../Controllers/WeatherForecastController.cs | 33 ++++++++ 1CDataBus/Program.cs | 25 ++++++ 1CDataBus/Properties/launchSettings.json | 41 ++++++++++ 1CDataBus/RabbitMQ/RabbitConnection.cs | 48 ++++++++++++ 1CDataBus/Structure/Contract.cs | 39 ++++++++++ 1CDataBus/Structure/ODataAccess.cs | 33 ++++++++ 1CDataBus/WeatherForecast.cs | 13 ++++ 1CDataBus/appsettings.Development.json | 8 ++ 1CDataBus/appsettings.json | 25 ++++++ ...вка по сервису 1CDataBus.docx | Bin 0 -> 13910 bytes 14 files changed, 392 insertions(+) create mode 100644 1CDataBus.sln create mode 100644 1CDataBus/1CDataBus.csproj create mode 100644 1CDataBus/1CDataBus.http create mode 100644 1CDataBus/Controllers/ContractsController.cs create mode 100644 1CDataBus/Controllers/WeatherForecastController.cs create mode 100644 1CDataBus/Program.cs create mode 100644 1CDataBus/Properties/launchSettings.json create mode 100644 1CDataBus/RabbitMQ/RabbitConnection.cs create mode 100644 1CDataBus/Structure/Contract.cs create mode 100644 1CDataBus/Structure/ODataAccess.cs create mode 100644 1CDataBus/WeatherForecast.cs create mode 100644 1CDataBus/appsettings.Development.json create mode 100644 1CDataBus/appsettings.json create mode 100644 1CDataBus/Справка по сервису 1CDataBus.docx diff --git a/1CDataBus.sln b/1CDataBus.sln new file mode 100644 index 0000000..e090786 --- /dev/null +++ b/1CDataBus.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34728.123 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "1CDataBus", "1CDataBus\1CDataBus.csproj", "{B0551536-536F-4719-96E8-56848F4F4F26}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B0551536-536F-4719-96E8-56848F4F4F26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B0551536-536F-4719-96E8-56848F4F4F26}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B0551536-536F-4719-96E8-56848F4F4F26}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B0551536-536F-4719-96E8-56848F4F4F26}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {19101D4F-6085-422C-A340-C3DFEEDD930D} + EndGlobalSection +EndGlobal diff --git a/1CDataBus/1CDataBus.csproj b/1CDataBus/1CDataBus.csproj new file mode 100644 index 0000000..1ae6714 --- /dev/null +++ b/1CDataBus/1CDataBus.csproj @@ -0,0 +1,24 @@ + + + + net8.0 + enable + enable + _1CDataBus + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/1CDataBus/1CDataBus.http b/1CDataBus/1CDataBus.http new file mode 100644 index 0000000..db3904f --- /dev/null +++ b/1CDataBus/1CDataBus.http @@ -0,0 +1,6 @@ +@_1CDataBus_HostAddress = http://localhost:5043 + +GET {{_1CDataBus_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/1CDataBus/Controllers/ContractsController.cs b/1CDataBus/Controllers/ContractsController.cs new file mode 100644 index 0000000..18ca13d --- /dev/null +++ b/1CDataBus/Controllers/ContractsController.cs @@ -0,0 +1,72 @@ +using _1CDataBus.RabbitMQ; +using _1CDataBus.Structure; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Simple.OData.Client; +using System.Text; +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace _1CDataBus.Controllers +{ + [ApiController] + [Route("[controller]")] + public class ContractsController : ControllerBase + { + private readonly IConfiguration _config; + private readonly ILogger _logger; + private RabbitConnection _rabbit; + private ODataClient _client; + + public ContractsController(ILogger logger, IConfiguration config) + { + _config = config; + _logger = logger; + _rabbit = new RabbitConnection(_config); + var odata = new ODataAccess(_config); + _client = odata.Client; + } + + [HttpPost("SendContractFromQDoc")] + public async Task SendContractFromQDoc(long id) + { + var contract = await _client + .For("IContract") + .Key(id) + .Expand("BusinessUnit") + .Expand("Counterparty") + .Expand("Currency") + .FindEntryAsync(); + var sendContract = new Contract(contract); + await SendContractTo1C(sendContract); + } + + [HttpPost("SendContract")] + public async Task SendContractTo1C(Contract contract) + { + JsonSerializerOptions options = new() + { + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + WriteIndented = true + }; + var serialized = JsonSerializer.Serialize(contract, options); + await _rabbit.SendMessage(serialized); + } + + [HttpGet("GetContract")] + public async Task GetContract(long contractId) + { + var contract = await _client + .For("IContracts") + .Expand("Versions/Body") + .Key(contractId) + .FindEntryAsync(); + var versions = (IEnumerable)contract["Versions"]; + var lastVersion = versions.OrderByDescending(x => x["Number"]).FirstOrDefault(); + byte[] bytes = lastVersion["Body"]["Value"]; + var base64 = Convert.ToBase64String(bytes); + return base64; + } + } +} diff --git a/1CDataBus/Controllers/WeatherForecastController.cs b/1CDataBus/Controllers/WeatherForecastController.cs new file mode 100644 index 0000000..938ce49 --- /dev/null +++ b/1CDataBus/Controllers/WeatherForecastController.cs @@ -0,0 +1,33 @@ +using Microsoft.AspNetCore.Mvc; + +namespace _1CDataBus.Controllers +{ + [ApiController] + [Route("[controller]")] + public class WeatherForecastController : ControllerBase + { + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet(Name = "GetWeatherForecast")] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} diff --git a/1CDataBus/Program.cs b/1CDataBus/Program.cs new file mode 100644 index 0000000..48863a6 --- /dev/null +++ b/1CDataBus/Program.cs @@ -0,0 +1,25 @@ +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); diff --git a/1CDataBus/Properties/launchSettings.json b/1CDataBus/Properties/launchSettings.json new file mode 100644 index 0000000..de90f50 --- /dev/null +++ b/1CDataBus/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:54967", + "sslPort": 44384 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5043", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7130;http://localhost:5043", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/1CDataBus/RabbitMQ/RabbitConnection.cs b/1CDataBus/RabbitMQ/RabbitConnection.cs new file mode 100644 index 0000000..5259f88 --- /dev/null +++ b/1CDataBus/RabbitMQ/RabbitConnection.cs @@ -0,0 +1,48 @@ +using RabbitMQ.Client; +using System.Text; + +namespace _1CDataBus.RabbitMQ +{ + public class RabbitConnection : IDisposable + { + private readonly IConnection _connection; + private readonly IChannel _channel; + private IConfiguration _configuration; + public RabbitConnection(IConfiguration configuration) + { + _configuration = configuration; + var factory = new ConnectionFactory + { + HostName = _configuration.GetValue("RabbitMqSettings:HostName"), + //HostName = "astsrvrabbit1", + UserName = _configuration.GetValue("RabbitMqSettings:UserName"), + //UserName = "erp", + Password = _configuration.GetValue("RabbitMqSettings:Password"), + //Password = @"Z!1;Q5#GE4v", + VirtualHost = _configuration.GetValue("RabbitMqSettings:VirtualHost") + //VirtualHost = "erp" + }; + + _connection = factory.CreateConnectionAsync().Result; + _channel = _connection.CreateChannelAsync().Result; + } + + public async Task SendMessage(string body) + { + await _channel.QueueDeclareAsync( + queue: "erp_test", + durable: false, + exclusive: false, + autoDelete: false, + arguments: null); + var encoded = Encoding.UTF8.GetBytes(body); + await _channel.BasicPublishAsync(string.Empty, "erp_test", encoded); + } + + public void Dispose() + { + _channel.Dispose(); + _connection.Dispose(); + } + } +} diff --git a/1CDataBus/Structure/Contract.cs b/1CDataBus/Structure/Contract.cs new file mode 100644 index 0000000..f81f181 --- /dev/null +++ b/1CDataBus/Structure/Contract.cs @@ -0,0 +1,39 @@ +namespace _1CDataBus.Structure +{ + public class Contract + { + private Dictionary _contractKinds = new Dictionary () + { + { 1, "Поставщик" }, + { 2, "Покупатель" }, + { 3, "Прочее" } + }; + + public Contract(dynamic contract) + { + Name = contract["Name"]; + BusinessUnit = contract["BusinessUnit"]["ExternalId"]; + BusinessUnitBIN = contract["BusinessUnit"]["BINArmadoc"]; + Counterparty = contract["Counterparty"]["ExternalId"]; + CounterpartyBIN = contract["Counterparty"]["BINArmadoc"]; + CreateDate = contract["Created"].Date; + Number = contract["RegistrationNumber"]; + Date = contract["ContractDateSungero"].Date; + Currency = contract["Currency"]["AlphaCode"]; + QDocID = contract["Id"]; + } + + public string Name { get; set; } + public string BusinessUnit { get; set; } + public string BusinessUnitBIN { get; set; } + public string Counterparty { get; set; } + public string CounterpartyBIN { get; set; } + public DateTimeOffset CreateDate { get; set; } = DateTimeOffset.Now; + public string Number { get; set; } + public DateTimeOffset Date { get; set; } + public string ContractKind { get; set; } = "Поставщик"; + public string Currency { get; set; } + public bool Orders { get; set; } = false; + public long QDocID { get; set; } + } +} diff --git a/1CDataBus/Structure/ODataAccess.cs b/1CDataBus/Structure/ODataAccess.cs new file mode 100644 index 0000000..79eee7d --- /dev/null +++ b/1CDataBus/Structure/ODataAccess.cs @@ -0,0 +1,33 @@ +using Microsoft.Extensions.Configuration; +using Simple.OData.Client; +using System.Text; + +namespace _1CDataBus.Structure +{ + public class ODataAccess + { + private IConfiguration _configuration; + + public ODataAccess(IConfiguration configuration) + { + _configuration = configuration; + var section = _configuration.GetSection("QDocSettings"); + + var IntegrationServiceUrl = section.GetValue("Url"); + var Login = section.GetValue("Login"); + var Password = section.GetValue("Password"); + + // Настройки Simple OData Client: добавление ко всем запросам URL сервиса и + // заголовка с данными аутентификации. + var odataClientSettings = new ODataClientSettings(new Uri(IntegrationServiceUrl)); + odataClientSettings.BeforeRequest += (HttpRequestMessage message) => + { + var authenticationHeaderValue = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{Login}:{Password}")); + message.Headers.Add("Authorization", "Basic " + authenticationHeaderValue); + }; + Client = new ODataClient(odataClientSettings); + } + + public ODataClient? Client { get; set; } + } +} diff --git a/1CDataBus/WeatherForecast.cs b/1CDataBus/WeatherForecast.cs new file mode 100644 index 0000000..bc308de --- /dev/null +++ b/1CDataBus/WeatherForecast.cs @@ -0,0 +1,13 @@ +namespace _1CDataBus +{ + public class WeatherForecast + { + public DateOnly Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } + } +} \ No newline at end of file diff --git a/1CDataBus/appsettings.Development.json b/1CDataBus/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/1CDataBus/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/1CDataBus/appsettings.json b/1CDataBus/appsettings.json new file mode 100644 index 0000000..4097c27 --- /dev/null +++ b/1CDataBus/appsettings.json @@ -0,0 +1,25 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "RabbitMqSettings": { + "HostName": "astsrvrabbit1", + "UserName": "erp", + "Password": "Z!1;Q5#GE4v", + "VirtualHost": "erp" + }, + "QDocSettings": { + "Url": "https://qdoc.solidcore-resources.com/Integration/odata/", + "Login": "Administrator", + "Password": "MQVuEw9avO" + }, + "QDocTestSettings": { + "Url": "https://astsrvqtest.solidcore-resources.com/Integration/odata/", + "Login": "Administrator", + "Password": "D3cTXol8Se" + } +} diff --git a/1CDataBus/Справка по сервису 1CDataBus.docx b/1CDataBus/Справка по сервису 1CDataBus.docx new file mode 100644 index 0000000000000000000000000000000000000000..adbc22302376439feb7d30d6885e1980bf8ab867 GIT binary patch literal 13910 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 bKeKa18E}Aj{I)d(2B;U{KJ{h!?e6~pxU?D- literal 0 HcmV?d00001