Commit c287f307 authored by Oliver Eglseder's avatar Oliver Eglseder
Browse files

[TASK] Add election end date limitations and summary

parent 3e25b2be
......@@ -28,6 +28,7 @@ class BeElectionController extends AbstractProtectedBeController
const ACTION_EDIT = 'edit';
const ACTION_UPDATE = 'update';
const ACTION_DELETE = 'delete';
const ACTION_SUMMARY = 'summary';
/**
* @var \TYPO3\Election\Domain\Repository\ElectionRepository
......@@ -118,6 +119,14 @@ class BeElectionController extends AbstractProtectedBeController
$this->redirect(self::ACTION_LIST);
}
/**
* @param Election $election
*/
public function summaryAction(Election $election)
{
$this->view->assign('election', $election);
}
/**
* @return string
*/
......@@ -132,6 +141,7 @@ class BeElectionController extends AbstractProtectedBeController
self::ACTION_UPDATE,
self::ACTION_EDIT,
self::ACTION_DELETE,
self::ACTION_SUMMARY,
]
);
}
......
......@@ -81,6 +81,15 @@ class FeElectionController extends ActionController
AbstractMessage::ERROR
);
$this->redirect(FeDashboardController::ACTION_INDEX, FeDashboardController::CONTROLLER_NAME);
} elseif ($electionInvitation->getElectionCircular()->getElection()->getEndDate()->getTimestamp()
< time()
) {
$this->addFlashMessage(
LocalizationUtility::translate('controller.fe.election.vote.election_finished', 'election'),
LocalizationUtility::translate('controller.fe.election.vote.request_failed', 'election'),
AbstractMessage::ERROR
);
$this->redirect(FeDashboardController::ACTION_INDEX, FeDashboardController::CONTROLLER_NAME);
} else {
$this->view->assign('electionInvitation', $electionInvitation);
$this->view->assign('electionVoting', new ElectionVoting());
......
......@@ -186,4 +186,111 @@ class Election extends AbstractEntity
{
$this->electionVotes = $electionVotes;
}
/**
* @return bool
*/
public function isElectionFinished()
{
if ($this->getEndDate()->getTimestamp() < time()) {
return true;
} else {
$anyoneVoted = true;
/** @var Elector $elector */
foreach ($this->electorate->getElectors() as $elector) {
$electionInvitation = $elector->getElectionInvitationForElection($this);
if (false !== $electionInvitation) {
if (!$electionInvitation->isVoted()) {
$anyoneVoted = false;
break;
}
}
}
}
return $anyoneVoted;
}
/**
* @return array
*/
public function getVotingElectors()
{
$votingElectors = [];
/** @var Elector $elector */
foreach ($this->electorate->getElectors() as $elector) {
$electionInvitation = $elector->getElectionInvitationForElection($this);
if (false !== $electionInvitation) {
if ($electionInvitation->isVoted()) {
$votingElectors[] = $elector;
}
}
}
return $votingElectors;
}
/**
* @return array
*/
public function getAbstinentElectors()
{
$votingElectors = [];
/** @var Elector $elector */
foreach ($this->electorate->getElectors() as $elector) {
$electionInvitation = $elector->getElectionInvitationForElection($this);
if (false !== $electionInvitation) {
if (!$electionInvitation->isVoted()) {
$votingElectors[] = $elector;
}
}
}
return $votingElectors;
}
/**
* @return array
*/
public function getUninvitedElectors()
{
$uninvitedElectors = [];
/** @var Elector $elector */
foreach ($this->electorate->getElectors() as $elector) {
$electionInvitation = $elector->getElectionInvitationForElection($this);
if (false === $electionInvitation) {
$uninvitedElectors[] = $elector;
}
}
return $uninvitedElectors;
}
/**
* @return array
*/
public function getElectedNomineesAndVotes()
{
$nominees = [];
/** @var ElectionVote $electionVote */
foreach ($this->electionVotes as $electionVote) {
$nominee = $electionVote->getNominee();
$uid = $nominee->getUid();
if (isset($nominees[$uid])) {
$nominees[$uid]['votes']++;
} else {
$nominees[$uid]['votes'] = 1;
$nominees[$uid]['nominee'] = $nominee;
}
}
uasort(
$nominees,
function ($a, $b) {
if ($a['votes'] > $b['votes']) {
return -1;
}
if ($a['votes'] < $b['votes']) {
return 1;
}
return 0;
}
);
return $nominees;
}
}
......@@ -95,4 +95,18 @@ class Elector extends AbstractPerson
}
return false;
}
/**
* @param Election $election
* @return bool|ElectionInvitation
*/
public function getElectionInvitationForElection(Election $election)
{
foreach ($this->getElectionInvitations() as $electionInvitation) {
if ($electionInvitation->getElectionCircular()->getElection() === $election) {
return $electionInvitation;
}
}
return false;
}
}
......@@ -240,6 +240,33 @@
<trans-unit id="view.be.election.list.voting_started">
<source>Can not alter or delete; Voting has started</source>
</trans-unit>
<trans-unit id="view.be.election.summary.preview_result">
<source>The election is still running, this is only a preview</source>
</trans-unit>
<trans-unit id="view.be.election.summary.final_result">
<source>The election finished, these are the final results</source>
</trans-unit>
<trans-unit id="view.be.election.summary.welcome">
<source>Election results</source>
</trans-unit>
<trans-unit id="view.be.election.election_finished">
<source>finished</source>
</trans-unit>
<trans-unit id="view.be.election.election_running">
<source>running</source>
</trans-unit>
<trans-unit id="view.be.election.summary.property">
<source>property / information</source>
</trans-unit>
<trans-unit id="view.be.election.summary.value">
<source>value / amount</source>
</trans-unit>
<trans-unit id="model.election.summary.abstinent_electors">
<source># of electors that did not vote</source>
</trans-unit>
<trans-unit id="model.election.summary.voting_electors">
<source># of electors that voted</source>
</trans-unit>
<!-- BE ELECTOR -->
......@@ -408,6 +435,9 @@
<trans-unit id="controller.fe.election.vote.success">
<source>Success</source>
</trans-unit>
<trans-unit id="controller.fe.election.vote.election_finished">
<source>The election has been finished already</source>
</trans-unit>
<!-- FE ELECTION -->
......
......@@ -9,6 +9,12 @@
<th>
<f:translate key="model.election.field.nominees_number"># Nominees</f:translate>
</th>
<th>
<f:translate key="model.election.field.end_date">end date</f:translate>
</th>
<th>
<f:translate key="model.election.status">status</f:translate>
</th>
<th>
<f:translate key="view.be.anything.options">Options</f:translate>
</th>
......@@ -25,6 +31,19 @@
<td>
{election.nominees -> f:count()}
</td>
<td>
<f:format.date date="{election.endDate}" format="Y-m-d H:i:s">{election.endDate.timestamp}</f:format.date>
</td>
<td>
<f:if condition="{election.electionFinished}">
<f:then>
<f:translate key="view.be.election.election_finished">finished</f:translate>
</f:then>
<f:else>
<f:translate key="view.be.election.election_running">running</f:translate>
</f:else>
</f:if>
</td>
<td>
<div class="btn-group">
<f:if condition="{election.electionVotes}">
......@@ -37,7 +56,7 @@
</span>
<f:link.action class="btn btn-default" action="summary" controller="BeElection"
arguments="{election:election}">
<core:icon identifier="actions-edit-rename"/>
<core:icon identifier="actions-document-info"/>
</f:link.action>
</f:then>
<f:else>
......
<f:if condition="{election.electionFinished}">
<f:then>
<h2><f:translate key="view.be.election.summary.final_result">this is the final result</f:translate></h2>
</f:then>
<f:else>
<h2><f:translate key="view.be.election.summary.preview_result">the election is still running, this is just a preview</f:translate></h2>
</f:else>
</f:if>
<table class="table">
<tr>
<th>
<f:translate key="view.be.election.summary.property">property</f:translate>
</th>
<th>
<f:translate key="view.be.election.summary.value">value</f:translate>
</th>
</tr>
<tr>
<td>
<f:translate key="model.election.field.number_of_votes"># of votes</f:translate>
</td>
<td>
{election.numberOfVotes}
</td>
</tr>
<tr>
<td>
<f:translate key="model.election.summary.voting_electors"># of electors that voted</f:translate>
</td>
<td>
{election.votingElectors -> f:count()}
</td>
</tr>
<tr>
<td>
<f:translate key="model.election.summary.abstinent_electors"># of electors that did not vote</f:translate>
</td>
<td>
{election.abstinentElectors -> f:count()}
</td>
</tr>
<tr>
<td>
<f:translate key="model.election.summary.uninvited_electors"># of electors that did not receive an invitation</f:translate>
</td>
<td>
{election.uninvitedElectors -> f:count()}
</td>
</tr>
</table>
<table class="table">
<tr>
<th>
<f:translate key="view.be.election.summary.nominee">nominee</f:translate>
</th>
<th>
<f:translate key="view.be.election.summary.votes">votes</f:translate>
</th>
</tr>
<f:for each="{election.electedNomineesAndVotes}" as="electionVote" iteration="i">
<f:if condition="{i.index} < {election.numberOfVotes}">
<f:then>
<tr style="background-color: green">
</f:then>
<f:else>
<tr>
</f:else>
</f:if>
<td>
{electionVote.nominee.fullName}
</td>
<td>
{electionVote.votes}
</td>
</tr>
</f:for>
</table>
<f:layout name="Backend"/>
<f:section name="LeftToolBar">
</f:section>
<f:section name="RightToolBar">
<f:render partial="View/Menu/GlobalOptions" arguments="{configuration:configuration}"/>
</f:section>
<f:section name="Welcome">
<h1>
<f:translate key="view.be.election.summary.welcome">
Election results
</f:translate>
</h1>
</f:section>
<f:section name="Main">
<f:render partial="Model/Election/Summary" arguments="{election:election}"/>
</f:section>
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment