mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-09-06 00:48:25 -04:00
Merge branch 'master' into flask-login-again
This commit is contained in:
156
app/models/contact_list.py
Normal file
156
app/models/contact_list.py
Normal file
@@ -0,0 +1,156 @@
|
||||
from functools import partial
|
||||
from os import path
|
||||
|
||||
from flask import abort, current_app
|
||||
from notifications_utils.formatters import strip_whitespace
|
||||
from notifications_utils.recipients import RecipientCSV
|
||||
from werkzeug.utils import cached_property
|
||||
|
||||
from app.models import JSONModel, ModelList
|
||||
from app.notify_client.contact_list_api_client import contact_list_api_client
|
||||
from app.s3_client.s3_csv_client import (
|
||||
get_csv_metadata,
|
||||
s3download,
|
||||
s3upload,
|
||||
set_metadata_on_csv_upload,
|
||||
)
|
||||
|
||||
|
||||
class ContactList(JSONModel):
|
||||
|
||||
ALLOWED_PROPERTIES = {
|
||||
'id',
|
||||
'created_at',
|
||||
'created_by',
|
||||
'service_id',
|
||||
'original_file_name',
|
||||
'row_count',
|
||||
'template_type',
|
||||
}
|
||||
|
||||
upload_type = 'contact_list'
|
||||
|
||||
@classmethod
|
||||
def from_id(cls, contact_list_id, *, service_id):
|
||||
return cls(contact_list_api_client.get_contact_list(
|
||||
service_id=service_id,
|
||||
contact_list_id=contact_list_id,
|
||||
))
|
||||
|
||||
@staticmethod
|
||||
def get_bucket_name():
|
||||
return current_app.config['CONTACT_LIST_UPLOAD_BUCKET_NAME']
|
||||
|
||||
@staticmethod
|
||||
def upload(service_id, file_dict):
|
||||
return s3upload(
|
||||
service_id,
|
||||
file_dict,
|
||||
current_app.config['AWS_REGION'],
|
||||
bucket=ContactList.get_bucket_name(),
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def download(service_id, upload_id):
|
||||
return strip_whitespace(s3download(
|
||||
service_id,
|
||||
upload_id,
|
||||
bucket=ContactList.get_bucket_name(),
|
||||
))
|
||||
|
||||
@staticmethod
|
||||
def set_metadata(service_id, upload_id, **kwargs):
|
||||
return set_metadata_on_csv_upload(
|
||||
service_id,
|
||||
upload_id,
|
||||
bucket=ContactList.get_bucket_name(),
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def get_metadata(service_id, upload_id):
|
||||
return get_csv_metadata(
|
||||
service_id,
|
||||
upload_id,
|
||||
bucket=ContactList.get_bucket_name(),
|
||||
)
|
||||
|
||||
def copy_to_uploads(self):
|
||||
metadata = self.get_metadata(self.service_id, self.id)
|
||||
new_upload_id = s3upload(
|
||||
self.service_id,
|
||||
{'data': self.contents},
|
||||
current_app.config['AWS_REGION'],
|
||||
)
|
||||
set_metadata_on_csv_upload(
|
||||
self.service_id,
|
||||
new_upload_id,
|
||||
**metadata,
|
||||
)
|
||||
return new_upload_id
|
||||
|
||||
@classmethod
|
||||
def create(cls, service_id, upload_id):
|
||||
|
||||
metadata = cls.get_metadata(service_id, upload_id)
|
||||
|
||||
if not metadata.get('valid'):
|
||||
abort(403)
|
||||
|
||||
return cls(contact_list_api_client.create_contact_list(
|
||||
service_id=service_id,
|
||||
upload_id=upload_id,
|
||||
original_file_name=metadata['original_file_name'],
|
||||
row_count=int(metadata['row_count']),
|
||||
template_type=metadata['template_type'],
|
||||
))
|
||||
|
||||
def delete(self):
|
||||
contact_list_api_client.delete_contact_list(
|
||||
service_id=self.service_id,
|
||||
contact_list_id=self.id,
|
||||
)
|
||||
|
||||
@property
|
||||
def contents(self):
|
||||
return self.download(self.service_id, self.id)
|
||||
|
||||
@cached_property
|
||||
def recipients(self):
|
||||
return RecipientCSV(
|
||||
self.contents,
|
||||
template_type=self.template_type,
|
||||
international_sms=True,
|
||||
max_initial_rows_shown=50,
|
||||
)
|
||||
|
||||
@property
|
||||
def saved_file_name(self):
|
||||
file_name, extention = path.splitext(self.original_file_name)
|
||||
return f'{file_name}.csv'
|
||||
|
||||
|
||||
class ContactLists(ModelList):
|
||||
|
||||
client_method = contact_list_api_client.get_contact_lists
|
||||
model = ContactList
|
||||
sort_function = partial(
|
||||
sorted,
|
||||
key=lambda item: item['created_at'],
|
||||
reverse=True,
|
||||
)
|
||||
|
||||
def __init__(self, service_id, template_type=None):
|
||||
super().__init__(service_id)
|
||||
self.items = self.sort_function([
|
||||
item for item in self.items
|
||||
if template_type in {item['template_type'], None}
|
||||
])
|
||||
|
||||
|
||||
class ContactListsAlphabetical(ContactLists):
|
||||
|
||||
sort_function = partial(
|
||||
sorted,
|
||||
key=lambda item: item['original_file_name'].lower(),
|
||||
)
|
||||
3
app/models/feedback.py
Normal file
3
app/models/feedback.py
Normal file
@@ -0,0 +1,3 @@
|
||||
QUESTION_TICKET_TYPE = 'ask-question-give-feedback'
|
||||
PROBLEM_TICKET_TYPE = 'report-problem'
|
||||
GENERAL_TICKET_TYPE = 'general'
|
||||
@@ -1,11 +1,8 @@
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from dateutil.parser import parse
|
||||
from flask import abort, current_app
|
||||
from notifications_utils.timezones import local_timezone
|
||||
from werkzeug.utils import cached_property
|
||||
|
||||
from app.models import JSONModel
|
||||
from app.models.contact_list import ContactLists
|
||||
from app.models.job import (
|
||||
ImmediateJobs,
|
||||
PaginatedJobs,
|
||||
@@ -497,10 +494,6 @@ class Service(JSONModel):
|
||||
key=lambda folder: folder['name'].lower(),
|
||||
)
|
||||
|
||||
@property
|
||||
def can_upload_letters(self):
|
||||
return self.has_permission('letter') and self.has_permission('upload_letters')
|
||||
|
||||
@cached_property
|
||||
def all_template_folder_ids(self):
|
||||
return {folder['id'] for folder in self.all_template_folders}
|
||||
@@ -671,27 +664,26 @@ class Service(JSONModel):
|
||||
if test:
|
||||
yield BASE + '_incomplete' + tag
|
||||
|
||||
@cached_property
|
||||
def returned_letter_statistics(self):
|
||||
return service_api_client.get_returned_letter_statistics(self.id)
|
||||
|
||||
@cached_property
|
||||
def returned_letter_summary(self):
|
||||
return service_api_client.get_returned_letter_summary(self.id)
|
||||
|
||||
@property
|
||||
def most_recent_returned_letter_report(self):
|
||||
if not self.returned_letter_summary:
|
||||
return None
|
||||
return parse(
|
||||
self.returned_letter_summary[0]['reported_at'] + " 00:00:00"
|
||||
).replace(tzinfo=local_timezone)
|
||||
def count_of_returned_letters_in_last_7_days(self):
|
||||
return self.returned_letter_statistics['returned_letter_count']
|
||||
|
||||
@property
|
||||
def count_of_returned_letters_in_last_7_days(self):
|
||||
seven_days_ago = (
|
||||
datetime.now() - timedelta(days=7)
|
||||
).replace(
|
||||
hour=0, minute=0, second=0
|
||||
)
|
||||
return sum(
|
||||
report['returned_letter_count']
|
||||
for report in self.returned_letter_summary
|
||||
if parse(report['reported_at'] + " 00:00:00") >= seven_days_ago
|
||||
)
|
||||
def date_of_most_recent_returned_letter_report(self):
|
||||
return self.returned_letter_statistics['most_recent_report']
|
||||
|
||||
@property
|
||||
def has_returned_letters(self):
|
||||
return bool(self.date_of_most_recent_returned_letter_report)
|
||||
|
||||
@property
|
||||
def contact_lists(self):
|
||||
return ContactLists(self.id)
|
||||
|
||||
Reference in New Issue
Block a user