using System; using System.Collections.Generic; using System.Linq; using Centron.BusinessLogic; using Centron.BusinessLogic.Administration.Settings; using Centron.BusinessLogic.Sales.CustomerAssets.EmailAdditionalRecipients; using Centron.BusinessLogic.Sales.Customers; using Centron.BusinessLogic.Sales.Receipts; using Centron.BusinessLogic.Sales.Receipts.DataAndResults; using Centron.BusinessLogic.Sales.Receipts.Internal; using Centron.BusinessLogic.Warehousing; using Centron.BusinessLogic.WebServices.Accounts; using Centron.BusinessLogic.WebServices.Sales.CustomerAssets.AutomaticFactura; using Centron.BusinessLogic.WebServices.Sales.CustomerAssets.TimerBilling; using Centron.BusinessLogic.WebServices.Sales.Receipts; using Centron.BusinessLogic.WebServices.Sales.Receipts.ReceiptSearch; using Centron.Core.Extensions; using Centron.Data.Entities.Sales.CustomerAssets.EmailAdditionalRecipients; using Centron.Data.WebServices.Sales.Receipts.Invoices; using Centron.Interfaces; using Centron.Interfaces.Accounts; using Centron.Interfaces.Administration.Environment; using Centron.Interfaces.BL; using Centron.Interfaces.CustomerArea; using Centron.Interfaces.Sales.BillingCenter.Contracts; using Centron.Interfaces.Sales.Receipts; using Centron.Interfaces.Sales.Receipts.InsertReceipts; using Centron.Interfaces.Sales.Receipts.ReceiptSearch; using Centron.Tests.EndToEnd.Infrastructure; using Centron.Tests.EndToEnd.Infrastructure.Verifier; using CentronSoftware.Centron.WebServices.Entities.ReportEngine; using CentronSoftware.Centron.WebServices.Entities.Sales.CustomerAssets.TimerBilling; using CentronSoftware.Centron.WebServices.EntitiesWrongPlace.Sales.Receipts.DataAndResults; using System.Reflection; using Xunit; using Xunit.Abstractions; namespace Centron.Tests.EndToEnd.Tests.ReceiptCompanyGroup; public class ReceiptCompanyGroupTests : EndToEndTest { public ReceiptCompanyGroupTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) { this.Verifier.Settings.IgnoreColumn("ChangedDate"); this.Verifier.Settings.IgnoreColumn("ChangedVersion"); } public const int AccountI3D = 1025; public const int CustomerNumber = 10026; public const int OfferI3D = 6692; public const int ArticleI3D = 17; //This article has different prices per price-list public const int CompanyGroupAccountI3D = 19; public const int CompanyGroupCustomerNumber = 10020; public const int ContractInvoiceAddressCustomerI3D = 10; public const int ContractInvoiceAddressAddressI3D = 20; public const int ContractInvoiceAddressContactPersonI3D = 30; public override void Execute() { this.PrepareDatabase(); this.CanSetUseSettingsFromCompanyGroupForReceipts(step: 1); this.CreateNewReceipt(step: 2); this.UsesZUGFeRDSettingsFromCompanyGroup(step: 3); this.CreateMail(step: 4); this.PriceCalculation(step: 5); this.ReceiptSearchInvoiceSendType(step: 6); this.TimerBillingInvoiceSendType(step: 7); this.ForwardReceiptAlternativeEmailRecipient(step: 8); this.ContractInvoiceOnCorporationUsesCorporationCustomer(); this.ContractInvoiceOnCorporationUsesContractInvoiceAddress(); } private void PrepareDatabase() { // Our main customer with CustomerNumber 10026 has all receipt-condition settings of NULL // And our company-group has them with some value // So to actually see a real difference between "no company group" and "with company group", we also reset the default-fallback-condition settings var defaultConditionSettings = new List { AppSettingsConst.DefaultCustomerInvoicePaymentCondition, AppSettingsConst.DefaultCustomerDeliveryCondition, AppSettingsConst.DefaultCustomerCreditVoucherPaymentCondition, AppSettingsConst.DefaultCustomerOfferPaymentCondition, AppSettingsConst.DefaultCustomerOrderPaymentCondition, AppSettingsConst.DefaultCustomerPickupListPaymentCondition, }; this.Sql($"UPDATE dbo.Stammdat SET Wert = 0 WHERE I3D IN ({defaultConditionSettings.Select(f => ((int)f).ToString()).JoinWithSeparator(",")})"); // Also set a alternative invoice receiver on the company-group this.Sql($"UPDATE dbo.Kunden SET AbwKundeI3D = 10, AbwAnschriftI3D = 20, AbwPersonI3D = 30, AbwEmpfaenger = 'Test-Empfänger' WHERE I3D = {CompanyGroupCustomerNumber}"); // And set alternative delivery receiver on the company-group this.Sql($"UPDATE dbo.Kunden SET AbwLiefKundeI3D = 40, AbwLiefAnschriftI3D = 50, AbwLiefPersonI3D = 60, AbwLiefEmpfaenger = 'Test-Lief-Empfänger' WHERE I3D = {CompanyGroupCustomerNumber}"); // There is no Bankverbindung for the company-group // So we just move the existing Bankverbindung to the company-group, so he can use it for this test this.Sql($"UPDATE dbo.Bankverbindungen SET ObjectI3D = {CompanyGroupCustomerNumber}"); // Enable export-zugferd for the company-group this.Sql($"UPDATE dbo.AccountCustomers SET ExportZUGFeRDDocument = 1, LeitwegID = '123456' WHERE Number = {CompanyGroupCustomerNumber}"); // Update some mailing recipient stuff, so we can test the mail-template logic this.Sql($"UPDATE dbo.AngKopf SET Mail = 'test@test-mail-from-offer.de' WHERE I3D = {OfferI3D}"); using var session = new BLSession(); session.GetBL().SaveEmailAdditionalRecipient(new EmailAdditionalRecipient { ObjectI3D = CompanyGroupCustomerNumber, EmailRecipientKind = EmailRecipientKind.AllOffersFromCustomer, To = new List { "empfänger@von-company-group.de", "noch-einer@hui-bub.de" }, CC = new List { "and-some@cc.de" }, BCC = new List { "and-wow@bcc.de" } }); // We could also add some partners to the company-group that get offers and orders, but I am too lazy for that right now // We could also add some alternative invoice CC and BCC recipients, but not now // Set company-group price-list to 1, the customer has 0 already this.Sql($"UPDATE dbo.Kunden SET Preisliste = 1 WHERE I3D = {CompanyGroupCustomerNumber}"); // The customer doesn't have a single invoice, so we move one around this.Sql($"UPDATE dbo.RechKopf SET KundenID = {CustomerNumber} WHERE I3D = 160"); // Set company-group invoice-send-type to Print, the customer has None already this.Sql($"UPDATE dbo.Kunden SET RechnungVersandArt = {(int)AssetSendType.Print} WHERE I3D = {CompanyGroupCustomerNumber}"); // The customer also doesn't have a single timer that we can find in the timer-billing search, so we move one around this.Sql($"UPDATE dbo.hlpdsk_requests SET KundeI3D = {CustomerNumber} WHERE I3D = 126"); // The company-group needs an alternative invoice mail recipient this.Sql($"UPDATE dbo.Kunden SET AbwMailRechnungEmpfaengerI3D = 74 WHERE I3D = {CompanyGroupCustomerNumber}"); } private void CanSetUseSettingsFromCompanyGroupForReceipts(int step) { var loggedInUser = this.GetLoggedInUser(); using var loadSession = new BLSession(); var accountFilter = new AccountFilter { AccountI3D = AccountI3D }; var account = loadSession.GetBL().GetAccount(loggedInUser, accountFilter, mixMode: false).ThrowIfError(); account.CompanyGroupI3D = CompanyGroupAccountI3D; account.UseSettingsFromCompanyGroupForReceipts = true; using var saveSession = new BLSession(); var saveResult = saveSession.GetBL().SaveAccount(loggedInUser, account, mixMode: false, isDataImport: false).ThrowIfError(); this.Verifier.VerifyTable($"{step}_Set_UseSettingsFromCompanyGroupForReceipts", "Accounts", $"I3D = {account.I3D}"); this.Verifier.VerifyTable($"{step}_KundeToKonzern", "KundeToKonzern"); } private void CreateNewReceipt(int step) { var receiptKinds = new List { CentronObjectKindNumeric.OfferClass, CentronObjectKindNumeric.OrderClass, CentronObjectKindNumeric.DeliveryListClass, CentronObjectKindNumeric.InvoiceClass, CentronObjectKindNumeric.PickupListClass, CentronObjectKindNumeric.CreditVoucherClass, }; foreach (var receiptKind in receiptKinds) { using var session = new BLSession(); var receiptResult = session.GetBL().CreateNewReceipt( receiptKind, this.GetLoggedInUser(), CustomerNumber, new CreateReceiptData { IgnoreCallbacks = true }, addressI3D: null, contactPersonI3D: null, insertSalutationAndAgreement: false, ignoreDefaultContract: false, insertCustomerDiscount: true); this.Verifier.Verify($"{step}_NewReceipt_{receiptKind.GetReceiptName()}", receiptResult); } } private void UsesZUGFeRDSettingsFromCompanyGroup(int step) { using var session = new BLSession(); var receipt = session.GetBL().GetReceiptByI3D(CentronObjectKindNumeric.OfferClass, OfferI3D); Assert.NotNull(receipt); var zugferdSetting = session.GetBL().GetLocalZUGFeRDSetting(receipt); this.Verifier.Verify($"{step}_ZUGFeRD_Settings", zugferdSetting); var leitwegID = session.GetBL().GetLeitwegID(CustomerNumber); this.Verifier.Verify($"{step}_LeitwegID", leitwegID); } private void CreateMail(int step) { using var session = new BLSession(); var receipt = session.GetBL().GetReceiptByI3D(OfferI3D, CentronObjectKindNumeric.OfferClass); var mailTemplate = session.GetBL().GetReceiptMailTemplate( this.GetLoggedInUser().User, receipt.Data, Guid.Parse(receipt.Data.GetReportGroup()), includeAttachmentFileData: false, reportDataI3D: null, includeReportAttachmentFileData: false, new CreateFullReportConfiguration()); this.Verifier.Verify($"{step}_MailTemplate", mailTemplate); } private void PriceCalculation(int step) { using var session = new BLSession(); var article = session.GetBL().GetArticleByI3D(ArticleI3D); var customer = session.GetBL().GetCustomer(CustomerNumber); var (basePrice, discount) = session.GetBL().GetBasePrice(purchaseBasePrice: 0, article, customer, contractI3D: null, specialAgreement: null, quantity: 1); this.Verifier.Verify($"{step}_Prices", new { BasePrice = basePrice, Discount = discount }); } private void ReceiptSearchInvoiceSendType(int step) { using var session = new BLSession(); var filter = new ReceiptSearchFilter { AccountI3D = CustomerNumber, ReceiptKinds = new List { CentronObjectKindNumeric.InvoiceClass }, IncludeClosedReceipts = true }; var receipts = session.GetBL().SearchReceipts(this.GetLoggedInUser(), filter, 1, 100); this.Verifier.Verify($"{step}_Receipts", receipts); } private void TimerBillingInvoiceSendType(int step) { using var session = new BLSession(); var filter = new TimerBillingFilter { CustomerI3Ds = new List { CustomerNumber } }; var timers = session.GetBL().SearchTimers(filter); this.Verifier.Verify($"{step}_Timers", timers); } private void ForwardReceiptAlternativeEmailRecipient(int step) { using var session = new BLSession(); var forwardResult = session.GetBL().ForwardReceipt( CentronObjectKindNumeric.InvoiceClass, this.GetLoggedInUser().User, new ForwardReceiptData { IgnoreCallbacks = true, CreateReceiptData = new CreateReceiptData { IgnoreCallbacks = true, }, CreateReceiptItemsFromExistingItemsData = new List { new() { IgnoreCallbacks = true, }, }, }, new List { new ReceiptToForward { ReceiptKind = CentronObjectKindNumeric.OfferClass, ReceiptI3D = OfferI3D } }, null, InsertReceiptTakeoverOptions.Reference, onlyTakeoverAvailableQuantity: true, ignoreDefaultContract: false); this.Verifier.Verify($"{step}_OfferToInvoice", forwardResult); } private void ContractInvoiceOnCorporationUsesCorporationCustomer() { using var session = new BLSession(); var loggedInUser = this.GetLoggedInUser(); var receiptWebServiceBL = session.GetBL(); var createResult = receiptWebServiceBL.CreateNewReceipt( CentronObjectKindNumeric.InvoiceClass, loggedInUser, CustomerNumber, new CreateReceiptData { IgnoreCallbacks = true }, addressI3D: null, contactPersonI3D: null, insertSalutationAndAgreement: false, ignoreDefaultContract: true, insertCustomerDiscount: false).ThrowIfError(); var invoice = (ReceiptInvoiceDTO)createResult.Receipt; var billingParam = new ContractToInvoiceParam { CorporationBilling = true, CreateInvoiceOnCorporation = true, CustomerI3D = CustomerNumber }; var adaptInvoiceHeadMethod = typeof(AutomaticFacturaWebServiceBL).GetMethod( "AdaptInvoiceHead", BindingFlags.NonPublic | BindingFlags.Instance); Assert.NotNull(adaptInvoiceHeadMethod); var automaticFacturaWebServiceBL = session.GetBL(); adaptInvoiceHeadMethod.Invoke(automaticFacturaWebServiceBL, new object[] { receiptWebServiceBL, billingParam, invoice, loggedInUser }); Assert.Equal(CompanyGroupCustomerNumber, invoice.CustomerI3D); var saveResult = receiptWebServiceBL.SaveReceipt( invoice, loggedInUser.User, new SaveReceiptData { IgnoreCallbacks = true }, autoLockIfNewReceipt: false, application: CreatedThroughApplication.CentronNet, receiptTemplateFolderI3D: null).ThrowIfError(); var savedCustomerI3D = this.Sql($"SELECT KundenID FROM dbo.RechKopf WHERE I3D = {saveResult.Receipt.I3D}"); Assert.Equal(CompanyGroupCustomerNumber, savedCustomerI3D); Assert.Equal(CompanyGroupCustomerNumber, ((ReceiptInvoiceDTO)saveResult.Receipt).CustomerI3D); } private void ContractInvoiceOnCorporationUsesContractInvoiceAddress() { using var session = new BLSession(); var loggedInUser = this.GetLoggedInUser(); var receiptWebServiceBL = session.GetBL(); var createResult = receiptWebServiceBL.CreateNewReceipt( CentronObjectKindNumeric.InvoiceClass, loggedInUser, CustomerNumber, new CreateReceiptData { IgnoreCallbacks = true }, addressI3D: null, contactPersonI3D: null, insertSalutationAndAgreement: false, ignoreDefaultContract: true, insertCustomerDiscount: false).ThrowIfError(); var invoice = (ReceiptInvoiceDTO)createResult.Receipt; var contractInvoiceAddress = receiptWebServiceBL.CreateReceiverText( dataUseNewAccountStructure: false, customerI3D: ContractInvoiceAddressCustomerI3D, addressI3D: ContractInvoiceAddressAddressI3D, contactPersonI3D: ContractInvoiceAddressContactPersonI3D); invoice.InvoiceAddress = contractInvoiceAddress; invoice.InvoiceAddressCustomerI3D = ContractInvoiceAddressCustomerI3D; invoice.InvoiceAddressAddressI3D = ContractInvoiceAddressAddressI3D; invoice.InvoiceAddressContactPersonI3D = ContractInvoiceAddressContactPersonI3D; invoice.ReceiptReceiverInvoice = null; invoice.Receiver = contractInvoiceAddress; invoice.UsedAlternativeInvoiceAddress = true; var billingParam = new ContractToInvoiceParam { CorporationBilling = true, CreateInvoiceOnCorporation = true, CustomerI3D = CustomerNumber }; var adaptInvoiceHeadMethod = typeof(AutomaticFacturaWebServiceBL).GetMethod( "AdaptInvoiceHead", BindingFlags.NonPublic | BindingFlags.Instance); Assert.NotNull(adaptInvoiceHeadMethod); var automaticFacturaWebServiceBL = session.GetBL(); adaptInvoiceHeadMethod.Invoke(automaticFacturaWebServiceBL, new object[] { receiptWebServiceBL, billingParam, invoice, loggedInUser }); Assert.Equal(CompanyGroupCustomerNumber, invoice.CustomerI3D); Assert.Equal(contractInvoiceAddress, invoice.Receiver); Assert.Equal(contractInvoiceAddress, invoice.InvoiceAddress); Assert.Equal(ContractInvoiceAddressCustomerI3D, invoice.InvoiceAddressCustomerI3D); Assert.Equal(ContractInvoiceAddressAddressI3D, invoice.InvoiceAddressAddressI3D); Assert.Equal(ContractInvoiceAddressContactPersonI3D, invoice.InvoiceAddressContactPersonI3D); Assert.True(invoice.UsedAlternativeInvoiceAddress); var saveResult = receiptWebServiceBL.SaveReceipt( invoice, loggedInUser.User, new SaveReceiptData { IgnoreCallbacks = true }, autoLockIfNewReceipt: false, application: CreatedThroughApplication.CentronNet, receiptTemplateFolderI3D: null).ThrowIfError(); var receiptI3D = saveResult.Receipt.I3D; Assert.Equal(CompanyGroupCustomerNumber, this.Sql($"SELECT KundenID FROM dbo.RechKopf WHERE I3D = {receiptI3D}")); Assert.Equal(contractInvoiceAddress, this.Sql($"SELECT Empfanger FROM dbo.RechKopf WHERE I3D = {receiptI3D}")); Assert.Equal(contractInvoiceAddress, this.Sql($"SELECT RechKundEmpfaenger FROM dbo.RechKopf WHERE I3D = {receiptI3D}")); Assert.Equal(ContractInvoiceAddressCustomerI3D, this.Sql($"SELECT RechKundI3D FROM dbo.RechKopf WHERE I3D = {receiptI3D}")); Assert.Equal(ContractInvoiceAddressAddressI3D, this.Sql($"SELECT RechKundAnschriftI3D FROM dbo.RechKopf WHERE I3D = {receiptI3D}")); Assert.Equal(ContractInvoiceAddressContactPersonI3D, this.Sql($"SELECT RechKundPersonI3D FROM dbo.RechKopf WHERE I3D = {receiptI3D}")); Assert.Equal(1, this.Sql($"SELECT RechKundFremd FROM dbo.RechKopf WHERE I3D = {receiptI3D}")); } }