Skip to content
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
Binary file modified src/backend/expungeservice/files/oregon_arrest.pdf
Binary file not shown.
Binary file modified src/backend/expungeservice/files/oregon_conviction.pdf
Binary file not shown.
24 changes: 4 additions & 20 deletions src/backend/expungeservice/form_filling.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,8 +482,7 @@ class PDF:
BUTTON_YES = PdfName("Yes")
TEXT_TYPE = "/Tx"
FONT_FAMILY = "TimesNewRoman"
FONT_SIZE = "10"
FONT_SIZE_SMALL = "6"
FONT_SIZE = "0"
DATE_FORMAT = "%b %-d, %Y"
STR_CONNECTOR = "; "

Expand All @@ -500,7 +499,6 @@ def fill_form(mapper: PDFFieldMapper, should_validate=False):
def __init__(self, mapper: PDFFieldMapper):
self.set_pdf(PdfReader(mapper.pdf_source_path))
self.mapper = mapper
self.shrunk_fields: Dict[str, str] = {}
self.writer = PdfWriter()

def set_pdf(self, pdf: PdfReader):
Expand Down Expand Up @@ -539,16 +537,7 @@ def set_text_value(self, annotation, value):
annotation.update(PdfDict(AP=""))

def set_font(self, annotation):
x1, x2 = float(annotation.Rect[0]), float(annotation.Rect[2])
max_chars = min((x2 - x1) * 0.3125, 90) # Times New Roman size 10; and 90 because the equation doesn't scale well to the longest field on the form, the Charges line in the non-Multnomah form
num_chars = len(annotation.V) - 2 # minus parens
font_size = self.FONT_SIZE

if num_chars > max_chars:
font_size = self.FONT_SIZE_SMALL
self.shrunk_fields[annotation.T] = annotation.V

annotation.DA = PdfString.encode(f"/{self.FONT_FAMILY} {font_size} Tf 0 g")
annotation.DA = PdfString.encode(f"/{self.FONT_FAMILY} {self.FONT_SIZE} Tf 0 g")

def update_annotations(self):
for annotation in self.annotations:
Expand Down Expand Up @@ -705,19 +694,14 @@ def _unify_sids(record_summary: RecordSummary) -> str:
return ""

@staticmethod
def _generate_warnings_text(shrunk_fields: Dict[str, str], mapper: PDFFieldMapper) -> Optional[str]:
def _generate_warnings_text(mapper: PDFFieldMapper) -> Optional[str]:
text = None
warnings: List[str] = []

if mapper.get("(has_ineligible_charges)"):
message = "This form will attempt to expunge a case in part. This is relatively rare, and thus these forms should be reviewed particularly carefully."
warnings.append(message)

if shrunk_fields:
for field_name, value in shrunk_fields.items():
message = f'* The font size of "{value[1:-1]}" was shrunk to fit the bounding box of "{field_name[1:-1]}". An addendum might be required if it still doesn\'t fit.'
warnings.append(message)

if warnings:
text = "# Warnings from RecordSponge \n"
text += "Do not submit this page to the District Attorney's office. \n \n"
Expand Down Expand Up @@ -784,7 +768,7 @@ def _create_and_write_pdf(
source_data = UserInfo(**data)

pdf = FormFilling._create_pdf(source_data, validate_initial_pdf_state)
warnings_text = FormFilling._generate_warnings_text(pdf.shrunk_fields, pdf.mapper)
warnings_text = FormFilling._generate_warnings_text(pdf.mapper)

if warnings_text:
pdf.add_text(warnings_text)
Expand Down
41 changes: 6 additions & 35 deletions src/backend/tests/test_form_filling.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,6 @@ class TestWarningsGeneration:
)
partial_expungement_warning = "\\* This form will attempt to expunge a case in part. This is relatively rare, and thus these forms should be reviewed particularly carefully. \n"

def font_warning(self, field_name, value):
return f'\\* * The font size of "{value[1:-1]}" was shrunk to fit the bounding box of "{field_name[1:-1]}". An addendum might be required if it still doesn\'t fit. \n'

@pytest.fixture
def mapper_factory(self):
def factory(has_ineligible_charges=False):
Expand All @@ -263,40 +260,16 @@ def factory(has_ineligible_charges=False):

return factory

@pytest.fixture
def shrunk_fields(self):
shrunk_fields: Dict[str, str] = {}
return shrunk_fields

def test_no_warnings_generated_if_no_ineligible_charges_or_shrunk_fields(self, mapper_factory, shrunk_fields):
warnings = FormFilling._generate_warnings_text(shrunk_fields, mapper_factory())
def test_no_warnings_generated_if_no_ineligible_charges(self, mapper_factory):
warnings = FormFilling._generate_warnings_text(mapper_factory())
assert warnings is None

def test_warnings_generated_if_there_are_ineligible_charges(self, mapper_factory, shrunk_fields):
expected = self.lead_warning
expected += self.partial_expungement_warning

mapper = mapper_factory(has_ineligible_charges=True)
warnings = FormFilling._generate_warnings_text(shrunk_fields, mapper)
assert warnings == expected

def test_warnings_generated_if_there_are_shrunk_fields(self, mapper_factory, shrunk_fields):
expected = self.lead_warning
expected += self.font_warning("(foo)", "(foo value)")
expected += self.font_warning("(bar)", "(bar value)")

shrunk_fields = {"(foo)": "(foo value)", "(bar)": "(bar value)"}
warnings = FormFilling._generate_warnings_text(shrunk_fields, mapper_factory())
assert warnings == expected

def test_warnings_generated_if_there_are_shrunk_fields_and_ineligible_charges(self, mapper_factory, shrunk_fields):
def test_warnings_generated_if_there_are_ineligible_charges(self, mapper_factory):
expected = self.lead_warning
expected += self.partial_expungement_warning
expected += self.font_warning("(foo)", "(foo value)")

mapper = mapper_factory(has_ineligible_charges=True)
shrunk_fields = {"(foo)": "(foo value)"}
warnings = FormFilling._generate_warnings_text(shrunk_fields, mapper)
warnings = FormFilling._generate_warnings_text(mapper)
assert warnings == expected


Expand Down Expand Up @@ -729,7 +702,7 @@ def test_arrest(self, pdf_factory: Callable, dismissed_charge_factory: Callable)
assert_pdf_values(pdf_factory(charges), expected_values)

@patch("expungeservice.form_filling.PdfWriter")
def test_font_shrinking_and_pdf_write_text(self, MockPdfWriter, pdf_factory: Mock, dismissed_charge_factory: Mock):
def test_long_charge_name_and_pdf_write_text(self, MockPdfWriter, pdf_factory: Mock, dismissed_charge_factory: Mock):
charge_name = (
"A.............. Very.................... Long................. Name......................"
+ "A.............. Very.................... Long................. Name......................"
Expand All @@ -755,9 +728,7 @@ def test_font_shrinking_and_pdf_write_text(self, MockPdfWriter, pdf_factory: Moc
charge.name = charge_name
pdf: PDF = pdf_factory([charge])

assert pdf.shrunk_fields.get("(Dismissed Charges)") == f"({charge_name})"
assert len(pdf.shrunk_fields) == 1
assert pdf.get_annotation_dict()["(Dismissed Charges)"].DA == "(/TimesNewRoman 6 Tf 0 g)"
assert pdf.get_annotation_dict()["(Dismissed Charges)"].DA == "(/TimesNewRoman 0 Tf 0 g)"
assert_pdf_values(pdf, expected_values)

assert not MockPdfWriter.return_value.addpages.called
Expand Down