Introduction

RWFM is a comprehensive R package that has been designed and developed to cater to the workforce management and call center analytics requirements. It offers a range of powerful tools and functions that can be utilized for a wide array of tasks related to managing call centers, staffing, and forecasting.

One of the core functionalities of RWFM is its ability to calculate staffing requirements. This function can take into account a range of factors, such as service level objectives, average handling time, and available agent hours, to determine the optimal number of agents required to meet business objectives. This feature can help organizations optimize their workforce management strategies and ensure that they have the right number of agents available to meet demand while also minimizing costs.

The package also includes various call center metrics that can be used to assess performance and identify areas for improvement. These metrics can help businesses track key performance indicators, such as average handle time, first call resolution, and service level, to identify trends and make data-driven decisions.

RWFM includes a feature for generating optimal schedule patterns for different combinations of availability and labor law requirements. This function takes into account a range of factors, such as employee preferences, labor laws, and business needs, to generate schedules that are fair and equitable while also meeting business objectives. This feature can help organizations optimize their scheduling processes, reduce labor costs, and improve employee satisfaction.

Example use cases are provided below.

Install and load to the memory space

#install and load devtools package
if(!require("devtools",character.only = TRUE)) install.packages("devtools")
library(devtools)

#install/load RWFM from github
devtools::install_github("tesfahunboshe/RWFM")
library("RWFM")

EXAMPLE USE CASES

You can use RWFM for capacity planning calculations for dynamic contacts such as live chat and phone calls. Below are example use cases for a single data point and for multiple combinations of metrics in a dataframe.

  1. for a point data calculations
# ReqFTE(volume, aht, sla, slatime, intervallength)
ReqFTE(0.00278,2092.2,0.8,60,1) # calculate required FTEs
## [1] 9
# Occupancy(volume, aht,intervallength, agentscount)
Occupancy(0.00278, 2092.2, 1,9) # calculate occupancy
## [1] 0.6462573
# CAI(agents, volume,aht, intervallength)
CAI(9,0.00278, 2092.2, 1) # calculate  % calls answered immediately
## [1] 83.04241
# CAI(agents, volume,aht, intervallength)
ASA(9, 0.00278, 2092.2, 1) # calculate average speed of answering
## [1] 111.439
# CAI(agents, volume,aht, slatime, intervallength)
SL(9, 0.00278, 2092.2, 60,1) # calculate service level
## [1] 0.8452209
  1. for dataframes with multiple data points
# read the data from a local file
data = read.csv("capacityPlanInput.csv")
head(data)
##   day hour      volume AHT slaTarget slaTime interval
## 1   1    0 0.001666667 360       0.8     120        1
## 2   1    1 0.002222222 360       0.8     120        1
## 3   1    2 0.002777778 360       0.8     120        1
## 4   1    3 0.003333333 360       0.8     120        1
## 5   1    4 0.003888889 360       0.8     120        1
## 6   1    5 0.004444444 360       0.8      60        1
# calculate the metrics and add additional columns
(data$agents <- mapply(ReqFTE,data$volume,data$AHT,data$slaTarget,data$slaTime,data$interval))
##  [1] 2 3 3 3 4 4 4 5 5 6 6 6 6 7 7 6 6 6 6 5 5 4 3 2
(data$Occupancy <- mapply(Occupancy,data$volume,data$AHT,data$interval,data$agents))
##  [1] 0.3000001 0.2666666 0.3333334 0.4000000 0.3500000 0.4000000 0.5000000
##  [8] 0.4800000 0.5600000 0.5000000 0.5333333 0.5666666 0.6000000 0.5714286
## [15] 0.5428572 0.6000000 0.5666666 0.5333333 0.5000000 0.5600000 0.4800000
## [22] 0.4000000 0.3333334 0.2000000
(data$CAI <- mapply(CAI,data$agents,data$volume,data$AHT,data$interval))
##  [1] 86.15384 94.79675 90.90909 85.88236 93.96961 90.93003 82.60869 88.64962
##  [9] 81.04839 90.08568 87.28969 84.04677 80.34337 86.48898 89.11074 80.34337
## [17] 84.04677 87.28969 90.08568 81.04839 88.64962 90.93003 90.90909 93.33333
(data$ASA <- mapply(CAI,data$agents,data$volume,data$AHT,data$interval))
##  [1] 86.15384 94.79675 90.90909 85.88236 93.96961 90.93003 82.60869 88.64962
##  [9] 81.04839 90.08568 87.28969 84.04677 80.34337 86.48898 89.11074 80.34337
## [17] 84.04677 87.28969 90.08568 81.04839 88.64962 90.93003 90.90909 93.33333
(data$SL <- mapply(CAI,data$agents,data$volume,data$AHT,data$slaTarget,data$interval))
##  [1] 79.54545 90.90909 84.45273 76.31579 88.16308 82.60870 68.01432 76.38484
##  [9] 62.21617 77.25815 71.52391 65.04780 57.83479 67.58501 73.24736 57.83479
## [17] 65.04780 71.52391 77.25815 62.21617 76.38484 82.60870 84.45273 90.00000
# save to a csv output
write.csv(data,"Output.csv",row.names = F)

Schedule Generation

# read from a sample capacity plan
Cap = read.csv("capacityPlanOutput.csv")

## generate schedule for contract based staff with only full timers
answer = OptimumSchedule(Cap, shiftLength = 8,weeklyWorkingDays = 5,minEfficiency = 0.8,intervals = 24,partTime = F)
answer$agents # number of agents needed
## [1] 3
answer$coverage # coverage per interval
## # A tibble: 168 × 4
##    Interval Date   RequiredHeads StaffedHeads
##       <int> <chr>          <int>        <dbl>
##  1        0 1_Date             1            1
##  2        0 2_Date             1            2
##  3        0 3_Date             1            2
##  4        0 4_Date             1            1
##  5        0 5_Date             1            1
##  6        0 6_Date             1            1
##  7        0 7_Date             1            1
##  8        1 1_Date             1            1
##  9        1 2_Date             1            1
## 10        1 3_Date             1            1
## # ℹ 158 more rows
answer$plot # coverage vs requirement plot

answer$schedule # schedule format per agent
##    AgentNumber days shift shiftLength
## 1            1    1     0           8
## 2            1    2     0           8
## 3            1    3     0           8
## 4            1    4     0           8
## 5            1    5     0           8
## 6            2    1    17           8
## 7            2    2    17           8
## 8            2    5    17           8
## 9            2    6    17           8
## 10           2    7    17           8
answer$efficiency # scheduling efficiency
## [1] 0.7142857
## generate schedule for contract based staff with full timers and part-timers
answer2 = OptimumSchedule(Cap, shiftLength = 8,weeklyWorkingDays = 5,minEfficiency = 1,intervals = 24,partTime = T,minShiftLength = 5)
answer2$agents # number of agents needed
## [1] 3
answer2$coverage # coverage per interval
## # A tibble: 168 × 4
##    Interval Date   RequiredHeads StaffedHeads
##       <int> <chr>          <int>        <dbl>
##  1        0 1_Date             1            1
##  2        0 2_Date             1            1
##  3        0 3_Date             1            1
##  4        0 4_Date             1            1
##  5        0 5_Date             1            1
##  6        0 6_Date             1            0
##  7        0 7_Date             1            0
##  8        1 1_Date             1            1
##  9        1 2_Date             1            1
## 10        1 3_Date             1            1
## # ℹ 158 more rows
answer2$plot # coverage vs requirement plot

answer2$schedule # schedule format per agent
##    AgentNumber days shift shiftLength
## 1            1    1     0           8
## 2            1    2     0           8
## 3            1    3     0           8
## 4            1    4     0           8
## 5            1    5     0           8
## 6            2    1    17           7
## 7            2    2    17           7
## 8            2    3    17           7
## 9            2    4    17           7
## 10           2    5    17           7
answer2$efficiency # scheduling efficiency
## [1] 0.7142857
## generate schedule for gigeconomy workforce
answer3 = gigSchedule(Cap, shiftLength = 8,minEfficiency = 1,intervals = 24,minShiftLength = 7)
answer3$agents # number of agents needed
## NULL
answer3$coverage # coverage per interval
## # A tibble: 168 × 4
##    Interval Date   RequiredHeads StaffedHeads
##       <int> <chr>          <int>        <dbl>
##  1        0 1_Date             1            1
##  2        0 2_Date             1            2
##  3        0 3_Date             1            2
##  4        0 4_Date             1            2
##  5        0 5_Date             1            2
##  6        0 6_Date             1            2
##  7        0 7_Date             1            2
##  8        1 1_Date             1            1
##  9        1 2_Date             1            1
## 10        1 3_Date             1            1
## # ℹ 158 more rows
answer3$plot # coverage vs requirement plot

answer3$schedule # schedule format per agent
##    day shift shiftLength
## 1    1     0           8
## 2    1    17           8
## 3    1    23           8
## 4    2    17           8
## 5    2    23           8
## 6    3    17           8
## 7    3    23           8
## 8    4    17           8
## 9    4    23           8
## 10   5    17           8
## 11   5    23           8
## 12   6    17           8
## 13   6    23           8
## 14   7    17           7
answer3$efficiency # scheduling efficiency
## [1] 0.8285714

Checking Coverage and efficiency

# capacity plan
Cap = read.csv("capacityPlanOutput.csv")

# schedule
schedule = read.csv("schedule.csv")
head(schedule)
##   DStart DEnd Tstart TEnd
## 1      1    1      1    9
## 2      2    2      2   10
## 3      3    3      3   11
## 4      4    4      4   12
## 5      5    5      5   13
## 6      6    6      6   14
# calculate the coverage
cvrg = coverage(schedule,nDays = 7,intervals=24)
cvrg
##    1_Date 2_Date 3_Date 4_Date 5_Date 6_Date 7_Date
## 1       0      0      0      1      0      0      0
## 2       1      0      0      1      0      0      0
## 3       1      1      0      1      0      0      0
## 4       1      1      1      1      0      0      0
## 5       1      1      1      2      0      0      0
## 6       1      1      1      2      1      0      0
## 7       1      1      1      1      1      1      0
## 8       1      1      1      1      1      1      1
## 9       1      1      1      1      1      1      1
## 10      0      1      1      1      1      1      1
## 11      0      0      1      1      1      1      1
## 12      0      0      0      1      1      1      1
## 13      0      0      0      0      1      1      1
## 14      0      0      0      0      0      1      1
## 15      0      0      0      0      0      0      1
## 16      1      0      0      0      0      0      0
## 17      1      0      0      0      0      0      0
## 18      1      1      0      0      0      0      0
## 19      1      1      0      0      0      0      0
## 20      1      1      1      0      0      0      0
## 21      1      1      1      0      0      0      0
## 22      1      1      1      0      0      0      0
## 23      0      1      1      0      0      0      0
## 24      0      1      1      0      0      0      0
## Check the scheduling efficiency
accuracy_F(cvrg,Cap)
## [1] 0.1619048