Fix international order VAT and currencies in Enova and Optima
This commit is contained in:
1 parent
75ef1ed69c
commit
248d7bac64
23 files changed
+308
-34
No files matched your search
@@ -2,6 +2,7 @@ using System.Collections.Concurrent;
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using SmartB2B.Optima.Adapter;
|
||||
using SmartB2B.Optima.Tests;
|
||||
using SmartB2B.Sync.Contracts;
|
||||
using SmartB2B.Sync.Service.Diagnostics;
|
||||
using SmartB2B.Sync.Service.Orders;
|
||||
@@ -18,6 +19,9 @@ var tests = new (string Name, Func<Task> Run)[]
|
||||
("Tryb brutto wybiera price_brutto", GrossDocumentSelectsGrossPrice),
|
||||
("Brak ceny wymaganej przez definicję jest stabilnym błędem", RequiredPriceIsEnforced),
|
||||
("Handler przekazuje pełny kontrakt do Optimy", HandlerMapsOptimaContract),
|
||||
("Flagi z WampOrder rozróżniają zamówienia krajowe i zagraniczne", HandlerMapsInternationalFlags),
|
||||
("Fasada ustawia walutę i rodzaj transakcji przed pozycjami", FacadeMapsInternationalOrders),
|
||||
("Fasada odrzuca nieznaną walutę przed zapisem", FacadeRejectsUnknownCurrency),
|
||||
("Handler przyjmuje i pomija opcjonalne extraFields", HandlerMapsOptionalExtraFields),
|
||||
("Handler odrzuca błędne extraFields", HandlerRejectsInvalidExtraFields),
|
||||
("Handler loguje pełne wywołanie place_order", HandlerLogsFullInvocation),
|
||||
@@ -34,8 +38,16 @@ var tests = new (string Name, Func<Task> Run)[]
|
||||
};
|
||||
|
||||
var failures = 0;
|
||||
var skipped = 0;
|
||||
foreach (var test in tests)
|
||||
{
|
||||
if (!OperatingSystem.IsWindows() &&
|
||||
(test.Run == (Func<Task>)FacadeRunsOnSingleStaThread || test.Run == (Func<Task>)AdapterSerializesComCalls))
|
||||
{
|
||||
skipped++;
|
||||
Console.WriteLine($"SKIP: {test.Name}: test COM STA wymaga Windows.");
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{
|
||||
await test.Run();
|
||||
@@ -48,7 +60,7 @@ foreach (var test in tests)
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine($"Wynik: {tests.Length - failures}/{tests.Length} testów zaliczonych.");
|
||||
Console.WriteLine($"Wynik: {tests.Length - skipped - failures}/{tests.Length - skipped} testów zaliczonych, pominięto: {skipped}.");
|
||||
return failures == 0 ? 0 : 1;
|
||||
|
||||
static Task NetPriceIsBackwardCompatible()
|
||||
@@ -115,6 +127,76 @@ static async Task HandlerMapsOptimaContract()
|
||||
AssertEqual(123m, request.Items[0].UnitPriceGross, "brutto");
|
||||
}
|
||||
|
||||
static async Task HandlerMapsInternationalFlags()
|
||||
{
|
||||
foreach (var (international, eu) in new[] { (false, true), (true, true), (true, false) })
|
||||
{
|
||||
using var adapter = new CapturingAdapter();
|
||||
var arguments = new Dictionary<string, object?>(CreateInvocation().KeywordArguments)
|
||||
{
|
||||
["companyIsInternational"] = new JValue(international),
|
||||
["companyIsInEuropeanUnion"] = new JValue(eu)
|
||||
};
|
||||
await new PlaceOrderHandler(adapter, CreateConfiguration())
|
||||
.HandleAsync(new RpcInvocation([], arguments), CancellationToken.None);
|
||||
AssertEqual(international, adapter.LastRequest?.CompanyIsInternational, "companyIsInternational");
|
||||
AssertEqual(eu, adapter.LastRequest?.CompanyIsInEuropeanUnion, "companyIsInEuropeanUnion");
|
||||
}
|
||||
using var legacyAdapter = new CapturingAdapter();
|
||||
await new PlaceOrderHandler(legacyAdapter, CreateConfiguration())
|
||||
.HandleAsync(CreateInvocation(), CancellationToken.None);
|
||||
AssertEqual(false, legacyAdapter.LastRequest?.CompanyIsInternational, "brak flagi zagranicznej");
|
||||
AssertEqual(false, legacyAdapter.LastRequest?.CompanyIsInEuropeanUnion, "brak flagi unijnej");
|
||||
}
|
||||
|
||||
static Task FacadeMapsInternationalOrders()
|
||||
{
|
||||
foreach (var currency in new[] { "PLN", "EUR", "USD", "CZK" })
|
||||
foreach (var (international, eu, export) in new[] { (false, true, 0), (true, true, 3), (true, false, 1) })
|
||||
{
|
||||
var session = new FakeOrderSession();
|
||||
var result = LateBoundOptimaComFacade.CreateOrderInSession(session, new OrderRequest
|
||||
{
|
||||
CurrencyIso = currency,
|
||||
CustomerCode = "123",
|
||||
WarehouseCode = "7",
|
||||
DocumentDefinition = "RO",
|
||||
CompanyIsInternational = international,
|
||||
CompanyIsInEuropeanUnion = eu,
|
||||
Items = [new OrderLineRequest { ProductCode = "TOWAR", Quantity = 2m,
|
||||
UnitPriceNet = 100m, UnitPriceGross = 123m, Discount = 10m }]
|
||||
}, false);
|
||||
|
||||
AssertEqual(true, session.Saved, "zapis dokumentu");
|
||||
AssertEqual(currency, session.Document.WalutaSymbol, "waluta dokumentu");
|
||||
AssertEqual(export, session.Document.Export, "rodzaj transakcji");
|
||||
AssertEqual(export, session.Document.Elementy.Items.Single().ExportWhenProductAssigned, "rodzaj przed towarem");
|
||||
AssertEqual(currency, session.Document.Elementy.Items.Single().CurrencyWhenProductAssigned, "waluta przed towarem");
|
||||
AssertEqual(180m, result.Net, "wynik netto w walucie");
|
||||
AssertEqual(international ? 180m : 221.40m, result.Gross, "wynik brutto w walucie");
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
static Task FacadeRejectsUnknownCurrency()
|
||||
{
|
||||
var session = new FakeOrderSession();
|
||||
try
|
||||
{
|
||||
LateBoundOptimaComFacade.CreateOrderInSession(session, new OrderRequest
|
||||
{
|
||||
CurrencyIso = "XXX", CustomerCode = "123", WarehouseCode = "7", DocumentDefinition = "RO",
|
||||
Items = [CreateLine(10m, 12.30m)]
|
||||
}, false);
|
||||
throw new InvalidOperationException("Oczekiwano błędu nieznanej waluty.");
|
||||
}
|
||||
catch (ErpOperationException exception) when (exception.ErrorUri == "eu.smartb2b.erp.currency_not_found")
|
||||
{
|
||||
AssertEqual(false, session.Saved, "brak zapisu dla nieznanej waluty");
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
static async Task DiagnosticsReadsOpenLogs()
|
||||
{
|
||||
var directory = Path.Combine(Path.GetTempPath(), $"smartb2b-log-test-{Guid.NewGuid():N}");
|
||||
|
||||
Reference in new issue
Block a user