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

Add state to departments table #981

Merged
merged 193 commits into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
193 commits
Select commit Hold shift + click to select a range
1913b2e
Update database.py
michplunkett Jul 18, 2023
f4b47f2
Create 2023-07-18-1616_33521389a38d_rename_star_date.py
michplunkett Jul 18, 2023
a87425a
Update alembic.ini
michplunkett Jul 18, 2023
189c2a5
Update env.py
michplunkett Jul 18, 2023
c6b0c9a
Delete 2023-07-18-1616_33521389a38d_rename_star_date.py
michplunkett Jul 18, 2023
65c7327
Create 2023-07-18-1717_9ce70d7ebd56_rename_star_date.py
michplunkett Jul 18, 2023
80b2094
Update 2023-07-18-1717_9ce70d7ebd56_rename_star_date.py
michplunkett Jul 18, 2023
15c837c
Update conftest.py
michplunkett Jul 18, 2023
8dce36a
Update bulk_upload.rst
michplunkett Jul 18, 2023
bd994ff
Update downloads.py
michplunkett Jul 18, 2023
e7b0de0
Update forms.py
michplunkett Jul 18, 2023
b0edeab
Update officer_assignment_history.html
michplunkett Jul 18, 2023
a99e4d9
Update forms.py
michplunkett Jul 18, 2023
bc4a323
Update test_commands.py
michplunkett Jul 18, 2023
7fc0486
Update commands.py
michplunkett Jul 18, 2023
b035d47
Update test_officer_and_department.py
michplunkett Jul 18, 2023
f7210a3
Update edit_assignment.html
michplunkett Jul 18, 2023
4abffbd
Update csv_imports.py
michplunkett Jul 18, 2023
c2704df
Update database.py
michplunkett Jul 18, 2023
86636a0
Update database_imports.py
michplunkett Jul 18, 2023
7507f55
Update database.py
michplunkett Jul 18, 2023
9aecce6
Create 2023-07-18-1921_eb0266dc8588_rename_descrip_to_description.py
michplunkett Jul 18, 2023
1e3c0f2
Update 2023-07-18-1921_eb0266dc8588_rename_descrip_to_description.py
michplunkett Jul 18, 2023
e217271
Update test_utils.py
michplunkett Jul 18, 2023
08fc13a
Update test_models.py
michplunkett Jul 18, 2023
358e512
Update test_functional.py
michplunkett Jul 18, 2023
a5d3d9e
Update test_officer_and_department.py
michplunkett Jul 18, 2023
94aa26f
Update conftest.py
michplunkett Jul 18, 2023
9ff47ce
Update officer_assignment_history.html
michplunkett Jul 18, 2023
86680d6
Update add_unit.html
michplunkett Jul 18, 2023
ec80755
Update views.py
michplunkett Jul 18, 2023
2d0df19
Update forms.py
michplunkett Jul 18, 2023
d65077f
Update downloads.py
michplunkett Jul 18, 2023
d5dbc4f
Update csv_imports.py
michplunkett Jul 18, 2023
374d47b
Update views.py
michplunkett Jul 18, 2023
eee34cc
Update test_functional.py
michplunkett Jul 18, 2023
e394434
Update forms.py
michplunkett Jul 18, 2023
19496b9
Update db.py
michplunkett Jul 18, 2023
e6ea9fb
Update views.py
michplunkett Jul 18, 2023
afd7560
Update forms.py
michplunkett Jul 18, 2023
9584bc1
Update list_officer.html
michplunkett Jul 18, 2023
44cbfb6
Merge branch 'develop' into timestamp_to_timestamptz
michplunkett Jul 18, 2023
1d0e5e3
Update database.py
michplunkett Jul 18, 2023
648174a
Create 2023-07-18-2027_07ace5f956ca_standardize_datetime_field_names.py
michplunkett Jul 18, 2023
27aa07d
Update 2023-07-18-2027_07ace5f956ca_standardize_datetime_field_names.py
michplunkett Jul 18, 2023
901e5e9
Update test_notes.py
michplunkett Jul 18, 2023
d62d18d
Update test_descriptions.py
michplunkett Jul 18, 2023
2cdaaa9
Update conftest.py
michplunkett Jul 18, 2023
cd18f92
Update forms.py
michplunkett Jul 18, 2023
46a5501
Update test_notes.py
michplunkett Jul 18, 2023
25a8021
Update test_descriptions.py
michplunkett Jul 18, 2023
0baae9a
Update views.py
michplunkett Jul 18, 2023
8913692
Update downloads.py
michplunkett Jul 18, 2023
63c17d0
Update test_models.py
michplunkett Jul 18, 2023
43964aa
Update cloud.py
michplunkett Jul 18, 2023
e4662d0
Update image.html
michplunkett Jul 18, 2023
60ce77f
Update officer_notes.html
michplunkett Jul 18, 2023
536044e
Update officer_descriptions.html
michplunkett Jul 18, 2023
c2bd06d
Update model_view.py
michplunkett Jul 18, 2023
de4bc5f
Merge branch 'develop' into timestamp_to_timestamptz
michplunkett Jul 19, 2023
a6f8cc5
Merge branch 'develop' into timestamp_to_timestamptz
michplunkett Jul 19, 2023
f2aa4ae
Update 2023-07-18-2027_07ace5f956ca_standardize_datetime_field_names.py
michplunkett Jul 19, 2023
df3097f
Update database.py
michplunkett Jul 19, 2023
46f1d9f
Update downloads.py
michplunkett Jul 19, 2023
0c61ec3
Update model_view.py
michplunkett Jul 19, 2023
de3416f
Update views.py
michplunkett Jul 19, 2023
60bee9c
Update image.html
michplunkett Jul 19, 2023
cf2bdb5
Update forms.py
michplunkett Jul 19, 2023
2071b1f
Update cloud.py
michplunkett Jul 19, 2023
9b0053d
Update officer_notes.html
michplunkett Jul 19, 2023
8725e99
Update officer_descriptions.html
michplunkett Jul 19, 2023
fa07a0d
Update conftest.py
michplunkett Jul 19, 2023
c96a376
Update test_descriptions.py
michplunkett Jul 19, 2023
3fcc7cb
Update test_notes.py
michplunkett Jul 19, 2023
636d45e
Update test_models.py
michplunkett Jul 19, 2023
254cf2d
Update database.py
michplunkett Jul 19, 2023
af6233e
Update test_notes.py
michplunkett Jul 19, 2023
b6bebd4
Update test_descriptions.py
michplunkett Jul 19, 2023
eedc11b
Update CONTRIB.md
michplunkett Jul 19, 2023
b64f5e2
Update config.py
michplunkett Jul 19, 2023
d25a24e
Update docker-compose.yml
michplunkett Jul 19, 2023
5dd16a4
Update docker-compose.yml
michplunkett Jul 19, 2023
d6927b6
Update database.py
michplunkett Jul 19, 2023
1638cce
Create 2023-07-19-1638_1931b987ce0d_convert_timestamp_to_timestamptz.py
michplunkett Jul 19, 2023
322f841
Update 2023-07-19-1638_1931b987ce0d_convert_timestamp_to_timestamptz.py
michplunkett Jul 19, 2023
f93c665
Update 2023-07-19-1638_1931b987ce0d_convert_timestamp_to_timestamptz.py
michplunkett Jul 19, 2023
82ded97
use snake case
michplunkett Jul 19, 2023
ef4e718
Update requirements.txt
michplunkett Jul 19, 2023
8bbcbba
Update database.py
michplunkett Jul 20, 2023
af0de50
Update 2023-07-19-1638_1931b987ce0d_convert_timestamp_to_timestamptz.py
michplunkett Jul 20, 2023
2fc9168
Update 2023-07-19-1638_1931b987ce0d_convert_timestamp_to_timestamptz.py
michplunkett Jul 20, 2023
7a1263b
Update config.py
michplunkett Jul 20, 2023
a0c0c4b
Update config.py
michplunkett Jul 20, 2023
11dac91
Update general.py
michplunkett Jul 20, 2023
3be0fed
Update views.py
michplunkett Jul 20, 2023
c0c690f
Update constants.py
michplunkett Jul 20, 2023
156f2b4
Update config.py
michplunkett Jul 20, 2023
ca8fbe7
Update views.py
michplunkett Jul 20, 2023
85f8919
Update base.html
michplunkett Jul 20, 2023
6856a10
Update database.py
michplunkett Jul 20, 2023
378a898
Update base.html
michplunkett Jul 20, 2023
7e62358
Update general.py
michplunkett Jul 20, 2023
5b18029
Update __init__.py
michplunkett Jul 20, 2023
f486f07
Update __init__.py
michplunkett Jul 20, 2023
ea73c91
Update general.py
michplunkett Jul 20, 2023
451d131
Update views.py
michplunkett Jul 20, 2023
1b69413
Create filters.py
michplunkett Jul 20, 2023
1359a58
Update __init__.py
michplunkett Jul 20, 2023
5d0fe5c
Update __init__.py
michplunkett Jul 20, 2023
895de26
Revert "Update __init__.py"
michplunkett Jul 20, 2023
b64b94e
Update __init__.py
michplunkett Jul 20, 2023
34ffc00
Update filters.py
michplunkett Jul 20, 2023
13b9263
Update views.py
michplunkett Jul 20, 2023
0731ffa
Update base.html
michplunkett Jul 20, 2023
ebac61d
Update filters.py
michplunkett Jul 20, 2023
641749b
Update __init__.py
michplunkett Jul 20, 2023
befc4d6
Update filters.py
michplunkett Jul 20, 2023
3b828c6
Update officer_notes.html
michplunkett Jul 20, 2023
ee380d5
Update officer_descriptions.html
michplunkett Jul 20, 2023
946485b
Update image.html
michplunkett Jul 20, 2023
42285fe
Update base.html
michplunkett Jul 20, 2023
7ec6375
Update __init__.py
michplunkett Jul 21, 2023
f9f02b9
Update views.py
michplunkett Jul 21, 2023
c3130d9
Update filters.py
michplunkett Jul 21, 2023
6d5f74d
Update filters.py
michplunkett Jul 21, 2023
a70dae1
Update filters.py
michplunkett Jul 21, 2023
f68e252
Update views.py
michplunkett Jul 21, 2023
4c99ce6
Update base.html
michplunkett Jul 21, 2023
5d8577e
Update test_other.py
michplunkett Jul 21, 2023
bb76e20
Update views.py
michplunkett Jul 21, 2023
07f3c98
Update database.py
michplunkett Jul 21, 2023
b7a02ef
Create 2023-07-21-2058_eb854f312a3a_add_state_to_department.py
michplunkett Jul 21, 2023
385dd76
Update constants.py
michplunkett Jul 21, 2023
0d1f037
Update test_incidents.py
michplunkett Jul 21, 2023
7677d03
Update database.py
michplunkett Jul 21, 2023
318a553
Update 2023-07-21-2058_eb854f312a3a_add_state_to_department.py
michplunkett Jul 21, 2023
27686b4
Update test_models.py
michplunkett Jul 21, 2023
1d496c2
Update test_commands.py
michplunkett Jul 21, 2023
5b64a06
Update conftest.py
michplunkett Jul 21, 2023
12f6001
Update conftest.py
michplunkett Jul 21, 2023
4dc5810
Update test_commands.py
michplunkett Jul 21, 2023
f7a5684
Update test_commands.py
michplunkett Jul 21, 2023
84396d6
Update test_commands.py
michplunkett Jul 24, 2023
87f277a
Update conftest.py
michplunkett Jul 24, 2023
ed27f8e
Update constants.py
michplunkett Jul 24, 2023
6478ebf
Merge branch 'develop' into add_state_filtering
michplunkett Jul 24, 2023
06bcff1
Update route_helpers.py
michplunkett Jul 24, 2023
e69522d
Update test_incidents.py
michplunkett Jul 24, 2023
fc96ebc
Merge branch 'develop' into add_state_filtering
michplunkett Jul 24, 2023
0aade93
Update database.py
michplunkett Jul 24, 2023
3d023fd
Take care of other .format strings
michplunkett Jul 24, 2023
a3d54a6
Merge branch 'develop' into add_state_filtering
michplunkett Jul 25, 2023
34fc413
Update test_models.py
michplunkett Jul 25, 2023
6848ce0
Update test_models.py
michplunkett Jul 25, 2023
c3a958d
Update test_models.py
michplunkett Jul 25, 2023
aae3f36
Update database.py
michplunkett Jul 25, 2023
25f02fd
Update test_models.py
michplunkett Jul 25, 2023
053bf5c
Update commands.py
michplunkett Jul 25, 2023
e59aa0d
Update test_commands.py
michplunkett Jul 25, 2023
48b2be4
Update test_commands.py
michplunkett Jul 25, 2023
a3727de
Delete 2023-07-21-2058_eb854f312a3a_add_state_to_department.py
michplunkett Jul 25, 2023
8aa3250
Update database.py
michplunkett Jul 25, 2023
abc0a2e
Update database.py
michplunkett Jul 25, 2023
55daad4
Create 2023-07-25-2122_bce7c55b6d90_add_state_column_to_departments.py
michplunkett Jul 25, 2023
1a3945f
Update 2023-07-25-2122_bce7c55b6d90_add_state_column_to_departments.py
michplunkett Jul 25, 2023
2f1f01e
Update test_commands.py
michplunkett Jul 25, 2023
69f19be
Update test_commands.py
michplunkett Jul 25, 2023
c58c224
Update conftest.py
michplunkett Jul 25, 2023
d95049c
Update test_commands.py
michplunkett Jul 25, 2023
97c5416
Update commands.py
michplunkett Jul 25, 2023
f06a042
Update test_officer_and_department.py
michplunkett Jul 25, 2023
060613a
csvs
michplunkett Jul 25, 2023
c0f22f0
Update commands.py
michplunkett Jul 25, 2023
3d2403b
Update conftest.py
michplunkett Jul 25, 2023
430899c
Update csv_imports.py
michplunkett Jul 25, 2023
cf734f0
Update test_commands.py
michplunkett Jul 25, 2023
5d6f10e
Update test_commands.py
michplunkett Jul 25, 2023
99b1c53
Update test_commands.py
michplunkett Jul 25, 2023
7213477
PoliceDepartment class
michplunkett Jul 25, 2023
3219610
Update test_utils.py
michplunkett Jul 26, 2023
1c93ee4
Update test_commands.py
michplunkett Jul 26, 2023
5a907b7
Update commands.py
michplunkett Jul 26, 2023
3c2065f
Update test_commands.py
michplunkett Jul 26, 2023
ecfe526
Update test_utils.py
michplunkett Jul 26, 2023
704fbf5
Update database.py
michplunkett Jul 26, 2023
0f87cbb
Update test_models.py
michplunkett Jul 26, 2023
93af8a7
Use fixture instance of faker
michplunkett Jul 26, 2023
22dc467
Delete 2023-07-25-2122_bce7c55b6d90_add_state_column_to_departments.py
michplunkett Jul 26, 2023
9a4cdef
Update database.py
michplunkett Jul 26, 2023
9a32f0f
Create 2023-07-26-1551_18f43ac4622f_add_state_column_to_departments.py
michplunkett Jul 26, 2023
1e53471
Update 2023-07-26-1551_18f43ac4622f_add_state_column_to_departments.py
michplunkett Jul 26, 2023
9117aa4
Update commands.py
michplunkett Jul 26, 2023
b5a120c
Update advanced_csv_import.rst
michplunkett Jul 26, 2023
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
26 changes: 19 additions & 7 deletions OpenOversight/app/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from typing import Dict, List

import click
import us
from dateutil.parser import parse
from flask import current_app
from flask.cli import with_appcontext
Expand Down Expand Up @@ -565,7 +566,11 @@ def bulk_add_officers(filename, no_create, update_by_name, update_static_fields)


@click.command()
@click.argument("department-name")
@click.argument("department-name", required=True)
@click.argument(
"department-state",
type=click.Choice([state.abbr for state in us.STATES]),
)
Comment on lines +570 to +573
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the next PR, once we can create and edit Departments from the front-end, we can make this required.

@click.option("--officers-csv", type=click.Path(exists=True))
@click.option("--assignments-csv", type=click.Path(exists=True))
@click.option("--salaries-csv", type=click.Path(exists=True))
Expand All @@ -576,6 +581,7 @@ def bulk_add_officers(filename, no_create, update_by_name, update_static_fields)
@with_appcontext
def advanced_csv_import(
department_name,
department_state,
officers_csv,
assignments_csv,
salaries_csv,
Expand All @@ -585,8 +591,8 @@ def advanced_csv_import(
overwrite_assignments,
):
"""
Add or update officers, assignments, salaries, links and incidents from csv
files in the department DEPARTMENT_NAME.
Add or update officers, assignments, salaries, links and incidents from
csv files in the department using the DEPARTMENT_NAME and DEPARTMENT_STATE.

The csv files are treated as the source of truth.
Existing entries might be overwritten as a result, backing up the
Expand All @@ -599,6 +605,7 @@ def advanced_csv_import(

import_csv_files(
department_name,
department_state,
officers_csv,
assignments_csv,
salaries_csv,
Expand All @@ -610,20 +617,25 @@ def advanced_csv_import(


@click.command()
@click.argument("name")
@click.argument("short_name")
@click.argument("name", required=True)
@click.argument("short_name", required=True)
@click.argument(
"state",
type=click.Choice([state.abbr for state in us.STATES]),
)
@click.argument("unique_internal_identifier", required=False)
@with_appcontext
def add_department(name, short_name, unique_internal_identifier):
def add_department(name, short_name, state, unique_internal_identifier):
"""Add a new department to OpenOversight."""
dept = Department(
name=name,
short_name=short_name,
state=state.upper(),
unique_internal_identifier_label=unique_internal_identifier,
)
db.session.add(dept)
db.session.commit()
print("Department added with id {}".format(dept.id))
print(f"Department added with id {dept.id}")


@click.command()
Expand Down
27 changes: 22 additions & 5 deletions OpenOversight/app/csv_imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ def _csv_reader(csv_filename):
def _handle_officers_csv(
officers_csv: str,
department_name: str,
department_state: str,
department_id: int,
id_to_officer,
force_create,
Expand All @@ -103,7 +104,9 @@ def _handle_officers_csv(
with _csv_reader(officers_csv) as csv_reader:
_check_provided_fields(
csv_reader,
required_fields=["id", "department_name"] if not force_create else ["id"],
required_fields=["id", "department_name", "department_state"]
if not force_create
else ["id"],
optional_fields=[
"last_name",
"first_name",
Expand All @@ -115,6 +118,7 @@ def _handle_officers_csv(
"birth_year",
"unique_internal_identifier",
"department_name",
"department_state",
# the following are unused, but allowed since they are included in the
# csv output
"badge_number",
Expand All @@ -131,6 +135,7 @@ def _handle_officers_csv(
# can only update department with given name
if not force_create:
assert row["department_name"] == department_name
assert row["department_state"] == department_state
row["department_id"] = department_id
connection_id = row["id"]
if row["id"].startswith("#"):
Expand Down Expand Up @@ -352,6 +357,7 @@ def _handle_salaries(
def _handle_incidents_csv(
incidents_csv: str,
department_name: str,
department_state: str,
department_id: int,
all_officers: Dict[str, Officer],
id_to_incident: Dict[int, Incident],
Expand All @@ -362,7 +368,7 @@ def _handle_incidents_csv(
with _csv_reader(incidents_csv) as csv_reader:
_check_provided_fields(
csv_reader,
required_fields=["id", "department_name"],
required_fields=["id", "department_name", "department_state"],
optional_fields=[
"date",
"time",
Expand All @@ -384,6 +390,7 @@ def _handle_incidents_csv(

for row in csv_reader:
assert row["department_name"] == department_name
assert row["department_state"] == department_state
row["department_id"] = department_id
row["officers"] = _objects_from_split_field(
row.get("officer_ids"), all_officers
Expand Down Expand Up @@ -481,6 +488,7 @@ def _handle_links_csv(

def import_csv_files(
department_name: str,
department_state: str,
officers_csv: Optional[str],
assignments_csv: Optional[str],
salaries_csv: Optional[str],
Expand All @@ -489,10 +497,13 @@ def import_csv_files(
force_create: bool = False,
overwrite_assignments: bool = False,
):
department = Department.query.filter_by(name=department_name).one_or_none()
department = Department.query.filter_by(
name=department_name, state=department_state
).one_or_none()
if department is None:
raise Exception(
"Department with name '{}' does not exist!".format(department_name)
f"Department with name '{department_name}' in {department_state} "
"does not exist!"
)
department_id = department.id

Expand All @@ -502,7 +513,12 @@ def import_csv_files(

if officers_csv is not None:
new_officers = _handle_officers_csv(
officers_csv, department_name, department_id, id_to_officer, force_create
officers_csv,
department_name,
department_state,
department_id,
id_to_officer,
force_create,
)
all_officers.update(new_officers)

Expand All @@ -527,6 +543,7 @@ def import_csv_files(
new_incidents = _handle_incidents_csv(
incidents_csv,
department_name,
department_state,
department_id,
all_officers,
id_to_incident,
Expand Down
68 changes: 33 additions & 35 deletions OpenOversight/app/models/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,26 @@
class Department(BaseModel):
__tablename__ = "departments"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255), index=True, unique=True, nullable=False)
name = db.Column(db.String(255), index=False, unique=False, nullable=False)
short_name = db.Column(db.String(100), unique=False, nullable=False)
state = db.Column(db.String(2), server_default="", nullable=False)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's been set to db.Column(db.String(2), server_default="", nullable=False), @abandoned-prototype.


# See https://github.com/lucyparsons/OpenOversight/issues/462
unique_internal_identifier_label = db.Column(
db.String(100), unique=False, nullable=True
)

__table_args__ = (UniqueConstraint("name", "state", name="departments_name_state"),)

def __repr__(self):
return "<Department ID {}: {}>".format(self.id, self.name)
return f"<Department ID {self.id}: {self.name} {self.state}>"

def to_custom_dict(self):
return {
"id": self.id,
"name": self.name,
"short_name": self.short_name,
"state": self.state,
"unique_internal_identifier_label": self.unique_internal_identifier_label,
}

Expand All @@ -76,7 +80,7 @@ class Job(BaseModel):
)

def __repr__(self):
return "<Job ID {}: {}>".format(self.id, self.job_title)
return f"<Job ID {self.id,}: {self.job_title}>"

def __str__(self):
return self.job_title
Expand Down Expand Up @@ -164,16 +168,14 @@ def full_name(self):
else self.middle_initial
)
if self.suffix:
return "{} {} {} {}".format(
self.first_name, middle_initial, self.last_name, self.suffix
return (
f"{self.first_name} {middle_initial} {self.last_name} {self.suffix}"
)
else:
return "{} {} {}".format(
self.first_name, middle_initial, self.last_name
)
return f"{self.first_name} {middle_initial} {self.last_name}"
if self.suffix:
return "{} {} {}".format(self.first_name, self.last_name, self.suffix)
return "{} {}".format(self.first_name, self.last_name)
return f"{self.first_name} {self.last_name} {self.suffix}"
return f"{self.first_name} {self.last_name}"

def race_label(self):
if self.race is None:
Expand Down Expand Up @@ -222,16 +224,13 @@ def currently_on_force(self):

def __repr__(self):
if self.unique_internal_identifier:
return "<Officer ID {}: {} {} {} {} ({})>".format(
self.id,
self.first_name,
self.middle_initial,
self.last_name,
self.suffix,
self.unique_internal_identifier,
return (
f"<Officer ID {self.id}: {self.first_name} {self.middle_initial} "
+ f"{self.last_name} {self.suffix} ({self.unique_internal_identifier})>"
)
return "<Officer ID {}: {} {} {} {}>".format(
self.id, self.first_name, self.middle_initial, self.last_name, self.suffix
return (
f"<Officer ID {self.id}: {self.first_name} {self.middle_initial} "
+ f"{self.last_name} {self.suffix}>"
)


Expand All @@ -247,7 +246,7 @@ class Salary(BaseModel):
is_fiscal_year = db.Column(db.Boolean, index=False, unique=False, nullable=False)

def __repr__(self):
return "<Salary: ID {} : {}".format(self.officer_id, self.salary)
return f"<Salary: ID {self.officer_id} : {self.salary}"


class Assignment(BaseModel):
Expand All @@ -265,7 +264,7 @@ class Assignment(BaseModel):
resign_date = db.Column(db.Date, index=True, unique=False, nullable=True)

def __repr__(self):
return "<Assignment: ID {} : {}>".format(self.officer_id, self.star_no)
return f"<Assignment: ID {self.officer_id} : {self.star_no}>"


class Unit(BaseModel):
Expand All @@ -279,7 +278,7 @@ class Unit(BaseModel):
)

def __repr__(self):
return "Unit: {}".format(self.description)
return f"Unit: {self.description}"


class Face(BaseModel):
Expand Down Expand Up @@ -324,7 +323,7 @@ class Face(BaseModel):
__table_args__ = (UniqueConstraint("officer_id", "img_id", name="unique_faces"),)

def __repr__(self):
return "<Tag ID {}: {} - {}>".format(self.id, self.officer_id, self.img_id)
return f"<Tag ID {self.id}: {self.officer_id} - {self.img_id}>"


class Image(BaseModel):
Expand Down Expand Up @@ -356,7 +355,7 @@ class Image(BaseModel):
department = db.relationship("Department", backref="raw_images")

def __repr__(self):
return "<Image ID {}: {}>".format(self.id, self.filepath)
return f"<Image ID {self.id}: {self.filepath}>"


incident_links = db.Table(
Expand Down Expand Up @@ -416,23 +415,22 @@ def validate_state(self, key, state):

def __repr__(self):
if self.street_name and self.cross_street2:
return "Intersection of {} and {}, {} {}".format(
self.street_name, self.cross_street2, self.city, self.state
return (
f"Intersection of {self.street_name} and {self.cross_street2}, "
+ f"{self.city} {self.state}"
)
elif self.street_name and self.cross_street1:
return "Intersection of {} and {}, {} {}".format(
self.street_name, self.cross_street1, self.city, self.state
return (
f"Intersection of {self.street_name} and {self.cross_street1}, "
+ f"{self.city} {self.state}"
)
elif self.street_name and self.cross_street1 and self.cross_street2:
return "Intersection of {} between {} and {}, {} {}".format(
self.street_name,
self.cross_street1,
self.cross_street2,
self.city,
self.state,
return (
f"Intersection of {self.street_name} between {self.cross_street1} "
f"and {self.cross_street2}, {self.city} {self.state}"
)
else:
return "{} {}".format(self.city, self.state)
return f"{self.city} {self.state}"


class LicensePlate(BaseModel):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""add state column to departments

Revision ID: 18f43ac4622f
Revises: 1931b987ce0d
Create Date: 2023-07-26 15:51:05.329701

"""
import sqlalchemy as sa
from alembic import op


# revision identifiers, used by Alembic.
revision = "18f43ac4622f"
down_revision = "1931b987ce0d"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table("departments", schema=None) as batch_op:
batch_op.add_column(
sa.Column("state", sa.String(length=2), server_default="", nullable=False)
)
batch_op.drop_index("ix_departments_name")
batch_op.create_unique_constraint("departments_name_state", ["name", "state"])

# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table("departments", schema=None) as batch_op:
batch_op.drop_constraint("departments_name_state", type_="unique")
batch_op.create_index("ix_departments_name", ["name"], unique=False)
batch_op.drop_column("state")

# ### end Alembic commands ###
Loading