Codebasis als Dateien ins Arbeitsrepo statt als Gitlink

QuellCode/CentronERP war nur als Gitlink (Submodul-Referenz auf 79c1142)
getrackt, ohne .gitmodules und ohne erreichbares Remote. Der
Untersuchungsgegenstand der Versuchsreihe war damit nicht reproduzierbar
gesichert: Ein Klon haette ein leeres Verzeichnis erhalten, und die Belege
der 3.287 Anforderungen waeren nicht ueberpruefbar gewesen.

Umstellung:
- Historie nach c:\DEV\CentronERP_git_snapshot_79c1142 ausgelagert
  (vollstaendig lesbar, enthaelt 79c1142 und Vorgaenger 89ccfd6)
- Gitlink aus dem Index entfernt
- Dateiinhalt aufgenommen: 24.557 Dateien, rund 333 MB

Die verschachtelte .gitignore der Codebasis gilt weiter, Build-Artefakte
bleiben ausgeschlossen. Details in Versuche/Versuch_01/_Codebasis-Nachweis.md
This commit is contained in:
Christoph Schwörer
2026-08-26 07:43:51 +02:00
parent 18edae75b6
commit f045b99a25
24664 changed files with 5846716 additions and 1 deletions
@@ -0,0 +1,399 @@
using Centron.BusinessLogic;
using Centron.BusinessLogic.EmployeeArea;
using Centron.BusinessLogic.Sales.CustomerAssets.TimerBilling;
using Centron.BusinessLogic.WebServices.Sales.Receipts;
using Centron.Data.WebServices.Sales.Receipts.Invoices;
using Centron.Interfaces;
using Centron.Tests.EndToEnd.Infrastructure;
using CentronSoftware.Centron.WebServices.Entities.Sales.CustomerAssets.TimerBilling;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Centron.BusinessLogic.Administration.Settings;
using Centron.BusinessLogic.Sales.Receipts.DataAndResults;
using Centron.BusinessLogic.Sales.Receipts.Internal;
using Centron.BusinessLogic.Sales.Support;
using Centron.BusinessLogic.WebServices.Sales.Support;
using Centron.Data.Entities.Sales.Support.HelpdeskTimerArea;
using Centron.Data.WebServices.Sales.Receipts;
using Centron.Data.WebServices.Sales.Receipts.Offers;
using Centron.Data.WebServices.Sales.Support;
using Centron.Interfaces.Administration.Environment;
using Centron.Interfaces.Administration.Settings;
using Centron.Interfaces.Sales.Receipts;
using CentronSoftware.Centron.WebServices.Extensions;
using Xunit;
using Xunit.Abstractions;
namespace Centron.Tests.EndToEnd.Tests.TimerBilling
{
public class TimerBillingTest : EndToEndTest
{
public TimerBillingTest(ITestOutputHelper testOutputHelper)
: base(testOutputHelper)
{
}
public override void Execute()
{
this.PrepareDatabase();
this.CreateReceiptWithDate(CentronObjectKindNumeric.InvoiceClass, reminderDateInDays: 0);
this.CreateReceiptWithDate(CentronObjectKindNumeric.InvoiceClass, reminderDateInDays: 10);
this.CreateReceiptWithDate(CentronObjectKindNumeric.DeliveryListClass, reminderDateInDays: 0);
this.CreateReceiptWithDate(CentronObjectKindNumeric.DeliveryListClass, reminderDateInDays: 10);
// Reset it to 0, so the invoices created afterwards don't change
this.SetReminderDateInDays(0);
this.FindTimersAndCreateInvoiceForCustomer(10008);
this.FindTimersAndCreateInvoiceForCustomer(10012);
this.FindTimersAndCreateInvoiceForCustomer(10017);
this.FindTimersAndCreateInvoiceForCustomer(10024);
this.ValidateUseTicketTimeAsServicePeriod();
this.ValidateBreakTimeFormat();
// Timer from orders
this.ExecuteMatrix(
new bool?[] {null, true, false},
new bool[] {true, false},
(takePriceFromOrder, globalTakePriceFromOrder) =>
{
this.CreateReceiptWithTimerFromOrder(takePriceFromOrder, globalTakePriceFromOrder);
});
// Timer with Master-Data-List infos
this.CreateInvoiceFromTicketWithMasterDataList();
// Timer start- and end-time fix
this.ExecuteMatrix(
new bool[] {true, false},
new bool[] {true, false},
(startTimeFormat, endTimeFormat) =>
{
this.CreateReceiptWithTimerFormat(startTimeFormat, endTimeFormat);
});
this.TestGetContractsMethod();
}
private void TestGetContractsMethod()
{
// This is just a function test so the different combinations work. We use in GetContracts a complex table valued function
// If it is called for one customer or one contract, we pass down it too the function too.
using var session = new BLSession();
var result = session.GetBL<TimerBillingBL>().GetContracts(new List<int>()
{
10000
}, null);
Verifier.Verify("TimerBillingTest_TestGetContractsMethod_SingleCustomer", result);
result = session.GetBL<TimerBillingBL>().GetContracts(null, new List<int>()
{
28
});
Verifier.Verify("TimerBillingTest_TestGetContractsMethod_SingleContract", result);
result = session.GetBL<TimerBillingBL>().GetContracts(new List<int>()
{
10000, 10003
}, null);
Verifier.Verify("TimerBillingTest_TestGetContractsMethod_MultipleCustomer", result);
result = session.GetBL<TimerBillingBL>().GetContracts(null, new List<int>()
{
28, 6
});
Verifier.Verify("TimerBillingTest_TestGetContractsMethod_MultipleContract", result);
}
private void PrepareDatabase()
{
this.Sql($"UPDATE dbo.Stammdat SET WertText = 'g' WHERE I3D = {(int)AppSettingsConst.HelpdeskTimerStartTimeFormat}");
this.Sql($"UPDATE dbo.Stammdat SET WertText = 'g' WHERE I3D = {(int)AppSettingsConst.HelpdeskTimerEndTimeFormat}");
}
private void CreateReceiptWithDate(CentronObjectKindNumeric receiptKind, int reminderDateInDays)
{
this.SetReminderDateInDays(reminderDateInDays);
// Prepare
var customerI3D = 10008;
var name = $"{receiptKind.GetReceiptName()}WithDateResultForCustomer{customerI3D}ReminderIn{reminderDateInDays}";
var timerI3Ds = this.FindTimers(customerI3D);
var billingDate = new DateTime(2021, 10, 30);
var settings = new TimerBillingSettingsDTO
{
ReceiptKind = receiptKind,
BillingDate = billingDate
};
// Act
var receipt = this.CreateReceipt(name, timerI3Ds, settings);
// Assert
Assert.Equal(billingDate, receipt.Date);
// The ReminderDate should be X days after the receipt-date
// So when today is X, billing date is X + 7, and reminderDateInDays is 5,
// then reminderDate should be X + 7 + 5
var expectedReminderDate = reminderDateInDays == 0
? (DateTime?)null
: billingDate.AddDays(reminderDateInDays);
Assert.Equal(expectedReminderDate, receipt.Get((IReceiptWithReminderDate r) => r.ReminderDate));
}
private void SetReminderDateInDays(int reminderDateInDays)
{
// Set reminder date settings
using (var session = new BLSession())
{
var updateSettings = session.GetBL<AppSettingsBL>().GetSettingsForUpdate(
AppSettingsConst.InvoiceReminderDays,
ApplicationSettingID.DeliveryListReminderDays);
updateSettings.UpdateInt(AppSettingsConst.InvoiceReminderDays, reminderDateInDays);
updateSettings.UpdateInt(ApplicationSettingID.DeliveryListReminderDays, reminderDateInDays);
updateSettings.SaveSettings();
}
}
private void FindTimersAndCreateInvoiceForCustomer(int customerI3D)
{
var name = $"InvoiceResultForCustomer{customerI3D}";
var timerI3Ds = this.FindTimers(customerI3D);
var settings = new TimerBillingSettingsDTO
{
InsertHelpdeskDescription = true,
InsertHelpdeskShortDescription = true,
InsertTimerText = true,
InsertTimerTime = true,
InsertTheFollowingAreTimersFromHelpdeskText = true,
Sorting = Interfaces.Sales.Receipts.TimerBilling.TimerSorting.ChronologicalUp,
ReceiptKind = CentronObjectKindNumeric.InvoiceClass,
AdditionalText = "Hier mein Text!"
};
var invoice = this.CreateReceipt(name, timerI3Ds, settings);
this.SaveInvoice(invoice);
}
private List<int> FindTimers(int customerI3D)
{
using (var session = new BLSession())
{
var filter = new TimerBillingFilter
{
OnlyOpenHelpdesks = true,
CustomerI3Ds = new List<int>
{
customerI3D
}
};
var timers = session.GetBL<TimerBillingBL>().SearchTimers(filter);
this.Verifier.Verify("FindTimersForCustomer" + customerI3D, timers);
return timers.Select(f => f.I3D).ToList();
}
}
private ReceiptBaseDTO CreateReceipt(string name, List<int> timerI3Ds, TimerBillingSettingsDTO settings)
{
using (var session = new BLSession())
{
var user = session.GetBL<AppUserBL>().GetAppUser(f => f.I3D == 11);
var invoiceResult = session.GetBL<ReceiptWebServiceBL>().CreateNewReceiptForHelpdekTimers(timerI3Ds, settings, user);
// Allow the caller to pass in a NULL name, to skip the .Verify call
if (name is not null)
this.Verifier.Verify(name, invoiceResult);
return invoiceResult.Data;
}
}
private void SaveInvoice(ReceiptBaseDTO invoice)
{
using (var session = new BLSession())
{
var user = session.GetBL<AppUserBL>().GetAppUser(f => f.I3D == 11);
var saveResult = session.GetBL<ReceiptWebServiceBL>().SaveReceipt(invoice, user, new SaveReceiptData
{
IgnoreCallbacks = true
}, false, CreatedThroughApplication.CentronNet, null);
this.Verifier.Verify($"SavedInvoice{invoice.Number}", saveResult);
}
}
private void ValidateBreakTimeFormat()
{
// Set break-time format
using (var session = new BLSession())
{
var updateSettings = session.GetBL<AppSettingsBL>().GetSettingsForUpdate(
ApplicationSettingID.HelpdeskTimerBreakTimeFormat);
updateSettings.UpdateString(ApplicationSettingID.HelpdeskTimerBreakTimeFormat, "davon @@Stunden@@ bzw. @@Minuten@@ bzw. @@StundenDezimal@@ Pause");
updateSettings.SaveSettings();
}
// Test the logic
using (var session = new BLSession())
{
var testTimer = new HelpdeskTimer
{
Start = new DateTime(2021, 1, 1, 15, 30, 0),
Stop = new DateTime(2021, 1, 1, 17, 45, 0),
LunchTime = (int)TimeSpan.FromMinutes(12).TotalSeconds
};
var text = session.GetBL<ReceiptItemTimerBL>().GetTimerTimeText(testTimer);
this.Verifier.Verify("TimerTimeTextWithBreak", text);
}
}
private void ValidateUseTicketTimeAsServicePeriod()
{
const int timerI3D = 10511;
var (start, stop) = this.GetHelpdeskTimerPeriod(timerI3D);
var receiptWithServicePeriod = this.CreateReceipt(null, new List<int> { timerI3D }, new TimerBillingSettingsDTO
{
ReceiptKind = CentronObjectKindNumeric.InvoiceClass,
UseTicketTimeAsServicePeriod = true,
});
var itemWithServicePeriod = receiptWithServicePeriod.GetReceiptItems().OfType<ReceiptInvoiceItemDTO>().First(f => f.ServicePeriodFrom != null);
Assert.Equal(start, itemWithServicePeriod.ServicePeriodFrom);
Assert.Equal(stop, itemWithServicePeriod.ServicePeriodTo);
var receiptPeriod = Assert.IsType<ReceiptInvoiceDTO>(receiptWithServicePeriod);
Assert.Equal(start, receiptPeriod.ServicePeriodFrom);
Assert.Equal(stop, receiptPeriod.ServicePeriodTo);
var receiptWithoutServicePeriod = this.CreateReceipt(null, new List<int> { timerI3D }, new TimerBillingSettingsDTO
{
ReceiptKind = CentronObjectKindNumeric.InvoiceClass,
UseTicketTimeAsServicePeriod = false,
});
foreach (var itemWithoutServicePeriod in receiptWithoutServicePeriod.GetReceiptItems().OfType<ReceiptInvoiceItemDTO>())
{
Assert.Null(itemWithoutServicePeriod.ServicePeriodFrom);
Assert.Null(itemWithoutServicePeriod.ServicePeriodTo);
}
var receiptWithoutPeriod = Assert.IsType<ReceiptInvoiceDTO>(receiptWithoutServicePeriod);
Assert.Null(receiptWithoutPeriod.ServicePeriodFrom);
Assert.Null(receiptWithoutPeriod.ServicePeriodTo);
}
private (DateTime Start, DateTime Stop) GetHelpdeskTimerPeriod(int timerI3D)
{
using var session = new BLSession();
var timer = session.GetBL<HelpdeskTimerBL>().GetHelpdeskTimerByI3D(timerI3D);
return (timer.Start, timer.Stop);
}
private void CreateReceiptWithTimerFromOrder(bool? takePriceFromOrder, bool globalTakePriceFromOrder)
{
var name = $"CreateReceiptWithTimerFromOrder_PriceFromOrder_{takePriceFromOrder?.ToString() ?? "NULL"}_GlobalPriceFromOrder_{globalTakePriceFromOrder}";
const int TimerI3DFromOrder = 10511;
const int OrderItemI3D = 7258;
var settings = new TimerBillingSettingsDTO
{
ReceiptKind = CentronObjectKindNumeric.InvoiceClass,
TakePriceFromOrder = globalTakePriceFromOrder,
OrderItemI3DForHelpdeskTimerI3Ds = new List<TimerBillingOrderItemI3DForHelpdeskTimerI3D>
{
new()
{
HelpdeskTimerI3D = TimerI3DFromOrder,
OrderItemI3D = OrderItemI3D,
TakePriceFromOrder = takePriceFromOrder
}
}
};
var invoice = this.CreateReceipt(name:null, new List<int> { TimerI3DFromOrder }, settings);
var item = invoice.GetReceiptItems().First(f => f.ArticleI3D == 12);
this.Verifier.Verify(name, item);
// Important here is mostly the IReceiptItemBase.BasePrice property
var expectedPriceFromOrder = takePriceFromOrder ?? globalTakePriceFromOrder;
var expectedPrice = expectedPriceFromOrder ? 400 : 0;
var price = item.BasePrice;
Assert.Equal(expectedPrice, price);
}
private void CreateInvoiceFromTicketWithMasterDataList()
{
// Add new timer to Helpdesk Ticket I3D 9447
int? timerI3D;
using (var session = new BLSession())
{
timerI3D = session.GetBL<HelpdeskTimerWebServiceBL>().SaveHelpdeskTimer(new HelpdeskTimerDTO
{
Start = new DateTime(2022, 2, 10, 12, 0, 0),
Stop = new DateTime(2022, 2, 10, 14, 30, 0),
Calculable = true,
HelpdeskI3D = 9447,
InternalNote = "Interne Notiz Blabla",
ExternalNote = "Externe Notiz Blabla",
IsPlanned = false,
ArticleI3D = 94,
State = 1,
}, this.GetLoggedInUser());
Assert.NotNull(timerI3D);
}
// Activate the setting to add Master-Data-List info when billing timers
this.Sql($"UPDATE dbo.Stammdat SET Wert = 1 WHERE I3D = {(int)AppSettingsConst.HelpdeskToCustomerAssetInsertMasterSheetData}");
// Act
var settings = new TimerBillingSettingsDTO
{
ReceiptKind = CentronObjectKindNumeric.InvoiceClass,
};
var receipt = this.CreateReceipt("InvoiceFromTicketWithMasterDataList", new List<int> {timerI3D.Value}, settings);
}
private void CreateReceiptWithTimerFormat(bool hasStartTimeFormat, bool hasEndTimeFormat)
{
var startTimeFormat = hasStartTimeFormat ? "g" : "";
this.Sql($"UPDATE dbo.Stammdat SET WertText = '{startTimeFormat}' WHERE I3D = {(int)AppSettingsConst.HelpdeskTimerStartTimeFormat}");
var endTimeFormat = hasEndTimeFormat ? "g" : "";
this.Sql($"UPDATE dbo.Stammdat SET WertText = '{endTimeFormat}' WHERE I3D = {(int)AppSettingsConst.HelpdeskTimerEndTimeFormat}");
using (var session = new BLSession())
{
var testTimer = new HelpdeskTimer
{
Start = new DateTime(2021, 1, 1, 15, 30, 0),
Stop = new DateTime(2021, 1, 1, 17, 45, 0),
LunchTime = (int)TimeSpan.FromMinutes(12).TotalSeconds
};
var text = session.GetBL<ReceiptItemTimerBL>().GetTimerTimeText(testTimer);
this.Verifier.Verify($"TimerTimeText_HasStartTime_{hasStartTimeFormat}_HasEndTime_{hasEndTimeFormat}", text);
}
}
}
}