So I have some staff, and was thinking a good way to evaluate if they do whats required is to make sure they fill out the forms properly while they are on shift. The following example data is what the output of my function gets.
id - id of the user
name - name of the user
after - after date for range
before - before date for range
total_shifts - number of shifts within date range
total_forms - number of forms completed within range
total_hours - total shift hours
shifts - data for the shifts with shift after and before range
In this sample the 9733 number is the ID of the post for shift, after and before date range for the shift. Total Forms they have finished within that range and points.
[shifts] => Array
(
[9733] => Array
(
[after] => March 15th, 2018 00:00:00
[before] => March 15th, 2018 08:00:00
[forms_in_shift] => 10
[points] =>
)
The points are what I need to calculate if they are doing whats required.
Requirements: 12 forms per shift (a form is just a form they fill out with data it creates a post)
The issue I have is that sometimes shifts overlap as you can see in the sample data, and I only require 12 forms per shift even if two people are working. So what I want to do is give either 1 or 0 points for each shift form that hits the requirements for each person. eg: if dave is working alone and does 12 he gets 12 points max, if dave and steve are working and together they do 12 forms they both get 12 points max. I would append the points to the points array item for each shift. I can then take that array and review once a month to see who is working. I assume I would walk the array and figure this out but I am at a loss.
Sample data that is output
array
(
[0] => Array
(
[id] => 24
[name] => Dave Smith
[after] => March 14th, 2018
[before] => May 9th, 2018
[total_shifts] => 0
[total_forms] => 0
[total_hours] => 0
[shifts] =>
)
[1] => Array
(
[id] => 16
[name] => Jake Paul
[after] => March 14th, 2018
[before] => May 9th, 2018
[total_shifts] => 2
[total_forms] => 20
[total_hours] => 20
[shifts] => Array
(
[9733] => Array
(
[after] => March 15th, 2018 00:00:00
[before] => March 15th, 2018 08:00:00
[forms_in_shift] => 10
[points] =>
)
[9828] => Array
(
[after] => March 18th, 2018 00:00:00
[before] => March 18th, 2018 12:00:00
[forms_in_shift] => 5
[points] =>
)
)
)
[2] => Array
(
[id] => 28
[name] => Ryan Blum
[after] => March 14th, 2018
[before] => May 9th, 2018
[total_shifts] => 6
[total_forms] => 44
[total_hours] => 42
[dates] => Array
(
[9722] => Array
(
[after] => March 14th, 2018 16:00:00
[before] => March 15th, 2018 00:00:00
[forms_in_shift] => 7
[points] =>
)
[9746] => Array
(
[after] => March 15th, 2018 16:00:00
[before] => March 16th, 2018 00:00:00
[forms_in_shift] => 9
[points] =>
)
[9810] => Array
(
[after] => March 17th, 2018 10:00:00
[before] => March 17th, 2018 16:00:00
[forms_in_shift] => 11
[points] =>
)
[9837] => Array
(
[after] => March 18th, 2018 00:00:00
[before] => March 18th, 2018 12:00:00
[forms_in_shift] => 5
[points] =>
)
[9858] => Array
(
[after] => March 19th, 2018 08:00:00
[before] => March 20th, 2018 00:00:00
[forms_in_shift] => 9
[points] =>
)
[9886] => Array
(
[after] => March 20th, 2018 15:00:00
[before] => March 21st, 2018 00:01:00
[forms_in_shift] => 3
[points] =>
)
)
)
)
John Cotton answers:
It's not clear from your sample data whether shifts always align when more than one person is working. ie If two or more people are working, will their shifts always start and end at the same time?
If not, then it could be tricky with the data you have.
If they do, then a first walk of the array could create a second associative array with start time as the index. As you walk the array, add the forms_in_shift to the index for the time (creating that index if it doesn't exist.
That will give you a total of forms for each shift. Then go back over your primary around setting the points value based on the secondary array.
Personally, I would convert all dates to timestamps to make comparison obvious.
John Cotton comments:
The code would be something along the lines of:
$primary = []; /// NOT EMPTY...should be your data.
$secondary = [];
// First pass
foreach( $primary as $employee ) {
foreach( (array) $employee['shifts'] as $shift ) {
$secondary[ $shift['after'] ] += $shift['forms_in_shift'];
}
}
// Second pass
foreach( $primary as $employee ) {
foreach( (array) $employee['shifts'] as $shift ) {
$shift['points'] = min( 12, $secondary[ $shift['after'] ] );
}
}
John Cotton comments:
Sorry, second pass should read
// Second pass
foreach( $primary as $i => $employee ) {
foreach( (array) $employee['shifts'] as $j => $shift ) {
$primary[$i]['shifts'][$j]['points'] = min( 12, $secondary[ $shift['after'] ] );
}
}
User179751 comments:
Hi John, thanks I think this works. do you have a suggestion when the shift hours don't align?
John Cotton comments:
>do you have a suggestion when the shift hours don't align?
I guess the answer would be to look at what percentage of each person's shift overlaps (eg Emp A works 8am to 12pm, Emp B works 11am to 3pm, therefore 25% of the shift overlaps.)
Take that % overlap and add that percentage of each employee's total form completions to the other user.
Not that complicated to do, just a case of working out the overlap each time, which means a lot more code than I have suggested so far.
Kyle answers:
I think you should be tracking the input time for a form in its own right. Why not create another post type for form entries that stores time entered, user ID, and shift ID. You can then query simply by form ID. Are your shift objects being generated automatically? They should be able to select them at the time of submission.
User179751 comments:
yes shift array is dynamically created by clock punch in out.
Kyle comments:
A separate object for form inputs with time that is in its own post type, that you could also pin to an array in a shift array field I think would be much more efficient than trying to jump through hoops with queries. I can help with that as needed.
User179751 comments:
I could do that myself without issue, I was looking for a way to avoid a massive amount of posts being created. I totally get what you are saying, this however would only be run once a month.