В продолжении статьи «Модификация «Голосование» для задачи согласования по регламенту»
Создать новый отчет по голосованию по протоколу совещания. Строки отчета должны быть сгруппированы по решению из протокола. В каждой группе выводится ФИО голосующего, дата и результат голосования. В подвале группы – итоговый результат по решению.
Требуемые модификации:
Постфикс и код компании: centrvd
Имя решение: Solution
Имя модуля: SolutionDatabook
Создадим отчет MinutesVotingReport . Добавим структуру, которую позже будем передавать в SQL таблицу:
/// <summary>
/// Строчка отчета.
/// </summary>
partial class TableLine
{
public string ReportSessionId { get; set; }
public string Decision { get; set; }
public string VoterName { get; set; }
public string VoteDate { get; set; }
public string VoterResult { get; set; }
public string OverallResult { get; set; }
}
Добавим константы отчета:
public static class MinutesVotingReport
{
public const string SourceTableName = "centrvd_Solution1_Reports_MinutesVoting";
}
Создадим 2 SQL запроса на создание и получение данные из таблицы:
CreateMinutesVotingReportSourceTable |
|
MSSQL |
POSTGRESQL |
create table {0} |
create table {0} |
SelectDataFromTable |
select * |
Добавим 3 параметра для передачи в отчет идентификатора сессии данных, протокола совещания и времени формирования отчета:
Имя |
Тип |
ReportSessionId |
String |
Minutes |
centrvd.Solution.IMinutes |
CurrentDate |
DateTime |
В дизайнере добавим источник данных на основе SQL-запроса:
Имя запроса: SourceTable
SQL зарос: SelectDataFromTable
Параметр запроса: ReportSessionId (тип string) (Expression = [ReportSessionId])
Поля запроса:
Имя |
Тип |
Decision |
String |
VoterName |
String |
VoteDate |
String |
VoterResult |
String |
OverallResult |
String |
Создадим ресурсы, которые позже будут использоваться в настройках бендов:
Имя |
Английская локализация |
Русская локализация |
DesignerDate |
Date: |
Дата: |
DesignerDecision |
Decision: |
Решение: |
DesignerDecisionsForVoting |
Decisions for voting: |
Решений для голосования: |
DesignerDocumentStatus |
Document status: |
Статус документа: |
DesignerResults |
Results: |
Результаты: |
DesignerVote |
Vote |
Голос |
DesignerVoteDate |
Vote date |
Дата голосования |
DesignerVoter |
Voter |
Голосующий |
DesignerVotingOnTheDocument |
Voting on the document: |
Голосование по документу: |
DidNotVote |
Did not vote |
Не проголосовал |
ThereWasNoVote |
There was no vote |
Голосование не проводилось |
VotingIsNotCompleted |
Voting is not completed. |
Голосование не завершено. |
Настроим дизайнер, как показано на скриншоте.
Группировка по полю [SourceTable.Decision]
Перейдем к серверному событию «До выполнения». В статье по модификации «Голосование» для задачи согласования по регламенту результаты голосования попадают в карточку протокола через асинхронный обработчик. Чтобы отчет отображал самую актуальную информацию, необходимо результаты получать из всех заданий на голосование. В том числе, если сотрудник еще не проголосовал. На случай перезапуска задач будем брать последние созданные задания:
public override void BeforeExecute(Sungero.Reporting.Server.BeforeExecuteEventArgs e)
{
MinutesVotingReport.ReportSessionId = Guid.NewGuid().ToString();
MinutesVotingReport.CurrentDate = Calendar.UserToday;
var dataTable = new List<Structures.MinutesVotingReport.TableLine>();
// Проход по всем решениям протокола.
foreach (var decision in MinutesVotingReport.Minutes.Decisionscentrvd.OrderBy(d => d.Number))
{
List<Sungero.Company.IEmployee> employees = decision.Matrix.Approvers.Select(a => a.Approver).ToList();
var voteIsOn = string.Empty;
// Рассчитать итоги по решению.
var decisionOverallResult = centrvd.Solution.PublicFunctions.Minutes.GetVotingResults(MinutesVotingReport.Minutes, decision);
var tableLine = Structures.MinutesVotingReport.TableLine.Create();
// Проход по всем голосующим из матрицы.
foreach (var employee in employees)
{
//Находим последнее созданное задание на голосование по протоколу c решением по текущему сотруднику.
var votingAssignment = centrvd.Solution.ApprovalSimpleAssignments.GetAll()
.Where(m => m.Task.AttachmentDetails.Any(d => d.EntityId.Value == MinutesVotingReport.Minutes.Id))
.Where(p => Equals(p.Performer, Users.As(employee)))
.Where(a => a.Voitingcentrvd.Any(d => d.MinutedDecisionId == decision.Id))
.OrderByDescending(a => a.Created)
.FirstOrDefault();
if (votingAssignment == null)
{
tableLine.Decision = decision.Decision;
tableLine.ReportSessionId = MinutesVotingReport.ReportSessionId;
tableLine.VoteDate = string.Empty;
tableLine.VoterName = employee.Name;
tableLine.VoterResult = string.Empty;
tableLine.OverallResult = centrvd.SolutionDataBook.Reports.Resources.MinutesVotingReport.ThereWasNoVote;
dataTable.Add(tableLine);
}
else
{
//Находим результат голосования по решению.
var decisionVote = votingAssignment.Voitingcentrvd.Where(r => r.MinutedDecisionId == decision.Id).FirstOrDefault();
var decisionVoteResult = string.Empty;
if (votingAssignment.Completed.HasValue && decisionVote.VoteFor.GetValueOrDefault())
decisionVoteResult = MinutesVotingReport.Minutes.Info.Properties.Decisionscentrvd.Properties.VoteFor.LocalizedName;
if (votingAssignment.Completed.HasValue && decisionVote.VoteAgainst.GetValueOrDefault())
decisionVoteResult = MinutesVotingReport.Minutes.Info.Properties.Decisionscentrvd.Properties.VoteAgainst.LocalizedName;
if (votingAssignment.Completed.HasValue && decisionVote.VoteAbstain.GetValueOrDefault())
decisionVoteResult = MinutesVotingReport.Minutes.Info.Properties.Decisionscentrvd.Properties.VoteAbstain.LocalizedName;
// Если есть незавершенные задания - то в итоговый результат добавляется текст.
if (!votingAssignment.Completed.HasValue)
voteIsOn = centrvd.SolutionDataBook.Reports.Resources.MinutesVotingReport.VotingIsNotCompleted;
tableLine.Decision = decision.Decision;
tableLine.ReportSessionId = MinutesVotingReport.ReportSessionId;
tableLine.VoteDate = votingAssignment.Completed.HasValue ? votingAssignment.Completed.Value.ToShortDateString() : centrvd.SolutionDataBook.Reports.Resources.MinutesVotingReport.DidNotVote;
tableLine.VoterName = employee.Name;
tableLine.VoterResult = !string.IsNullOrEmpty(decisionVoteResult) ? decisionVoteResult : centrvd.SolutionBook.Reports.Resources.MinutesVotingReport.DidNotVote;
tableLine.OverallResult = voteIsOn + decisionOverallResult;
dataTable.Add(tableLine);
}
}
}
Sungero.Docflow.PublicFunctions.Module.WriteStructuresToTable(Constants.MinutesVotingReport.SourceTableName, dataTable);
}
В серверные функции перекрытого протокола (Minutes) добавим функцию GetVotingResults() для вычисления итогов по решению (возможно вычислять итоги по решению и До выполнения отчета, но тогда нужно будет внимательно относиться к выбору данных из таблицы). Эти итоги будут отображаться в подвале группы:
/// <summary>
/// Получить результаты голосования по решению протокола совещания.
/// </summary>
/// <param name="decision">Строка коллекции решений.</param>
/// <returns>Результаты в форме строки: За - х, Против - х, Воздержался - х.</returns>
[Public]
public string GetVotingResults(IMinutesDecisionscentrvd decision)
{
if (!centrvd.Solution.DocumentKinds.As(_obj.DocumentKind).NeedVoitingcentrvd.GetValueOrDefault() || !_obj.Decisionscentrvd.Any())
return string.Empty;
int voteFor = 0;
int voteAgainst = 0;
int voteAbstain = 0;
List<Sungero.Company.IEmployee> employees = decision.Matrix.Approvers.Select(a => a.Approver).ToList();
foreach (var employee in employees)
{
var votingAssignment = centrvd.Solution.ApprovalSimpleAssignments.GetAll()
.Where(m => m.Task.AttachmentDetails.Any(d => d.EntityId.Value == _obj.Id))
.Where(p => Equals(p.Performer, Users.As(employee)))
.Where(a => a.Voitingcentrvd.Any(d => d.MinutedDecisionId == decision.Id))
.OrderByDescending(a => a.Created)
.FirstOrDefault();
if (votingAssignment != null && votingAssignment.Status == centrvd.Solution.ApprovalSimpleAssignment.Status.Completed)
{
var assignmentDecision = votingAssignment.Voitingcentrvd.Where(v => v.MinutedDecisionId == decision.Id).FirstOrDefault();
if (assignmentDecision.VoteFor.GetValueOrDefault())
voteFor++;
if (assignmentDecision.VoteAgainst.GetValueOrDefault())
voteAgainst++;
if (assignmentDecision.VoteAbstain.GetValueOrDefault())
voteAbstain++;
}
}
return centrvd.SolutionDataBook.Resources.ResultsFormat(voteFor, voteAgainst, voteAbstain);
}
Перейдем к серверному событию «После выполнения» и удалим данные из таблицы:
public override void AfterExecute(Sungero.Reporting.Server.AfterExecuteEventArgs e)
{
Sungero.Docflow.PublicFunctions.Module.DeleteReportData(centrvd.SolutionDataBook.Constants.MinutesVotingReport.SourceTableName, MinutesVotingReport.ReportSessionId);
}
Добавим удаление и создание SQL таблицы centrvd_Solution1_Reports_MinutesVoting в инициализацию модуля. А также выдачу прав всем пользователям на выполнение отчета:
public override void Initializing(Sungero.Domain.ModuleInitializingEventArgs e)
{
//Отчеты
CreateReportsTables();
GrantingRightsToReports();
}
/// [summary](summary)
/// Создать таблицы для отчетов.
/// </summary>
public static void CreateReportsTables()
{
var minutesVotingTableName = Constants.MinutesVotingReport.SourceTableName;
Sungero.Docflow.PublicFunctions.Module.DropReportTempTables(new[] {minutesVotingTableName});
Sungero.Docflow.PublicFunctions.Module.ExecuteSQLCommandFormat(Queries.MinutesVotingReport.CreateMinutesVotingReportSourceTable, new[] {minutesVotingTableName});
}
/// [summary](summary)
/// Выдача прав на выполнение отчетов
/// </summary>
public static void GrantingRightsToReports()
{
InitializationLogger.Debug("Init: Выдача всем пользователям прав на выполнение отчета Итоги голосования по протоколу совещания.");
Reports.AccessRights.Grant(Reports.GetMinutesVotingReport().Info, Roles.AllUsers, DefaultReportAccessRightsTypes.Execute);
}
Добавим действие на ленту протокола совещания. Кнопка должна отображаться только для протоколов с видом, требующим голосование. Формат имени формируемого файла: «Итоги голосования по {Имя_протокола}»:
partial class MinutesActions
{
public virtual void VotingReportcentrvd(Sungero.Domain.Client.ExecuteActionArgs e)
{
var votingReport = centrvd.SolutionDataBook.Reports.GetMinutesVotingReport();
votingReport.Minutes = _obj;
votingReport.ExportToFile(centrvd.Solution.Minuteses.Resources.VotingReportFileNameFormat(_obj.Name));
}
public virtual bool CanVotingReportcentrvd(Sungero.Domain.Client.CanExecuteActionArgs e)
{
return !_obj.State.IsInserted && centrvd.Solution.DocumentKinds.As(_obj.DocumentKind).NeedVoitingcentrvd.GetValueOrDefault();
}
}
Авторизуйтесь, чтобы написать комментарий