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
218 lines
9.5 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|