diff --git a/apps/discord_bot/src/five08/discord_bot/cogs/crm.py b/apps/discord_bot/src/five08/discord_bot/cogs/crm.py index 18694e2..b79e4bb 100644 --- a/apps/discord_bot/src/five08/discord_bot/cogs/crm.py +++ b/apps/discord_bot/src/five08/discord_bot/cogs/crm.py @@ -1269,11 +1269,12 @@ async def callback(self, interaction: discord.Interaction) -> None: class ResumeApplyDiscordRolesButton(discord.ui.Button["ResumeUpdateConfirmationView"]): """Button that applies suggested Discord roles to the linked member.""" - def __init__(self) -> None: + def __init__(self, *, disabled: bool = False) -> None: super().__init__( label="Apply Discord Roles", style=discord.ButtonStyle.success, custom_id="resume_apply_discord_roles", + disabled=disabled, ) async def callback(self, interaction: discord.Interaction) -> None: @@ -1284,6 +1285,13 @@ async def callback(self, interaction: discord.Interaction) -> None: ) return + if not view.can_apply_discord_roles: + await interaction.response.send_message( + "❌ Discord roles can only be applied after linking this contact to a Discord user.", + ephemeral=True, + ) + return + target_user_id_raw: str | None = None def _audit_apply_roles_event( @@ -1605,6 +1613,7 @@ def __init__( parsed_seniority: str | None = None, discord_role_suggestions: list[str] | None = None, discord_role_target_user_id: str | None = None, + can_apply_discord_roles: bool = False, ) -> None: super().__init__(timeout=300) self.crm_cog = crm_cog @@ -1615,6 +1624,7 @@ def __init__( self.link_discord = link_discord self.parsed_seniority = parsed_seniority self.discord_role_target_user_id = discord_role_target_user_id + self.can_apply_discord_roles = can_apply_discord_roles self.discord_role_suggestions = list( dict.fromkeys(discord_role_suggestions or []) ) @@ -1637,7 +1647,9 @@ def __init__( self.add_item(ResumeEditRolesButton()) if self.discord_role_suggestions: self.add_item(ResumeEditDiscordRolesButton()) - self.add_item(ResumeApplyDiscordRolesButton()) + self.add_item( + ResumeApplyDiscordRolesButton(disabled=not self.can_apply_discord_roles) + ) self.add_item(ResumeEditLocationButton()) def _set_seniority_override(self, value: str) -> str: @@ -3667,6 +3679,7 @@ def _build_role_suggestions_embed( locality_roles: list[str] | None = None, extracted_profile: dict[str, Any] | None = None, current_discord_roles: list[str] | None = None, + can_apply_discord_roles: bool = False, ) -> discord.Embed | None: """Build a separate embed suggesting Discord roles to add based on resume data. @@ -3689,6 +3702,16 @@ def _build_role_suggestions_embed( description=f"Roles to **add** for **{contact_name}** based on resume — never remove existing roles.", color=0x57F287, ) + if not can_apply_discord_roles: + embed.add_field( + name="🔒 Link required", + value=( + "This contact is not currently linked to a Discord user, so suggested roles " + "cannot be applied automatically. Link them first in CRM or use " + "`/link-discord-user`." + ), + inline=False, + ) if technical: embed.add_field( @@ -3890,6 +3913,7 @@ async def _run_resume_extract_and_preview( role_suggestions_embed: discord.Embed | None = None suggested_discord_roles: list[str] = [] discord_role_target_user_id: str | None = None + can_apply_discord_roles = False if action_name == "crm.reprocess_resume" or ( action_name == "crm.upload_resume" and link_member ): @@ -3932,10 +3956,12 @@ async def _run_resume_extract_and_preview( suggested_discord_roles = list( dict.fromkeys(technical_suggestions + locality_suggestions) ) + can_apply_discord_roles = bool(discord_role_target_user_id or link_member) role_suggestions_embed = self._build_role_suggestions_embed( contact_name=contact_name, technical_roles=technical_suggestions, locality_roles=locality_suggestions, + can_apply_discord_roles=can_apply_discord_roles, ) if not proposed_updates and not link_member and not parsed_seniority: @@ -3970,6 +3996,7 @@ async def _run_resume_extract_and_preview( parsed_seniority=parsed_seniority, discord_role_suggestions=suggested_discord_roles, discord_role_target_user_id=discord_role_target_user_id, + can_apply_discord_roles=can_apply_discord_roles, ) if action_name != "crm.reprocess_resume": self._audit_command( @@ -4015,6 +4042,7 @@ async def _run_resume_extract_and_preview( parsed_seniority=parsed_seniority, discord_role_suggestions=suggested_discord_roles, discord_role_target_user_id=discord_role_target_user_id, + can_apply_discord_roles=can_apply_discord_roles, ) if action_name != "crm.reprocess_resume": self._audit_command(