diff --git a/README.md b/README.md index 1a5b9028..872a0f04 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,14 @@ BeInX does not collect or transmit any personal data. See our full [privacy poli # Change Log -
v0.5.2 +
v0.5.3 + +>- Update ZUGFeRD-csharp v18.0.0-beta2 +>- Using basic ZUGFeRD-csharp format (ZUGFeRDVersion.Version23, Profile.Basic, ZUGFeRDFormats.CII) + +
+ +
v0.5.2 >- Improved mobile responsiveness. >- Refined collapsed navigation menu behavior. diff --git a/src/beinx.db/Services/ZugferdMapper.cs b/src/beinx.db/Services/ZugferdMapper.cs index e9b662fe..4486b790 100644 --- a/src/beinx.db/Services/ZugferdMapper.cs +++ b/src/beinx.db/Services/ZugferdMapper.cs @@ -15,7 +15,6 @@ public static string MapToZugferd(BlazorInvoiceDto invoice) bool isSmallBusiness = taxRate == 0; // keine Umsatzsteuer nach § 19 UStG decimal taxAmount = isSmallBusiness ? 0 : Math.Round(payableAmount - taxExclusiveAmount, 2); - InvoiceDescriptor desc = InvoiceDescriptor.CreateInvoice( invoice.Id, invoice.IssueDate, @@ -36,7 +35,7 @@ public static string MapToZugferd(BlazorInvoiceDto invoice) id: string.Empty ); desc.AddBuyerTaxRegistration(invoice.BuyerParty.TaxId, TaxRegistrationSchemeID.VA); - desc.SetBuyerElectronicAddress(invoice.BuyerParty.Email, ElectronicAddressSchemeIdentifiers.EM); + desc.SetBuyerElectronicAddress(invoice.BuyerParty.Email, ElectronicAddressSchemeIdentifiers.GermanyVatNumber); desc.SetBuyerContact( name: invoice.BuyerParty.Name, emailAddress: invoice.BuyerParty.Email, @@ -57,7 +56,7 @@ public static string MapToZugferd(BlazorInvoiceDto invoice) emailAddress: invoice.SellerParty.Email, phoneno: invoice.SellerParty.Telefone ); - desc.SetSellerElectronicAddress(invoice.SellerParty.Email, ElectronicAddressSchemeIdentifiers.EM); + desc.SetSellerElectronicAddress(invoice.SellerParty.Email, ElectronicAddressSchemeIdentifiers.GermanyVatNumber); desc.AddApplicableTradeTax( basisAmount: taxExclusiveAmount, @@ -72,7 +71,6 @@ public static string MapToZugferd(BlazorInvoiceDto invoice) description: invoice.PaymentTermsNote, dueDate: invoice.DueDate ); - desc.AddCreditorFinancialAccount( iban: invoice.PaymentMeans.Iban, bic: invoice.PaymentMeans.Bic, @@ -98,9 +96,10 @@ public static string MapToZugferd(BlazorInvoiceDto invoice) ); using var memoryStream = new MemoryStream(); - desc.Save(memoryStream, ZUGFeRDVersion.Version23, Profile.Comfort); + desc.Save(memoryStream, ZUGFeRDVersion.Version23, Profile.Basic, ZUGFeRDFormats.CII); memoryStream.Position = 0; - return Encoding.UTF8.GetString(memoryStream.ToArray()); + var xml = Encoding.UTF8.GetString(memoryStream.ToArray()); + return xml; } private static void AddLine(InvoiceLineAnnotationDto line, BlazorInvoiceDto invoice, InvoiceDescriptor desc) @@ -147,6 +146,8 @@ public static BlazorInvoiceDto MapFromZugferd(string xmlText) using var stream = new MemoryStream(Encoding.UTF8.GetBytes(xmlText)); var desc = InvoiceDescriptor.Load(stream); + var terms = desc.GetTradePaymentTerms(); + var dto = new BlazorInvoiceDto { Id = desc.InvoiceNo, @@ -193,12 +194,12 @@ public static BlazorInvoiceDto MapFromZugferd(string xmlText) GlobalTaxCategory = desc.TradeLineItems.FirstOrDefault()?.TaxCategoryCode.ToString() ?? string.Empty, PaymentMeans = new PaymentAnnotationDto { - Iban = desc.CreditorBankAccounts.FirstOrDefault()?.IBAN ?? string.Empty, - Bic = desc.CreditorBankAccounts.FirstOrDefault()?.BIC ?? string.Empty, - Name = desc.CreditorBankAccounts.FirstOrDefault()?.BankName ?? string.Empty, + Iban = desc.GetCreditorFinancialAccounts().FirstOrDefault()?.IBAN ?? string.Empty, + Bic = desc.GetCreditorFinancialAccounts().FirstOrDefault()?.BIC ?? string.Empty, + Name = desc.GetCreditorFinancialAccounts().FirstOrDefault()?.BankName ?? string.Empty, PaymentMeansTypeCode = desc.PaymentMeans.TypeCode == null ? "30" : GetEnumAttributeValue(desc.PaymentMeans.TypeCode.Value) }, - PaymentTermsNote = desc.PaymentTerms.FirstOrDefault()?.Description ?? string.Empty, + PaymentTermsNote = desc.GetTradePaymentTerms().FirstOrDefault()?.Description ?? string.Empty, DueDate = desc.PaymentTerms.FirstOrDefault()?.DueDate, InvoiceLines = desc.TradeLineItems.Select((line, index) => new InvoiceLineAnnotationDto { @@ -207,9 +208,7 @@ public static BlazorInvoiceDto MapFromZugferd(string xmlText) Description = line.Description, Quantity = (double)line.BilledQuantity, QuantityCode = line.UnitCode.ToString() ?? string.Empty, -# pragma warning disable CS0618 - UnitPrice = line.NetUnitPrice == null ? 0 : (double)line.NetUnitPrice, -#pragma warning restore CS0618 + UnitPrice = (double)line.NetUnitPrice, StartDate = line.BillingPeriodStart, EndDate = line.BillingPeriodEnd }).ToList() diff --git a/src/beinx.shared/beinx.shared.csproj b/src/beinx.shared/beinx.shared.csproj index 55a07e33..61708b98 100644 --- a/src/beinx.shared/beinx.shared.csproj +++ b/src/beinx.shared/beinx.shared.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/beinx.web/InvoiceImportComponent.razor b/src/beinx.web/InvoiceImportComponent.razor index 0912824f..16c01694 100644 --- a/src/beinx.web/InvoiceImportComponent.razor +++ b/src/beinx.web/InvoiceImportComponent.razor @@ -3,6 +3,7 @@ @using Microsoft.AspNetCore.Components.Forms @using Microsoft.Extensions.Localization @using System.Text.Json +@using Microsoft.Extensions.Logging @using beinx.loc @using beinx.shared @using beinx.shared.Interfaces @@ -13,6 +14,7 @@ @inject IToastService ToastService @inject IStringLocalizer Loc @inject IPdfJsInterop PdfJsInterop +@inject ILogger Logger
diff --git a/src/beinx.web/InvoiceImportComponent.razor.cs b/src/beinx.web/InvoiceImportComponent.razor.cs index c733b65e..10e01cc9 100644 --- a/src/beinx.web/InvoiceImportComponent.razor.cs +++ b/src/beinx.web/InvoiceImportComponent.razor.cs @@ -1,5 +1,6 @@ using beinx.shared; using Microsoft.AspNetCore.Components.Forms; +using Microsoft.Extensions.Logging; using pax.XRechnung.NET; using pax.XRechnung.NET.XmlModels; using System.Text; @@ -146,7 +147,7 @@ private void ValidateXml(string? xml) importResult = new InvoiceImportResult { Message = Loc["Failed getting xml data"] }; return; } - + Logger.LogInformation(xml); var doc = XDocument.Parse(xml); var root = doc.Root; diff --git a/src/beinx.web/NavMenuCanvas.razor b/src/beinx.web/NavMenuCanvas.razor index ecf8ddb4..68010d90 100644 --- a/src/beinx.web/NavMenuCanvas.razor +++ b/src/beinx.web/NavMenuCanvas.razor @@ -86,7 +86,7 @@ else {
- v0.5.2 + v0.5.3
} @if (IsHomePage) diff --git a/tests/beinx.Tests/Test1.cs b/tests/beinx.Tests/Test1.cs deleted file mode 100644 index 60ceca03..00000000 --- a/tests/beinx.Tests/Test1.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace beinx.Tests; - -[TestClass] -public sealed class Test1 -{ - [TestMethod] - public void TestMethod1() - { - } -} diff --git a/tests/beinx.Tests/Zugferd.Tests.cs b/tests/beinx.Tests/Zugferd.Tests.cs index 0df06a36..05d08c59 100644 --- a/tests/beinx.Tests/Zugferd.Tests.cs +++ b/tests/beinx.Tests/Zugferd.Tests.cs @@ -18,8 +18,8 @@ public static BlazorInvoiceDto GetInvoiceAnnDto() IssueDate = DateTime.UtcNow, InvoiceTypeCode = "380", DocumentCurrencyCode = "EUR", - Note = "Dies ist eine Testrechnung.", - SellerParty = new SellerAnnotationDto() + Note = "Test Note", + SellerParty = new() { Name = "Seller Name", StreetName = "Test Street", @@ -30,9 +30,9 @@ public static BlazorInvoiceDto GetInvoiceAnnDto() Email = "seller@example.com", RegistrationName = "Seller Name", TaxId = "DE12345678", - CompanyId = "000/0000/000" + CompanyId = "000/000/0000 0", }, - BuyerParty = new BuyerAnnotationDto() + BuyerParty = new() { Name = "Buyer Name", StreetName = "Test Street", @@ -42,21 +42,23 @@ public static BlazorInvoiceDto GetInvoiceAnnDto() Telefone = "1234/54321", Email = "buyer@example.com", RegistrationName = "Buyer Name", - BuyerReference = "DE87654321" + BuyerReference = "04011000-12345-34", }, - PaymentMeans = new PaymentAnnotationDto() + PaymentMeans = new() { Iban = "DE12 1234 1234 1234 1234 12", Bic = "BICABCDE", Name = "Bank Name", PaymentMeansTypeCode = "30", }, - PaymentTermsNote = "Zahlbar innerhalb 14 Tagen nach Erhalt der Rechnung.", + PaymentTermsNote = "Zahlbar innerhalb von 14 Tagen nach Erhalt der Rechnung.", PayableAmount = 119.0, InvoiceLines = [ - new InvoiceLineAnnotationDto() + new() { Id = "1", + StartDate = new(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 0, 0, 0), + EndDate = new(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 0, 0, 0), Quantity = 1.0, QuantityCode = "HUR", UnitPrice = 100.0, @@ -75,7 +77,7 @@ public void CanMapDto() Assert.Contains("Test Job", xmlText, "Invoice line description not found in XML."); Assert.Contains("Buyer Name", xmlText, "Buyer name not found in XML."); Assert.Contains("Seller Name", xmlText, "Seller name not found in XML."); - Assert.Contains("Zahlbar innerhalb 14 Tagen", xmlText, "Payment terms not included."); + Assert.Contains("Zahlbar innerhalb von 14 Tagen", xmlText, "Payment terms not included."); } [TestMethod] @@ -88,7 +90,7 @@ public void CanMapNoTaxDto() Assert.Contains("Test Job", xmlText, "Invoice line description not found in XML."); Assert.Contains("Buyer Name", xmlText, "Buyer name not found in XML."); Assert.Contains("Seller Name", xmlText, "Seller name not found in XML."); - Assert.Contains("Zahlbar innerhalb 14 Tagen", xmlText, "Payment terms not included."); + Assert.Contains("Zahlbar innerhalb von 14 Tagen", xmlText, "Payment terms not included."); } @@ -146,7 +148,15 @@ public void CanDeepReverseMapDto() var invoice = GetInvoiceAnnDto(); var xmlText = ZugferdMapper.MapToZugferd(invoice); var reverseDto = ZugferdMapper.MapFromZugferd(xmlText); - reverseDto.PaymentMeans.Name = invoice.PaymentMeans.Name; // Manually set for now + + // manually fix missing properties for ZUGFeRDVersion.Version23, Profile.Basic + reverseDto.SellerParty.Telefone = invoice.SellerParty.Telefone; + reverseDto.BuyerParty.Telefone = invoice.BuyerParty.Telefone; + reverseDto.SellerParty.RegistrationName = invoice.SellerParty.RegistrationName; + reverseDto.BuyerParty.RegistrationName = invoice.BuyerParty.RegistrationName; + reverseDto.PaymentMeans.Name = invoice.PaymentMeans.Name; + reverseDto.PaymentMeans.Bic = invoice.PaymentMeans.Bic; + DtoAssert.AreEqual(invoice, reverseDto); } } @@ -189,7 +199,7 @@ private static void AssertBuyer(BuyerAnnotationDto e, BuyerAnnotationDto a) Assert.AreEqual(e.Telefone, a.Telefone); Assert.AreEqual(e.TaxId, a.TaxId); Assert.AreEqual(e.BuyerReference, a.BuyerReference); - //Assert.AreEqual(e.RegistrationName, a.RegistrationName); + Assert.AreEqual(e.RegistrationName, a.RegistrationName); } private static void AssertSeller(SellerAnnotationDto e, SellerAnnotationDto a) @@ -203,7 +213,7 @@ private static void AssertSeller(SellerAnnotationDto e, SellerAnnotationDto a) Assert.AreEqual(e.Telefone, a.Telefone); Assert.AreEqual(e.TaxId, a.TaxId); Assert.AreEqual(e.CompanyId, a.CompanyId); - //Assert.AreEqual(e.RegistrationName, a.RegistrationName); + Assert.AreEqual(e.RegistrationName, a.RegistrationName); } private static void AssertPayment(PaymentAnnotationDto e, PaymentAnnotationDto a)