using Centron.BusinessLogic.EDI.Opentrans21; using Centron.Data.WebServices.Accounts; using Centron.Data.WebServices.Administration.MandatoryArea; using Centron.Data.WebServices.Administration.MasterData; using Centron.Data.WebServices.Sales.Receipts; using Centron.Interfaces.EDI; using CentronSoftware.Centron.WebServices.Entities.EDI; using CentronSoftware.Centron.WebServices.Entities.Sales.Receipts.SupplierOrders; using CentronSoftware.Centron.WebServices.Entities.Warehousing; using JetBrains.Annotations; namespace Centron.Tests.BL.EDI.Opentrans21; [TestSubject(typeof(Opentrans21OrderBL))] public class Opentrans21OrderBLTest { private readonly List _testCountries; private readonly ReceiptSupplierOrderDTO _testReceipt; private readonly MandatoryDTO _testMandatory; private readonly AccountSearchItemDTO _testAddress; private readonly AccountSearchItemDTO _testLicenceAddress; private readonly AccountSearchItemDTO _testSupplierAccount; private readonly ReceiptSettingsDTO _testReceiptSettings; private readonly List _testReceiptItems; private readonly List _testSpecialAgreements; private const string _customerNumberAtSupplier = "CUST123"; private const string _supplierID = "SUPP456"; public Opentrans21OrderBLTest() { _testCountries = CreateTestCountries(); _testReceipt = CreateTestReceipt(); _testMandatory = CreateTestMandatory(); _testAddress = CreateTestAddress(); _testLicenceAddress = CreateTestLicenceAddress(); _testSupplierAccount = CreateTestSupplierAccount(); _testReceiptSettings = CreateTestReceiptSettings(); _testReceiptItems = CreateTestReceiptItems(); _testSpecialAgreements = CreateTestSpecialAgreements(); } [Fact] public async Task CreateOrderDocument_ShouldSetCorrectOrderInfo_WhenValidDataProvided() { // Arrange var orderBL = new Opentrans21OrderBL( _testReceipt, _customerNumberAtSupplier, _supplierID, (int)EDIOrderSpecificity.none, _testCountries ); // Act var result = await orderBL.CreateOrderDocument( _testReceiptItems, _testMandatory, _testSpecialAgreements, _testAddress, _testLicenceAddress, _testSupplierAccount, EDIMultidistributors.None, _testReceiptSettings, "test@example.com" ); // Assert Assert.True(result.IsSuccess); var xmlDoc = result.Data; var orderInfo = xmlDoc.Descendants().FirstOrDefault(x => x.Name.LocalName == "ORDER_INFO"); Assert.NotNull(orderInfo); var orderId = orderInfo.Descendants().FirstOrDefault(x => x.Name.LocalName == "ORDER_ID"); Assert.NotNull(orderId); Assert.Equal(_testReceipt.Number.ToString(), orderId.Value); var orderDate = orderInfo.Descendants().FirstOrDefault(x => x.Name.LocalName == "ORDER_DATE"); Assert.NotNull(orderDate); Assert.Equal(_testReceipt.Date.ToString("yyyy-MM-dd"), orderDate.Value); } [Fact] public async Task CreateOrderDocument_ShouldIncludeCorrectParties_WhenStandardDistributor() { // Arrange var orderBL = new Opentrans21OrderBL( _testReceipt, _customerNumberAtSupplier, _supplierID, (int)EDIOrderSpecificity.none, _testCountries ); // Act var result = await orderBL.CreateOrderDocument( _testReceiptItems, _testMandatory, _testSpecialAgreements, _testAddress, _testLicenceAddress, _testSupplierAccount, EDIMultidistributors.None, _testReceiptSettings, "test@example.com" ); // Assert Assert.True(result.IsSuccess); var xmlDoc = result.Data; var parties = xmlDoc.Descendants().Where(x => x.Name.LocalName == "PARTY").ToList(); // Should have buyer, supplier, and delivery parties Assert.True(parties.Count >= 3); var partyRoles = parties.SelectMany(p => p.Descendants().Where(x => x.Name.LocalName == "PARTY_ROLE")) .Select(r => r.Value).ToList(); Assert.Contains("buyer", partyRoles); Assert.Contains("supplier", partyRoles); Assert.Contains("delivery", partyRoles); } [Fact] public async Task CreateOrderDocument_ShouldCalculateCorrectTotalAmount_WhenMultipleItems() { // Arrange var receiptItems = new List { CreateTestReceiptItem(1, 2.0m, 10.50m), // 2 * 10.50 = 21.00 CreateTestReceiptItem(2, 3.0m, 15.75m), // 3 * 15.75 = 47.25 CreateTestReceiptItem(3, 1.0m, 5.25m) // 1 * 5.25 = 5.25 }; // Total expected: 73.50 var orderBL = new Opentrans21OrderBL( _testReceipt, _customerNumberAtSupplier, _supplierID, (int)EDIOrderSpecificity.none, _testCountries ); // Act var result = await orderBL.CreateOrderDocument( receiptItems, _testMandatory, _testSpecialAgreements, _testAddress, _testLicenceAddress, _testSupplierAccount, EDIMultidistributors.None, _testReceiptSettings, "test@example.com" ); // Assert Assert.True(result.IsSuccess); var xmlDoc = result.Data; var totalAmount = xmlDoc.Descendants().FirstOrDefault(x => x.Name.LocalName == "TOTAL_AMOUNT"); Assert.NotNull(totalAmount); Assert.Equal("73.50", totalAmount.Value); var totalItemNum = xmlDoc.Descendants().FirstOrDefault(x => x.Name.LocalName == "TOTAL_ITEM_NUM"); Assert.NotNull(totalItemNum); Assert.Equal("3", totalItemNum.Value); } [Fact] public async Task CreateOrderDocument_ShouldSetDeliveryDate_WhenDeliveryDateSpecified() { // Arrange var receipt = CreateTestReceipt(); receipt.DeliveryDate = new DateTime(2024, 12, 25); var orderBL = new Opentrans21OrderBL( receipt, _customerNumberAtSupplier, _supplierID, (int)EDIOrderSpecificity.none, _testCountries ); // Act var result = await orderBL.CreateOrderDocument( _testReceiptItems, _testMandatory, _testSpecialAgreements, _testAddress, _testLicenceAddress, _testSupplierAccount, EDIMultidistributors.None, _testReceiptSettings, "test@example.com" ); // Assert Assert.True(result.IsSuccess); var xmlDoc = result.Data; var deliveryStartDate = xmlDoc.Descendants().FirstOrDefault(x => x.Name.LocalName == "DELIVERY_START_DATE"); var deliveryEndDate = xmlDoc.Descendants().FirstOrDefault(x => x.Name.LocalName == "DELIVERY_END_DATE"); Assert.NotNull(deliveryStartDate); Assert.NotNull(deliveryEndDate); Assert.Equal("2024-12-25", deliveryStartDate.Value); Assert.Equal("2024-12-25", deliveryEndDate.Value); } [Fact] public async Task CreateOrderDocument_ShouldHandleTHSSpecificity_WhenTHSOrderSpecificity() { // Arrange var orderBL = new Opentrans21OrderBL( _testReceipt, _customerNumberAtSupplier, _supplierID, (int)EDIOrderSpecificity.THS, _testCountries ); // Act var result = await orderBL.CreateOrderDocument( _testReceiptItems, _testMandatory, _testSpecialAgreements, null, // No delivery address for THS _testLicenceAddress, _testSupplierAccount, EDIMultidistributors.None, _testReceiptSettings, "test@example.com" ); // Assert Assert.True(result.IsSuccess); var xmlDoc = result.Data; var orderItems = xmlDoc.Descendants().Where(x => x.Name.LocalName == "ORDER_ITEM").ToList(); foreach (var item in orderItems) { var remarks = item.Descendants().Where(x => x.Name.LocalName == "REMARKS").ToList(); Assert.Equal(10, remarks.Count); // THS should have exactly 10 remarks } } [Fact] public async Task CreateOrderDocument_ShouldReturnError_WhenExceptionOccurs() { // Arrange var orderBL = new Opentrans21OrderBL( _testReceipt, _customerNumberAtSupplier, _supplierID, (int)EDIOrderSpecificity.none, _testCountries ); // Create invalid receipt items that will cause an exception var invalidReceiptItems = new List { null // This should cause an exception }; // Act var result = await orderBL.CreateOrderDocument( invalidReceiptItems, _testMandatory, _testSpecialAgreements, _testAddress, _testLicenceAddress, _testSupplierAccount, EDIMultidistributors.None, _testReceiptSettings, "test@example.com" ); // Assert Assert.False(result.IsSuccess); Assert.NotNull(result.Error); } [Fact] public async Task CreateOrderDocument_ShouldSetCorrectCurrency_WhenCurrencyFound() { // Arrange var receipt = CreateTestReceipt(); receipt.CurrencyString = "EUR"; var orderBL = new Opentrans21OrderBL( receipt, _customerNumberAtSupplier, _supplierID, (int)EDIOrderSpecificity.none, _testCountries ); // Act var result = await orderBL.CreateOrderDocument( _testReceiptItems, _testMandatory, _testSpecialAgreements, _testAddress, _testLicenceAddress, _testSupplierAccount, EDIMultidistributors.None, _testReceiptSettings, "test@example.com" ); // Assert Assert.True(result.IsSuccess); var xmlDoc = result.Data; var currency = xmlDoc.Descendants().FirstOrDefault(x => x.Name.LocalName == "CURRENCY"); Assert.NotNull(currency); Assert.Equal("EUR", currency.Value); } [Fact] public async Task CreateOrderDocument_ShouldIncludeLicenceAddress_WhenLicenceAddressProvided() { // Arrange var orderBL = new Opentrans21OrderBL( _testReceipt, _customerNumberAtSupplier, _supplierID, (int)EDIOrderSpecificity.none, _testCountries ); // Act var result = await orderBL.CreateOrderDocument( _testReceiptItems, _testMandatory, _testSpecialAgreements, _testAddress, _testLicenceAddress, _testSupplierAccount, EDIMultidistributors.None, _testReceiptSettings, "test@example.com" ); // Assert Assert.True(result.IsSuccess); var xmlDoc = result.Data; var parties = xmlDoc.Descendants().Where(x => x.Name.LocalName == "PARTY").ToList(); // Should have buyer, supplier, delivery, and licence parties Assert.True(parties.Count >= 4); var partyRoles = parties.SelectMany(p => p.Descendants().Where(x => x.Name.LocalName == "PARTY_ROLE")) .Select(r => r.Value).ToList(); Assert.Contains("buyer", partyRoles); Assert.Contains("supplier", partyRoles); Assert.Contains("delivery", partyRoles); // Find the licence party var licenceParty = parties.FirstOrDefault(p => p.Descendants().Any(x => x.Name.LocalName == "PARTY_ROLE" && x.Value == "customer")); Assert.NotNull(licenceParty); // Verify licence party contains the correct information var partyName = licenceParty.Descendants().FirstOrDefault(x => x.Name.LocalName == "NAME"); Assert.NotNull(partyName); Assert.Equal(_testLicenceAddress.AccountName, partyName.Value); var street = licenceParty.Descendants().FirstOrDefault(x => x.Name.LocalName == "STREET"); Assert.NotNull(street); Assert.Equal(_testLicenceAddress.AddressStreet, street.Value); var city = licenceParty.Descendants().FirstOrDefault(x => x.Name.LocalName == "CITY"); Assert.NotNull(city); Assert.Equal(_testLicenceAddress.AddressCity, city.Value); var zip = licenceParty.Descendants().FirstOrDefault(x => x.Name.LocalName == "ZIP"); Assert.NotNull(zip); Assert.Equal(_testLicenceAddress.AddressZip, zip.Value); } [Fact] public async Task CreateOrderDocument_ShouldHandleNullLicenceAddress_WhenLicenceAddressNotProvided() { // Arrange var orderBL = new Opentrans21OrderBL( _testReceipt, _customerNumberAtSupplier, _supplierID, (int)EDIOrderSpecificity.none, _testCountries ); // Act var result = await orderBL.CreateOrderDocument( _testReceiptItems, _testMandatory, _testSpecialAgreements, _testAddress, null, // No licence address _testSupplierAccount, EDIMultidistributors.None, _testReceiptSettings, "test@example.com" ); // Assert Assert.True(result.IsSuccess); var xmlDoc = result.Data; var parties = xmlDoc.Descendants().Where(x => x.Name.LocalName == "PARTY").ToList(); // Should have buyer, supplier, and delivery parties (no licence party) var partyRoles = parties.SelectMany(p => p.Descendants().Where(x => x.Name.LocalName == "PARTY_ROLE")) .Select(r => r.Value).ToList(); Assert.Contains("buyer", partyRoles); Assert.Contains("supplier", partyRoles); Assert.Contains("delivery", partyRoles); // Ensure no licence party is present Assert.DoesNotContain("licencee", partyRoles); } #region Test Data Creation Methods private static List CreateTestCountries() { return [ new CountryDTO { I3D = 1, CountryCode = "DE", CurrencySymbol = "EUR", CurrencyISO = "EUR" }, new CountryDTO { I3D = 2, CountryCode = "US", CurrencySymbol = "USD", CurrencyISO = "USD" } ]; } private static ReceiptSupplierOrderDTO CreateTestReceipt() { return new ReceiptSupplierOrderDTO { Number = 12345, Version = 1, Date = new DateTime(2024, 10, 14), CurrencyString = "EUR", DeliveryDate = null }; } private static MandatoryDTO CreateTestMandatory() { return new MandatoryDTO { Mandator = "Test Company GmbH", Street = "Test Street 123", City = "Test City", PostalCode = "12345", Mail = "test@company.com", Telephone = "+49 123 456789", Country = new CountryDTO { I3D = 1, CountryCode = "DE" } }; } private static AccountSearchItemDTO CreateTestAddress() { return new AccountSearchItemDTO { AddressI3D = 1001, AccountName = "Delivery Company", AddressStreet = "Delivery Street 456", AddressCity = "Delivery City", AddressZip = "54321", AddressCountryI3D = 1, AddressDepartment = "Receiving Department", AddressContactFirstname = "John", AddressContactLastname = "Doe", AddressContactTitle = "Mr.", PrintName = true, PrintDepartment = true, PrintAddressContact = true }; } private static AccountSearchItemDTO CreateTestLicenceAddress() { return new AccountSearchItemDTO { AddressI3D = 1002, AccountName = "Licence Company", AddressStreet = "Licence Street 789", AddressCity = "Licence City", AddressZip = "65432", AddressCountryI3D = 1, AddressDepartment = "Licence Department", AddressContactFirstname = "John", AddressContactLastname = "Doe", AddressContactTitle = "Mr.", PrintName = true, PrintDepartment = true, PrintAddressContact = true }; } private static AccountSearchItemDTO CreateTestSupplierAccount() { return new AccountSearchItemDTO { AccountName = "Supplier Company Ltd", AddressStreet = "Supplier Street 789", AddressCity = "Supplier City", AddressZip = "98765", AddressCountryI3D = 1, AddressDepartment = "Sales Department", AddressContactFirstname = "Jane", AddressContactLastname = "Smith", AddressContactTitle = "Ms.", ItScopeSupplierNumber = "12345", PrintName = true, PrintAddressContact = true, PrintDepartment = true, PrintDepartmentAddressContact = true }; } private static ReceiptSettingsDTO CreateTestReceiptSettings() { return new ReceiptSettingsDTO { ItScopeApiKey = "test-api-key" }; } private static List CreateTestReceiptItems() { return [ CreateTestReceiptItem(1, 2.0m, 25.50m), CreateTestReceiptItem(2, 1.0m, 15.75m) ]; } private static ReceiptSupplierOrderItemDTO CreateTestReceiptItem(int position, decimal quantity, decimal basePrice) { return new ReceiptSupplierOrderItemDTO { I3D = 1000 + position, InternalPosition = position, ArticleI3D = 2000 + position, ArticleCode = $"ART-{position:D3}", Text = $"Test Article {position}", EANCode = $"123456789012{position}", ManufacturerCode = $"MFG-{position:D3}", SupplierManufacturerCode = $"SUP-MFG-{position:D3}", QuantityComplete = quantity, QuantityProcessed = 0, BasePrice = basePrice, PurchaseInformations = $"Purchase info for item {position}", PurchaseOrderNumber = $"PO-{position:D6}", SpecialAgreementI3D = null }; } private static List CreateTestSpecialAgreements() { return [ new SpecialAgreementPreviewDTO { I3D = 1, Number = "SA-001", Text = "Special Agreement 1", IsProjectPrice = true, IsInternal = false } ]; } #endregion }