Skip to main content

DocType Overview

ION Career introduces three custom DocTypes that work together to create a flexible job screening questionnaire system. These DocTypes integrate with ERPNext’s existing Job Opening and Job Applicant DocTypes.

Job Question Set

The Job Question Set is a container DocType that groups related screening questions together.

Structure

{
  "name": "Job Question Set",
  "module": "ION Career",
  "naming_rule": "By fieldname",
  "autoname": "field:title"
}

Fields

title
Data
required
Unique title for the question set
questions
Table
Child table containing Job Question records

Usage Example

Create a question set for software engineering roles:
qset = frappe.get_doc({
    "doctype": "Job Question Set",
    "title": "Software Engineer Screening",
    "questions": [
        {
            "question": "Do you have experience with Python?",
            "fieldname": "python_exp",
            "required": 1,
            "order": 1
        },
        {
            "question": "Are you familiar with Frappe Framework?",
            "fieldname": "frappe_exp",
            "required": 0,
            "order": 2
        }
    ]
})
qset.insert()

Job Question

Job Question is a child DocType (table) that defines individual screening questions within a question set.

Structure

{
  "name": "Job Question",
  "module": "ION Career",
  "istable": 1,
  "editable_grid": 1
}
The istable: 1 property marks this as a child DocType that can only exist within a parent document.

Fields

question
Data
required
The question text displayed to applicants
fieldname
Data
Unique identifier for the question (auto-generated, hidden from user)
input_type
Select
default:"Select"
Type of input control (Checkbox or Select)
required
Check
default:"0"
Whether the question must be answered
order
Int
Display order of the question

Field Configuration

Notice that several fields are marked as hidden and read_only:
job_question.json
{
  "fieldname": "fieldname",
  "fieldtype": "Data",
  "hidden": 1,
  "label": "Fieldname",
  "read_only": 1
}
This allows the system to auto-generate field names while keeping the interface clean for admins.

Job Applicant Question Answer

This child DocType stores individual answers from applicants, creating a structured record of their responses.

Structure

{
  "name": "Job Applicant Question Answer",
  "module": "ION Career",
  "istable": 1,
  "editable_grid": 1
}

Fields

question
Data
The question text (copied from Job Question)
fieldname
Data
The question’s fieldname identifier
answer
Data
The applicant’s answer (typically “Yes” or “No”)
job_opening
Link
Reference to the job opening being applied for

Answer Processing

Answers are created automatically by the process_job_questions() handler:
handlers.py
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
    })

Relationship with ERPNext DocTypes

Job Opening Extension

ION Career adds a custom field to link question sets:
custom_field.json
{
  "dt": "Job Opening",
  "fieldname": "custom_job_question_set",
  "fieldtype": "Link",
  "label": "Job Question Set",
  "options": "Job Question Set",
  "reqd": 1,
  "insert_after": "designation"
}
The reqd: 1 setting makes it mandatory to select a question set when creating a job opening.

Job Applicant Extension

Multiple custom fields are added to Job Applicant:
Read-only field displaying the calculated score (0-10).
{
  "fieldname": "custom_score",
  "fieldtype": "Data",
  "label": "Score",
  "read_only": 1,
  "insert_after": "applicant_rating"
}
Hidden field storing raw JSON answers from the web form.
{
  "fieldname": "custom_job_question_answers",
  "fieldtype": "Text",
  "label": "Job Question Answers",
  "hidden": 1
}
Table field displaying structured answer records.
{
  "fieldname": "custom_question_answers",
  "fieldtype": "Table",
  "label": "Question Answers",
  "options": "Job Applicant Question Answer"
}
UI element creating a dedicated tab for viewing questions and answers.
{
  "fieldname": "custom_questions",
  "fieldtype": "Tab Break",
  "label": "Questions",
  "insert_after": "upper_range"
}

Data Flow Between DocTypes

Permissions

Job Question Set

Only System Manager role has full CRUD permissions

Job Question

Inherits permissions from parent (Job Question Set)

Job Applicant Question Answer

Inherits permissions from parent (Job Applicant)
Child DocTypes (istable: 1) don’t have independent permissions. They inherit from their parent document.

API Methods

The api.py module provides whitelisted methods for web form integration:
api.py
@frappe.whitelist()
def get_job_questions(job_opening):
    """Fetch questions for a specific job opening"""
    jo = frappe.get_doc("Job Opening", job_opening)
    qset_name = jo.custom_job_question_set
    
    if not qset_name:
        return []
    
    qset = frappe.get_doc("Job Question Set", qset_name)
    
    return [{
        "question": q.question,
        "fieldname": q.fieldname,
        "input_type": q.input_type,
        "required": q.required
    } for q in qset.questions]
This API allows the job application web form to dynamically load questions based on the selected job opening.

Build docs developers (and LLMs) love