Training project
Job Application Tracker
Built a Salesforce job application tracking system that manages applications through a defined lifecycle and automatically creates stage-specific follow-up tasks as each application progresses.
Project context
Developed as a Cloud Code Academy capstone project to apply Salesforce development, automation, data modeling, testing, teamwork, and Agile practices to a practical job-search workflow.
Business problem
Managing multiple job applications requires tracking changing statuses, follow-up actions, networking tasks, interview preparation, and offer-related activities. Without a structured system, important actions can be missed and application history can become difficult to follow.
Users and stakeholders
- Individual job seekers managing an active application pipeline.
Solution
Built a custom Salesforce application around Job_Application__c. Applications move through defined lifecycle stages, and Apex automation creates relevant Tasks for each stage while preventing duplicate task creation and preserving Tasks from earlier stages. The system also connects applications to company and contact information and includes automation for stale applications.
Architecture and process
- A job application is stored in Job_Application__c.
- The application progresses through statuses such as Saved, Applying, Applied, Interviewing, Negotiating, Accepted, and Closed.
- Apex trigger/helper logic detects new records and status changes.
- JobApplicationHelper determines which follow-up activities are appropriate for the current stage.
- TaskManager creates Tasks associated with the application and records an application-status snapshot.
- Existing Tasks are checked to prevent duplicate activities for the same application stage while retaining Tasks created for prior stages.
- Company Contacts can be associated with applications through primary-contact logic.
- A Batch Apex process identifies applications whose follow-up dates are at least 30 days stale and closes them when appropriate, excluding applications already Closed or Accepted.
Key features
- Custom Job Application object
- Defined application lifecycle/statuses
- Status-based, stage-specific Task automation
- Duplicate-Task prevention while preserving prior-stage Tasks
- Application status snapshots on Tasks
- Company and Contact relationships
- Automatic primary-contact assignment
- Follow-up Task due dates
- Batch Apex cleanup for stale applications
- Custom Salesforce application interface
Technical decisions
- Used Apex helper classes to keep trigger logic separated from business logic.
- Centralized Task creation in TaskManager.
- Stored the application status on each generated Task so activity history retains the stage that caused the Task to be created.
- Checked status changes, existing Task subjects, and status snapshots before creation so prior-stage Tasks remain while duplicate activities are avoided.
- Used Batch Apex for stale-application cleanup rather than trying to handle long-running record cleanup synchronously.
- Used with sharing in application and Task helper classes.
Testing and validation
- The repository contains dedicated Apex test classes for the application helper logic, stale-application cleanup, and related automation. The Task workflow was debugged and tested across the full application lifecycle so a fix for one stage did not break another.
Challenges
- The most difficult part of my contribution was the stage-based Task creation logic. As a team, we decided that Tasks from previous application stages needed to remain in place while also preventing duplicate Tasks from being created when records were updated. Getting that behavior right required several iterations. At different points, one application stage would populate Tasks correctly while another would stop working, so I had to keep debugging the status-change and duplicate-prevention logic until the stages worked together consistently.
Lessons learned
- This project reinforced the importance of teamwork, collaboration, and communication when requirements evolve during development. The Task-creation behavior changed based on a team decision, which meant the implementation had to adapt without losing earlier functionality. It also taught me to test automation across the full lifecycle rather than validating only the stage I was actively working on.