diff --git a/results-tabulation-api/ext/ExtendedElection/__init__.py b/results-tabulation-api/ext/ExtendedElection/__init__.py
index 302e171b..033979a9 100644
--- a/results-tabulation-api/ext/ExtendedElection/__init__.py
+++ b/results-tabulation-api/ext/ExtendedElection/__init__.py
@@ -60,12 +60,122 @@ def get_area_map_for_tally_sheet(self, tally_sheet):
return self.get_area_map(area=area)
- def get_area_map(self):
+ def get_area_map(self, area=None, group_by=None, filter_by=None):
+ from orm.enums import AreaTypeEnum
+
area_map_subquery = self.get_area_map_query().subquery()
- return db.session.query(area_map_subquery).filter(
- area_map_subquery.c.electionId.in_(self.election.get_this_and_below_election_ids())
- )
+ if area is None:
+ return db.session.query(area_map_subquery).filter(
+ area_map_subquery.c.electionId.in_(self.election.get_this_and_below_election_ids())
+ )
+
+ column_name_list = [
+ "pollingStationId", "pollingStationName",
+ "pollingDistrictId", "pollingDistrictName",
+ "countingCentreId", "countingCentreName",
+ "pollingDivisionId", "pollingDivisionName",
+ "electoralDistrictId", "electoralDistrictName",
+ "countryId", "countryName"
+ ]
+ column_name_to_column_map = {
+ "pollingStationId": area_map_subquery.c.pollingStationId,
+ "pollingStationName": area_map_subquery.c.pollingStationName,
+ "pollingDistrictId": area_map_subquery.c.pollingDistrictId,
+ "pollingDistrictName": area_map_subquery.c.pollingDistrictName,
+ "countingCentreId": area_map_subquery.c.countingCentreId,
+ "countingCentreName": area_map_subquery.c.countingCentreName,
+ "pollingDivisionId": area_map_subquery.c.pollingDivisionId,
+ "pollingDivisionName": area_map_subquery.c.pollingDivisionName,
+ "electoralDistrictId": area_map_subquery.c.electoralDistrictId,
+ "electoralDistrictName": area_map_subquery.c.electoralDistrictName,
+ "countryId": area_map_subquery.c.countryId,
+ "countryName": area_map_subquery.c.countryName
+ }
+ query_args = []
+ query_filter = []
+ query_group_by = []
+ area_and_vote_type_wise_group_by_map = {
+ AreaTypeEnum.CountingCentre: [
+ "countingCentreId",
+ "countingCentreName",
+ "pollingDivisionId",
+ "pollingDivisionName",
+ "electoralDistrictId",
+ "electoralDistrictName",
+ "countryId",
+ "countryName"
+ ],
+ AreaTypeEnum.PollingStation: [
+ "pollingDistrictId",
+ "pollingDistrictName",
+ "pollingStationId",
+ "pollingStationName",
+ "countingCentreId",
+ "countingCentreName",
+ "pollingDivisionId",
+ "pollingDivisionName",
+ "electoralDistrictId",
+ "electoralDistrictName",
+ "countryId",
+ "countryName"
+ ],
+ AreaTypeEnum.PollingDivision: [
+ "pollingDivisionId",
+ "pollingDivisionName",
+ "electoralDistrictId",
+ "electoralDistrictName",
+ "countryId",
+ "countryName"
+ ],
+ AreaTypeEnum.ElectoralDistrict: [
+ "electoralDistrictId",
+ "electoralDistrictName",
+ "countryId",
+ "countryName"
+ ],
+ AreaTypeEnum.Country: [
+ "countryId",
+ "countryName"
+ ]
+ }
+
+ area_and_vote_type_wise_filter_map = {
+ AreaTypeEnum.PollingStation: [area_map_subquery.c.pollingStationId == area.areaId],
+ AreaTypeEnum.PollingDistrict: [area_map_subquery.c.pollingDistrictId == area.areaId],
+ AreaTypeEnum.CountingCentre: [area_map_subquery.c.countingCentreId == area.areaId],
+ AreaTypeEnum.PollingDivision: [area_map_subquery.c.pollingDivisionId == area.areaId],
+ AreaTypeEnum.ElectoralDistrict: [area_map_subquery.c.electoralDistrictId == area.areaId],
+ AreaTypeEnum.Country: [area_map_subquery.c.countryId == area.areaId]
+ }
+
+ if group_by is None:
+ if area.areaType in area_and_vote_type_wise_group_by_map:
+ group_by = area_and_vote_type_wise_group_by_map[area.areaType]
+ else:
+ group_by = []
+
+ for column_name in column_name_list:
+ column = column_name_to_column_map[column_name]
+ if column_name in group_by:
+ query_group_by.append(column)
+
+ # Append the column to query.
+ query_args.append(column)
+ else:
+ query_args.append(bindparam(column_name, None))
+
+ if filter_by is None:
+ if area.areaType in area_and_vote_type_wise_filter_map:
+ filter_by = area_and_vote_type_wise_filter_map[area.areaType]
+ else:
+ filter_by = []
+
+ query_filter = filter_by
+
+ area_map = db.session.query(*query_args).filter(*query_filter).group_by(*query_group_by).all()
+
+ return area_map
def get_area_map_query(self):
diff --git a/results-tabulation-api/orm/entities/Submission/TallySheet/__init__.py b/results-tabulation-api/orm/entities/Submission/TallySheet/__init__.py
index 6508b145..82faf346 100644
--- a/results-tabulation-api/orm/entities/Submission/TallySheet/__init__.py
+++ b/results-tabulation-api/orm/entities/Submission/TallySheet/__init__.py
@@ -68,47 +68,6 @@ class TallySheetModel(db.Model):
secondaryjoin="TallySheetModel.tallySheetId==TallySheetTallySheetModel.parentTallySheetId"
)
- def get_tally_sheet_workflow_instance_actions(self):
- tally_sheet_workflow_instance_actions = db.session.query(
- WorkflowActionModel.workflowActionId,
- WorkflowActionModel.actionName,
- WorkflowActionModel.actionType,
- WorkflowActionModel.fromStatus,
- WorkflowActionModel.toStatus,
- WorkflowInstance.Model.status
- ).filter(
- WorkflowInstance.Model.workflowInstanceId == self.workflowInstanceId,
- WorkflowActionModel.workflowId == WorkflowInstance.Model.workflowId
- ).order_by(
- WorkflowActionModel.workflowActionId
- ).all()
-
- processed_tally_sheet_workflow_instance_actions = []
- for tally_sheet_workflow_instance_action in tally_sheet_workflow_instance_actions:
- processed_tally_sheet_workflow_instance_actions.append({
- "workflowActionId": tally_sheet_workflow_instance_action.workflowActionId,
- "actionName": tally_sheet_workflow_instance_action.actionName,
- "actionType": tally_sheet_workflow_instance_action.actionType,
- "fromStatus": tally_sheet_workflow_instance_action.fromStatus,
- "toStatus": tally_sheet_workflow_instance_action.toStatus,
- "allowed": tally_sheet_workflow_instance_action.fromStatus == tally_sheet_workflow_instance_action.status,
- "authorized": has_role_based_access(tally_sheet=self,
- access_type=tally_sheet_workflow_instance_action.actionType)
- })
-
- return processed_tally_sheet_workflow_instance_actions
-
- @hybrid_property
- def workflowInstanceActions(self):
- return self.get_tally_sheet_workflow_instance_actions()
-
- @hybrid_property
- def areaMapList(self):
- extended_election = self.submission.election.get_extended_election()
- area_map = extended_election.get_area_map_for_tally_sheet(tally_sheet=self)
-
- return area_map
-
def add_parent(self, parentTallySheet):
parentTallySheet.add_child(self)
@@ -140,8 +99,6 @@ def set_latest_version(self, tallySheetVersion: TallySheetVersion):
else:
self.submission.set_latest_version(submissionVersion=tallySheetVersion.submissionVersion)
- self.update_status_report()
-
@hybrid_property
def latestVersion(self):
return TallySheetVersion.Model.query.filter(
@@ -425,6 +382,21 @@ def _get_electoral_district_name(polling_division):
return electoral_district_name
+def refactor_tally_sheet_response(tally_sheet):
+ workflow_instance = tally_sheet.workflowInstance
+ workflow_actions = tally_sheet.workflowInstance.workflow.actions
+ for workflow_action in workflow_actions:
+ setattr(workflow_action, "allowed", workflow_action.fromStatus == workflow_instance.status)
+ setattr(workflow_action, "authorized", has_role_based_access(tally_sheet=tally_sheet,
+ access_type=workflow_action.actionType))
+ setattr(tally_sheet.workflowInstance, "actions", workflow_actions)
+
+ setattr(tally_sheet, "areaId", tally_sheet.submission.areaId)
+ setattr(tally_sheet, "area", tally_sheet.submission.area)
+
+ return tally_sheet
+
+
def get_by_id(tallySheetId, tallySheetCode=None):
# Filter by authorized areas
user_access_area_ids: Set[int] = get_user_access_area_ids()
@@ -450,7 +422,7 @@ def get_by_id(tallySheetId, tallySheetCode=None):
code=MESSAGE_CODE_TALLY_SHEET_NOT_AUTHORIZED_TO_VIEW
)
- return tally_sheet
+ return refactor_tally_sheet_response(tally_sheet)
def get_all(electionId=None, areaId=None, tallySheetCode=None, voteType=None):
@@ -484,6 +456,7 @@ def get_all(electionId=None, areaId=None, tallySheetCode=None, voteType=None):
authorized_tally_sheet_list = []
for tally_sheet in tally_sheet_list:
if has_role_based_access(tally_sheet=tally_sheet, access_type=WORKFLOW_ACTION_TYPE_VIEW):
+ refactor_tally_sheet_response(tally_sheet)
authorized_tally_sheet_list.append(tally_sheet)
return authorized_tally_sheet_list
diff --git a/results-tabulation-api/orm/entities/Workflow/WorkflowInstance/__init__.py b/results-tabulation-api/orm/entities/Workflow/WorkflowInstance/__init__.py
index 277a5629..d281be82 100644
--- a/results-tabulation-api/orm/entities/Workflow/WorkflowInstance/__init__.py
+++ b/results-tabulation-api/orm/entities/Workflow/WorkflowInstance/__init__.py
@@ -18,6 +18,7 @@ class WorkflowInstanceModel(db.Model):
latestLogId = db.Column(db.Integer, db.ForeignKey("workflowInstanceLog.workflowInstanceLogId"), nullable=True)
proofId = db.Column(db.Integer, db.ForeignKey("proof.proofId"), nullable=True)
+ workflow = relationship("WorkflowModel", foreign_keys=[workflowId], lazy='subquery')
latestLog = relationship(WorkflowInstanceLog.Model, foreign_keys=[latestLogId])
proof = relationship(Proof.Model, foreign_keys=[proofId])
diff --git a/results-tabulation-api/orm/entities/Workflow/__init__.py b/results-tabulation-api/orm/entities/Workflow/__init__.py
index 26be0d61..9058ec8e 100644
--- a/results-tabulation-api/orm/entities/Workflow/__init__.py
+++ b/results-tabulation-api/orm/entities/Workflow/__init__.py
@@ -1,5 +1,6 @@
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy import case
+from sqlalchemy.orm import relationship
from app import db
@@ -12,6 +13,8 @@ class WorkflowModel(db.Model):
firstStatus = db.Column(db.String(100), nullable=False)
lastStatus = db.Column(db.String(100), nullable=False)
+ actions = relationship("WorkflowActionModel", lazy='subquery')
+
@classmethod
def create(cls, workflowName, statuses, actions, firstStatus, lastStatus):
workflow: WorkflowModel = cls(workflowName=workflowName, firstStatus=firstStatus, lastStatus=lastStatus)
diff --git a/results-tabulation-api/schemas/__init__.py b/results-tabulation-api/schemas/__init__.py
index 521e5aad..a18165c5 100644
--- a/results-tabulation-api/schemas/__init__.py
+++ b/results-tabulation-api/schemas/__init__.py
@@ -393,12 +393,12 @@ class Meta:
"templateId",
"template",
"electionId",
- # "areaId",
- # "area",
+ "areaId",
+ "area",
# "areaMapList",
"latestVersion",
"metaDataList",
- # "workflowInstance",
+ "workflowInstance",
"latestVersionId"
)
@@ -407,7 +407,7 @@ class Meta:
# to use for deserialization
sqla_session = db.session
- template = ma.Nested("TemplateSchema", only=["templateId", "templateName", "isDerived"])
+ template = ma.Nested("TemplateSchema", only=["templateId", "templateName", "isDerived", "rows"])
area = ma.Nested(AreaSchema, only=["areaId", "areaName"])
versions = ma.Nested(SubmissionVersionSchema, only="submissionVersionId", many=True)
latestVersion = ma.Nested(TallySheetVersionSchema)
@@ -417,7 +417,7 @@ class Meta:
submissionProof = ma.Nested(Proof_Schema)
metaDataList = ma.Nested(MetaDataSchema, many=True)
areaMapList = ma.Nested('AreaMapSchema', many=True, partial=True)
- workflowInstance = ma.Nested(WorkflowInstanceSchema, only=["workflowId", "statuses", "status"])
+ workflowInstance = ma.Nested(WorkflowInstanceSchema, only=["workflowId", "actions", "status"])
class TallySheetSchema(ma.ModelSchema):
@@ -428,14 +428,12 @@ class Meta:
"templateId",
"template",
"electionId",
- # "areaId",
- # "area",
+ "areaId",
+ "area",
# "areaMapList",
"metaDataList",
"workflowInstance",
- "workflowInstanceActions",
- "latestVersionId",
- "submission"
+ "latestVersionId"
)
model = TallySheet.Model
@@ -454,7 +452,7 @@ class Meta:
submissionProof = ma.Nested(Proof_Schema)
metaDataList = ma.Nested(MetaDataSchema, many=True)
areaMapList = ma.Nested('AreaMapSchema', many=True, partial=True)
- workflowInstance = ma.Nested(WorkflowInstanceSchema, only=["workflowId", "status"])
+ workflowInstance = ma.Nested(WorkflowInstanceSchema, only=["workflowId", "actions", "status"])
workflowInstanceActions = ma.Nested(StatusActionSchema, many=True)
diff --git a/results-tabulation-ui/src/components/election/extended-election/ParliamentElection2020/tally-sheet-edit/tally-sheet-edit-pe-27.js b/results-tabulation-ui/src/components/election/extended-election/ParliamentElection2020/tally-sheet-edit/tally-sheet-edit-pe-27.js
index 810825f5..935f5c7f 100644
--- a/results-tabulation-ui/src/components/election/extended-election/ParliamentElection2020/tally-sheet-edit/tally-sheet-edit-pe-27.js
+++ b/results-tabulation-ui/src/components/election/extended-election/ParliamentElection2020/tally-sheet-edit/tally-sheet-edit-pe-27.js
@@ -244,7 +244,7 @@ export default function TallySheetEdit_PE_27({history, queryString, election, ta
Party Name
Party Symbol
Count in words
- Count in figures
+ Count in figures
@@ -270,7 +270,7 @@ export default function TallySheetEdit_PE_27({history, queryString, election, ta
}}
/>
-
+
Total valid vote count
-
+
Total rejected vote count
-
Total vote count
-
+
{
@@ -126,21 +126,6 @@ export default function TallySheetEdit_PE_4({history, queryString, election, tal
return total;
}
- function calculateTotalFirstPreferenceCount() {
- return calculateTotalValidFirstPreferenceCount();
- }
-
-
- const handleTotalFirstPreferenceCountChange = () => event => {
- const {value} = event.target;
- setFirstPreferenceCountRow((firstPreferenceCountRow) => {
- return {
- ...firstPreferenceCountRow,
- numValue: processNumericValue(value)
- }
- });
- };
-
function getTallySheetEditForm() {
if (saved) {
return
@@ -154,10 +139,10 @@ export default function TallySheetEdit_PE_4({history, queryString, election, tal
{candidateWiseFirstPreferenceCountRows.map((candidateWiseFirstPreferenceCountRow) => {
- const {candidateId, candidateName, strValue, numValue} = candidateWiseFirstPreferenceCountRow;
+ const {candidateId, candidateName, candidateNumber, strValue, numValue} = candidateWiseFirstPreferenceCountRow;
return
{candidateName}
-
+ {candidateNumber}
{strValue}
{numValue}
@@ -165,16 +150,11 @@ export default function TallySheetEdit_PE_4({history, queryString, election, tal
-
- Total vote count
- {calculateTotalFirstPreferenceCount()}
-
{getActionsBar()}
-
@@ -185,17 +165,17 @@ export default function TallySheetEdit_PE_4({history, queryString, election, tal
Candidate Name
Candidate Number
Count in words
- Count in figures
+ Count in figures
{candidateWiseFirstPreferenceCountRows.map((candidateWiseFirstPreferenceCountRow, candidateWiseFirstPreferenceCountRowIndex) => {
- const {candidateId, candidateName, strValue, numValue} = candidateWiseFirstPreferenceCountRow;
+ const {candidateId, candidateName, candidateNumber, strValue, numValue} = candidateWiseFirstPreferenceCountRow;
return
{candidateName}
-
+ {candidateNumber}
-
- Total vote count
-
-
-
-
{getActionsBar()}
-
diff --git a/results-tabulation-ui/src/services/tally-sheet.provider.js b/results-tabulation-ui/src/services/tally-sheet.provider.js
index 093e2d5c..282da8e3 100644
--- a/results-tabulation-ui/src/services/tally-sheet.provider.js
+++ b/results-tabulation-ui/src/services/tally-sheet.provider.js
@@ -29,8 +29,6 @@ export function TallySheetProvider(props) {
async function refactorTallySheetObject(tallySheet) {
tallySheet.tallySheetCode = tallySheet.tallySheetCode.replace(/_/g, "-");
tallySheet.election = await electionContext.getElectionById(tallySheet.electionId);
- tallySheet.workflowInstance.actions = tallySheet.workflowInstanceActions;
- tallySheet.area = tallySheet.submission.area;
tallySheet.areaMapList = await electionContext.getElectionAreaMap(tallySheet.electionId);
// TODO fetch actions and area maps
@@ -88,9 +86,10 @@ export function TallySheetProvider(props) {
url: ENDPOINT_PATH_TALLY_SHEETS_BY_ID(tallySheetId),
method: 'get',
params: {}
- }).then((tallySheet) => {
+ }).then(async (tallySheet) => {
+ await refactorTallySheetObject(tallySheet);
_updateTallySheetState(tallySheet);
- return refactorTallySheetObject(tallySheet);
+ return tallySheet;
})
}