diff --git a/app/blueprints/fund_builder/routes.py b/app/blueprints/fund_builder/routes.py index dd6ab4b..52c5536 100644 --- a/app/blueprints/fund_builder/routes.py +++ b/app/blueprints/fund_builder/routes.py @@ -16,6 +16,7 @@ from app.blueprints.fund_builder.forms.round import RoundForm from app.db.models.fund import Fund from app.db.models.round import Round +from app.db.queries.application import clone_single_round from app.db.queries.application import get_form_by_id from app.db.queries.fund import add_fund from app.db.queries.fund import get_all_funds @@ -67,6 +68,15 @@ def view_app_config(round_id): return render_template("view_application_config.html", round=round, fund=fund) +@build_fund_bp.route("/fund//round//clone") +def clone_round(round_id, fund_id): + + cloned = clone_single_round(round_id=round_id, new_fund_id=fund_id, new_short_name=f"R-C{randint(0,999)}") + flash(f"Cloned new round: {cloned.short_name}") + + return redirect(url_for("build_fund_bp.view_fund", fund_id=fund_id)) + + @build_fund_bp.route("/fund/round//assessment_config") def view_assess_config(round_id): """ diff --git a/app/blueprints/fund_builder/templates/view_fund_config.html b/app/blueprints/fund_builder/templates/view_fund_config.html index d54706d..6813973 100644 --- a/app/blueprints/fund_builder/templates/view_fund_config.html +++ b/app/blueprints/fund_builder/templates/view_fund_config.html @@ -159,6 +159,12 @@

{{round.title_json["en"]}}

"href": url_for("build_fund_bp.view_assess_config", round_id=round.round_id), "classes": "govuk-button--secondary" }) }} + + {{ govukButton({ + "text": "Clone this round", + "href": url_for("build_fund_bp.clone_round", round_id=round.round_id, fund_id=fund.fund_id), + "classes": "govuk-button--secondary" + }) }} {% endfor %} {% endset %} diff --git a/app/db/migrations/versions/~2024_07_19_1320-da88c6b36588_.py b/app/db/migrations/versions/~2024_07_19_1320-da88c6b36588_.py new file mode 100644 index 0000000..5adba7a --- /dev/null +++ b/app/db/migrations/versions/~2024_07_19_1320-da88c6b36588_.py @@ -0,0 +1,38 @@ +"""empty message + +Revision ID: da88c6b36588 +Revises: 3de2807b6917 +Create Date: 2024-07-19 13:20:24.997440 + +""" + +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision = "da88c6b36588" +down_revision = "3de2807b6917" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table("round", schema=None) as batch_op: + batch_op.add_column(sa.Column("prospectus_link", sa.String(), nullable=False)) + batch_op.add_column(sa.Column("privacy_notice_link", sa.String(), nullable=False)) + batch_op.drop_column("privacy_notice") + batch_op.drop_column("prospectus") + + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table("round", schema=None) as batch_op: + batch_op.add_column(sa.Column("prospectus", sa.VARCHAR(), autoincrement=False, nullable=False)) + batch_op.add_column(sa.Column("privacy_notice", sa.VARCHAR(), autoincrement=False, nullable=False)) + batch_op.drop_column("privacy_notice_link") + batch_op.drop_column("prospectus_link") + + # ### end Alembic commands ### diff --git a/app/db/models/round.py b/app/db/models/round.py index 289c26d..c3ceca2 100644 --- a/app/db/models/round.py +++ b/app/db/models/round.py @@ -7,6 +7,7 @@ from sqlalchemy import ForeignKey from sqlalchemy import String from sqlalchemy import UniqueConstraint +from sqlalchemy import inspect from sqlalchemy.dialects.postgresql import JSON from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import Mapped @@ -24,31 +25,35 @@ class Round(BaseModel): __table_args__ = (UniqueConstraint("fund_id", "short_name"),) round_id = Column( - "round_id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, nullable=False, ) fund_id = Column( - "fund_id", UUID(as_uuid=True), ForeignKey("fund.fund_id"), nullable=False, ) - title_json = Column("title_json", JSON(none_as_null=True), nullable=False, unique=False) - short_name = Column("short_name", db.String(), nullable=False, unique=False) - opens = Column("opens", DateTime()) - deadline = Column("deadline", DateTime()) - assessment_start = Column("assessment_start", DateTime()) - reminder_date = Column("reminder_date", DateTime()) - assessment_deadline = Column("assessment_deadline", DateTime()) - prospectus_link = Column("prospectus", db.String(), nullable=False, unique=False) - privacy_notice_link = Column("privacy_notice", db.String(), nullable=False, unique=False) - audit_info = Column("audit_info", JSON(none_as_null=True)) - is_template = Column("is_template", Boolean, default=False, nullable=False) + title_json = Column(JSON(none_as_null=True), nullable=False, unique=False) + short_name = Column(db.String(), nullable=False, unique=False) + opens = Column(DateTime()) + deadline = Column(DateTime()) + assessment_start = Column(DateTime()) + reminder_date = Column(DateTime()) + assessment_deadline = Column(DateTime()) + prospectus_link = Column(db.String(), nullable=False, unique=False) + privacy_notice_link = Column(db.String(), nullable=False, unique=False) + audit_info = Column(JSON(none_as_null=True)) + is_template = Column(Boolean, default=False, nullable=False) source_template_id = Column(UUID(as_uuid=True), nullable=True) template_name = Column(String(), nullable=True) sections: Mapped[list["Section"]] = relationship("Section") criteria: Mapped[list["Criteria"]] = relationship("Criteria") # several other fields to add + + def __repr__(self): + return f"Round({self.short_name - self.title_json['en']}, Sections: {self.sections})" + + def as_dict(self): + return {col.name: self.__getattribute__(col.name) for col in inspect(self).mapper.columns} diff --git a/app/db/queries/application.py b/app/db/queries/application.py index 338adc1..727c651 100644 --- a/app/db/queries/application.py +++ b/app/db/queries/application.py @@ -181,15 +181,16 @@ def clone_multiple_components(component_ids: list[str], new_page_id=None, new_th return clones -def clone_single_round(round_id, new_fund_id) -> Round: +def clone_single_round(round_id, new_fund_id, new_short_name) -> Round: round_to_clone = db.session.query(Round).where(Round.round_id == round_id).one_or_none() - cloned_round = Round(**round_to_clone) + cloned_round = Round(**round_to_clone.as_dict()) + cloned_round.short_name = new_short_name cloned_round.round_id = uuid4() cloned_round.fund_id = new_fund_id cloned_round.is_template = False cloned_round.source_template_id = round_to_clone.round_id cloned_round.template_name = None - cloned_round.sections = None + cloned_round.sections = [] db.session.add(cloned_round) db.session.commit()