Designing the Placement Officer Workflow for My Placement Portal
Today, I spent more time designing the Placement Officer workflow in my Placement Portal.
This wasn't about writing a new API or creating another frontend page.
It was about defining something much more fundamental:
What should a Placement Officer actually be allowed to do?
The more I think about the administrative side of the portal, the more I realize that role-based access isn't simply about giving someone permission to access a model.
It's about defining their responsibilities within the actual placement workflow.
And that led me to several decisions around job postings, applications, resumes, exports, shortlisting, and eligibility.
Starting With a New Project Branch
Before working on this new phase, I made another architectural decision from the project perspective.
I created a separate branch from the version where the resume parser hasn't been implemented yet, but the email notification infrastructure is already available.
The reason is fairly simple.
Email notifications will be required in later phases of the Placement Officer workflow.
For example, when application statuses change or other placement-related events occur, the notification system will become important.
So rather than continuing to build everything on top of the resume parser branch, I created another master branch from the version that already contains the notification infrastructure.
This gives me a cleaner starting point for the next phase of development.
Defining the Placement Officer's Responsibilities
The next question was:
What can the Placement Officer actually do?
I don't want the role to have unrestricted access to everything.
Instead, I'm defining permissions around the responsibilities of the officer.
The first major responsibility is Job Posting.
For job postings, the Placement Officer should have full CRUD access:
- Create
- Read
- Update
- Delete
While creating or updating a job posting, the officer should also be able to define the fields required from students.
This is where the dynamic application form architecture becomes important.
Different companies can require different information, so the Placement Officer needs control over the application fields associated with each job.
Managing Applications
Applications are different.
The Placement Officer shouldn't be able to arbitrarily change everything inside an application.
Their responsibility is primarily to review and manage the recruitment process.
Therefore, the current idea is to provide:
- Read access.
- Partial update access.
In API terms, this means the officer can use operations similar to a PATCH rather than completely replacing an application.
Some examples of information they may need to update include:
- Application status.
- Student resume associated with the application.
- Other placement-related information required during the recruitment process.
This gives the officer enough control to manage applications without giving the role unnecessary authority over the entire application record.
Resume Access Changes the Export Workflow
Another interesting relationship appeared while thinking through exports.
The Placement Officer should be able to view the student's resume.
But I don't want the export functionality to exist independently from that access.
The idea is:
If the officer can legitimately view the candidate's resume, they can also include that resume information when exporting application data.
This becomes particularly useful when generating an Excel file containing candidate information for recruiters.
The export could contain application information along with access to the corresponding resume.
This makes the export much more useful than simply generating a spreadsheet containing names and statuses.
The Shortlisting Problem
This is where the design became more interesting.
Right now, I don't have a fixed shortlisting criterion implemented.
Instead, my initial idea was to provide filters that allow the Placement Officer to narrow down candidates and export the filtered results.
For example, the officer could eventually filter candidates based on information collected through the application process.
But then I noticed a problem.
What happens to the students who aren't included in the filtered result?
If I simply export the filtered candidates, the remaining students could stay in an undefined state.
They would effectively remain:
Unacknowledged.
That isn't a complete recruitment workflow.
Shortlisting isn't just about identifying the candidates you want.
It's also about defining what happens to everyone else.
This is something I still need to design properly.
Shortlisting Is More Than a Filter
This realization changed how I'm thinking about the feature.
A filter answers:
"Which candidates match these conditions?"
A shortlisting system needs to answer a much bigger question:
"What happens to candidates after the recruitment decision is made?"
That could eventually involve states such as:
- Applied
- Under Review
- Shortlisted
- Not Shortlisted
- Interview
- Selected
- Rejected
I'm not treating this as a finalized design yet.
The important thing is that I have identified the gap before implementing a simple filtering system that would create another problem later.
Eligibility Is Another Design Challenge
There is another decision I need to make during job posting.
At the moment, the primary information that determines whether a student can see a job posting is their batch.
This is relatively straightforward because batch information already exists as a structured field in the student data.
But the dynamic application system introduces another possibility.
What if eligibility depends on fields that are dynamically configured for a job?
For example, what if a company requires a specific CGPA or another student attribute?
Now I potentially have to evaluate data stored dynamically, including values with different data types.
That makes querying more complicated.
Why I'm Being Careful With JSON
One of the options I've considered is storing some dynamic configuration inside JSON.
The problem isn't storing the data.
The problem is querying it efficiently and predictably.
If eligibility depends on dynamically stored values, I may need to query JSON data while also considering the data type of each attribute.
That can become considerably more complicated than querying normal structured database fields.
For the current phase, I'm therefore keeping the visibility logic simpler.
Batch remains the primary field determining whether a student can see a job posting.
The more advanced eligibility system can evolve later once the requirements are clearer.
The Bigger Lesson
What surprised me today is how quickly a simple question turned into an architecture problem.
The question was:
"What can a Placement Officer do?"
But answering it required thinking about:
- Permissions.
- Job posting management.
- Dynamic fields.
- Application updates.
- Resume access.
- Excel exports.
- Shortlisting.
- Candidate states.
- Eligibility.
- Database querying.
This is why I'm increasingly trying to design the workflow before implementing the API.
A model can tell me what data exists.
A permission class can tell me who can access it.
But neither automatically tells me how the real-world workflow should operate.
That part requires understanding the people using the system.
Final Thoughts
The Placement Officer workflow is still evolving.
I haven't finalized every shortlisting rule or advanced eligibility condition yet.
And that's intentional.
I'd rather identify these problems during design than discover them after the feature has already been implemented.
The goal isn't to build the most complicated placement system possible.
The goal is to build a system that accurately represents how placement work actually happens.
Because sometimes the hardest part of building software isn't writing the code.
It's deciding what the code should actually do.