using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using Centron.BusinessLogic; using Centron.BusinessLogic.EmployeeArea; using Centron.BusinessLogic.Sales.Receipts.DataAndResults; using Centron.BusinessLogic.Warehousing; using Centron.BusinessLogic.WebServices; using Centron.BusinessLogic.WebServices.Sales.Receipts; using Centron.Common.Extensions; using Centron.Controls.Shared; using Centron.DAO.AdoNETDataAccess; using Centron.Data.Entities.Administration.Logins; using Centron.Data.WebServices.Sales.Receipts.Invoices; using Centron.Data.WebServices.Sales.Receipts.Offers; using Centron.Interfaces; using Centron.Interfaces.Administration.Environment; using Centron.Interfaces.BL; using Centron.Interfaces.Sales.Receipts; using Centron.Interfaces.Sales.Receipts.InsertReceipts; using Centron.Tests.EndToEnd.Infrastructure; using Centron.Tests.EndToEnd.Infrastructure.Verifier; using CentronSoftware.Centron.WebServices.EntitiesWrongPlace.Sales.Receipts.DataAndResults; using Newtonsoft.Json; using Xunit; using Xunit.Abstractions; using Centron.Core.Extensions; namespace Centron.Tests.EndToEnd.Tests.SaveReceiptPerformance { /// /// This test measures how long it takes to save a huge new invoice. /// It used to take around 32 seconds, but after all of my improvements, it's down to less than 5 seconds. /// public class SaveReceiptPerformanceTest : PerformanceTest { public SaveReceiptPerformanceTest(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { } protected override TimeSpan? AllowedDuration => TimeSpan.FromSeconds(5); private ReceiptInvoiceDTO _invoiceToSave; private ReceiptInvoiceDTO _savedInvoice; protected override void Prepare() { // Set DTALastschrift to 0, so we are not required to select a correct sepa-mandate (Bankverbindung/Mandat) this.Sql("UPDATE dbo.Zahkond SET DTALastschrift = 0"); // Needed because this test was written before the "only forward picked quantity" functionality existed this.Sql("UPDATE dbo.ARTIK SET Kommisionieren = 0"); this._invoiceToSave = this.CreateNewInvoice(); } protected override void Measure() { using (var session = new BLSession()) { var user = session.GetBL().GetAppUser(f => f.I3D == 11); var saveResult = session.GetBL().SaveReceipt( this._invoiceToSave, user, new SaveReceiptData {IgnoreCallbacks = true}, autoLockIfNewReceipt: false, CreatedThroughApplication.CentronNet, receiptTemplateFolderI3D: null); Assert.Equal(ResultStatus.Success, saveResult.Status); Assert.NotNull(saveResult.Data.Receipt); this._savedInvoice = (ReceiptInvoiceDTO) saveResult.Data.Receipt; } } protected override void AssertResults() { Assert.NotNull(this._savedInvoice); this.Verifier.Verify("SavedReceipt", _savedInvoice); var settings = new CentronVerifierSettings(); settings.IgnoreColumn("Geandert_am"); //dbo.ARTIK settings.IgnoreColumn("VKDatum"); //dbo.ARTIK settings.IgnoreColumn("VKDatumDyn"); //dbo.ARTIK settings.IgnoreColumn("Datum"); //dbo.BarcodeHistory, dbo.SeriennummerToPosition var articleI3Ds = _savedInvoice.Items.Select(f => f.ArticleI3D).Where(f => f != null).Distinct().ToList(); this.Verifier.VerifyTable("ArticlesTable", "dbo.ARTIK", $"I3D IN ({string.Join(", ", articleI3Ds)})", settings); var barcodeI3Ds = _savedInvoice.Items.SelectMany(f => f.Barcodes).Select(f => f.BarcodeI3D).Distinct().ToList(); this.Verifier.VerifyTable("BarcodesTable", "dbo.Barcode", $"I3D IN ({string.Join(", ", barcodeI3Ds)})", settings); this.Verifier.VerifyTable("BarcodeHistoryTable", "dbo.BarcodeHistory", $"BarcodeI3D IN ({string.Join(", ", barcodeI3Ds)})", settings); this.Verifier.VerifyTable("SeriennummerToPositionTable", "dbo.SeriennummerToPosition", $"SNI3D IN ({string.Join(", ", barcodeI3Ds)})", settings); var originReceipts = _savedInvoice.Items .Select(f => new { ReceiptKind = f.OriginKind?.ToReceiptKind(), ReceiptI3D = f.OriginReceiptI3D }) .Where(f => f.ReceiptKind != null && f.ReceiptI3D != null) .ToList(); using (var session = new BLSession()) { foreach (var originReceipt in originReceipts) { var origin = session.GetBL().GetReceiptByI3D(originReceipt.ReceiptI3D.Value, originReceipt.ReceiptKind.Value); this.Verifier.Verify($"Origin{originReceipt.ReceiptKind.Value.GetReceiptName()}{originReceipt.ReceiptI3D}", origin.Data); } } } private ReceiptInvoiceDTO CreateNewInvoice() { using (var session = new BLSession()) { var user = session.GetBL().GetAppUser(f => f.I3D == 11); var invoice = (ReceiptInvoiceDTO) session.GetBL().CreateNewReceipt( CentronObjectKindNumeric.InvoiceClass, new LoggedInUser(user), customerI3D:10022, new CreateReceiptData {IgnoreCallbacks = true}, addressI3D: null, contactPersonI3D: null, insertSalutationAndAgreement: false, ignoreDefaultContract: false, insertCustomerDiscount:false).Data.Receipt; Assert.NotNull(invoice); invoice.Items.Clear(); void AddArticleToInvoice(int i3D, decimal quantity = 1, params string[] barcodes) { if (barcodes.EmptyIfNull().Any()) quantity = barcodes.Length; var articleReceiptItems = session.GetBL().CreateArticleReceiptItems(invoice, false, i3D, null, null, -1, new LoggedInUser(user)).Data.ReceiptItems; Assert.NotNull(articleReceiptItems); var invoiceItems = articleReceiptItems.Cast().ToList(); foreach (var item in invoiceItems.Where(f => f.Kind == ReceiptItemKind.Article)) { item.QuantityComplete *= quantity; if (item.ArticleI3D == i3D) { item.Barcodes.AddRange(barcodes.Select(f => new ReceiptItemBarcode { BarcodeI3D = this.Sql("SELECT B.I3D FROM dbo.Barcode B WHERE B.Barcode = @Barcode", d => d.AddParameter("Barcode", f)), BarcodeCaption = f, IsActive = true })); } } foreach (var item in invoiceItems) { item.RichText = TextHelper.PlainToRtf(item.Text); } invoice.Items.AddRange(invoiceItems); } void AddTextToInvoice(string text) { var invoiceItem = (ReceiptInvoiceItemDTO)session.GetBL().CreateFreetextReceiptItem(invoice, text); Assert.NotNull(invoiceItem); invoiceItem.RichText = TextHelper.PlainToRtf(invoiceItem.Text); invoice.Items.Add(invoiceItem); } void AddExistingReceiptToInvoice(CentronObjectKindNumeric receiptKind, int receiptI3D) { var forwardResult = session.GetBL().ForwardReceipt( CentronObjectKindNumeric.InvoiceClass, user, new ForwardReceiptData { IgnoreCallbacks = true, CreateReceiptData = new CreateReceiptData { IgnoreCallbacks = true }, CreateReceiptItemsFromExistingItemsData = new List { new() { IgnoreCallbacks = true, }, }, }, new List { new ReceiptToForward { ReceiptKind = receiptKind, ReceiptI3D = receiptI3D } }, null, InsertReceiptTakeoverOptions.Reference, onlyTakeoverAvailableQuantity: false, ignoreDefaultContract: false); Assert.Equal(ResultStatus.Success, forwardResult.Status); Assert.NotNull(forwardResult.Data.Receipt); var forwardedInvoice = (ReceiptInvoiceDTO) forwardResult.Data.Receipt; foreach (var item in forwardedInvoice.Items) { item.RichText = TextHelper.PlainToRtf(item.Text); } invoice.Items.AddRange(forwardedInvoice.Items); } // A little SQL-Statement to help you find articles that you can insert into the invoice // // SELECT A.I3D, A.Abbuchung, A.Menge, A.BarcodeScanen, A.* // FROM dbo.ARTIK A // WHERE // A.Lieferbar = 1 AND // ( // A.BarcodeScanen = 0 OR // A.I3D IN // ( // SELECT B.ArtikelI3D // FROM dbo.Barcode B // WHERE B.Status = 1 // ) // ) AND // ( // A.Abbuchung = 'N' OR // A.Menge > 0 // ) AddTextToInvoice("Hallo lieber Kunde, hier eine super tolle Rechnung von uns!"); AddArticleToInvoice(i3D: 4345); AddArticleToInvoice(i3D: 4331, quantity:3); AddArticleToInvoice(i3D: 2328, quantity:7); AddTextToInvoice("Ein bisschen Blabla"); AddArticleToInvoice(i3D: 1313, quantity:2); AddArticleToInvoice(i3D: 1299, barcodes: "dfsgdfgdfgsdfg"); AddArticleToInvoice(i3D: 1289, barcodes: "ssasdfsdfadfad"); AddArticleToInvoice(i3D: 1288, barcodes: "100021417"); AddArticleToInvoice(i3D: 1277, quantity:2); AddArticleToInvoice(i3D: 2326, barcodes: "ASDFSDAFSD"); AddTextToInvoice("Nochmal mehr blabla"); AddTextToInvoice("Und eine weitere Position, for good measure"); AddTextToInvoice("Einer geht noch, einer geht noch rein!"); AddArticleToInvoice(i3D: 1277, barcodes: "asdasdfasdafsdfsd"); AddArticleToInvoice(i3D: 1256, barcodes: new []{"100032017", "100062017", "100092017", "100102017"}); AddArticleToInvoice(i3D: 1253, barcodes: new []{"asdfasdsfadfa", "100031417"}); AddArticleToInvoice(i3D: 1233, barcodes: "sdafdsfsdfasdf"); AddArticleToInvoice(i3D: 1230, barcodes: "sdfgsdfgsdfgsdfg"); AddArticleToInvoice(i3D: 1214, barcodes: "wruiwehrzuhfn mv s,.an.f,d"); AddArticleToInvoice(i3D: 1213, barcodes: new []{"VDVSDFASDFASDFD", "ASDFASDFDF"}); AddArticleToInvoice(i3D: 1212, barcodes: "fgsdgdfgdfgsdfgsfgf"); AddArticleToInvoice(i3D: 1210, barcodes: "DFGMJHSDFJGDFL"); AddArticleToInvoice(i3D: 1208, barcodes: "sasdfasdasdfsdf"); AddArticleToInvoice(i3D: 1193, quantity:3); AddArticleToInvoice(i3D: 1186, quantity:35); AddArticleToInvoice(i3D: 1185, quantity:30); AddTextToInvoice("Blabla"); AddArticleToInvoice(i3D: 1186, quantity:35); AddArticleToInvoice(i3D: 1185, quantity:30); AddArticleToInvoice(i3D: 176, barcodes:new [] {"300500", "741852", "asdfjdsfklasdklöf"}); AddTextToInvoice("Heyaa"); AddArticleToInvoice(i3D: 1186, quantity:2); AddArticleToInvoice(i3D: 1185, quantity:3); AddArticleToInvoice(i3D: 1186, quantity:2); AddArticleToInvoice(i3D: 1185, quantity:3); AddTextToInvoice("Heyaa"); AddArticleToInvoice(i3D: 1186, quantity:2); AddArticleToInvoice(i3D: 1185, quantity:3); AddArticleToInvoice(i3D: 1186, quantity:2); AddTextToInvoice("Heyaa"); AddArticleToInvoice(i3D: 167, quantity:10); AddArticleToInvoice(i3D: 159, barcodes: "8874452"); AddArticleToInvoice(i3D: 158, barcodes: new []{"11849848", "12189489", "15165847", "1541874189"}); AddArticleToInvoice(i3D: 156, barcodes: "555666442"); AddArticleToInvoice(i3D: 155, quantity:2); AddArticleToInvoice(i3D: 154, barcodes: "sn23112010001"); AddArticleToInvoice(i3D: 154, barcodes: "sn23112010004"); AddArticleToInvoice(i3D: 167, quantity:10); AddArticleToInvoice(i3D: 167, quantity:10); AddArticleToInvoice(i3D: 167, quantity:10); AddArticleToInvoice(i3D: 1186, quantity:2); AddArticleToInvoice(i3D: 1185, quantity:3); AddTextToInvoice("MEEEEEHR DIENSTLEISTUNG!"); AddArticleToInvoice(i3D: 167, quantity:10); AddArticleToInvoice(i3D: 167, quantity:10); AddArticleToInvoice(i3D: 167, quantity:10); AddArticleToInvoice(i3D: 1186, quantity:2); AddArticleToInvoice(i3D: 1185, quantity:3); AddArticleToInvoice(i3D: 167, quantity:10); AddArticleToInvoice(i3D: 167, quantity:10); AddArticleToInvoice(i3D: 167, quantity:10); AddArticleToInvoice(i3D: 1186, quantity:2); AddArticleToInvoice(i3D: 1185, quantity:3); AddTextToInvoice("Und noch ein paar Artikel"); AddArticleToInvoice(i3D: 152, barcodes: "1225544"); AddArticleToInvoice(i3D: 151, barcodes: "3333333"); AddArticleToInvoice(i3D: 151, barcodes: "2200500"); AddArticleToInvoice(i3D: 146, quantity:10); AddArticleToInvoice(i3D: 146, quantity:15); AddArticleToInvoice(i3D: 132, quantity:8); AddArticleToInvoice(i3D: 128, barcodes: "SN2910093"); AddArticleToInvoice(i3D: 126, barcodes: "gfdgd"); AddArticleToInvoice(i3D: 120, barcodes: "32332"); AddArticleToInvoice(i3D: 114, barcodes: "100074210"); AddArticleToInvoice(i3D: 114, barcodes: "100084210"); AddArticleToInvoice(i3D: 132, quantity:8); AddArticleToInvoice(i3D: 146, quantity:15); AddArticleToInvoice(i3D: 167, quantity:10); AddTextToInvoice("Und jetzt noch ein paar bestehende Belege, sodass auch die weiterverarbeitung und so geprüft wird"); AddExistingReceiptToInvoice(CentronObjectKindNumeric.OrderClass, 1294); AddExistingReceiptToInvoice(CentronObjectKindNumeric.OrderClass, 1291); AddExistingReceiptToInvoice(CentronObjectKindNumeric.OrderClass, 1296); AddExistingReceiptToInvoice(CentronObjectKindNumeric.OrderClass, 1303); AddExistingReceiptToInvoice(CentronObjectKindNumeric.OrderClass, 1317); AddExistingReceiptToInvoice(CentronObjectKindNumeric.OrderClass, 1325); AddExistingReceiptToInvoice(CentronObjectKindNumeric.OrderClass, 1310); AddExistingReceiptToInvoice(CentronObjectKindNumeric.OrderClass, 1332); AddExistingReceiptToInvoice(CentronObjectKindNumeric.OrderClass, 1333); AddTextToInvoice("Und jetzt noch ein paar Positionen mit vielen SNs"); AddArticleToInvoice(i3D: 139, barcodes: new []{"101004211", "101014211", "101024211", "101034211", "101054211", "101064211", "101074211"}); AddArticleToInvoice(i3D: 139, barcodes: new []{"101084211", "101094211", "101104211", "101114211"}); AddArticleToInvoice(i3D: 139, barcodes: new []{"101124211", "101134211", "101144211", "101154211", "101164211"}); AddArticleToInvoice(i3D: 139, barcodes: new []{"101174211", "101184211", "101194211", "101204211", "101214211", "101224211", "101234211", "101244211", "101254211", "101264211"}); AddArticleToInvoice(i3D: 139, barcodes: new []{"101274211", "101284211", "101294211", "101304211", "101314211", "101324211", "101334211"}); AddArticleToInvoice(i3D: 52, barcodes: new []{"100034211", "100044211", "100064211", "100084211", "100094211", "100104211"}); AddArticleToInvoice(i3D: 52, barcodes: new []{"100224211", "100234211", "100244211", "100254211", "100264211", "100274211", "100284211", "100294211", "100304211", "100314211"}); AddArticleToInvoice(i3D: 52, barcodes: new []{"100114211", "100124211", "100134211", "100144211", "100154211", "100164211", "100174211", "100184211", "100194211", "100204211", "100214211"}); AddArticleToInvoice(i3D: 52, barcodes: new []{"100324211", "100334211", "100344211", "100354211", "100364211", "100374211", "100384211", "100394211", "100404211", "100414211"}); AddArticleToInvoice(i3D: 52, barcodes: new []{"100424211", "100434211", "100444211", "100454211", "100464211", "100474211", "100484211", "100494211", "100504211", "100514211", "100524211"}); AddArticleToInvoice(i3D: 52, barcodes: new []{"100534211", "100544211", "100554211", "100564211", "100574211", "100584211", "100594211", "100604211", "100614211", "100624211", "100634211", "100644211", "100654211", "100664211", "100674211", "100684211", "100694211", "100704211", "100714211", "100724211", "100734211", "100744211", "100754211"}); AddArticleToInvoice(i3D: 52, barcodes: new []{"100764211", "100774211", "100784211", "100794211", "100804211", "100814211", "100824211", "100834211", "100844211", "100854211", "100864211", "100874211", "100884211", "100894211", "100904211", "100914211", "100924211", "100934211", "100944211", "100954211", "100964211", "100974211", "100984211", "100994211"}); AddArticleToInvoice(i3D: 22, barcodes: new []{"101251711", "101261711", "101271711", "101291711", "101301711", "101311711", "101321711", "101331711", "101341711", "101351711", "101361711", "101371711", "101381711", "101391711", "101401711", "101411711", "101421711", "101431711"}); AddTextToInvoice("Weil es noch nicht lange genug dauert, jetzt noch ein paar Lieferscheine"); AddExistingReceiptToInvoice(CentronObjectKindNumeric.DeliveryListClass, 5153); AddExistingReceiptToInvoice(CentronObjectKindNumeric.DeliveryListClass, 5165); AddExistingReceiptToInvoice(CentronObjectKindNumeric.DeliveryListClass, 85); AddExistingReceiptToInvoice(CentronObjectKindNumeric.DeliveryListClass, 87); AddExistingReceiptToInvoice(CentronObjectKindNumeric.DeliveryListClass, 88); AddExistingReceiptToInvoice(CentronObjectKindNumeric.DeliveryListClass, 89); AddTextToInvoice("Ende Gelände"); var itemsCount = invoice.Items.Count; var articleCount = invoice.Items.Count(f => f.Kind == ReceiptItemKind.Article); var quantityCount = invoice.Items.Where(f => f.Kind == ReceiptItemKind.Article).Sum(f => f.QuantityComplete); var barcodeCount = invoice.Items.SelectMany(f => f.Barcodes.EmptyIfNull()).Count(); return invoice; } } } }