Добавьте файлы проекта.

This commit is contained in:
AnboevDD 2025-02-25 10:06:21 +05:00
parent 977a9fa2f4
commit 7df93dc822
14 changed files with 392 additions and 0 deletions

25
1CDataBus.sln Normal file
View File

@ -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

View File

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>_1CDataBus</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="8.0.4" />
<PackageReference Include="Microsoft.OData.Core" Version="7.21.0" />
<PackageReference Include="RabbitMQ.Client" Version="7.0.0" />
<PackageReference Include="Simple.OData.V4.Client" Version="6.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<None Update="Справка по сервису 1CDataBus.docx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

6
1CDataBus/1CDataBus.http Normal file
View File

@ -0,0 +1,6 @@
@_1CDataBus_HostAddress = http://localhost:5043
GET {{_1CDataBus_HostAddress}}/weatherforecast/
Accept: application/json
###

View File

@ -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<ContractsController> _logger;
private RabbitConnection _rabbit;
private ODataClient _client;
public ContractsController(ILogger<ContractsController> 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<string> GetContract(long contractId)
{
var contract = await _client
.For("IContracts")
.Expand("Versions/Body")
.Key(contractId)
.FindEntryAsync();
var versions = (IEnumerable<dynamic>)contract["Versions"];
var lastVersion = versions.OrderByDescending(x => x["Number"]).FirstOrDefault();
byte[] bytes = lastVersion["Body"]["Value"];
var base64 = Convert.ToBase64String(bytes);
return base64;
}
}
}

View File

@ -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<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> 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();
}
}
}

25
1CDataBus/Program.cs Normal file
View File

@ -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();

View File

@ -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"
}
}
}
}

View File

@ -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<string>("RabbitMqSettings:HostName"),
//HostName = "astsrvrabbit1",
UserName = _configuration.GetValue<string>("RabbitMqSettings:UserName"),
//UserName = "erp",
Password = _configuration.GetValue<string>("RabbitMqSettings:Password"),
//Password = @"Z!1;Q5#GE4v",
VirtualHost = _configuration.GetValue<string>("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();
}
}
}

View File

@ -0,0 +1,39 @@
namespace _1CDataBus.Structure
{
public class Contract
{
private Dictionary<int, string> _contractKinds = new Dictionary<int, string> ()
{
{ 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; }
}
}

View File

@ -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<string>("Url");
var Login = section.GetValue<string>("Login");
var Password = section.GetValue<string>("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; }
}
}

View File

@ -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; }
}
}

View File

@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@ -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"
}
}

View File

@ -0,0 +1,25 @@
Сервис предназначен для обмена договорами с 1С и QDoc.
POST-запросы:
https://astsrvqtest02.polymetal.ru:9812/Contracts/SendContractFromQDoc?id=2274
Отправляет в очередь сериализованный договор из QDoc по идентификатору договора.
https://astsrvqtest02.polymetal.ru:9812/Contracts/SendContract
Отправляет в очередь JSON-структуру представляющую договор.
Образец:
{
"name": "string",
"businessUnit": "string",
"businessUnitBIN": "string",
"counterparty": "string",
"counterpartyBIN": "string",
"createDate": "2025-02-24T11:27:09.476Z",
"number": "string",
"date": "2025-02-24T11:27:09.476Z",
"contractKind": "string",
"currency": "string",
"orders": true,
"qDocID": 0
}
GET-запросы:
https://astsrvqtest02.polymetal.ru:9812/Contracts/GetContract?contractId=2274
Возвращает из QDoc последнюю версию файла договорного документа по идентификатору договора в виде строки Base64