Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

validate Batch Inventory Worksheet uploaded to ballot manifest #2021

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion server/api/ballot_manifest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Optional
from typing import BinaryIO, Optional
import uuid
import logging
from datetime import datetime
Expand All @@ -12,6 +12,7 @@
from ..models import * # pylint: disable=wildcard-import
from ..auth import restrict_access, UserType, get_loggedin_user, get_support_user
from ..worker.tasks import (
UserError,
background_task,
create_background_task,
)
Expand Down Expand Up @@ -57,6 +58,8 @@ class CountingGroup(str, enum.Enum):
NUMBER_OF_BALLOTS = "Number of Ballots"
CVR = "CVR"

BATCH_INVENTORY_WORKSHEET_UPLOADED_ERROR = 'You have uploaded a Batch Inventory Worksheet. Please upload a ballot manifest file exported from Step 4: "Download Audit Files".'


def all_manifests_uploaded(contest: Contest):
return all(
Expand Down Expand Up @@ -143,6 +146,7 @@ def process() -> None:
)

manifest_file = retrieve_file(jurisdiction.manifest_file.storage_path)
validate_is_not_batch_inventory_worksheet(manifest_file)
manifest_csv = parse_csv(manifest_file, columns)

counting_group_allowlist = [item.value for item in CountingGroup]
Expand Down Expand Up @@ -229,6 +233,17 @@ def process() -> None:
session.commit()


def is_batch_inventory_worksheet(first_line: bytes) -> bool:
return first_line.decode("utf-8").strip() == "Batch Inventory Worksheet"


def validate_is_not_batch_inventory_worksheet(file: BinaryIO):
first_line = file.readline()
file.seek(0)
if is_batch_inventory_worksheet(first_line):
raise UserError(BATCH_INVENTORY_WORKSHEET_UPLOADED_ERROR)


def save_ballot_manifest_file(
storage_path: str, file_name: str, jurisdiction: Jurisdiction
):
Expand Down
35 changes: 35 additions & 0 deletions server/tests/api/test_ballot_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,41 @@ def test_ballot_manifest_upload_missing_file_path(
}


def test_ballot_manifest_upload_batch_inventory_worksheet(
client: FlaskClient, election_id: str, jurisdiction_ids: List[str]
):
set_logged_in_user(
client, UserType.JURISDICTION_ADMIN, default_ja_email(election_id)
)

rv = upload_ballot_manifest(
client,
io.BytesIO(b"Batch Inventory Worksheet \r\n"),
election_id,
jurisdiction_ids[0],
)
assert_ok(rv)

rv = client.get(
f"/api/election/{election_id}/jurisdiction/{jurisdiction_ids[0]}/ballot-manifest"
)
compare_json(
json.loads(rv.data),
{
"file": {
"name": asserts_startswith("manifest"),
"uploadedAt": assert_is_date,
},
"processing": {
"status": ProcessingStatus.ERRORED,
"startedAt": assert_is_date,
"completedAt": assert_is_date,
"error": 'You have uploaded a Batch Inventory Worksheet. Please upload a ballot manifest file exported from Step 4: "Download Audit Files".',
},
},
)


def test_ballot_manifest_upload_bad_csv(
client: FlaskClient, election_id: str, jurisdiction_ids: List[str]
):
Expand Down