Files
Christoph Schwörer f045b99a25 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
2026-08-26 07:43:51 +02:00

218 lines
9.5 KiB
C#

using System;
using Centron.BusinessLogic;
using Centron.BusinessLogic.EmployeeArea;
using Centron.BusinessLogic.WebServices.TaskManager;
using Centron.Data.Entities.TaskManager;
using Centron.Data.WebServices.Administration.Employees;
using Centron.Data.WebServices.Sales.Customers;
using Centron.Data.WebServices.Sales.Support;
using Centron.Data.WebServices.TaskManager;
using Centron.Data.WebServices.TaskManager.Actions;
using Centron.Data.WebServices.TaskManager.Recurrence;
using Centron.Interfaces;
using Centron.Interfaces.BL;
using Centron.Tests.EndToEnd.Infrastructure;
using Xunit;
using Xunit.Abstractions;
namespace Centron.Tests.EndToEnd.Tests.TaskHelpdeskAction
{
/// <summary>
/// Ticket 168833: duplicating a task template onto another customer used to carry the source customer's
/// contact person over, so every generated ticket got a foreign contact. Covers both branches of the
/// customer check in TaskManagementHelpdeskActionHandler.
/// </summary>
public class TaskHelpdeskActionContactPersonTest : EndToEndTest
{
private const int CustomerI3D = 10022;
private const int UserI3D = 11;
public TaskHelpdeskActionContactPersonTest(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
{
}
public override void Execute()
{
this.ContactOfTheOwnCustomerIsUsedForTheTicket();
this.ContactOfAnotherCustomerIsNotUsedForTheTicket();
}
private void ContactOfTheOwnCustomerIsUsedForTheTicket()
{
// Needs a customer with two contacts, so the configured contact differs from the default contact -
// otherwise the assertion could not tell the configured contact and the fallback apart.
var customerI3D = this.GetCustomerWithTwoContactsOnDefaultAddress();
var defaultTicketContactI3D = this.MakeSingleDefaultTicketContact(customerI3D);
var ownContactI3D = this.GetActiveContactOfCustomer(customerI3D, exceptContactI3D: defaultTicketContactI3D);
var taskI3D = this.CreateStartedTask("Task mit eigenem Ansprechpartner", customerI3D, ownContactI3D);
this.ExecuteTask(taskI3D);
this.AssertEveryTicketOfTaskUsesContact(taskI3D, ownContactI3D);
}
private void ContactOfAnotherCustomerIsNotUsedForTheTicket()
{
var defaultTicketContactI3D = this.MakeSingleDefaultTicketContact(CustomerI3D);
var foreignContactI3D = this.GetActiveContactOfAnotherCustomer(CustomerI3D);
var taskI3D = this.CreateStartedTask("Task mit fremdem Ansprechpartner", CustomerI3D, foreignContactI3D);
// The task itself must keep what was stored - the handler corrects the ticket, not the task data.
var storedContactI3D = this.Sql<int>(
$"SELECT ISNULL(ContactI3D, 0) FROM TaskManagementAction WHERE I3D = (SELECT TaskManagementActionI3D FROM TaskManagementTask WHERE I3D = {taskI3D})");
Assert.True(storedContactI3D == foreignContactI3D,
$"Expected the task to keep the stored contact {foreignContactI3D}, but it was changed to {storedContactI3D}.");
this.ExecuteTask(taskI3D);
this.AssertEveryTicketOfTaskUsesContact(taskI3D, defaultTicketContactI3D);
}
/// <summary>
/// Asserts that the task created at least one ticket and that every single one of them uses the expected
/// contact - checking only one ticket would miss a second one that kept the foreign contact.
/// </summary>
private void AssertEveryTicketOfTaskUsesContact(int taskI3D, int expectedContactI3D)
{
var ticketFilter = $@"
FROM hlpdsk_requests
WHERE CreatedFromObjectI3D = {taskI3D}
AND CreatedFromObjectKind = {(int)CentronObjectKindNumeric.TaskManagementClass}";
var ticketCount = this.Sql<int>($"SELECT COUNT(*) {ticketFilter}");
Assert.True(ticketCount > 0, $"No ticket was created for task {taskI3D}.");
var wrongContactCount = this.Sql<int>(
$"SELECT COUNT(*) {ticketFilter} AND ISNULL(AnsprechpartnerI3D, 0) <> {expectedContactI3D}");
Assert.True(wrongContactCount == 0,
$"{wrongContactCount} of {ticketCount} tickets of task {taskI3D} do not use the expected contact {expectedContactI3D}.");
}
/// <summary>
/// Marks one active contact of the customer's default address as the only ticket default contact and
/// returns it. This is the contact HelpdeskBL falls back to when a task carries no usable contact.
/// </summary>
private int MakeSingleDefaultTicketContact(int customerI3D)
{
var contactI3D = this.Sql<int>($@"
SELECT ISNULL(MIN(p.I3D), 0)
FROM Personen p
INNER JOIN Anschrif a ON a.I3D = p.AnschriftID
WHERE p.Status = 1 AND a.Status = 1 AND a.Kunde = {customerI3D} AND a.KundeDefault = 1");
Assert.True(contactI3D > 0,
$"The test database has no active contact on the default address of customer {customerI3D}.");
this.Sql($@"
UPDATE c SET c.DefaultTicket = 0
FROM AccountAddressContacts c
INNER JOIN Personen p ON p.I3D = c.OldReferenceI3D
INNER JOIN Anschrif a ON a.I3D = p.AnschriftID
WHERE a.Kunde = {customerI3D}");
this.Sql($"UPDATE AccountAddressContacts SET DefaultTicket = 1 WHERE OldReferenceI3D = {contactI3D}");
return contactI3D;
}
private int GetCustomerWithTwoContactsOnDefaultAddress()
{
var customerI3D = this.Sql<int>(@"
SELECT ISNULL(MIN(candidates.Kunde), 0)
FROM (
SELECT a.Kunde
FROM Personen p
INNER JOIN Anschrif a ON a.I3D = p.AnschriftID
WHERE p.Status = 1 AND a.Status = 1 AND a.Kunde IS NOT NULL AND a.KundeDefault = 1
GROUP BY a.Kunde
HAVING COUNT(*) >= 2
) candidates");
Assert.True(customerI3D > 0,
"The test database has no customer with two active contacts on its default address.");
return customerI3D;
}
private int CreateStartedTask(string name, int customerI3D, int contactPersonI3D)
{
using (var session = new BLSession())
{
var user = session.GetBL<AppUserBL>().GetAppUser(f => f.I3D == UserI3D);
var task = new TaskManagementTaskDTO
{
Name = name,
Description = name,
Status = ProjectStatus.Started,
Action = new TaskManagementHelpdeskActionDTO
{
Customer = new CustomerPreviewDTO { I3D = customerI3D },
ContactPersonOldReferenceI3D = contactPersonI3D,
Category = new HelpdeskCategoryDTO { I3D = 6 },
Priority = new HelpdeskPrioritiesDTO { I3D = 1 },
Type = new HelpdeskTypeDTO { I3D = 6 },
State = new HelpdeskStatusDTO { I3D = 1 },
ResponsiblePerson = new EmployeePreviewDTO { I3D = 22 }
},
Recurrence = new TaskManagementDailyRecurrenceDTO
{
AppointmentStart = new DateTime(2020, 2, 2, 13, 0, 0),
StartTime = new DateTime(2020, 2, 2, 13, 0, 0),
DayInterval = 14,
NumberOfRecurrence = 1
}
};
var savedTask = session.GetBL<TaskManagementTaskWebServiceBL>().SaveOrUpdateTask(task, user);
Assert.True(savedTask.Status == ResultStatus.Success, savedTask.Message);
return savedTask.Data.I3D;
}
}
private void ExecuteTask(int taskI3D)
{
using (var session = new BLSession())
{
var user = session.GetBL<AppUserBL>().GetAppUser(f => f.I3D == UserI3D);
var result = session.GetBL<TaskManagementTaskWebServiceBL>().ExecuteTask(taskI3D, user);
Assert.True(result.Status != ResultStatus.Error, result.Message);
}
}
private int GetActiveContactOfCustomer(int customerI3D, int exceptContactI3D)
{
var contactI3D = this.Sql<int>($@"
SELECT ISNULL(MIN(p.I3D), 0)
FROM Personen p
INNER JOIN Anschrif a ON a.I3D = p.AnschriftID
WHERE p.Status = 1 AND a.Status = 1 AND a.Kunde = {customerI3D} AND p.I3D <> {exceptContactI3D}");
Assert.True(contactI3D > 0,
$"The test database has no second active contact for customer {customerI3D}.");
return contactI3D;
}
private int GetActiveContactOfAnotherCustomer(int customerI3D)
{
var contactI3D = this.Sql<int>($@"
SELECT ISNULL(MIN(p.I3D), 0)
FROM Personen p
INNER JOIN Anschrif a ON a.I3D = p.AnschriftID
WHERE p.Status = 1 AND a.Status = 1 AND a.Kunde IS NOT NULL AND a.Kunde <> {customerI3D}");
Assert.True(contactI3D > 0, "The test database has no active contact of another customer.");
return contactI3D;
}
}
}