Skip to main content

Overview

The Job Applicant Question Answer DocType is a child table that stores individual answers provided by job applicants to questions from a Job Question Set. It links questions to their answers for a specific job application.

Fields

question
Data
The question text that was askedProperties:
  • Shown in list view
  • Plain text display of the question
fieldname
Data
Internal field name identifier from the original questionProperties:
  • Shown in list view
  • Used to match answer to original question
answer
Data
The applicant’s response to the questionProperties:
  • Shown in list view
  • Stores the actual answer text (e.g., “Yes”, “No”)
job_opening
Link
Link to the Job Opening this answer relates toProperties:
  • Links to: Job Opening DocType
  • Shown in list view
  • Tracks which position the answer is for

Properties

istable
boolean
True - This is a child table DocType used within Job Applicant
editable_grid
boolean
True - Answers can be viewed directly in the grid view

Permissions

As a child table of Job Applicant, this DocType inherits permissions from its parent. It has no independent permissions.

JSON Structure

{
  "doctype": "DocType",
  "name": "Job Applicant Question Answer",
  "module": "ION Career",
  "istable": 1,
  "editable_grid": 1,
  "fields": [
    {
      "fieldname": "question",
      "fieldtype": "Data",
      "label": "Question",
      "in_list_view": 1
    },
    {
      "fieldname": "fieldname",
      "fieldtype": "Data",
      "label": "Fieldname",
      "in_list_view": 1
    },
    {
      "fieldname": "answer",
      "fieldtype": "Data",
      "label": "Answer",
      "in_list_view": 1
    },
    {
      "fieldname": "job_opening",
      "fieldtype": "Link",
      "label": "Job Opening",
      "options": "Job Opening",
      "in_list_view": 1
    }
  ],
  "permissions": []
}

Usage

Created Automatically

Question answers are automatically created by the process_job_questions handler when a Job Applicant is inserted.
# From handlers.py - automatic creation
for q in qset.questions:
    doc.append("custom_question_answers", {
        "question": q.question,
        "fieldname": q.fieldname,
        "answer": answers.get(q.fieldname),
        "job_opening": job_opening
    })

Reading Applicant Answers

import frappe

# Get a job applicant
applicant = frappe.get_doc("Job Applicant", "APP-2024-001")

# Iterate through their answers
for answer in applicant.custom_question_answers:
    print(f"Q: {answer.question}")
    print(f"A: {answer.answer}")
    print(f"Job: {answer.job_opening}")
    print("---")

Filtering Answers

# Get all answers for a specific job opening
applicant = frappe.get_doc("Job Applicant", "APP-2024-001")

for answer in applicant.custom_question_answers:
    if answer.job_opening == "Software Engineer - 2024":
        print(f"{answer.question}: {answer.answer}")

Querying Answers Across Applicants

# Find applicants who answered "Yes" to a specific question
applicants = frappe.get_all(
    "Job Applicant",
    filters={
        "custom_question_answers.fieldname": "python_experience",
        "custom_question_answers.answer": "Yes"
    },
    fields=["name", "applicant_name", "custom_score"]
)

for app in applicants:
    print(f"{app.applicant_name} - Score: {app.custom_score}")

Example Document

{
    "doctype": "Job Applicant Question Answer",
    "question": "Do you have 5+ years of Python experience?",
    "fieldname": "python_experience_5y",
    "answer": "Yes",
    "job_opening": "Software Engineer - 2024"
}

Scoring System

Answers are used to calculate an applicant’s score in the process_job_questions handler:
# Count "Yes" answers
total_answered = 0
for q in qset.questions:
    if answers.get(q.fieldname) == "Yes":
        total_answered += 1

# Calculate score (0-10 scale)
score_multiplier = 10 / len(qset.questions)
doc.custom_score = score_multiplier * total_answered

Scoring Example

Question Set: 5 questions total
  • Question 1: “Python experience?” → Yes
  • Question 2: “Work authorization?” → Yes
  • Question 3: “Frappe experience?” → No
  • Question 4: “Remote work?” → Yes
  • Question 5: “Available immediately?” → No
Score Calculation:
total_answered = 3 (Yes answers)
score_multiplier = 10 / 5 = 2.0
final_score = 2.0 * 3 = 6.0

Data Flow

  1. Web Form Submission - Applicant submits job application with answers in JSON format
  2. Job Applicant Created - Document inserted with custom_job_question_answers JSON field
  3. Handler Triggered - after_insert hook fires process_job_questions
  4. Answers Parsed - JSON converted to individual answer records
  5. Child Table Populated - Each answer becomes a Job Applicant Question Answer row
  6. Score Calculated - Based on “Yes” answers
  7. Document Saved - Updated with structured answers and score
  • Job Question - The original question definition
  • Job Question Set - Collection of questions
  • Job Applicant - Parent DocType (standard Frappe HR)

Build docs developers (and LLMs) love