from pathlib import Path from inbox.models import Inbox_Messages # match_status (inbox/tasks.py) -> the resume badge the inbox tabs render. _RESUME_STATUS = { "processing": "Parsing", "matched": "Parsed", "no_text": "Failed", "failed": "Failed", "dlq": "Failed", "skipped": "Pending", } def _sender_name(message: Inbox_Messages) -> str: """Graph's display name when the payload carries one, else the raw address.""" sender_name = message.message_from full = message.full_email_response if isinstance(full, dict): from_block = full.get("from") if isinstance(from_block, dict): email_address = from_block.get("emailAddress") if isinstance(email_address, dict): name = email_address.get("name") if name: sender_name = name return sender_name def _attachment_name(message: Inbox_Messages) -> str | None: if message.file_name: return message.file_name.split(",")[0].strip() or None if message.file_path: return Path(message.file_path.split(",")[0].strip()).name or None return None def serialize_message(message: Inbox_Messages) -> dict: """inbox_messages row -> the shape the #inbox Email tab renders.""" sender_name = _sender_name(message) attachment_name = _attachment_name(message) return { "id": str(message.id), "message_id": str(message.message_id) if message.message_id else None, "full_email_response": message.full_email_response, "sender_name": sender_name, "fromEmail": message.message_from, "subject": message.message_subject, "body": message.message_body, "when": message.message_received_time, "unread": not message.message_read, "attachment": message.attachment, "attachment_name": attachment_name, "file_name": message.file_name, "message_to": message.message_to, "message_cc": message.message_cc, "message_bcc": message.message_bcc, "message_sent_time": message.message_sent_time, "message_reply": message.message_reply, "file_path": message.file_path, "suggested_job_post_ids": list(message.suggested_job_post_ids or []), "match_summary": message.match_summary, "match_reasoning": message.match_reasoning, "match_status": message.match_status, "match_error": message.match_error, "matched_at": message.matched_at.isoformat() if message.matched_at else None, } def serialize_application(message: Inbox_Messages) -> dict: """inbox_messages row -> the shape the #inbox All Applications tab renders. `position` is the mail subject and `source` is the To address, which is where the board tag (Rozee, Mustakbil, Employee Referral, ...) lands. The tab also wants ats_score, phone, experience, recruiter, duplicate and a processing state beyond read/unread. inbox_messages has no columns for any of those, so they come back null instead of invented — see the note in inbox/file_decoder.py. `processing` is derived from message_read alone, so it is only ever "Unread" or "Read"; Imported/Processed/Rejected need a column. """ return { "id": str(message.id), "name": _sender_name(message), "email": message.message_from, "position": message.message_subject, "source": message.message_to, "received": message.message_received_time, "unread": not message.message_read, "processing": "Read" if message.message_read else "Unread", "application_status": message.application_status, "resume_status": _RESUME_STATUS.get(message.match_status, "Pending"), "attachment": _attachment_name(message), "has_attachment": message.attachment, "resume_text": message.resume_text, "ats_score": None, "phone": None, "experience": message.experience or "", "recruiter": None, "duplicate": None, }