backend/services/campaign_service.py (146 lines of code) (raw):

from backend import db from flask import current_app from sqlalchemy.exc import IntegrityError from psycopg2.errors import UniqueViolation, NotNullViolation from backend.models.dtos.campaign_dto import ( CampaignDTO, NewCampaignDTO, CampaignProjectDTO, CampaignListDTO, ) from backend.models.postgis.campaign import ( Campaign, campaign_projects, campaign_organisations, ) from backend.models.postgis.utils import NotFound from backend.models.postgis.project import Project from backend.models.postgis.organisation import Organisation from backend.services.organisation_service import OrganisationService class CampaignService: @staticmethod def get_campaign(campaign_id: int) -> Campaign: """Gets the specified campaign""" campaign = Campaign.query.get(campaign_id) if campaign is None: raise NotFound() return campaign @staticmethod def get_campaign_by_name(campaign_name: str) -> Campaign: campaign = Campaign.query.filter_by(name=campaign_name).first() if campaign is None: raise NotFound() return campaign @staticmethod def delete_campaign(campaign_id: int): """Delete campaign for a project""" campaign = Campaign.query.get(campaign_id) campaign.delete() campaign.save() @staticmethod def get_campaign_as_dto(campaign_id: int, user_id: int): """Gets the specified campaign""" campaign = CampaignService.get_campaign(campaign_id) campaign_dto = CampaignDTO() campaign_dto.id = campaign.id campaign_dto.url = campaign.url campaign_dto.name = campaign.name campaign_dto.logo = campaign.logo campaign_dto.description = campaign.description return campaign_dto @staticmethod def get_project_campaigns_as_dto(project_id: int) -> CampaignListDTO: """Gets all the campaigns for a specified project""" query = ( Campaign.query.join(campaign_projects) .filter(campaign_projects.c.project_id == project_id) .all() ) return Campaign.campaign_list_as_dto(query) @staticmethod def delete_project_campaign(project_id: int, campaign_id: int): """ Delete campaign for a project""" campaign = Campaign.query.get(campaign_id) project = Project.query.get(project_id) project.campaign.remove(campaign) db.session.commit() new_campaigns = CampaignService.get_project_campaigns_as_dto(project_id) return new_campaigns @staticmethod def get_all_campaigns() -> CampaignListDTO: """ Returns a list of all campaigns """ query = Campaign.query.order_by(Campaign.name).distinct() return Campaign.campaign_list_as_dto(query) @staticmethod def create_campaign(campaign_dto: NewCampaignDTO): """ Creates a new campaign """ campaign = Campaign.from_dto(campaign_dto) try: campaign.create() if campaign_dto.organisations: for org_id in campaign_dto.organisations: organisation = OrganisationService.get_organisation_by_id(org_id) campaign.organisation.append(organisation) db.session.commit() except IntegrityError as e: current_app.logger.info("Integrity error: {}".format(e.args[0])) if isinstance(e.orig, UniqueViolation): raise ValueError("Campaign name already exists") from e if isinstance(e.orig, NotNullViolation): raise ValueError("Campaign name cannot be null") from e return campaign @staticmethod def create_campaign_project(dto: CampaignProjectDTO): """Assign a campaign with a project""" statement = campaign_projects.insert().values( campaign_id=dto.campaign_id, project_id=dto.project_id ) db.session.execute(statement) db.session.commit() new_campaigns = CampaignService.get_project_campaigns_as_dto(dto.project_id) return new_campaigns @staticmethod def create_campaign_organisation(organisation_id: int, campaign_id: int): """ Creates new campaign from DTO """ statement = campaign_organisations.insert().values( campaign_id=campaign_id, organisation_id=organisation_id ) db.session.execute(statement) db.session.commit() new_campaigns = CampaignService.get_organisation_campaigns_as_dto( organisation_id ) return new_campaigns @staticmethod def get_organisation_campaigns_as_dto(organisation_id: int) -> CampaignListDTO: """ Gets all the campaigns for a specified project """ query = ( Campaign.query.join(campaign_organisations) .filter(campaign_organisations.c.organisation_id == organisation_id) .all() ) return Campaign.campaign_list_as_dto(query) @staticmethod def campaign_organisation_exists(campaign_id: int, org_id: int): return ( Campaign.query.join(campaign_organisations) .filter( campaign_organisations.c.organisation_id == org_id, campaign_organisations.c.campaign_id == campaign_id, ) .one_or_none() ) @staticmethod def delete_organisation_campaign(organisation_id: int, campaign_id: int): """ Delete campaign for a organisation""" campaign = Campaign.query.get(campaign_id) org = Organisation.query.get(organisation_id) try: org.campaign.remove(campaign) except ValueError: raise NotFound() db.session.commit() new_campaigns = CampaignService.get_organisation_campaigns_as_dto( organisation_id ) return new_campaigns @staticmethod def update_campaign(campaign_dto: CampaignDTO, campaign_id: int): campaign = Campaign.query.get(campaign_id) if not campaign: raise NotFound(f"Campaign id {campaign_id} not found") try: campaign.update(campaign_dto) except IntegrityError as e: current_app.logger.info("Integrity error: {}".format(e.args[0])) raise ValueError() return campaign