diff --git a/backend/app/db/models/portfolio.py b/backend/app/db/models/portfolio.py index f1355197..7580a27d 100644 --- a/backend/app/db/models/portfolio.py +++ b/backend/app/db/models/portfolio.py @@ -3,6 +3,7 @@ import pytz import datetime from sqlalchemy import Column, Integer, Text, Boolean, Float, DateTime, Enum, ForeignKey, CheckConstraint from sqlalchemy.ext.declarative import declarative_base +from backend.app.db.models.users import UserModel # noqa Base = declarative_base() @@ -210,7 +211,7 @@ class PropertyTargetsModel(Base): class PortfolioUsers(Base): __tablename__ = "portfolioUsers" id = Column(Integer, primary_key=True, autoincrement=True) - userId = Column(Integer, ForeignKey('user.id'), nullable=False) + user_id = Column(Integer, ForeignKey('user.id'), nullable=False) portfolioId = Column(Integer, ForeignKey('portfolio.id'), nullable=False) role = Column(Text, nullable=False) created_at = Column(DateTime, nullable=False, default=datetime.datetime.now(pytz.utc)) diff --git a/backend/app/plan/router.py b/backend/app/plan/router.py index 25e41e52..23d3f5d2 100644 --- a/backend/app/plan/router.py +++ b/backend/app/plan/router.py @@ -313,7 +313,7 @@ def get_on_site_data(body: PlanTriggerRequest): def extract_property_on_site_recommendations(config, patches, already_installed, non_invasive_recommendations, uprn): - patch_has_uprn = "uprn" in patches[0] + patch_has_uprn = "uprn" in patches[0] if patches else True if patch_has_uprn: patch = next(( x for x in patches if str(x["uprn"]) == str(config["uprn"]) @@ -330,7 +330,7 @@ def extract_property_on_site_recommendations(config, patches, already_installed, # Because we have some non-invasive recommendations that match on address and postcode, but not UPRN # we need to check existence of uprn - has_uprn = "uprn" in non_invasive_recommendations[0] + has_uprn = "uprn" in non_invasive_recommendations[0] if non_invasive_recommendations else True if has_uprn: property_non_invasive_recommendations = next(( x for x in non_invasive_recommendations if diff --git a/etl/ownership/projects/midlands_portfolio/app.py b/etl/ownership/projects/midlands_portfolio/app.py index 905ff0e4..bf18d846 100644 --- a/etl/ownership/projects/midlands_portfolio/app.py +++ b/etl/ownership/projects/midlands_portfolio/app.py @@ -1,9 +1,9 @@ from sqlalchemy.orm import sessionmaker -from sqlalchemy.orm.exc import NoResultFound from backend.app.db.connection import db_engine from backend.app.db.models.portfolio import Portfolio, PortfolioUsers from etl.ownership.Ownership import Ownership from etl.ownership.config import OWNERS_WHO_CANT_SELL as EXCLUDED_OWNERS +from utils.s3 import save_csv_to_s3 # Set up the project configuration USER_IDS = [ @@ -61,46 +61,51 @@ PROPERTY_VALUE_ESTIMATE = 200_000 PORTFOLIO_VALUE = 75_000_000 -def create_sfr_portfolio(project_name, user_ids): +def create_sfr_portfolio(project_name, user_ids, status, goal): session = sessionmaker(bind=db_engine)() - session.begin() - - # Check for an existing portfolio by name try: - portfolio = session.query(Portfolio).filter_by(name=project_name).one() - except NoResultFound: - portfolio = None + session.begin() - if portfolio: - # Fetch the associated users - existing_user_ids = { - pu.userId for pu in session.query(PortfolioUsers.userId).filter_by(portfolioId=portfolio.id) - } + # Check for an existing portfolio by name + portfolio = session.query(Portfolio).filter_by(name=project_name).one_or_none() - # Check if the specified user_ids match any existing associations - if existing_user_ids.intersection(set(user_ids)): - print("Portfolio already exists under this name, for specified users.") - else: - print("Portfolio already exists under this name, for different users.") - return None # Optional: You could also update the user associations here if needed + if portfolio: + # Fetch the associated users + existing_user_ids = { + pu.user_id for pu in session.query(PortfolioUsers.user_id).filter_by(portfolioId=portfolio.id) + } - return portfolio # Return the existing portfolio data + # Check if the specified user_ids match any existing associations + if existing_user_ids.intersection(set(user_ids)): + print("Portfolio already exists under this name, for specified users.") + else: + print("Portfolio already exists under this name, for different users.") + session.rollback() # No changes to be committed + return None # Optional: You could also update the user associations here if needed - # If portfolio does not exist, create a new one - new_portfolio = Portfolio(name=project_name) - session.add(new_portfolio) - session.flush() # Ensures that 'id' is available before committing if needed + return portfolio # Return the existing portfolio data - # Create new user associations in PortfolioUsers - for user_id in user_ids: - new_association = PortfolioUsers(userId=user_id, portfolioId=new_portfolio.id) - session.add(new_association) + # If portfolio does not exist, create a new one with the provided status and goal + new_portfolio = Portfolio(name=project_name, status=status, goal=goal) + session.add(new_portfolio) + session.flush() # Ensures that 'id' is available before committing if needed - session.commit() - print(f"New portfolio created with ID: {new_portfolio.id}") - session.close() + # Create new user associations in PortfolioUsers + for user_id in user_ids: + new_association = PortfolioUsers(user_id=user_id, portfolioId=new_portfolio.id) # corrected attribute name + session.add(new_association) - return new_portfolio + session.commit() + print(f"New portfolio created with ID: {new_portfolio.id}") + return new_portfolio + + except Exception as e: + session.rollback() # Ensure no partial changes are committed + print(f"An error occurred: {e}") + raise + + finally: + session.close() def app(): @@ -125,3 +130,33 @@ def app(): # Create the asset list and the body of the portfolio asset_list = ownership_instance.get_asset_list() + + # Create the portfolio + # TODO: Wasn't working + # create_sfr_portfolio(project_name=PROJECT_NAME, user_ids=USER_IDS, status="scoping", goal="Increasing EPC") + + portfolio_id = 99 + user_id = 8 + + filename = f"{user_id}/{portfolio_id}/asset_list.csv" + save_csv_to_s3( + dataframe=asset_list, + bucket_name="retrofit-plan-inputs-dev", + file_name=filename + ) + + body = { + "portfolio_id": str(portfolio_id), + "housing_type": "Private", + "goal": "Increasing EPC", + "goal_value": "C", + "trigger_file_path": filename, + "already_installed_file_path": "", + "patches_file_path": "", + "non_invasive_recommendations_file_path": "", + "scenario_name": "Hit EPC C", + "multi_plan": True, + "exclusions": ["fireplace", "floor_insulation"], + "budget": None, + } + print(body)