diff --git a/app/dao/template_categories_dao.py b/app/dao/template_categories_dao.py index 5aca12ff7b..03d4851498 100644 --- a/app/dao/template_categories_dao.py +++ b/app/dao/template_categories_dao.py @@ -1,6 +1,5 @@ import uuid -from flask import current_app from sqlalchemy import asc from app import db @@ -8,11 +7,13 @@ from app.models import TemplateCategory +@transactional def dao_create_template_category(template_category: TemplateCategory): template_category.id = uuid.uuid4() db.session.add(template_category) +@transactional def dao_update_template_category(template_category: TemplateCategory): db.session.add(template_category) diff --git a/app/dao/templates_dao.py b/app/dao/templates_dao.py index 822296cae4..7c4dd09bd1 100644 --- a/app/dao/templates_dao.py +++ b/app/dao/templates_dao.py @@ -78,6 +78,40 @@ def dao_update_template_reply_to(template_id, reply_to): return template +@transactional +def dao_update_template_category(template_id, category_id): + Template.query.filter_by(id=template_id).update( + { + "template_category_id": category_id, + "updated_at": datetime.utcnow(), + "version": Template.version + 1, + } + ) + + template = Template.query.filter_by(id=template_id).one() + + history = TemplateHistory( + **{ + "id": template.id, + "name": template.name, + "template_type": template.template_type, + "created_at": template.created_at, + "updated_at": template.updated_at, + "content": template.content, + "service_id": template.service_id, + "subject": template.subject, + "postage": template.postage, + "created_by_id": template.created_by_id, + "version": template.version, + "archived": template.archived, + "process_type": template.process_type, + "service_letter_contact_id": template.service_letter_contact_id, + } + ) + db.session.add(history) + return template + + @transactional def dao_redact_template(template, user_id): template.template_redacted.redact_personalisation = True diff --git a/app/models.py b/app/models.py index dbe2174e27..a9abcc0277 100644 --- a/app/models.py +++ b/app/models.py @@ -1045,6 +1045,23 @@ class TemplateCategory(BaseModel): email_process_type = db.Column(db.String(200), nullable=False) hidden = db.Column(db.Boolean, nullable=False, default=False) + def serialize(self): + return { + "id": self.id, + "name_en": self.name_en, + "name_fr": self.name_fr, + "description_en": self.description_en, + "description_fr": self.description_fr, + "sms_process_type": self.sms_process_type, + "email_process_type": self.email_process_type, + "hidden": self.hidden, + } + + @classmethod + def from_json(cls, data): + fields = data.copy() + return cls(**fields) + class TemplateBase(BaseModel): __abstract__ = True @@ -1196,7 +1213,7 @@ class Template(TemplateBase): service = db.relationship("Service", backref="templates") version = db.Column(db.Integer, default=0, nullable=False) - template_category = db.relationship("TemplateCategory", backref="templates") + category = db.relationship("TemplateCategory", backref="templates") folder = db.relationship( "TemplateFolder", diff --git a/app/schemas.py b/app/schemas.py index 75a6a2e78f..79996c0949 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -107,6 +107,32 @@ def make_instance(self, data, **kwargs): return super(BaseSchema, self).make_instance(data) +class TemplateCategorySchema(BaseSchema): + class Meta(BaseSchema.Meta): + model = models.TemplateCategory + exclude = ("id",) + + @validates("name_en") + def validate_name_en(self, value): + if not value: + raise ValidationError("Invalid name") + + @validates("name_fr") + def validate_name_fr(self, value): + if not value: + raise ValidationError("Invalid name") + + @validates("sms_process_type") + def validate_sms_process_type(self, value): + if value not in models.TEMPLATE_PROCESS_TYPE: + raise ValidationError("Invalid SMS process type") + + @validates("email_process_type") + def validate_email_process_type(self, value): + if value not in models.TEMPLATE_PROCESS_TYPE: + raise ValidationError("Invalid email process type") + + class UserSchema(BaseSchema): permissions = fields.Method("user_permissions", dump_only=True) password_changed_at = field_for(models.User, "password_changed_at", format="%Y-%m-%d %H:%M:%S.%f") @@ -805,6 +831,7 @@ def validate_archived(self, data, **kwargs): service_history_schema = ServiceHistorySchema() api_key_history_schema = ApiKeyHistorySchema() template_history_schema = TemplateHistorySchema() +template_category_schema = TemplateCategorySchema() event_schema = EventSchema() provider_details_schema = ProviderDetailsSchema() provider_details_history_schema = ProviderDetailsHistorySchema() diff --git a/app/template/rest.py b/app/template/rest.py index 46e5348dbf..32043496a5 100644 --- a/app/template/rest.py +++ b/app/template/rest.py @@ -25,6 +25,7 @@ dao_get_template_versions, dao_redact_template, dao_update_template, + dao_update_template_category, dao_update_template_reply_to, get_precompiled_letter_template, ) @@ -132,6 +133,25 @@ def create_template(service_id): return jsonify(data=template_schema.dump(new_template)), 201 +@template_blueprint.route("//template-category/", methods=["POST"]) +def update_templates_category(template_id, template_category_id): + updated = dao_update_template_category(template_id, template_category_id) + return jsonify(data=template_schema.dump(updated)), 200 + + +@template_blueprint.route("//process-type", methods=["POST"]) +def update_template_process_type(template_id): + data = request.get_json() + if "process_type" not in data: + message = "Field is required" + errors = {"process_type": [message]} + raise InvalidRequest(errors, status_code=400) + + # updated = dao_update_template_process_type(template_id=template_id, process_type=data.get("process_type")) + # return jsonify(data=template_schema.dump(updated)), 200 + pass + + @template_blueprint.route("/", methods=["POST"]) def update_template(service_id, template_id): fetched_template = dao_get_template_by_id_and_service_id(template_id=template_id, service_id=service_id) diff --git a/app/template/template_category_rest.py b/app/template/template_category_rest.py new file mode 100644 index 0000000000..dfd1d20efb --- /dev/null +++ b/app/template/template_category_rest.py @@ -0,0 +1,49 @@ +from flask import Blueprint, jsonify, request + +from app.dao.template_categories_dao import ( + dao_create_template_category, + dao_get_all_template_categories, + dao_get_template_category_by_id, + dao_update_template_category, +) +from app.models import TemplateCategory +from app.schemas import template_category_schema + +template_category_blueprint = Blueprint( + "template_category", + __name__, + url_prefix="template/category", +) + + +@template_category_blueprint.route("", methods=["POST"]) +def create_template_category(): + data = request.get_json() + + template_category_schema.load(data) + template_category = TemplateCategory.from_json(data) + + dao_create_template_category(template_category) + + return jsonify(data=template_category_schema.dump(template_category)), 201 + + +@template_category_blueprint.route("/", methods=["POST"]) +def update_template_category(template_category_id): + request_json = request.get_json() + update_dict = template_category_schema.load(request_json) + + category_to_update = dao_get_template_category_by_id(template_category_id) + + for key in request_json: + setattr(category_to_update, key, update_dict[key]) + + dao_update_template_category(category_to_update) + + return jsonify(data=category_to_update.serialize()), 200 + + +@template_category_blueprint.route("", methods=["GET"]) +def get_template_categories(): + template_categories = dao_get_all_template_categories() + return jsonify(data=template_category_schema.dump(template_categories, many=True)), 200 diff --git a/migrations/versions/0454_add_template_category.py b/migrations/versions/0454_add_template_category.py index 07d60a0383..e59b5599b7 100644 --- a/migrations/versions/0454_add_template_category.py +++ b/migrations/versions/0454_add_template_category.py @@ -19,6 +19,7 @@ DEFAULT_MEDIUM = "f75d6706-21b7-437e-b93a-2c0ab771e28e" DEFAULT_HIGH = "c4f87d7c-a55b-4c0f-91fe-e56c65bb1871" + def upgrade(): op.create_table( "template_categories", @@ -57,17 +58,20 @@ def upgrade(): op.create_foreign_key("fk_template_template_categories", "templates", "template_categories", ["template_category_id"], ["id"]) # Insert the generic low, medium, and high categories - op.execute(f""" + op.execute( + f""" INSERT INTO template_category (id, name_en, name_fr, sms_process_type, email_process_type, hidden) VALUES ({DEFAULT_LOW}, 'Low Category (Bulk)', 'Catégorie Basse (En Vrac)', true """ ) - op.execute(f""" + op.execute( + f""" INSERT INTO template_category (id, name_en, name_fr, sms_process_type, email_process_type, hidden) VALUES ({DEFAULT_MEDIUM}, 'Medium Category (Normal)', 'Catégorie Moyenne (Normale)', true """ ) - op.execute(f""" + op.execute( + f""" INSERT INTO template_category (id, name_en, name_fr, sms_process_type, email_process_type, hidden) VALUES ({DEFAULT_HIGH}, 'High Category (Priority)', 'Catégorie Haute (Priorité)', true """ diff --git a/tests/app/dao/test_template_categories_dao.py b/tests/app/dao/test_template_categories_dao.py index 2b5fbcfd36..a0925cbe0b 100644 --- a/tests/app/dao/test_template_categories_dao.py +++ b/tests/app/dao/test_template_categories_dao.py @@ -1,5 +1,3 @@ -import pytest - from app.dao.template_categories_dao import ( dao_create_template_category, dao_get_all_template_categories, @@ -8,7 +6,7 @@ dao_update_template_category, ) from app.dao.templates_dao import dao_create_template -from app.models import BULK, NORMAL, PRIORITY, Template, TemplateCategory +from app.models import BULK, NORMAL, Template, TemplateCategory def test_create_template_category(notify_db_session): @@ -60,7 +58,7 @@ def test_update_template_category(notify_db_session): assert dao_get_all_template_categories()[0].description_fr == "new french description" assert dao_get_all_template_categories()[0].sms_process_type == BULK assert dao_get_all_template_categories()[0].email_process_type == BULK - assert dao_get_all_template_categories()[0].hidden == True + assert dao_get_all_template_categories()[0].hidden assert dao_get_all_template_categories()[0].id == template_category.id @@ -116,8 +114,8 @@ def test_get_all_template_categories(notify_db_session): "name_fr": "french", "description_en": "english description", "description_fr": "french description", - "sms_process_type": NORMAL, - "email_process_type": NORMAL, + "sms_process_type": "normal", + "email_process_type": "normal", "hidden": False, } @@ -143,11 +141,11 @@ def test_get_all_template_categories(notify_db_session): assert dao_get_all_template_categories()[0].description_fr == "french description" assert dao_get_all_template_categories()[0].sms_process_type == NORMAL assert dao_get_all_template_categories()[0].email_process_type == NORMAL - assert dao_get_all_template_categories()[0].hidden == False + assert not dao_get_all_template_categories()[0].hidden assert dao_get_all_template_categories()[1].name_en == "english2" assert dao_get_all_template_categories()[1].name_fr == "french2" assert dao_get_all_template_categories()[1].description_en == "english description2" assert dao_get_all_template_categories()[1].description_fr == "french description2" assert dao_get_all_template_categories()[1].sms_process_type == BULK assert dao_get_all_template_categories()[1].email_process_type == BULK - assert dao_get_all_template_categories()[1].hidden == True + assert dao_get_all_template_categories()[1].hidden