Skip to content

Commit

Permalink
Add email/sms annual limit columns to services table (#2329)
Browse files Browse the repository at this point in the history
* Add email/sms annual limit columns to services table

* Add feature flag check

- formatting

* Add FF removal comments

* Add tests

* Update migration version

* Update migration version

* Bump utils
  • Loading branch information
whabanks authored Oct 31, 2024
1 parent b75c267 commit 868d8f4
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 6 deletions.
3 changes: 3 additions & 0 deletions app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,8 @@ class Config(object):
"job": "{}-dvla-file-per-job".format(os.getenv("NOTIFY_ENVIRONMENT", "development")),
"notification": "{}-dvla-letter-api-files".format(os.getenv("NOTIFY_ENVIRONMENT", "development")),
}
SERVICE_ANNUAL_EMAIL_LIMIT = env.int("SERVICE_ANNUAL_EMAIL_LIMIT", 10_000_000)
SERVICE_ANNUAL_SMS_LIMIT = env.int("SERVICE_ANNUAL_SMS_LIMIT", 25_000)

FREE_SMS_TIER_FRAGMENT_COUNT = 250000

Expand Down Expand Up @@ -566,6 +568,7 @@ class Config(object):
FF_CELERY_CUSTOM_TASK_PARAMS = env.bool("FF_CELERY_CUSTOM_TASK_PARAMS", True)
FF_CLOUDWATCH_METRICS_ENABLED = env.bool("FF_CLOUDWATCH_METRICS_ENABLED", False)
FF_SALESFORCE_CONTACT = env.bool("FF_SALESFORCE_CONTACT", False)
FF_ANNUAL_LIMIT = env.bool("FF_ANNUAL_LIMIT", False)

# SRE Tools auth keys
SRE_USER_NAME = "SRE_CLIENT_USER"
Expand Down
6 changes: 6 additions & 0 deletions app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
DELIVERY_STATUS_CALLBACK_TYPE = "delivery_status"
COMPLAINT_CALLBACK_TYPE = "complaint"
SERVICE_CALLBACK_TYPES = [DELIVERY_STATUS_CALLBACK_TYPE, COMPLAINT_CALLBACK_TYPE]
DEFAULT_SMS_ANNUAL_LIMIT = 25000
DEFAULT_EMAIL_ANNUAL_LIMIT = 10000000

sms_sending_vehicles = db.Enum(*[vehicle.value for vehicle in SmsSendingVehicles], name="sms_sending_vehicles")

Expand Down Expand Up @@ -565,6 +567,8 @@ class Service(BaseModel, Versioned):
sensitive_service = db.Column(db.Boolean, nullable=True)
organisation_id = db.Column(UUID(as_uuid=True), db.ForeignKey("organisation.id"), index=True, nullable=True)
organisation = db.relationship("Organisation", backref="services")
email_annual_limit = db.Column(db.BigInteger, nullable=False, default=DEFAULT_EMAIL_ANNUAL_LIMIT)
sms_annual_limit = db.Column(db.BigInteger, nullable=False, default=DEFAULT_SMS_ANNUAL_LIMIT)

email_branding = db.relationship(
"EmailBranding",
Expand Down Expand Up @@ -608,6 +612,8 @@ def from_json(cls, data):
fields.pop("letter_contact_block", None)
fields.pop("email_branding", None)
fields["sms_daily_limit"] = fields.get("sms_daily_limit", 100)
fields["email_annual_limit"] = fields.get("email_annual_limit", DEFAULT_EMAIL_ANNUAL_LIMIT)
fields["sms_annual_limit"] = fields.get("sms_annual_limit", DEFAULT_SMS_ANNUAL_LIMIT)

return cls(**fields)

Expand Down
2 changes: 2 additions & 0 deletions app/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ class ServiceSchema(BaseSchema, UUIDsAsStringsMixin):
go_live_at = field_for(models.Service, "go_live_at", format="%Y-%m-%d %H:%M:%S.%f")
organisation_notes = field_for(models.Service, "organisation_notes")
sensitive_service = field_for(models.Service, "sensitive_service")
email_annual_limit = field_for(models.Service, "email_annual_limit")
sms_annual_limit = field_for(models.Service, "sms_annual_limit")

def get_letter_logo_filename(self, service):
return service.letter_branding and service.letter_branding.filename
Expand Down
25 changes: 25 additions & 0 deletions app/service/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ def create_service():
return jsonify(data=service_schema.dump(valid_service)), 201


# TODO: FF_ANNUAL_LIMIT removal: Temporarily ignore complexity
# flake8: noqa: C901
@service_blueprint.route("/<uuid:service_id>", methods=["POST"])
def update_service(service_id):
req_json = request.get_json()
Expand All @@ -276,6 +278,12 @@ def update_service(service_id):
service_name_changed = fetched_service.name != req_json.get("name", fetched_service.name)
message_limit_changed = fetched_service.message_limit != req_json.get("message_limit", fetched_service.message_limit)
sms_limit_changed = fetched_service.sms_daily_limit != req_json.get("sms_daily_limit", fetched_service.sms_daily_limit)
email_annual_limit_changed = fetched_service.email_annual_limit != req_json.get(
"email_annual_limit", fetched_service.email_annual_limit
)
sms_annual_limit_changed = fetched_service.sms_annual_limit != req_json.get(
"sms_annual_limit", fetched_service.sms_annual_limit
)
current_data = dict(service_schema.dump(fetched_service).items())

current_data.update(request.get_json())
Expand Down Expand Up @@ -305,6 +313,15 @@ def update_service(service_id):
if not fetched_service.restricted:
_warn_service_users_about_sms_limit_changed(service_id, current_data)

# TODO: FF_ANNUAL_LIMIT removal
if current_app.config["FF_ANNUAL_LIMIT"]:
if sms_annual_limit_changed:
# TODO: Delete cache for sms annual limit (if used)
_warn_service_users_about_annual_sms_limit_changed(service_id, current_data)
if email_annual_limit_changed:
# TODO: Delete cache for email annual limit (if used)
_warn_service_users_about_annual_email_limit_changed(service_id, current_data)

if service_going_live:
_warn_services_users_about_going_live(service_id, current_data)

Expand All @@ -329,6 +346,14 @@ def update_service(service_id):
return jsonify(data=service_schema.dump(fetched_service)), 200


def _warn_service_users_about_annual_email_limit_changed(service_id, data):
pass


def _warn_service_users_about_annual_sms_limit_changed(service_id, data):
pass


def _warn_service_users_about_message_limit_changed(service_id, data):
send_notification_to_service_users(
service_id=service_id,
Expand Down
69 changes: 69 additions & 0 deletions migrations/versions/0463_add_annual_limit_column.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""
Revision ID: 0463_add_annual_limit_column
Revises: 0462_add_pinpoint_fields
Create Date: 2024-06-27 13:32:00
"""
import os

import sqlalchemy as sa
from alembic import op

from app import config

revision = "0463_add_annual_limit_column"
down_revision = "0462_add_pinpoint_fields"

cfg = config.configs[os.environ["NOTIFY_ENVIRONMENT"]] # type: ignore
default_email_annual_limit = str(cfg.SERVICE_ANNUAL_EMAIL_LIMIT)
default_sms_annual_limit = str(cfg.SERVICE_ANNUAL_SMS_LIMIT)


def upgrade():
# Add the new column to the templates table
op.add_column(
"services", sa.Column("email_annual_limit", sa.BigInteger(), nullable=True, server_default=default_email_annual_limit)
)
op.add_column(
"services", sa.Column("sms_annual_limit", sa.BigInteger(), nullable=True, server_default=default_sms_annual_limit)
)
# Add the new column to the templates_history table
op.add_column(
"services_history",
sa.Column("email_annual_limit", sa.BigInteger(), nullable=True, server_default=default_email_annual_limit),
)
op.add_column(
"services_history", sa.Column("sms_annual_limit", sa.BigInteger(), nullable=True, server_default=default_sms_annual_limit)
)

# Set the default values for existing services
op.execute(
f"""
UPDATE services
SET email_annual_limit = {default_email_annual_limit},
sms_annual_limit = {default_sms_annual_limit}
"""
)
# Since sms / email annual limit have been statically set to 25k and 10mil respectively
# we can update all service history rows safely
op.execute(
f"""
UPDATE services_history
SET email_annual_limit = {default_email_annual_limit},
sms_annual_limit = {default_sms_annual_limit}
"""
)

op.alter_column("services", "email_annual_limit", nullable=False)
op.alter_column("services", "sms_annual_limit", nullable=False)
op.alter_column("services_history", "email_annual_limit", nullable=False)
op.alter_column("services_history", "sms_annual_limit", nullable=False)


def downgrade():
# Remove the column from the services table
op.drop_column("services", "email_annual_limit")
op.drop_column("services", "sms_annual_limit")

# Remove the column from the services_history table
op.drop_column("services_history", "email_annual_limit")
op.drop_column("services_history", "sms_annual_limit")
Loading

0 comments on commit 868d8f4

Please sign in to comment.