mirror of
https://github.com/GSA/notifications-api.git
synced 2026-08-11 09:27:56 -04:00
Merge branch 'master' into return-service_sms_sender_value
This commit is contained in:
3
Makefile
3
Makefile
@@ -283,6 +283,9 @@ cf-deploy: ## Deploys the app to Cloud Foundry
|
||||
.PHONY: cf-deploy-api-db-migration
|
||||
cf-deploy-api-db-migration:
|
||||
$(if ${CF_SPACE},,$(error Must specify CF_SPACE))
|
||||
cf unbind-service notify-api-db-migration notify-db
|
||||
cf unbind-service notify-api-db-migration notify-config
|
||||
cf unbind-service notify-api-db-migration notify-aws
|
||||
cf push notify-api-db-migration -f manifest-api-${CF_SPACE}.yml
|
||||
cf run-task notify-api-db-migration "python db.py db upgrade" --name api_db_migration
|
||||
|
||||
|
||||
@@ -370,7 +370,7 @@ def create_dvla_file_contents_for_notifications(notifications):
|
||||
notification.template.__dict__,
|
||||
notification.personalisation,
|
||||
notification_reference=notification.reference,
|
||||
contact_block=notification.service.letter_contact_block,
|
||||
contact_block=notification.service.get_default_letter_contact(),
|
||||
org_id=notification.service.dvla_organisation.id,
|
||||
))
|
||||
for notification in notifications
|
||||
|
||||
@@ -285,3 +285,23 @@ class PopulateServiceSmsSender(Command):
|
||||
print("Populated sms sender {} services from services".format(second_result.rowcount))
|
||||
print("{} services in table".format(services_count_query))
|
||||
print("{} service_sms_senders".format(service_sms_sender_count_query))
|
||||
|
||||
|
||||
class PopulateServiceLetterContact(Command):
|
||||
|
||||
def run(self):
|
||||
services_to_update = """
|
||||
INSERT INTO service_letter_contacts(id, service_id, contact_block, is_default, created_at)
|
||||
SELECT uuid_in(md5(random()::text || now()::text)::cstring), id, letter_contact_block, true, '{}'
|
||||
FROM services
|
||||
WHERE letter_contact_block IS NOT NULL
|
||||
AND id NOT IN(
|
||||
SELECT service_id
|
||||
FROM service_letter_contacts
|
||||
)
|
||||
""".format(datetime.utcnow())
|
||||
|
||||
result = db.session.execute(services_to_update)
|
||||
db.session.commit()
|
||||
|
||||
print("Populated letter contacts for {} services".format(result.rowcount))
|
||||
|
||||
@@ -358,15 +358,13 @@ def dao_fetch_monthly_historical_stats_for_service(service_id, year):
|
||||
|
||||
|
||||
@statsd(namespace='dao')
|
||||
def dao_fetch_todays_stats_for_all_services(include_from_test_key=True, trial_mode_services=None):
|
||||
def dao_fetch_todays_stats_for_all_services(include_from_test_key=True):
|
||||
|
||||
query = db.session.query(
|
||||
Notification.notification_type,
|
||||
Notification.status,
|
||||
Notification.service_id,
|
||||
func.count(Notification.id).label('count')
|
||||
).join(
|
||||
Service
|
||||
).filter(
|
||||
func.date(Notification.created_at) == date.today(),
|
||||
).group_by(
|
||||
@@ -380,9 +378,6 @@ def dao_fetch_todays_stats_for_all_services(include_from_test_key=True, trial_mo
|
||||
if not include_from_test_key:
|
||||
query = query.filter(Notification.key_type != KEY_TYPE_TEST)
|
||||
|
||||
if trial_mode_services is not None:
|
||||
query = query.filter(Service.restricted == trial_mode_services)
|
||||
|
||||
return query.all()
|
||||
|
||||
|
||||
|
||||
@@ -208,8 +208,7 @@ class Service(db.Model, Versioned):
|
||||
created_by = db.relationship('User')
|
||||
created_by_id = db.Column(UUID(as_uuid=True), db.ForeignKey('users.id'), index=True, nullable=False)
|
||||
_reply_to_email_address = db.Column("reply_to_email_address", db.Text, index=False, unique=False, nullable=True)
|
||||
letter_contact_block = db.Column(db.Text, index=False, unique=False, nullable=True)
|
||||
# This column is now deprecated
|
||||
_letter_contact_block = db.Column('letter_contact_block', db.Text, index=False, unique=False, nullable=True)
|
||||
sms_sender = db.Column(db.String(11), nullable=False, default=lambda: current_app.config['FROM_NUMBER'])
|
||||
organisation_id = db.Column(UUID(as_uuid=True), db.ForeignKey('organisation.id'), index=True, nullable=True)
|
||||
organisation = db.relationship('Organisation')
|
||||
@@ -274,8 +273,7 @@ class Service(db.Model, Versioned):
|
||||
if len(default_letter_contact) > 1:
|
||||
raise Exception("There should only ever be one default")
|
||||
else:
|
||||
return default_letter_contact[0].contact_block if default_letter_contact else \
|
||||
self.letter_contact_block # need to update this to None after dropping the letter_contact_block column
|
||||
return default_letter_contact[0].contact_block if default_letter_contact else None
|
||||
|
||||
|
||||
class InboundNumber(db.Model):
|
||||
@@ -549,7 +547,7 @@ class Template(db.Model):
|
||||
return LetterDVLATemplate(
|
||||
{'content': self.content, 'subject': self.subject},
|
||||
notification_reference=1,
|
||||
contact_block=self.service.letter_contact_block,
|
||||
contact_block=self.service.get_default_letter_contact(),
|
||||
)
|
||||
|
||||
def serialize(self):
|
||||
@@ -1450,3 +1448,24 @@ class ServiceLetterContact(db.Model):
|
||||
'created_at': self.created_at.strftime(DATETIME_FORMAT),
|
||||
'updated_at': self.updated_at.strftime(DATETIME_FORMAT) if self.updated_at else None
|
||||
}
|
||||
|
||||
|
||||
class NotificationEmailReplyTo(db.Model):
|
||||
__tablename__ = "notification_to_email_reply_to"
|
||||
|
||||
notification_id = db.Column(
|
||||
UUID(as_uuid=True),
|
||||
db.ForeignKey('notifications.id'),
|
||||
unique=True,
|
||||
index=True,
|
||||
nullable=False,
|
||||
primary_key=True
|
||||
)
|
||||
service_email_reply_to_id = db.Column(
|
||||
UUID(as_uuid=True),
|
||||
db.ForeignKey('service_email_reply_to.id'),
|
||||
unique=False,
|
||||
index=True,
|
||||
nullable=False,
|
||||
primary_key=True
|
||||
)
|
||||
|
||||
@@ -184,6 +184,7 @@ class ServiceSchema(BaseSchema):
|
||||
override_flag = False
|
||||
reply_to_email_address = fields.Method(method_name="get_reply_to_email_address")
|
||||
sms_sender = fields.Method(method_name="get_sms_sender")
|
||||
letter_contact_block = fields.Method(method_name="get_letter_contact")
|
||||
|
||||
def get_free_sms_fragment_limit(selfs, service):
|
||||
return service.free_sms_fragment_limit()
|
||||
@@ -197,9 +198,12 @@ class ServiceSchema(BaseSchema):
|
||||
def get_sms_sender(self, service):
|
||||
return service.get_default_sms_sender()
|
||||
|
||||
def get_letter_contact(self, service):
|
||||
return service.get_default_letter_contact()
|
||||
|
||||
class Meta:
|
||||
model = models.Service
|
||||
dump_only = ['free_sms_fragment_limit', 'reply_to_email_address']
|
||||
dump_only = ['free_sms_fragment_limit', 'reply_to_email_address', 'letter_contact_block']
|
||||
exclude = (
|
||||
'updated_at',
|
||||
'created_at',
|
||||
|
||||
@@ -90,7 +90,6 @@ def get_services():
|
||||
detailed = request.args.get('detailed') == 'True'
|
||||
user_id = request.args.get('user_id', None)
|
||||
include_from_test_key = request.args.get('include_from_test_key', 'True') != 'False'
|
||||
trial_mode_services = request.args.get('trial_mode_services')
|
||||
|
||||
# If start and end date are not set, we are expecting today's stats.
|
||||
today = str(datetime.utcnow().date())
|
||||
@@ -103,8 +102,7 @@ def get_services():
|
||||
elif detailed:
|
||||
result = jsonify(data=get_detailed_services(start_date=start_date, end_date=end_date,
|
||||
only_active=only_active,
|
||||
include_from_test_key=include_from_test_key,
|
||||
trial_mode_services=trial_mode_services
|
||||
include_from_test_key=include_from_test_key
|
||||
))
|
||||
return result
|
||||
else:
|
||||
@@ -149,7 +147,6 @@ def update_service(service_id):
|
||||
fetched_service = dao_fetch_service_by_id(service_id)
|
||||
# Capture the status change here as Marshmallow changes this later
|
||||
service_going_live = fetched_service.restricted and not req_json.get('restricted', True)
|
||||
|
||||
current_data = dict(service_schema.dump(fetched_service).data.items())
|
||||
current_data.update(request.get_json())
|
||||
update_dict = service_schema.load(current_data).data
|
||||
@@ -369,12 +366,10 @@ def get_detailed_service(service_id, today_only=False):
|
||||
return detailed_service_schema.dump(service).data
|
||||
|
||||
|
||||
def get_detailed_services(start_date, end_date, only_active=False, include_from_test_key=True,
|
||||
trial_mode_services=None):
|
||||
def get_detailed_services(start_date, end_date, only_active=False, include_from_test_key=True):
|
||||
services = {service.id: service for service in dao_fetch_all_services(only_active)}
|
||||
if start_date == datetime.utcnow().date():
|
||||
stats = dao_fetch_todays_stats_for_all_services(include_from_test_key=include_from_test_key,
|
||||
trial_mode_services=trial_mode_services)
|
||||
stats = dao_fetch_todays_stats_for_all_services(include_from_test_key=include_from_test_key)
|
||||
else:
|
||||
|
||||
stats = fetch_stats_by_date_range_for_all_services(start_date=start_date,
|
||||
|
||||
@@ -20,6 +20,7 @@ manager.add_command('populate_monthly_billing', commands.PopulateMonthlyBilling)
|
||||
manager.add_command('backfill_processing_time', commands.BackfillProcessingTime)
|
||||
manager.add_command('populate_service_email_reply_to', commands.PopulateServiceEmailReplyTo)
|
||||
manager.add_command('populate_service_sms_sender', commands.PopulateServiceSmsSender)
|
||||
manager.add_command('populate_service_letter_contact', commands.PopulateServiceLetterContact)
|
||||
|
||||
|
||||
@manager.command
|
||||
|
||||
30
migrations/versions/0123_add_noti_to_email_reply.py
Normal file
30
migrations/versions/0123_add_noti_to_email_reply.py
Normal file
@@ -0,0 +1,30 @@
|
||||
"""
|
||||
|
||||
Revision ID: 0123_add_noti_to_email_reply
|
||||
Revises: 0122_add_service_letter_contact
|
||||
Create Date: 2017-09-27 09:42:39.412731
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
revision = '0123_add_noti_to_email_reply'
|
||||
down_revision = '0122_add_service_letter_contact'
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table('notification_to_email_reply_to',
|
||||
sa.Column('notification_id', postgresql.UUID(as_uuid=True), nullable=False),
|
||||
sa.Column('service_email_reply_to_id', postgresql.UUID(as_uuid=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['notification_id'], ['notifications.id'], ),
|
||||
sa.ForeignKeyConstraint(['service_email_reply_to_id'], ['service_email_reply_to.id'], ),
|
||||
sa.PrimaryKeyConstraint('notification_id', 'service_email_reply_to_id')
|
||||
)
|
||||
op.create_index(op.f('ix_notification_to_email_reply_to_notification_id'), 'notification_to_email_reply_to', ['notification_id'], unique=True)
|
||||
op.create_index(op.f('ix_notification_to_email_reply_to_service_email_reply_to_id'), 'notification_to_email_reply_to', ['service_email_reply_to_id'], unique=False)
|
||||
|
||||
def downgrade():
|
||||
op.drop_index(op.f('ix_notification_to_email_reply_to_service_email_reply_to_id'), table_name='notification_to_email_reply_to')
|
||||
op.drop_index(op.f('ix_notification_to_email_reply_to_notification_id'), table_name='notification_to_email_reply_to')
|
||||
op.drop_table('notification_to_email_reply_to')
|
||||
@@ -1,4 +1,5 @@
|
||||
boto3==1.4.7
|
||||
cffi==1.11.0 # pyup: != 1.11.1 # 1.11.1 is missing .whl
|
||||
celery==3.1.25 # pyup: <4
|
||||
docopt==0.6.2
|
||||
Flask-Bcrypt==0.7.1
|
||||
|
||||
@@ -1 +1 @@
|
||||
python-3.5.2
|
||||
python-3.5.4
|
||||
|
||||
@@ -2,7 +2,6 @@ import json
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from unittest.mock import Mock
|
||||
|
||||
import pytest
|
||||
import requests_mock
|
||||
from flask import current_app
|
||||
@@ -29,14 +28,17 @@ from app.celery.tasks import (
|
||||
from app.config import QueueNames
|
||||
from app.dao import jobs_dao, services_dao
|
||||
from app.models import (
|
||||
Notification,
|
||||
EMAIL_TYPE,
|
||||
JOB_STATUS_ERROR,
|
||||
KEY_TYPE_NORMAL,
|
||||
KEY_TYPE_TEAM,
|
||||
KEY_TYPE_TEST,
|
||||
KEY_TYPE_NORMAL,
|
||||
SMS_TYPE,
|
||||
EMAIL_TYPE,
|
||||
LETTER_TYPE,
|
||||
Job)
|
||||
SERVICE_PERMISSION_TYPES,
|
||||
SMS_TYPE,
|
||||
Job,
|
||||
Notification
|
||||
)
|
||||
|
||||
from tests.app import load_example_csv
|
||||
from tests.app.conftest import (
|
||||
@@ -46,7 +48,16 @@ from tests.app.conftest import (
|
||||
sample_email_template as create_sample_email_template,
|
||||
sample_notification as create_sample_notification
|
||||
)
|
||||
from tests.app.db import create_user, create_notification, create_job, create_service_inbound_api, create_inbound_sms
|
||||
from tests.app.db import (
|
||||
create_inbound_sms,
|
||||
create_job,
|
||||
create_letter_contact,
|
||||
create_notification,
|
||||
create_service_inbound_api,
|
||||
create_service,
|
||||
create_template,
|
||||
create_user
|
||||
)
|
||||
|
||||
|
||||
class AnyStringWith(str):
|
||||
@@ -1076,8 +1087,11 @@ def test_build_dvla_file_retries_if_all_notifications_are_not_created(sample_let
|
||||
mocked_send_task.assert_not_called()
|
||||
|
||||
|
||||
def test_create_dvla_file_contents_for_job(sample_letter_template, mocker):
|
||||
job = create_job(template=sample_letter_template, notification_count=2)
|
||||
def test_create_dvla_file_contents(notify_db_session, mocker):
|
||||
service = create_service(service_permissions=SERVICE_PERMISSION_TYPES)
|
||||
create_letter_contact(service=service, contact_block='London,\nNW1A 1AA')
|
||||
letter_template = create_template(service=service, template_type=LETTER_TYPE)
|
||||
job = create_job(template=letter_template, notification_count=2)
|
||||
create_notification(template=job.template, job=job, reference=1)
|
||||
create_notification(template=job.template, job=job, reference=2)
|
||||
mocked_letter_template = mocker.patch("app.celery.tasks.LetterDVLATemplate")
|
||||
@@ -1093,9 +1107,8 @@ def test_create_dvla_file_contents_for_job(sample_letter_template, mocker):
|
||||
# Personalisation
|
||||
assert not calls[0][0][1]
|
||||
assert not calls[1][0][1]
|
||||
|
||||
# Named arguments
|
||||
assert calls[1][1]['contact_block'] == 'London,\nSW1A 1AA'
|
||||
assert calls[1][1]['contact_block'] == 'London,\nNW1A 1AA'
|
||||
assert calls[0][1]['notification_reference'] == '1'
|
||||
assert calls[1][1]['notification_reference'] == '2'
|
||||
assert calls[1][1]['org_id'] == '001'
|
||||
|
||||
@@ -46,7 +46,8 @@ from tests.app.db import (
|
||||
create_notification,
|
||||
create_service,
|
||||
create_api_key,
|
||||
create_inbound_number
|
||||
create_inbound_number,
|
||||
create_letter_contact,
|
||||
)
|
||||
|
||||
|
||||
@@ -138,7 +139,6 @@ def sample_service(
|
||||
email_from=None,
|
||||
permissions=[SMS_TYPE, EMAIL_TYPE],
|
||||
research_mode=None,
|
||||
letter_contact_block='London,\nSW1A 1AA',
|
||||
):
|
||||
if user is None:
|
||||
user = create_user()
|
||||
@@ -150,8 +150,7 @@ def sample_service(
|
||||
'message_limit': limit,
|
||||
'restricted': restricted,
|
||||
'email_from': email_from,
|
||||
'created_by': user,
|
||||
'letter_contact_block': letter_contact_block,
|
||||
'created_by': user
|
||||
}
|
||||
service = Service.query.filter_by(name=service_name).first()
|
||||
if not service:
|
||||
@@ -184,7 +183,9 @@ def sample_service_full_permissions(notify_db, notify_db_session):
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def sample_service_custom_letter_contact_block(notify_db, notify_db_session):
|
||||
return sample_service(notify_db, notify_db_session, letter_contact_block='((contact block))')
|
||||
service = sample_service(notify_db, notify_db_session)
|
||||
create_letter_contact(service, contact_block='((contact block))')
|
||||
return service
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
|
||||
@@ -1548,8 +1548,7 @@ def test_get_services_with_detailed_flag_accepts_date_range(client, mocker):
|
||||
start_date=date(2001, 1, 1),
|
||||
end_date=date(2002, 2, 2),
|
||||
only_active=ANY,
|
||||
include_from_test_key=ANY,
|
||||
trial_mode_services=ANY
|
||||
include_from_test_key=ANY
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
|
||||
@@ -1566,8 +1565,7 @@ def test_get_services_with_detailed_flag_defaults_to_today(client, mocker):
|
||||
end_date=date(2002, 2, 2),
|
||||
include_from_test_key=ANY,
|
||||
only_active=ANY,
|
||||
start_date=date(2002, 2, 2),
|
||||
trial_mode_services=ANY
|
||||
start_date=date(2002, 2, 2)
|
||||
)
|
||||
|
||||
assert resp.status_code == 200
|
||||
|
||||
Reference in New Issue
Block a user