feat(ticket): système de ticket recrutement avec questions et DM accept/refus

- Ajout catégorie recrutement avec questions personnalisées
- Modal dynamique affichant les questions lors de la création
- Envoi des réponses dans un salon staff configurable
- Fermeture avec boutons Accepter/Refuser et envoi DM automatique au candidat
- Mise à jour des modèles TicketCategory et TicketData

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lowei 2026-05-22 14:26:02 +02:00
parent db4876e085
commit b3db1ef9f5
2 changed files with 451 additions and 25 deletions

View file

@ -60,7 +60,10 @@ class TicketCategory:
priority_enabled: bool = True,
allow_claims: bool = True,
survey_enabled: bool = True,
discord_category_id: Optional[int] = None
discord_category_id: Optional[int] = None,
is_recruitment: bool = False,
questions: List[str] = None,
responses_channel_id: Optional[int] = None
):
self.id = id
self.name = name
@ -76,7 +79,10 @@ class TicketCategory:
self.allow_claims = allow_claims
self.survey_enabled = survey_enabled
self.discord_category_id = discord_category_id
self.is_recruitment = is_recruitment
self.questions = questions or []
self.responses_channel_id = responses_channel_id
def to_dict(self) -> Dict[str, Any]:
"""Convert category to dictionary for storage"""
return {
@ -93,7 +99,10 @@ class TicketCategory:
"priority_enabled": self.priority_enabled,
"allow_claims": self.allow_claims,
"survey_enabled": self.survey_enabled,
"discord_category_id": self.discord_category_id
"discord_category_id": self.discord_category_id,
"is_recruitment": self.is_recruitment,
"questions": self.questions,
"responses_channel_id": self.responses_channel_id
}
@classmethod
@ -113,7 +122,10 @@ class TicketCategory:
priority_enabled=data.get("priority_enabled", True),
allow_claims=data.get("allow_claims", True),
survey_enabled=data.get("survey_enabled", True),
discord_category_id=data.get("discord_category_id")
discord_category_id=data.get("discord_category_id"),
is_recruitment=data.get("is_recruitment", False),
questions=data.get("questions", []),
responses_channel_id=data.get("responses_channel_id")
)
@ -188,7 +200,8 @@ class TicketData:
transcript_path: Optional[str] = None
rating: Optional[int] = None
feedback: Optional[str] = None
recruitment_responses: Dict[str, str] = field(default_factory=dict)
@property
def is_open(self) -> bool:
return self.status in [TicketStatus.OPEN, TicketStatus.CLAIMED]
@ -214,9 +227,10 @@ class TicketData:
"reason": self.reason,
"transcript_path": self.transcript_path,
"rating": self.rating,
"feedback": self.feedback
"feedback": self.feedback,
"recruitment_responses": self.recruitment_responses
}
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> 'TicketData':
messages = [TicketMessage.from_dict(m) for m in data.get("messages", [])]
@ -234,7 +248,8 @@ class TicketData:
reason=data.get("reason", ""),
transcript_path=data.get("transcript_path"),
rating=data.get("rating"),
feedback=data.get("feedback")
feedback=data.get("feedback"),
recruitment_responses=data.get("recruitment_responses", {})
)