mirror of
https://github.com/GSA/notifications-api.git
synced 2026-09-02 17:48:36 -04:00
Merge pull request #2873 from alphagov/serialise-template-immediately
Serialise template as soon as possible
This commit is contained in:
@@ -6,7 +6,14 @@ from app.notifications.process_notifications import persist_notification
|
|||||||
|
|
||||||
|
|
||||||
def create_letter_notification(
|
def create_letter_notification(
|
||||||
letter_data, template, api_key, status, reply_to_text=None, billable_units=None, updated_at=None
|
letter_data,
|
||||||
|
template,
|
||||||
|
service,
|
||||||
|
api_key,
|
||||||
|
status,
|
||||||
|
reply_to_text=None,
|
||||||
|
billable_units=None,
|
||||||
|
updated_at=None,
|
||||||
):
|
):
|
||||||
notification = persist_notification(
|
notification = persist_notification(
|
||||||
template_id=template.id,
|
template_id=template.id,
|
||||||
@@ -14,7 +21,7 @@ def create_letter_notification(
|
|||||||
template_postage=template.postage,
|
template_postage=template.postage,
|
||||||
# we only accept addresses_with_underscores from the API (from CSV we also accept dashes, spaces etc)
|
# we only accept addresses_with_underscores from the API (from CSV we also accept dashes, spaces etc)
|
||||||
recipient=PostalAddress.from_personalisation(letter_data['personalisation']).normalised,
|
recipient=PostalAddress.from_personalisation(letter_data['personalisation']).normalised,
|
||||||
service=template.service,
|
service=service,
|
||||||
personalisation=letter_data['personalisation'],
|
personalisation=letter_data['personalisation'],
|
||||||
notification_type=LETTER_TYPE,
|
notification_type=LETTER_TYPE,
|
||||||
api_key_id=api_key.id,
|
api_key_id=api_key.id,
|
||||||
|
|||||||
@@ -9,6 +9,11 @@ from notifications_utils.recipients import (
|
|||||||
validate_and_format_phone_number,
|
validate_and_format_phone_number,
|
||||||
format_email_address
|
format_email_address
|
||||||
)
|
)
|
||||||
|
from notifications_utils.template import (
|
||||||
|
PlainTextEmailTemplate,
|
||||||
|
SMSMessageTemplate,
|
||||||
|
LetterPrintTemplate,
|
||||||
|
)
|
||||||
from notifications_utils.timezones import convert_bst_to_utc
|
from notifications_utils.timezones import convert_bst_to_utc
|
||||||
|
|
||||||
from app import redis_store
|
from app import redis_store
|
||||||
@@ -44,7 +49,34 @@ REDIS_GET_AND_INCR_DAILY_LIMIT_DURATION_SECONDS = Histogram(
|
|||||||
|
|
||||||
|
|
||||||
def create_content_for_notification(template, personalisation):
|
def create_content_for_notification(template, personalisation):
|
||||||
template_object = template._as_utils_template_with_personalisation(personalisation)
|
if template.template_type == EMAIL_TYPE:
|
||||||
|
template_object = PlainTextEmailTemplate(
|
||||||
|
{
|
||||||
|
'content': template.content,
|
||||||
|
'subject': template.subject,
|
||||||
|
'template_type': template.template_type,
|
||||||
|
},
|
||||||
|
personalisation,
|
||||||
|
)
|
||||||
|
if template.template_type == SMS_TYPE:
|
||||||
|
template_object = SMSMessageTemplate(
|
||||||
|
{
|
||||||
|
'content': template.content,
|
||||||
|
'template_type': template.template_type,
|
||||||
|
},
|
||||||
|
personalisation,
|
||||||
|
)
|
||||||
|
if template.template_type == LETTER_TYPE:
|
||||||
|
template_object = LetterPrintTemplate(
|
||||||
|
{
|
||||||
|
'content': template.content,
|
||||||
|
'subject': template.subject,
|
||||||
|
'template_type': template.template_type,
|
||||||
|
},
|
||||||
|
personalisation,
|
||||||
|
contact_block=template.reply_to_text,
|
||||||
|
)
|
||||||
|
|
||||||
check_placeholders(template_object)
|
check_placeholders(template_object)
|
||||||
|
|
||||||
return template_object
|
return template_object
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ def send_notification(notification_type):
|
|||||||
api_key_id=api_user.id,
|
api_key_id=api_user.id,
|
||||||
key_type=api_user.key_type,
|
key_type=api_user.key_type,
|
||||||
simulated=simulated,
|
simulated=simulated,
|
||||||
reply_to_text=template.get_reply_to_text()
|
reply_to_text=template.reply_to_text
|
||||||
)
|
)
|
||||||
if not simulated:
|
if not simulated:
|
||||||
queue_name = QueueNames.PRIORITY if template.process_type == PRIORITY else None
|
queue_name = QueueNames.PRIORITY if template.process_type == PRIORITY else None
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from notifications_utils.recipients import (
|
|||||||
)
|
)
|
||||||
from notifications_utils.clients.redis import rate_limit_cache_key, daily_limit_cache_key
|
from notifications_utils.clients.redis import rate_limit_cache_key, daily_limit_cache_key
|
||||||
|
|
||||||
from app.dao import services_dao, templates_dao
|
from app.dao import services_dao
|
||||||
from app.dao.service_sms_sender_dao import dao_get_service_sms_senders_by_id
|
from app.dao.service_sms_sender_dao import dao_get_service_sms_senders_by_id
|
||||||
from app.models import (
|
from app.models import (
|
||||||
INTERNATIONAL_SMS_TYPE, SMS_TYPE, EMAIL_TYPE, LETTER_TYPE,
|
INTERNATIONAL_SMS_TYPE, SMS_TYPE, EMAIL_TYPE, LETTER_TYPE,
|
||||||
@@ -21,6 +21,7 @@ from app.notifications.process_notifications import create_content_for_notificat
|
|||||||
from app.utils import get_public_notify_type_text
|
from app.utils import get_public_notify_type_text
|
||||||
from app.dao.service_email_reply_to_dao import dao_get_reply_to_by_id
|
from app.dao.service_email_reply_to_dao import dao_get_reply_to_by_id
|
||||||
from app.dao.service_letter_contact_dao import dao_get_letter_contact_by_id
|
from app.dao.service_letter_contact_dao import dao_get_letter_contact_by_id
|
||||||
|
from app.serialised_models import SerialisedTemplate
|
||||||
|
|
||||||
from gds_metrics.metrics import Histogram
|
from gds_metrics.metrics import Histogram
|
||||||
|
|
||||||
@@ -156,11 +157,9 @@ def check_notification_content_is_not_empty(template_with_content):
|
|||||||
|
|
||||||
|
|
||||||
def validate_template(template_id, personalisation, service, notification_type):
|
def validate_template(template_id, personalisation, service, notification_type):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
template = templates_dao.dao_get_template_by_id_and_service_id(
|
template = SerialisedTemplate.from_id_and_service_id(template_id, service.id)
|
||||||
template_id=template_id,
|
|
||||||
service_id=service.id
|
|
||||||
)
|
|
||||||
except NoResultFound:
|
except NoResultFound:
|
||||||
message = 'Template not found'
|
message = 'Template not found'
|
||||||
raise BadRequestError(message=message,
|
raise BadRequestError(message=message,
|
||||||
|
|||||||
@@ -343,7 +343,9 @@ class BaseTemplateSchema(BaseSchema):
|
|||||||
|
|
||||||
class TemplateSchema(BaseTemplateSchema):
|
class TemplateSchema(BaseTemplateSchema):
|
||||||
|
|
||||||
created_by = field_for(models.Template, 'created_by', required=True)
|
created_by_id = field_for(
|
||||||
|
models.Template, 'created_by_id', dump_to='created_by', dump_only=True
|
||||||
|
)
|
||||||
process_type = field_for(models.Template, 'process_type')
|
process_type = field_for(models.Template, 'process_type')
|
||||||
redact_personalisation = fields.Method("redact")
|
redact_personalisation = fields.Method("redact")
|
||||||
|
|
||||||
@@ -357,6 +359,9 @@ class TemplateSchema(BaseTemplateSchema):
|
|||||||
if not subject or subject.strip() == '':
|
if not subject or subject.strip() == '':
|
||||||
raise ValidationError('Invalid template subject', 'subject')
|
raise ValidationError('Invalid template subject', 'subject')
|
||||||
|
|
||||||
|
class Meta(BaseTemplateSchema.Meta):
|
||||||
|
exclude = BaseTemplateSchema.Meta.exclude + ('created_by',)
|
||||||
|
|
||||||
|
|
||||||
class TemplateHistorySchema(BaseSchema):
|
class TemplateHistorySchema(BaseSchema):
|
||||||
|
|
||||||
|
|||||||
57
app/serialised_models.py
Normal file
57
app/serialised_models.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
from abc import ABC, abstractmethod
|
||||||
|
|
||||||
|
from app.dao import templates_dao
|
||||||
|
|
||||||
|
|
||||||
|
class SerialisedModel(ABC):
|
||||||
|
|
||||||
|
"""
|
||||||
|
A SerialisedModel takes a dictionary, typically created by
|
||||||
|
serialising a database object. It then takes the value of specified
|
||||||
|
keys from the dictionary and adds them to itself as properties, so
|
||||||
|
that it can be interacted with like a normal database model object,
|
||||||
|
but with no risk that it will actually go back to the database.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
@abstractmethod
|
||||||
|
def ALLOWED_PROPERTIES(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __init__(self, _dict):
|
||||||
|
for property in self.ALLOWED_PROPERTIES:
|
||||||
|
setattr(self, property, _dict[property])
|
||||||
|
|
||||||
|
def __dir__(self):
|
||||||
|
return super().__dir__() + list(sorted(self.ALLOWED_PROPERTIES))
|
||||||
|
|
||||||
|
|
||||||
|
class SerialisedTemplate(SerialisedModel):
|
||||||
|
ALLOWED_PROPERTIES = {
|
||||||
|
'archived',
|
||||||
|
'content',
|
||||||
|
'id',
|
||||||
|
'postage',
|
||||||
|
'process_type',
|
||||||
|
'reply_to_text',
|
||||||
|
'subject',
|
||||||
|
'template_type',
|
||||||
|
'version',
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_id_and_service_id(cls, template_id, service_id):
|
||||||
|
return cls(cls.get_dict(template_id, service_id))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_dict(template_id, service_id):
|
||||||
|
from app.schemas import template_schema
|
||||||
|
|
||||||
|
fetched_template = templates_dao.dao_get_template_by_id_and_service_id(
|
||||||
|
template_id=template_id,
|
||||||
|
service_id=service_id
|
||||||
|
)
|
||||||
|
|
||||||
|
template_dict = template_schema.dump(fetched_template).data
|
||||||
|
|
||||||
|
return template_dict
|
||||||
@@ -98,14 +98,13 @@ def post_precompiled_letter_notification():
|
|||||||
'address_line_1': 'Provided as PDF'
|
'address_line_1': 'Provided as PDF'
|
||||||
}
|
}
|
||||||
|
|
||||||
reply_to = get_reply_to_text(LETTER_TYPE, form, template)
|
|
||||||
|
|
||||||
notification = process_letter_notification(
|
notification = process_letter_notification(
|
||||||
letter_data=form,
|
letter_data=form,
|
||||||
api_key=api_user,
|
api_key=api_user,
|
||||||
|
service=authenticated_service,
|
||||||
template=template,
|
template=template,
|
||||||
template_with_content=None, # not required for precompiled
|
template_with_content=None, # not required for precompiled
|
||||||
reply_to_text=reply_to,
|
reply_to_text='', # not required for precompiled
|
||||||
precompiled=True
|
precompiled=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -147,6 +146,7 @@ def post_notification(notification_type):
|
|||||||
notification = process_letter_notification(
|
notification = process_letter_notification(
|
||||||
letter_data=form,
|
letter_data=form,
|
||||||
api_key=api_user,
|
api_key=api_user,
|
||||||
|
service=authenticated_service,
|
||||||
template=template,
|
template=template,
|
||||||
template_with_content=template_with_content,
|
template_with_content=template_with_content,
|
||||||
reply_to_text=reply_to
|
reply_to_text=reply_to
|
||||||
@@ -156,7 +156,8 @@ def post_notification(notification_type):
|
|||||||
form=form,
|
form=form,
|
||||||
notification_type=notification_type,
|
notification_type=notification_type,
|
||||||
api_key=api_user,
|
api_key=api_user,
|
||||||
template=template_with_content,
|
template=template,
|
||||||
|
template_with_content=template_with_content,
|
||||||
template_process_type=template.process_type,
|
template_process_type=template.process_type,
|
||||||
service=authenticated_service,
|
service=authenticated_service,
|
||||||
reply_to_text=reply_to
|
reply_to_text=reply_to
|
||||||
@@ -166,7 +167,15 @@ def post_notification(notification_type):
|
|||||||
|
|
||||||
|
|
||||||
def process_sms_or_email_notification(
|
def process_sms_or_email_notification(
|
||||||
*, form, notification_type, api_key, template, template_process_type, service, reply_to_text=None
|
*,
|
||||||
|
form,
|
||||||
|
notification_type,
|
||||||
|
api_key,
|
||||||
|
template,
|
||||||
|
template_with_content,
|
||||||
|
template_process_type,
|
||||||
|
service,
|
||||||
|
reply_to_text=None,
|
||||||
):
|
):
|
||||||
notification_id = uuid.uuid4()
|
notification_id = uuid.uuid4()
|
||||||
form_send_to = form['email_address'] if notification_type == EMAIL_TYPE else form['phone_number']
|
form_send_to = form['email_address'] if notification_type == EMAIL_TYPE else form['phone_number']
|
||||||
@@ -186,19 +195,19 @@ def process_sms_or_email_notification(
|
|||||||
)
|
)
|
||||||
if document_download_count:
|
if document_download_count:
|
||||||
# We changed personalisation which means we need to update the content
|
# We changed personalisation which means we need to update the content
|
||||||
template.values = personalisation
|
template_with_content.values = personalisation
|
||||||
key_type = api_key.key_type
|
key_type = api_key.key_type
|
||||||
service_in_research_mode = service.research_mode
|
service_in_research_mode = service.research_mode
|
||||||
resp = create_response_for_post_notification(
|
resp = create_response_for_post_notification(
|
||||||
notification_id=notification_id,
|
notification_id=notification_id,
|
||||||
client_reference=form.get('reference', None),
|
client_reference=form.get('reference', None),
|
||||||
template_id=template.id,
|
template_id=template.id,
|
||||||
template_version=template._template['version'],
|
template_version=template.version,
|
||||||
service_id=service.id,
|
service_id=service.id,
|
||||||
notification_type=notification_type,
|
notification_type=notification_type,
|
||||||
reply_to=reply_to_text,
|
reply_to=reply_to_text,
|
||||||
scheduled_for=form.get("scheduled_for", None),
|
scheduled_for=form.get("scheduled_for", None),
|
||||||
template_with_content=template)
|
template_with_content=template_with_content)
|
||||||
|
|
||||||
if str(service.id) in current_app.config.get('HIGH_VOLUME_SERVICE') and api_key.key_type == KEY_TYPE_NORMAL \
|
if str(service.id) in current_app.config.get('HIGH_VOLUME_SERVICE') and api_key.key_type == KEY_TYPE_NORMAL \
|
||||||
and notification_type == EMAIL_TYPE:
|
and notification_type == EMAIL_TYPE:
|
||||||
@@ -229,7 +238,7 @@ def process_sms_or_email_notification(
|
|||||||
persist_notification(
|
persist_notification(
|
||||||
notification_id=notification_id,
|
notification_id=notification_id,
|
||||||
template_id=template.id,
|
template_id=template.id,
|
||||||
template_version=template._template['version'],
|
template_version=template.version,
|
||||||
recipient=form_send_to,
|
recipient=form_send_to,
|
||||||
service=service,
|
service=service,
|
||||||
personalisation=personalisation,
|
personalisation=personalisation,
|
||||||
@@ -276,7 +285,7 @@ def save_email_to_queue(
|
|||||||
data = {
|
data = {
|
||||||
"id": notification_id,
|
"id": notification_id,
|
||||||
"template_id": str(template.id),
|
"template_id": str(template.id),
|
||||||
"template_version": template._template['version'],
|
"template_version": template.version,
|
||||||
"to": form['email_address'],
|
"to": form['email_address'],
|
||||||
"service_id": str(service_id),
|
"service_id": str(service_id),
|
||||||
"personalisation": personalisation,
|
"personalisation": personalisation,
|
||||||
@@ -328,7 +337,7 @@ def process_document_uploads(personalisation_data, service, simulated=False):
|
|||||||
|
|
||||||
|
|
||||||
def process_letter_notification(
|
def process_letter_notification(
|
||||||
*, letter_data, api_key, template, template_with_content, reply_to_text, precompiled=False
|
*, letter_data, api_key, service, template, template_with_content, reply_to_text, precompiled=False
|
||||||
):
|
):
|
||||||
if api_key.key_type == KEY_TYPE_TEAM:
|
if api_key.key_type == KEY_TYPE_TEAM:
|
||||||
raise BadRequestError(message='Cannot send letters with a team api key', status_code=403)
|
raise BadRequestError(message='Cannot send letters with a team api key', status_code=403)
|
||||||
@@ -339,6 +348,7 @@ def process_letter_notification(
|
|||||||
if precompiled:
|
if precompiled:
|
||||||
return process_precompiled_letter_notifications(letter_data=letter_data,
|
return process_precompiled_letter_notifications(letter_data=letter_data,
|
||||||
api_key=api_key,
|
api_key=api_key,
|
||||||
|
service=service,
|
||||||
template=template,
|
template=template,
|
||||||
reply_to_text=reply_to_text)
|
reply_to_text=reply_to_text)
|
||||||
|
|
||||||
@@ -360,6 +370,7 @@ def process_letter_notification(
|
|||||||
queue = QueueNames.CREATE_LETTERS_PDF if not test_key else QueueNames.RESEARCH_MODE
|
queue = QueueNames.CREATE_LETTERS_PDF if not test_key else QueueNames.RESEARCH_MODE
|
||||||
|
|
||||||
notification = create_letter_notification(letter_data=letter_data,
|
notification = create_letter_notification(letter_data=letter_data,
|
||||||
|
service=service,
|
||||||
template=template,
|
template=template,
|
||||||
api_key=api_key,
|
api_key=api_key,
|
||||||
status=status,
|
status=status,
|
||||||
@@ -414,7 +425,7 @@ def validate_address(api_key, letter_data):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def process_precompiled_letter_notifications(*, letter_data, api_key, template, reply_to_text):
|
def process_precompiled_letter_notifications(*, letter_data, api_key, service, template, reply_to_text):
|
||||||
try:
|
try:
|
||||||
status = NOTIFICATION_PENDING_VIRUS_CHECK
|
status = NOTIFICATION_PENDING_VIRUS_CHECK
|
||||||
letter_content = base64.b64decode(letter_data['content'])
|
letter_content = base64.b64decode(letter_data['content'])
|
||||||
@@ -422,6 +433,7 @@ def process_precompiled_letter_notifications(*, letter_data, api_key, template,
|
|||||||
raise BadRequestError(message='Cannot decode letter content (invalid base64 encoding)', status_code=400)
|
raise BadRequestError(message='Cannot decode letter content (invalid base64 encoding)', status_code=400)
|
||||||
|
|
||||||
notification = create_letter_notification(letter_data=letter_data,
|
notification = create_letter_notification(letter_data=letter_data,
|
||||||
|
service=service,
|
||||||
template=template,
|
template=template,
|
||||||
api_key=api_key,
|
api_key=api_key,
|
||||||
status=status,
|
status=status,
|
||||||
@@ -460,7 +472,7 @@ def get_reply_to_text(notification_type, form, template):
|
|||||||
service_email_reply_to_id = form.get("email_reply_to_id", None)
|
service_email_reply_to_id = form.get("email_reply_to_id", None)
|
||||||
reply_to = check_service_email_reply_to_id(
|
reply_to = check_service_email_reply_to_id(
|
||||||
str(authenticated_service.id), service_email_reply_to_id, notification_type
|
str(authenticated_service.id), service_email_reply_to_id, notification_type
|
||||||
) or template.get_reply_to_text()
|
) or template.reply_to_text
|
||||||
|
|
||||||
elif notification_type == SMS_TYPE:
|
elif notification_type == SMS_TYPE:
|
||||||
service_sms_sender_id = form.get("sms_sender_id", None)
|
service_sms_sender_id = form.get("sms_sender_id", None)
|
||||||
@@ -470,10 +482,10 @@ def get_reply_to_text(notification_type, form, template):
|
|||||||
if sms_sender_id:
|
if sms_sender_id:
|
||||||
reply_to = try_validate_and_format_phone_number(sms_sender_id)
|
reply_to = try_validate_and_format_phone_number(sms_sender_id)
|
||||||
else:
|
else:
|
||||||
reply_to = template.get_reply_to_text()
|
reply_to = template.reply_to_text
|
||||||
|
|
||||||
elif notification_type == LETTER_TYPE:
|
elif notification_type == LETTER_TYPE:
|
||||||
reply_to = template.get_reply_to_text()
|
reply_to = template.reply_to_text
|
||||||
|
|
||||||
return reply_to
|
return reply_to
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from app.models import LETTER_TYPE
|
|||||||
from app.models import Notification
|
from app.models import Notification
|
||||||
from app.models import NOTIFICATION_CREATED
|
from app.models import NOTIFICATION_CREATED
|
||||||
from app.notifications.process_letter_notifications import create_letter_notification
|
from app.notifications.process_letter_notifications import create_letter_notification
|
||||||
|
from app.serialised_models import SerialisedTemplate
|
||||||
|
|
||||||
|
|
||||||
def test_create_letter_notification_creates_notification(sample_letter_template, sample_api_key):
|
def test_create_letter_notification_creates_notification(sample_letter_template, sample_api_key):
|
||||||
@@ -13,7 +14,17 @@ def test_create_letter_notification_creates_notification(sample_letter_template,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
notification = create_letter_notification(data, sample_letter_template, sample_api_key, NOTIFICATION_CREATED)
|
template = SerialisedTemplate.from_id_and_service_id(
|
||||||
|
sample_letter_template.id, sample_letter_template.service_id
|
||||||
|
)
|
||||||
|
|
||||||
|
notification = create_letter_notification(
|
||||||
|
data,
|
||||||
|
template,
|
||||||
|
sample_letter_template.service,
|
||||||
|
sample_api_key,
|
||||||
|
NOTIFICATION_CREATED,
|
||||||
|
)
|
||||||
|
|
||||||
assert notification == Notification.query.one()
|
assert notification == Notification.query.one()
|
||||||
assert notification.job is None
|
assert notification.job is None
|
||||||
@@ -38,7 +49,17 @@ def test_create_letter_notification_sets_reference(sample_letter_template, sampl
|
|||||||
'reference': 'foo'
|
'reference': 'foo'
|
||||||
}
|
}
|
||||||
|
|
||||||
notification = create_letter_notification(data, sample_letter_template, sample_api_key, NOTIFICATION_CREATED)
|
template = SerialisedTemplate.from_id_and_service_id(
|
||||||
|
sample_letter_template.id, sample_letter_template.service_id
|
||||||
|
)
|
||||||
|
|
||||||
|
notification = create_letter_notification(
|
||||||
|
data,
|
||||||
|
template,
|
||||||
|
sample_letter_template.service,
|
||||||
|
sample_api_key,
|
||||||
|
NOTIFICATION_CREATED,
|
||||||
|
)
|
||||||
|
|
||||||
assert notification.client_reference == 'foo'
|
assert notification.client_reference == 'foo'
|
||||||
|
|
||||||
@@ -52,7 +73,17 @@ def test_create_letter_notification_sets_billable_units(sample_letter_template,
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
notification = create_letter_notification(data, sample_letter_template, sample_api_key, NOTIFICATION_CREATED,
|
template = SerialisedTemplate.from_id_and_service_id(
|
||||||
billable_units=3)
|
sample_letter_template.id, sample_letter_template.service_id
|
||||||
|
)
|
||||||
|
|
||||||
|
notification = create_letter_notification(
|
||||||
|
data,
|
||||||
|
template,
|
||||||
|
sample_letter_template.service,
|
||||||
|
sample_api_key,
|
||||||
|
NOTIFICATION_CREATED,
|
||||||
|
billable_units=3,
|
||||||
|
)
|
||||||
|
|
||||||
assert notification.billable_units == 3
|
assert notification.billable_units == 3
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ from app.models import (
|
|||||||
Notification,
|
Notification,
|
||||||
NotificationHistory,
|
NotificationHistory,
|
||||||
ScheduledNotification,
|
ScheduledNotification,
|
||||||
Template,
|
|
||||||
LETTER_TYPE
|
LETTER_TYPE
|
||||||
)
|
)
|
||||||
from app.notifications.process_notifications import (
|
from app.notifications.process_notifications import (
|
||||||
@@ -21,32 +20,41 @@ from app.notifications.process_notifications import (
|
|||||||
send_notification_to_queue,
|
send_notification_to_queue,
|
||||||
simulated_recipient
|
simulated_recipient
|
||||||
)
|
)
|
||||||
|
from app.serialised_models import SerialisedTemplate
|
||||||
from notifications_utils.recipients import validate_and_format_phone_number, validate_and_format_email_address
|
from notifications_utils.recipients import validate_and_format_phone_number, validate_and_format_email_address
|
||||||
from app.v2.errors import BadRequestError
|
from app.v2.errors import BadRequestError
|
||||||
from tests.app.db import create_service, create_template, create_api_key
|
from tests.app.db import create_service, create_template, create_api_key
|
||||||
|
|
||||||
|
|
||||||
def test_create_content_for_notification_passes(sample_email_template):
|
def test_create_content_for_notification_passes(sample_email_template):
|
||||||
template = Template.query.get(sample_email_template.id)
|
template = SerialisedTemplate.from_id_and_service_id(
|
||||||
|
sample_email_template.id, sample_email_template.service_id
|
||||||
|
)
|
||||||
content = create_content_for_notification(template, None)
|
content = create_content_for_notification(template, None)
|
||||||
assert str(content) == template.content + '\n'
|
assert str(content) == template.content + '\n'
|
||||||
|
|
||||||
|
|
||||||
def test_create_content_for_notification_with_placeholders_passes(sample_template_with_placeholders):
|
def test_create_content_for_notification_with_placeholders_passes(sample_template_with_placeholders):
|
||||||
template = Template.query.get(sample_template_with_placeholders.id)
|
template = SerialisedTemplate.from_id_and_service_id(
|
||||||
|
sample_template_with_placeholders.id, sample_template_with_placeholders.service_id
|
||||||
|
)
|
||||||
content = create_content_for_notification(template, {'name': 'Bobby'})
|
content = create_content_for_notification(template, {'name': 'Bobby'})
|
||||||
assert content.content == template.content
|
assert content.content == template.content
|
||||||
assert 'Bobby' in str(content)
|
assert 'Bobby' in str(content)
|
||||||
|
|
||||||
|
|
||||||
def test_create_content_for_notification_fails_with_missing_personalisation(sample_template_with_placeholders):
|
def test_create_content_for_notification_fails_with_missing_personalisation(sample_template_with_placeholders):
|
||||||
template = Template.query.get(sample_template_with_placeholders.id)
|
template = SerialisedTemplate.from_id_and_service_id(
|
||||||
|
sample_template_with_placeholders.id, sample_template_with_placeholders.service_id
|
||||||
|
)
|
||||||
with pytest.raises(BadRequestError):
|
with pytest.raises(BadRequestError):
|
||||||
create_content_for_notification(template, None)
|
create_content_for_notification(template, None)
|
||||||
|
|
||||||
|
|
||||||
def test_create_content_for_notification_allows_additional_personalisation(sample_template_with_placeholders):
|
def test_create_content_for_notification_allows_additional_personalisation(sample_template_with_placeholders):
|
||||||
template = Template.query.get(sample_template_with_placeholders.id)
|
template = SerialisedTemplate.from_id_and_service_id(
|
||||||
|
sample_template_with_placeholders.id, sample_template_with_placeholders.service_id
|
||||||
|
)
|
||||||
create_content_for_notification(template, {'name': 'Bobby', 'Additional placeholder': 'Data'})
|
create_content_for_notification(template, {'name': 'Bobby', 'Additional placeholder': 'Data'})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ from app.notifications.validators import (
|
|||||||
validate_and_format_recipient,
|
validate_and_format_recipient,
|
||||||
validate_template,
|
validate_template,
|
||||||
)
|
)
|
||||||
|
from app.serialised_models import SerialisedTemplate
|
||||||
from app.utils import get_template_instance
|
from app.utils import get_template_instance
|
||||||
|
|
||||||
from app.v2.errors import (
|
from app.v2.errors import (
|
||||||
@@ -314,7 +315,7 @@ def test_check_content_char_count_passes_for_long_email_or_letter(sample_service
|
|||||||
|
|
||||||
def test_check_notification_content_is_not_empty_passes(notify_api, mocker, sample_service):
|
def test_check_notification_content_is_not_empty_passes(notify_api, mocker, sample_service):
|
||||||
template_id = create_template(sample_service, content="Content is not empty").id
|
template_id = create_template(sample_service, content="Content is not empty").id
|
||||||
template = templates_dao.dao_get_template_by_id_and_service_id(
|
template = SerialisedTemplate.from_id_and_service_id(
|
||||||
template_id=template_id,
|
template_id=template_id,
|
||||||
service_id=sample_service.id
|
service_id=sample_service.id
|
||||||
)
|
)
|
||||||
@@ -330,7 +331,7 @@ def test_check_notification_content_is_not_empty_fails(
|
|||||||
notify_api, mocker, sample_service, template_content, notification_values
|
notify_api, mocker, sample_service, template_content, notification_values
|
||||||
):
|
):
|
||||||
template_id = create_template(sample_service, content=template_content).id
|
template_id = create_template(sample_service, content=template_content).id
|
||||||
template = templates_dao.dao_get_template_by_id_and_service_id(
|
template = SerialisedTemplate.from_id_and_service_id(
|
||||||
template_id=template_id,
|
template_id=template_id,
|
||||||
service_id=sample_service.id
|
service_id=sample_service.id
|
||||||
)
|
)
|
||||||
@@ -356,7 +357,7 @@ def test_validate_template_calls_all_validators(mocker, fake_uuid, sample_servic
|
|||||||
)
|
)
|
||||||
mock_check_not_empty = mocker.patch('app.notifications.validators.check_notification_content_is_not_empty')
|
mock_check_not_empty = mocker.patch('app.notifications.validators.check_notification_content_is_not_empty')
|
||||||
mock_check_message_is_too_long = mocker.patch('app.notifications.validators.check_content_char_count')
|
mock_check_message_is_too_long = mocker.patch('app.notifications.validators.check_content_char_count')
|
||||||
validate_template(template.id, {}, sample_service, "email")
|
template, template_with_content = validate_template(template.id, {}, sample_service, "email")
|
||||||
|
|
||||||
mock_check_type.assert_called_once_with("email", "email")
|
mock_check_type.assert_called_once_with("email", "email")
|
||||||
mock_check_if_active.assert_called_once_with(template)
|
mock_check_if_active.assert_called_once_with(template)
|
||||||
|
|||||||
Reference in New Issue
Block a user