-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #406 from CityOfNewYork/develop
OpenRecords v2.3
- Loading branch information
Showing
129 changed files
with
6,872 additions
and
4,364 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"globals": { | ||
"$": true, | ||
"document": true, | ||
"window": true, | ||
"jstz": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
language: python | ||
python: | ||
- 3.5.3 | ||
install: pip install -r requirements/dev.txt | ||
before_script: | ||
- psql -c 'create database openrecords_test;' -U postgres | ||
- psql -c 'create user testuser;' -U postgres | ||
- psql -c 'grant all privileges on all tables in schema public to testuser;' -U postgres | ||
- mkdir -p /home/travis/build/CityOfNewYork/NYCOpenRecords/logs/ | ||
- sleep 10 | ||
addons: | ||
postgresql: "9.5" | ||
services: | ||
- postgresql | ||
- redis-server | ||
- elasticsearch | ||
script: pytest -v "tests/" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,144 @@ | ||
from itertools import groupby | ||
from typing import Any, Dict, List, Sequence, Tuple | ||
|
||
from operator import itemgetter | ||
from sqlalchemy import or_ | ||
|
||
from app.models import ( | ||
Agencies, | ||
LetterTemplates | ||
) | ||
from app.models import Agencies, LetterTemplates, Reasons | ||
|
||
|
||
def get_active_users_as_choices(agency_ein): | ||
""" | ||
Retrieve a list of users that are active for a given agency | ||
:param agency_ein: Agency EIN (String) | ||
:return: A list of user tuples (id, name) | ||
def get_active_users_as_choices(agency_ein: str) -> List[Tuple[str, str]]: | ||
"""Retrieve a list of tuples representing users that are active for a given agency. Each tuple contains the | ||
following elements: | ||
(Users.guid, Users.name) | ||
Params: | ||
agency_ein (str): Agency EIN (4 Character String) | ||
Returns: | ||
List(Tuple(str, str)): A list of tuples with the following elements: | ||
(Users.guid, Users.name) | ||
""" | ||
active_users = sorted( | ||
[(user.get_id(), user.name) | ||
for user in Agencies.query.filter_by(ein=agency_ein).one().active_users], | ||
key=lambda x: x[1]) | ||
active_users.insert(0, ('', 'All')) | ||
[ | ||
(user.get_id(), user.name) | ||
for user in Agencies.query.filter_by(ein=agency_ein).one().active_users | ||
], | ||
key=lambda x: x[1], | ||
) | ||
active_users.insert(0, ("", "All")) | ||
return active_users | ||
|
||
|
||
def get_letter_templates(agency_ein, template_type=None): | ||
def get_reasons(agency_ein: str, reason_type: str = None) -> Dict: | ||
"""Retrieve the determination reasons (used in emails) for the specified agency as a JSON object. If reason_type is | ||
provided, only retrieve determination_reasons of that type. | ||
Args: | ||
agency_ein (str): Agency EIN | ||
reason_type (str): One of ("denial", "closing", "re-opening") | ||
Returns: | ||
Dict: | ||
{ | ||
'type_', [(reason_id, reason_title),...] | ||
} | ||
""" | ||
Retrieve letter templates for the specified agency as a JSON object. If template type is provided, only get | ||
templates of that type. | ||
if reason_type is not None: | ||
reasons = ( | ||
Reasons.query.with_entities(Reasons.id, Reasons.title, Reasons.type) | ||
.filter( | ||
Reasons.type == reason_type, | ||
or_(Reasons.agency_ein == agency_ein, Reasons.agency_ein == None), | ||
) | ||
.all() | ||
) | ||
else: | ||
reasons = ( | ||
Reasons.query.with_entities(Reasons.id, Reasons.title, Reasons.type) | ||
.filter(or_(Reasons.agency_ein == agency_ein, Reasons.agency_ein == None)) | ||
.all() | ||
) | ||
grouped_reasons = list(_group_items(reasons, 2)) | ||
|
||
reasons_dict = {} | ||
|
||
:param agency_ein: Agency EIN (String) | ||
:param template_type: One of "acknowledgment", "denial", "closing", "letter", "extension", "re-opening" (String) | ||
:return: Dictionary | ||
for group in grouped_reasons: | ||
determination_type = group[0] | ||
reasons = group[1] | ||
|
||
reasons_dict[determination_type] = [] | ||
|
||
for reason in reasons: | ||
reasons_dict[determination_type].append((reason[0], reason[1])) | ||
|
||
return reasons_dict | ||
|
||
|
||
def get_letter_templates(agency_ein: str, template_type: str = None) -> Dict: | ||
"""Retrieve letter templates for the specified agency as a dictionary. If template type is provided, only get | ||
templates of that type | ||
Params: | ||
Args: | ||
agency_ein (str): Agency EIN | ||
reason_type (str): One of "acknowledgment", "denial", "closing", "letter", "extension", "re-opening" | ||
Returns: | ||
Dict: | ||
{ | ||
'type_': [(template_id, template_name),...] | ||
} | ||
""" | ||
if template_type is not None: | ||
templates = LetterTemplates.query.with_entities(LetterTemplates.id, LetterTemplates.title, | ||
LetterTemplates.type_).filter( | ||
LetterTemplates.type_ == template_type).all() | ||
templates = ( | ||
LetterTemplates.query.with_entities( | ||
LetterTemplates.id, LetterTemplates.title, LetterTemplates.type_ | ||
) | ||
.filter(LetterTemplates.type_ == template_type) | ||
.all() | ||
) | ||
else: | ||
templates = LetterTemplates.query.with_entities(LetterTemplates.id, LetterTemplates.title, | ||
LetterTemplates.type_).filter_by(agency_ein=agency_ein).all() | ||
templates = ( | ||
LetterTemplates.query.with_entities( | ||
LetterTemplates.id, LetterTemplates.title, LetterTemplates.type_ | ||
) | ||
.filter_by(agency_ein=agency_ein) | ||
.all() | ||
) | ||
|
||
templates = list(_group_templates(templates)) | ||
grouped_templates = list(_group_items(templates, 2)) | ||
|
||
template_dict = {} | ||
|
||
for i in templates: | ||
type_ = i[0] | ||
vals = i[1] | ||
for group in grouped_templates: | ||
template_type = group[0] | ||
templates = group[1] | ||
|
||
template_dict[type_] = [] | ||
template_dict[template_type] = [] | ||
|
||
for i in vals: | ||
template_dict[type_].append((i[0], i[1])) | ||
for template in templates: | ||
template_dict[template_type].append((template[0], template[1])) | ||
|
||
if template_type is not None: | ||
return template_dict[template_type] | ||
return template_dict | ||
|
||
|
||
def _group_templates(templates): | ||
""" | ||
Group a list of templates by their type | ||
:param templates: List of templates (template.id, template.title, template.type_) | ||
:return: a generator containing each grouped template type | ||
def _group_items(items: Sequence[Sequence], sort_index: int) -> Tuple[Any, list]: | ||
"""Group a collection of items by a specified key | ||
Args: | ||
collections (Sequence): A collection of items to be grouped | ||
sort_index (int): Index of the item to use for grouping | ||
Yields: | ||
tuple: | ||
( | ||
items[sort_index_1], (Sequence[i], Sequence[j], ...), | ||
items[sort_index_2], (Sequence[i], Sequence[j], ...), | ||
... | ||
) | ||
""" | ||
grouped = groupby(templates, itemgetter(2)) | ||
grouped = groupby(items, itemgetter(sort_index)) | ||
|
||
for key, sub_iter in grouped: | ||
yield key, list(sub_iter) | ||
for item_index, sub_iter in grouped: | ||
yield item_index, list(sub_iter) |
Oops, something went wrong.