using System;
using System.Collections.Generic;
using System.Linq;
using Centron.BusinessLogic;
using Centron.BusinessLogic.EmployeeArea;
using Centron.BusinessLogic.Mail.Factory;
using Centron.BusinessLogic.Sales.Support;
using Centron.BusinessLogic.WebServices.Administration.Settings.SettingGroups;
using Centron.BusinessLogic.WebServices.Sales.Support;
using Centron.BusinessLogic.WebServices.TaskManager;
using Centron.Data.Entities.Administration.Logins;
using Centron.Data.Entities.Sales.Support;
using Centron.Data.Entities.TaskManager;
using Centron.Data.WebServices.Administration.Employees;
using Centron.Data.WebServices.Sales.CustomerAssets.Contracts;
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
{
///
/// Reproduction for Ticket #167558 (Raphael Frasch GmbH) — "Taskmanagement geht bringt Fehler".
///
/// A helpdesk task whose action has
/// = true drives the second-save / ForwardHelpdesk path
/// (TaskManagementHelpdeskActionHandler.Execute -> HelpdeskWebServiceBL.ForwardHelpdesk ->
/// HelpdeskForwardBL.ForwardHelpdesk, which re-saves the just-created helpdesk).
///
/// Before the fix the customer saw:
/// "Batch update returned unexpected row count from update; actual row count: 0; expected: 1"
/// on UPDATE dbo.hlpdsk_requests ... WHERE ID = @p
/// and no ticket was created. Root cause: HelpdeskReportBL.GetReportForHelpdesk (reached via the
/// forward step) ran a throw-away transaction and rolled it back even when nested inside the task's
/// ambient transaction, dropping the just-created ticket.
///
/// The existing never sets SendMailToSelectedHelpdeskEmployees,
/// so it does not exercise this path. This test does, and asserts the task creates a ticket and
/// reports success. It is a regression guard for that fix.
///
public class TaskHelpdeskForwardActionTest : EndToEndTest
{
public const int CustomerI3D = 10022;
public const int ContractI3D = 35;
public const int ResponsibleEmployeeI3D = 22;
public const int UserI3D = 11;
public TaskHelpdeskForwardActionTest(ITestOutputHelper testOutputHelper) : base(testOutputHelper)
{
}
public override void Execute()
{
this.PrepareDatabase();
var taskI3D = this.CreateForwardingTask();
this.ExecuteAndAssertTicketCreated(taskI3D);
}
private void PrepareDatabase()
{
// The handler aborts/logs when the Task-Management sender address is empty, so set it.
using (var session = new BLSession())
{
var settings = session.GetBL().GetTaskManagementSettings();
settings.TaskManagementSenderAddress = "task-sender@example.com";
session.GetBL().UpdateTaskManagementSettings(settings);
}
// Make sure the employee we forward to has an e-mail address (used to build the internal mail).
this.Sql($"UPDATE dbo.Personal SET Email = 'editor@example.com' WHERE I3D = {ResponsibleEmployeeI3D} AND (Email IS NULL OR Email = '')");
}
private int CreateForwardingTask()
{
using (var session = new BLSession())
{
var user = session.GetBL().GetAppUser(f => f.I3D == UserI3D);
var task = new TaskManagementTaskDTO
{
Name = "Forwarding task (#167558 repro)",
Description = "Ticket should be created and forwarded to the selected employees.",
Status = ProjectStatus.Started,
Action = new TaskManagementHelpdeskActionDTO
{
Customer = new CustomerPreviewDTO { I3D = CustomerI3D },
Category = new HelpdeskCategoryDTO { I3D = 6 },
Contract = new ContractDTO { I3D = ContractI3D },
Priority = new HelpdeskPrioritiesDTO { I3D = 1 },
Type = new HelpdeskTypeDTO { I3D = 6 },
State = new HelpdeskStatusDTO { I3D = 1 },
ResponsiblePerson = new EmployeePreviewDTO { I3D = ResponsibleEmployeeI3D },
// This is the flag that triggers the ForwardHelpdesk second-save path.
SendMailToSelectedHelpdeskEmployees = true,
Members = new List
{
new TaskManagementActionMemberDTO
{
Employee = new EmployeePreviewDTO { I3D = ResponsibleEmployeeI3D }
}
}
},
Recurrence = new TaskManagementDailyRecurrenceDTO
{
AppointmentStart = new DateTime(2020, 2, 2, 13, 0, 0),
StartTime = new DateTime(2020, 2, 2, 13, 0, 0),
DayInterval = 14,
NumberOfRecurrence = 53
}
};
var saved = session.GetBL().SaveOrUpdateTask(task, user).ThrowIfError();
return saved.I3D;
}
}
private void ExecuteAndAssertTicketCreated(int taskI3D)
{
Result executeResult = null;
// Route the forward mail through the in-memory test transport so the test does not depend
// on a configured SMTP host.
TestMails.Start(() =>
{
using var session = new BLSession();
var user = session.GetBL().GetAppUser(f => f.I3D == UserI3D);
// Manual execution (single recurrence date), matching the Frasch case where even a
// manual run fails. Isolates a single create+forward cycle.
executeResult = session.GetBL().ExecuteTaskNow(taskI3D, user);
});
Assert.True(executeResult.Status == ResultStatus.Success,
$"ExecuteTask did not succeed (this reproduces #167558). Status={executeResult.Status}, Message={executeResult.Message}");
using (var session = new BLSession())
{
var user = session.GetBL().GetAppUser(f => f.I3D == UserI3D);
var tickets = session.GetBL().GetHelpdesksThroughPaging(
new HelpdeskFilter
{
CreatedByTasks = true,
CreatedFromObjectKind = CentronObjectKindNumeric.TaskManagementClass,
CreatedFromObjectI3D = taskI3D
},
HelpdeskSort.Number,
true,
1,
int.MaxValue,
new LoggedInUser(user)).ThrowIfError();
Assert.True(tickets.Result.Any(),
"No ticket was created for the forwarding task (this reproduces #167558: task runs but no ticket exists).");
}
}
}
}