Business Case
I work for a non-profit that uses volunteers to deliver meals to their clients. Based on their volunteer-recurrence schedule, and the client's meal-recurrence schedule, each volunteer has a daily route of meals that they deliver. Currently, the routing is being done manually by our employees and that takes a lot of time. I'm planning to build a very custom apex class that handles Multi-Route processing.
What I mean by that is, using my own use case as an example, when I have for example, 5 volunteers and 40 meals scheduled for today, the class will give me the 5 best routes for those volunteers based on the location of the meal "delivery points", and the volunteer's own personal criteria (ability to climb steps, strength level, etc.).
Things to consider:
- I built Meals as a custom object that has a Master-detail relationship to Contacts (One Client can have many Meals).
- I built Routes as a custom object that has a lookup relationship to Volunteer Hours - The 'Volunteers For Salesforce' custom object - and a lookup relationship to Meals (There is one route for each volunteer hour in a day, and each route can have many meals).
- Volunteers have certain criteria associated with them, such as their ability to climb steps, or their ability to lift & carry a certain number of meal trays. Each of these criteria are tracked both on the Contact object, and on the related object. ('No Steps' is a checkbox field on the Contact object, and 'Has Steps' is a checkbox on the Address object in the NPSP')
- The Route object will be built and populated programmatically.
- Routes (Deliveries) all start at the same time and at the same place.
- I used Clean Rules to get the geolocation data for the Contact records.
My Approach
In the apex class, SOQL Queries create lists of Volunteers that have Volunteer Hours scheduled for that day, where that Volunteer Hour object doesn't have an associated Route and a particular criteria on the Volunteer ('No Steps', etc) is present, e.g. The first SOQL query would look for the Volunteers with the 'No Steps' checkbox checked since that's the highest priority criteria. The second SOQL query would look for the Volunteers with the second highest priority criteria, and so on.
The reason for this is to build and populate the routes for the most 'picky' and restricted volunteers first so as to limit the occurrence of Meals that cannot be routed because the final available Volunteers have too much criteria on them.
Immediately following each SOQL query, I intend to loop through all the volunteers in the each and build (Not populate) Route objects for each. During each iteration un-routed meals will assessed based on their compatibility with the route, their distance from the starting point and then their distance from each other. The route will be populated with the closest meal matching all the following criteria, and the meal will be marked as routed.
My Problem
After tracing the logic of the code (Hand-drawing points on a map and using the program's logic to create the routes), I realized that if meals are clustered together, around the general route (delivery) start-point for example, the first route would pick up all (and possibly only depending on how many there are) those clustered meals in that area and follow what I feel is an illogical path. I think checking the traveling direction of the current and next meal would allow me to be able to fix that, but I'm not sure how to tell direction in Salesforce.
Anyone with a solution to my problem, or any advice or critique of my approach is welcome to answer.