#' @import methods
NULL
#' Compute Personnel Cost
#'
#' Calculates monthly personnel cost for each cost center Personnel costs are
#' comprised by:
#' \describe{
#' \item{60300000}{Payroll - Salaries (Regular)}
#' \item{60300001}{Payroll - Salaries (Seasonal)}
#' \item{60300004}{Payroll - Overtime (Regular)}
#' \item{60300005}{Payroll - Overtime (Seasonal)}
#' \item{60300008}{Payroll - 13th Month and Other Bonuses (Regular)}
#' \item{60300009}{Payroll - 13th Month and Other Bonuses (Seasonal)}
#' \item{60300011}{Payroll - Leave Commutation (Regular)}
#' \item{60300012}{Payroll - Leave Commutation (Seasonal)}
#' \item{60300014}{Payroll - De Minimis Benefits (Regular)}
#' \item{60300015}{Payroll - De Minimis Benefits (Seasonal)}
#' \item{60300017}{SSS Contributions (Regular)}
#' \item{60300018}{SSS Contributions (Seasonal)}
#' \item{60300020}{PHIC Contributions (Regular)}
#' \item{60300021}{PHIC Contributions (Seasonal)}
#' \item{60300023}{HDMF Contributions (Regular)}
#' \item{60300024}{HDMF Contributions (Seasonal)}
#' \item{60300029}{Other Employee Allowances}
#' \item{60300033}{Hospital and Medical Expenses - Employees}
#' \item{60300036}{Awards and Prizes}
#' \item{60900000}{Life and Medical Insurance - Employees}
#' \item{61100000}{Contract Fee - Agency Services}
#' }
#'
#' @param mhDB a \code{\link{data.frame}} similar to \code{mhDB} return by
#' \code{\link{getmhDB}}
#' @param listR a list of \code{\link{Employee-class}} objects representing the
#' employee pool
#' @param wage a \code{\link{data.frame}} composed of two columns:
#' \describe{
#' \item{ID}{character string representing a unique identifier of an
#' employee}
#' \item{s}{integer value representing the salary of an employee
#'
#' For rank and file, this value represents the daily salary at the
#' beginning of the year. For non-rank and file, this value represents
#' the monthly salary at the beginning of the year.}
#' }
#' @param forecast logical value \cr
#' Compute cost for forecast?
#' @param bonusFactorYearEnd a numeric value for the salary multiplier for the
#' year-end bonus
#' @param absentee a \code{\link{data.frame}} composed of at least two columns:
#' \describe{
#' \item{ID}{character string representing a unique identifier of an
#' employee}
#' \item{costCenter}{Cost centers wherein the leave commutation or the
#' holiday pays are distributed whenever the employee does not report for
#' work for a month.
#' }
#' }
#' @param monthStart an integer representing the month of start of forecasting
#' @param leaveConversionFactor numeric value for the monthly salary fraction
#' assumed as leave conversion
#' @return a list containing the following:
#'
#' \enumerate{
#' \item a data.frame with 16 columns
#'
#' The last 12 columns represents the cost per month.
#' The 1st column is the activity cost center.
#' The 2nd column is the description of the general ledger code.
#' The 3rd column is the equipment type used.
#' The 4th column is the general ledger code.
#'
#' \item tabulated total man hours per month per cost center
#' \item tabulated 13th month pay per month per cost center
#' \item tabulated bonus cost per month per cost center
#' \item a data.frame with 16 columns similar to the first element of the
#' returned list but with an additional column indicating the employment
#' status
#' }
#' @export getCost
#' @importFrom dplyr "%>%" bind_rows case_when filter group_by left_join mutate select summarise ungroup
#' @importFrom data.table data.table rbindlist
#' @importFrom tidyr gather pivot_longer pivot_wider spread
getCost <- function(mhDB,
listR,
wage,
forecast = FALSE,
bonusFactorYearEnd = 1.5,
absentee = NA,
monthStart = 1L,
leaveConversionFactor = 0.5) {
HM <-
ID <-
LC <-
PHIC <-
PI <-
X <-
XholHours <-
Xmh <-
abCost <-
abHours <-
absenteeList <-
allow <-
code <-
conversion <-
cost <-
costCenters <-
costCenter <-
costCenterNew <-
costNP <-
costWage <-
description <-
equipment <-
hRateA <-
hRateB <-
i <-
isOT.R <-
isOT.S <-
isStaff <-
maxReg <-
mh <-
mhDB.m.R.Reg.M <-
mhTot <-
mhType <-
mp <-
np <-
npR <-
npS <-
premiumR <-
premiumS <-
retentionBonus <-
riceSub <-
s <-
sB <-
sal <-
salH <-
salM <-
salMB <-
scheme <-
sg <-
status <-
totalCost <-
totMH <-
totMHCostCenter <- NULL
distType <- c("reg", "rd", "sh", "lh", "nh", "rs", "rl", "rn")
# Arrange absentee to a data.frame
if (!any(is.na(absentee))) {
absenteeList <- lapply(1:nrow(absentee), function(x) {
costCenters <- rmWS(absentee$costCenter[x])
costCenters <- unique(strsplit(x = costCenters,
split = " ",
fixed = TRUE)[[1]])
dfOut <- data.frame(ID = absentee$ID[x], costCenters = costCenters)
}) %>%
data.table::rbindlist()
}
#### Sanity Check ####
# Error if any ID in wage is duplicated
if (anyDuplicated(wage$ID) > 0) {
tempData <- wage$ID[which(duplicated(wage$ID))]
cat(paste("Duplicated :", tempData, "\n", sep = ""))
stop("There must be no duplicated ID's in wage data!")
}
# Employee salary link and maximum regular hours per month
empSM <- lapply(listR, function(x) {
if (forecast) {
# For the forecasting in 2022, there is a salary adjustment in September
# due to the new governemnt regulations.
sm <- data.frame(
month = 1:12, sal = c(rep("a", times = 8), rep("b", times = 4))
)
} else if (isRF(x)) {
sm <- payB
} else {
sm <- payA
}
sm$maxReg <- x@maxReg
sm$ID <- x@ID
return(sm)
}) %>% data.table::rbindlist()
# Employee payment scheme and status
empSS <- lapply(listR, function(x) {
data.frame(ID = x@ID,
scheme = ifelse(isRF(x), "d", "m"),
status = x@status,
isRF = isRF(x),
isStaff = is(x, "Staff"))
}) %>% data.table::rbindlist()
duplicatedID <- empSS$ID[which(duplicated(empSS$ID))]
if (length(duplicatedID) > 0)
stop(paste0("ID ", duplicatedID, " duplicated"))
# Error if any ID in listR is not in wage$ID
if (any(!empSS$ID %in% wage$ID)) {
empID <- empSS$ID[which(!empSS$ID %in% wage$ID)]
cat(paste("No wage data for :", empID, "\n", sep = ""))
stop("All ID's must have wage data")
}
# Assign if employee
# > isRF
# > isStaff
# > assign salary increase
wage <- dplyr::left_join(wage,
dplyr::select(empSS, ID, isRF, isStaff),
by = "ID") %>%
dplyr::mutate(sB = dplyr::case_when(forecast ~ s, TRUE ~ i)) %>%
dplyr::select(-i)
#### Assign totHours ####
wage$totHours <- sapply(wage$ID, FUN = function(x) {
# index <- which(empID == x)
# sum(listR[[index]]@totHours)
# total days per year is 313 as advised by Accounting
return(313 * 8)
})
#### Compute hourly rates ####
tempData <- apply(wage[, 2:6], MARGIN = 1, FUN = function(x) {
sal <- c(NA, NA)
if (x[2]) {
sal[1] <- x[1] / 8
sal[2] <- x[4] / 8
} else {
sal[1] <- x[1] / x[5]
sal[2] <- x[4] / x[5]
sal <- sal * 12
}
sal <- round(sal, digits = 2)
return(sal)
})
wage$hRateA <- tempData[1,]
wage$hRateB <- tempData[2,]
wageM <- dplyr::select(wage, ID, s, sB)
wageH <- dplyr::select(wage, ID, hRateA, hRateB)
colnames(wageM)[c(2,3)] <- c("a", "b")
colnames(wageH)[c(2,3)] <- c("a", "b")
wageM <- wageM %>%
tidyr::pivot_longer(-ID, names_to = "sal", values_to = "salM")
wageH <- wageH %>%
tidyr::pivot_longer(-ID, names_to = "sal", values_to = "salH")
wageEmp <- dplyr::left_join(x = wageM, y = wageH, by = c("ID", "sal")) %>%
dplyr::left_join(dplyr::select(wage, ID, isRF), by = "ID")
# Join sal, scheme, status, and maxReg
mhDB <- dplyr::left_join(dplyr::ungroup(mhDB),
dplyr::select(empSS, ID, scheme, status),
by = "ID") %>%
dplyr::left_join(empSM, by = c("ID", "month")) %>%
dplyr::mutate(costCenter = cleanCC(costCenter))
mhDBYear <- dplyr::group_by(mhDB, ID, costCenter, equipment) %>%
dplyr::summarise(mh = sum(mh))
empStatus <- lapply(listR, function(x) {
data.frame(ID = x@ID, status = x@status)
}) %>%
data.table::rbindlist(use.names = TRUE)
# A dummy man hours assignment intended to distributed cost during months that
# a personnel is not employed.
mhDBdummy <- dplyr::filter(empSM, maxReg == 0) %>%
dplyr::select(month, ID) %>%
dplyr::left_join(mhDBYear) %>%
dplyr::left_join(empStatus)
#### Compute Salaries for monthly wagers ####
cat("\nComputing salaries for non-RF.\n")
mhDB.m <- dplyr::filter(mhDB, scheme == "m") %>% dplyr::select(-scheme)
## Separate Regular Employees
mhDB.m.R <- dplyr::filter(mhDB.m, status == "reg") %>%
dplyr::select(-c(sal, status, maxReg)) %>%
dplyr::left_join(
dplyr::select(premium.nonRF, isOT.R, premiumR, npR, mhType),
by = c("mhType")
)
### Separate non-OT
mhDB.m.R.Reg <- dplyr::filter(mhDB.m.R, !isOT.R) %>%
dplyr::select(-c(mhType, isOT.R, premiumR))
#### Get monthly wage minus absences
mhDB.m.R.Reg.M <- mhDB.m.R.Reg %>%
dplyr::group_by(ID, month) %>%
dplyr::summarise(mhTot = sum(mh)) %>%
dplyr::left_join(
unique(dplyr::select(mhDB, ID, month, maxReg)),
by = c("ID", "month")
) %>%
dplyr::mutate(abHours = maxReg - mhTot) %>%
dplyr::left_join(unique(dplyr::select(mhDB, ID, month, sal)),
by = c("ID", "month")) %>%
dplyr::left_join(dplyr::select(wageEmp, -isRF),
by = c("ID", "sal")) %>%
dplyr::mutate(abCost = round(salH * abHours, digits = 2)) %>%
dplyr::mutate(salMB = salM - abCost)
#### Combine salMB
mhDB.m.R.Reg <- dplyr::left_join(
x = mhDB.m.R.Reg,
y = dplyr::select(mhDB.m.R.Reg.M, ID, month, mhTot, salH, salMB),
by = c("ID", "month")
) %>%
dplyr::mutate(Xmh = mh / mhTot) %>%
dplyr::mutate(costWage = round(Xmh * salMB, digits = 2),
costNP = round(salH * np * npR, digits = 2))
### Separate OT
mhDB.m.R.OT <- dplyr::filter(mhDB.m.R, isOT.R) %>%
dplyr::select(-mhType) %>%
dplyr::left_join(unique(dplyr::select(mhDB, ID, month, sal)),
by = c("ID", "month")) %>%
dplyr::left_join(dplyr::select(wageEmp, -c(salM, isRF)),
by = c("ID", "sal")) %>%
dplyr::mutate(costWage = round(salH * mh * premiumR, digits = 2),
costNP = round(salH * np * npR, digits = 2))
## Separate probationary employees
mhDB.m.P <- dplyr::filter(mhDB.m, status == "pro") %>%
dplyr::select(-c(sal, status, maxReg)) %>%
dplyr::left_join(
dplyr::select(premium.nonRF, isOT.S, premiumS, npS, mhType),
by = "mhType"
)
### Separate non-OT
mhDB.m.P.Reg <- dplyr::filter(mhDB.m.P, !isOT.S) %>%
dplyr::select(-c(mhType, isOT.S, premiumS))
#### Get monthly wage minus absences
mhDB.m.P.Reg.M <- mhDB.m.P.Reg %>%
dplyr::group_by(ID, month) %>%
dplyr::summarise(mhTot = sum(mh)) %>%
dplyr::left_join(unique(dplyr::select(mhDB, ID, month, maxReg)),
by = c("ID", "month")) %>%
dplyr::mutate(abHours = maxReg - mhTot) %>%
dplyr::left_join(unique(dplyr::select(mhDB, ID, month, sal)),
by = c("ID", "month")) %>%
dplyr::left_join(dplyr::select(wageEmp, -isRF),
by = c("ID", "sal")) %>%
dplyr::mutate(abCost = round(salH * abHours, digits = 2)) %>%
dplyr::mutate(salMB = salM - abCost)
#### Combine salMB
mhDB.m.P.Reg <- dplyr::left_join(
x = mhDB.m.P.Reg,
y = dplyr::select(mhDB.m.P.Reg.M, ID, month, mhTot, salH, salMB),
by = c("ID", "month")
) %>%
dplyr::mutate(Xmh = mh / mhTot) %>%
dplyr::mutate(costWage = round(Xmh * salMB, digits = 2),
costNP = round(salH * np * npS, digits = 2))
### Separate OT
mhDB.m.P.OT <- dplyr::filter(mhDB.m.P, isOT.S) %>%
dplyr::select(-mhType) %>%
dplyr::left_join(unique(dplyr::select(mhDB, ID, month, sal)),
by = c("ID", "month")) %>%
dplyr::left_join(dplyr::select(wageEmp, -c(salM, isRF)),
by = c("ID", "sal")) %>%
dplyr::mutate(costWage = round(salH * mh * premiumS, digits = 2),
costNP = round(salH * np * npS, digits = 2))
## Separate seasonal employees
mhDB.m.S <- dplyr::filter(mhDB.m, status == "sea") %>%
dplyr::select(-c(sal, status, maxReg)) %>%
dplyr::left_join(
dplyr::select(premium.nonRF, isOT.S, premiumS, npS, mhType),
by = "mhType"
)
### Separate non-OT
mhDB.m.S.Reg <- dplyr::filter(mhDB.m.S, !isOT.S) %>%
dplyr::select(-c(mhType, isOT.S, premiumS))
#### Get monthly wage minus absences
mhDB.m.S.Reg.M <- mhDB.m.S.Reg %>%
dplyr::group_by(ID, month) %>%
dplyr::summarise(mhTot = sum(mh)) %>%
dplyr::left_join(
unique(dplyr::select(mhDB, ID, month, maxReg)),
by = c("ID", "month")
) %>%
dplyr::mutate(abHours = maxReg - mhTot) %>%
dplyr::left_join(unique(dplyr::select(mhDB, ID, month, sal)),
by = c("ID", "month")) %>%
dplyr::left_join(dplyr::select(wageEmp, -isRF),
by = c("ID", "sal")) %>%
dplyr::mutate(abCost = round(salH * abHours, digits = 2)) %>%
dplyr::mutate(salMB = salM - abCost)
#### Combine salMB
mhDB.m.S.Reg <- dplyr::left_join(
x = mhDB.m.S.Reg,
y = dplyr::select(mhDB.m.S.Reg.M, ID, month, mhTot, salH, salMB),
by = c("ID", "month")
) %>%
dplyr::mutate(Xmh = mh / mhTot) %>%
dplyr::mutate(costWage = round(Xmh * salMB, digits = 2),
costNP = round(salH * np * npS, digits = 2))
### Separate OT
mhDB.m.S.OT <- dplyr::filter(mhDB.m.S, isOT.S) %>%
dplyr::select(-mhType) %>%
dplyr::left_join(unique(dplyr::select(mhDB, ID, month, sal)),
by = c("ID", "month")) %>%
dplyr::left_join(dplyr::select(wageEmp, -c(salM, isRF)),
by = c("ID", "sal")) %>%
dplyr::mutate(costWage = round(salH * mh * premiumS, digits = 2),
costNP = round(salH * np * npS, digits = 2))
#### Compute Salaries for daily wagers ####
cat("\nComputing salaries for RF.\n")
mhDB.d <- dplyr::filter(mhDB, scheme == "d") %>%
dplyr::select(-scheme) %>%
dplyr::left_join(dplyr::select(wageEmp, -c(salM, isRF)),
by = c("ID", "sal"))
## Separate Regular Employees
mhDB.d.R <- dplyr::filter(mhDB.d, status == "reg") %>%
dplyr::select(-c(status, maxReg)) %>%
dplyr::left_join(
y = dplyr::select(premium.RF, isOT.R, premiumR, npR, mhType),
by = "mhType"
) %>%
dplyr::mutate(costWage = round(salH * mh * premiumR, digits = 2),
costNP = round(salH * np * npR, digits = 2))
### Separate non-OT and OT
mhDB.d.R.Reg <- dplyr::filter(mhDB.d.R, !isOT.R)
mhDB.d.R.OT <- dplyr::filter(mhDB.d.R, isOT.R)
## Separate probationary employees
mhDB.d.P <- dplyr::filter(mhDB.d, status == "pro") %>%
dplyr::select(-c(status, maxReg)) %>%
dplyr::left_join(dplyr::select(premium.RF, isOT.S, premiumS, npS, mhType),
by = "mhType") %>%
dplyr::mutate(costWage = round(salH * mh * premiumS, digits = 2),
costNP = round(salH * np * npS, digits = 2))
### Separate non-OT and OT
mhDB.d.P.Reg <- dplyr::filter(mhDB.d.P, !isOT.S)
mhDB.d.P.OT <- dplyr::filter(mhDB.d.P, isOT.S)
## Separate seasonal employees
mhDB.d.S <- dplyr::filter(mhDB.d, status == "sea") %>%
dplyr::select(-c(status, maxReg)) %>%
dplyr::left_join(dplyr::select(premium.RF, isOT.S, premiumS, npS, mhType),
by = "mhType") %>%
dplyr::mutate(costWage = round(salH * mh * premiumS, digits = 2),
costNP = round(salH * np * npS, digits = 2))
### Separate non-OT and OT
mhDB.d.S.Reg <- dplyr::filter(mhDB.d.S, !isOT.S)
mhDB.d.S.OT <- dplyr::filter(mhDB.d.S, isOT.S)
## Separate agency employees
mhDB.d.A <- dplyr::filter(mhDB.d, status == "age") %>%
dplyr::select(-c(status, maxReg)) %>%
dplyr::left_join(dplyr::select(premium.RF, isOT.S, premiumS, npS, mhType),
by = "mhType") %>%
dplyr::mutate(costWage = round(salH * mh * premiumS, digits = 2),
costNP = round(salH * np * npS, digits = 2)) %>%
dplyr::mutate(cost = costWage + costNP)
#### Distribute holHours ####
hol.mhDB <- dplyr::filter(mhDB, mhType == "reg") %>%
dplyr::select(-c(mhType, np, scheme, maxReg)) %>%
dplyr::left_join(unique(dplyr::select(wageEmp, ID, isRF)),
by = "ID")
hol.mhDB.m <- dplyr::filter(hol.mhDB, !isRF)
hol.mhDB.d <- dplyr::filter(hol.mhDB, isRF)
## Create data.frame of holHours
holHours <- lapply(listR, FUN = function(x) {
data.frame(ID = x@ID, month = 1:12, holHours = x@holHours)
}) %>%
data.table::rbindlist(use.names = TRUE) %>%
dplyr::left_join(unique(dplyr::select(mhDB, ID, month, sal)),
by = c("ID", "month")) %>%
dplyr::left_join(dplyr::select(wageEmp, -salM),
by = c("ID", "sal"))
holHours.m <- dplyr::filter(holHours, !isRF)
holHours.d <- dplyr::filter(holHours, isRF) %>%
dplyr::mutate(costWage = salH * holHours)
## Merge costWage and holHours to hol.mhDB.d
hol.mhDB.d <- dplyr::left_join(
x = hol.mhDB.d,
y = unique(dplyr::select(holHours.d, ID, month, holHours, costWage)),
by = c("ID", "month")
)
hol.mhDB.m <- dplyr::left_join(
x = hol.mhDB.m,
y = dplyr::select(holHours.m, ID, month, holHours),
by = c("ID", "month")
)
## Compute for total mh per month per employee
hol.mhDB.d <- hol.mhDB.d %>%
dplyr::group_by(ID, month) %>%
dplyr::mutate(totHours = sum(mh))
hol.mhDB.m <- hol.mhDB.m %>%
dplyr::group_by(ID, month) %>%
dplyr::mutate(totHours = sum(mh))
## Compute mh fraction
hol.mhDB.d$X <- hol.mhDB.d$mh / hol.mhDB.d$totHours
hol.mhDB.m$X <- hol.mhDB.m$mh / hol.mhDB.m$totHours
## Compute for distributed holHours and costWage
hol.mhDB.d$XholHours <- hol.mhDB.d$X * hol.mhDB.d$holHours
hol.mhDB.m$XholHours <- hol.mhDB.m$X * hol.mhDB.m$holHours
hol.mhDB.d$XcostWage <- round(hol.mhDB.d$X * hol.mhDB.d$costWage, digits = 2)
## Separate employees by status
hol.mhDB.d.R <- dplyr::filter(hol.mhDB.d, status %in% c("reg", "pro"))
hol.mhDB.d.S <- dplyr::filter(hol.mhDB.d, status == "sea")
hol.mhDB.d.A <- dplyr::filter(hol.mhDB.d, status == "age")
#### Compute for Employee Allowances ####
cat("\nComputing employee allowances.\n")
allowance <- data.table::rbindlist(lapply(listR, getAllowance),
use.names = TRUE)
mhDB.allow <- dplyr::filter(mhDB, mhType %in% distType) %>%
dplyr::group_by(ID, month, costCenter, status, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID, month, status) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::left_join(allowance, by = c("ID", "month")) %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::mutate(cost = round(X * allowance, digits = 2))
#### Compute for Safety Gadgets ####
cat("\nComputing safety gadgets.\n")
safetyGadgets <- data.table::rbindlist(lapply(listR, getSafetyGadgets),
use.names = TRUE)
mhDB.safetyGadgets <- dplyr::filter(mhDB, mhType %in% distType) %>%
dplyr::group_by(ID, month, costCenter, status, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID, month, status) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::left_join(safetyGadgets, by = c("ID", "month")) %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::mutate(cost = round(X * sg, digits = 2))
#### Compute for Group Life Insurance ####
cat("\nComputing for group life insurance.\n")
groupLife <- data.table::rbindlist(lapply(listR, getGroupLife),
use.names = TRUE)
mhDB.groupLife <- dplyr::filter(mhDB, mhType %in% distType) %>%
dplyr::group_by(ID, month, costCenter, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID, month) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::left_join(groupLife, by = c("ID", "month")) %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::mutate(cost = round(X * gl, digits = 2))
#### Compute for Signing Bonus ####
cat("\nComputing for Signing Bonus.\n")
signingBonus <- data.table::rbindlist(lapply(listR, getSigningBonus),
use.names = TRUE)
mhDB.signingBonus <- dplyr::filter(mhDB,
mhType %in% distType,
month < 6) %>%
dplyr::group_by(ID, costCenter, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID) %>%
dplyr::mutate(totMH = sum(mh), month = 5L) %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::left_join(signingBonus, by = c("ID", "month")) %>%
dplyr::mutate(cost = round(X * signingBonus, digits = 2)) %>%
dplyr::filter(!is.na(cost)) %>%
dplyr::group_by(costCenter, month, equipment) %>%
dplyr::summarise(cost = sum(cost))
#### Compute for HMO ####
cat("\nComputing for HMO.\n")
hmo <- data.table::rbindlist(lapply(listR, getHMO), use.names = TRUE)
mhDB.hmo <- dplyr::filter(mhDB, mhType %in% distType) %>%
dplyr::group_by(ID, month, costCenter, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID, month) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::left_join(hmo, by = c("ID", "month")) %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::mutate(cost = round(X * hmo, digits = 2))
#### Employee benefits ####
# cat("\nComputing for employee benefits.\n")
benefits <- data.table::rbindlist(list(
data.table::rbindlist(lapply(listR, getCBA), use.names = TRUE),
data.table::rbindlist(lapply(listR, getLongShirt), use.names = TRUE),
data.table::rbindlist(lapply(listR, getLaborDayShirt), use.names = TRUE),
data.table::rbindlist(lapply(listR, FUN = function(x) {
if (isReg(x)) {
return(getGC(x))
} else {
return(NULL)
}
}), use.names = TRUE)
), use.names = TRUE) %>%
dplyr::group_by(month, ID) %>%
dplyr::summarise(benefits = sum(benefits))
mhDB.benefits <- dplyr::filter(mhDB, mhType %in% distType) %>%
dplyr::group_by(ID, month, costCenter, status, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID, month) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::left_join(benefits, by = c("ID", "month")) %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::mutate(cost = round(X * benefits, digits = 2))
mhDB.benefits.sea <- dplyr::filter(mhDB.benefits, status == "sea") %>%
dplyr::select(-status)
gcSea <- data.table::rbindlist(lapply(listR, FUN = function(x) {
if (x@status == "sea") {
return(getGC(x))
} else {
return(NULL)
}
}) , use.names = TRUE)
if (ncol(gcSea) > 0 & nrow(gcSea) > 0) {
mhDB.GC.sea <- dplyr::filter(mhDB,
mhType %in% distType,
status == "sea",
month %in% 4:10) %>%
dplyr::group_by(ID, costCenter, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::ungroup() %>%
dplyr::mutate(month = 11L, X = mh / totMH) %>%
dplyr::left_join(gcSea, by = c("ID", "month")) %>%
dplyr::mutate(cost = round(X * benefits, digits = 2))
mhDB.benefits.sea <- data.table::rbindlist(list(mhDB.benefits.sea,
mhDB.GC.sea),
use.names = TRUE)
mhDB.GC.sea$status <- "sea"
} else {
mhDB.GC.sea <- NULL
}
mhDB.benefits <- data.table::rbindlist(list(mhDB.benefits, mhDB.GC.sea),
use.names = TRUE)
##### Compute for Safety Bonus ####
cat("\nComputing safety bonus.\n")
mhDB.SB <- mhDB %>%
dplyr::group_by(costCenter, month, equipment, status) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::mutate(
cost = round(mh * 0.2, digits = 2),
costCenterNew = dplyr::case_when(
grepl("1100CM", x = costCenter) ~ "1100CM",
grepl("1100DM", x = costCenter) ~ "1100DM",
grepl("1100MP", x = costCenter) ~ "1100MP",
grepl("13[0-4][0-9]{2,}", x = costCenter) ~ "13102D",
grepl("14\\d00", x = costCenter) ~ "14000",
grepl("1100Y", x = costCenter) ~ "1100B",
grepl("1100Z", x = costCenter) ~ "1100B",
TRUE ~ "1100B"
)
) %>%
dplyr::ungroup() %>%
dplyr::mutate(costCenter = costCenterNew)
#### Compute for Pag-ibig contribution of employer ####
cat("\nComputing Pag-ibig contributions.\n")
mhDB.PI <- dplyr::filter(mhDB, mhType %in% distType) %>%
dplyr::group_by(ID, month, costCenter, status, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::ungroup() %>%
dplyr::mutate(PI = 150) %>%
dplyr::group_by(ID, month, status) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::ungroup() %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::mutate(cost = round(X * PI, digits = 2))
mhDB.PI.A <- dplyr::filter(mhDB.PI, status == "age")
mhDB.PI <- dplyr::filter(mhDB.PI, status != "age")
#### Compute for Phil-Health contribution of employer ####
cat("\nComputing Philhealth contribution.\n")
#- PHIC Contribution is fixed
#- For monthly wagers, PHIC is based on basic monthly salary
#- For daily wagers, PHIC is based on daily wage * 313 / 12
PHICdb <- lapply(listR, FUN = function(x) {
max_salary <- 80000
phic_premium <- 0.02
phic_premium_max <- 1600
phic_premium_min <- 200
tempData <- getCM(x)
if (!isReg(x)) {
tempData$sal <- "a"
} else {
if (isRF(x)) {
tempData <- dplyr::left_join(x = tempData, y = payB, by = "month")
} else {
tempData <- dplyr::left_join(x = tempData, y = payA, by = "month")
}
}
if (isRF(x)) {
tempData <- dplyr::left_join(
x = tempData,
y = dplyr::filter(wageEmp, isRF) %>% dplyr::select(-c(salH, isRF)),
by = c("ID", "sal")
) %>%
dplyr::mutate(salM = round(salM * 313 / 12, digits = 2))
} else {
tempData <- dplyr::left_join(
x = tempData,
y = dplyr::filter(wageEmp, !isRF) %>% dplyr::select(-c(salH, isRF)),
by = c("ID", "sal")
)
}
tempData <- dplyr::mutate(tempData,
salG = round(salM * allow, digits = 2)) %>%
dplyr::mutate(PHIC = dplyr::case_when(
salG < 0.01 ~ 0,
salG < 10000.01 ~ phic_premium_min,
salG < max_salary ~ round(salG * phic_premium, digits = 2),
TRUE ~ phic_premium_max
)) %>%
dplyr::select(month, ID, PHIC)
tempData
}) %>%
data.table::rbindlist(use.names = TRUE)
mhDB.PHIC <- dplyr::filter(mhDB, mhType %in% distType) %>%
dplyr::group_by(ID, month, costCenter, status, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID, month, status) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::ungroup() %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::left_join(PHICdb, by = c("ID", "month")) %>%
dplyr::mutate(cost = round(X * PHIC, digits = 2))
mhDB.PHIC.A <- dplyr::filter(mhDB.PHIC, status == "age")
mhDB.PHIC <- dplyr::filter(mhDB.PHIC, status != "age")
#### Compute for Leave Commutation ####
cat("\nComputing leave commutation.\n")
## Separate regular employees
### Extract maximum regular hours for each employee
maxRegDB <- lapply(listR[sapply(listR, isReg)], FUN = function(x) {
data.frame(ID = x@ID, month = 1:12, maxReg = x@maxReg)
})
if (length(maxRegDB) > 0) {
### Get total reg hours attendance (RH)
mhDB.RH <- dplyr::filter(
mhDB, status == "reg", mhType == "reg", month >= monthStart
) %>%
dplyr::group_by(ID, month) %>%
dplyr::summarise(mh = sum(mh)) %>%
tidyr::pivot_wider(names_from = month,
values_from = mh,
values_fill = list(mh = 0)) %>%
tidyr::pivot_longer(names_to = "month", values_to = "mh", -ID) %>%
dplyr::mutate(month = as.integer(month)) %>%
dplyr::left_join(
lapply(listR, function(x) {
if (isReg(x)) {
if (isRF(x)) {
dfOut <- payB
} else {
dfOut <- payA
}
dfOut$ID <- x@ID
return(dfOut)
}
return(NULL)
}) %>%
data.table::rbindlist()
)
### Join RH to maxRegDB then compute leave hours (LH) per month
tempID <- sapply(listR, FUN = function(x) {x@ID})
maxRegDB <- lapply(maxRegDB, FUN = function(z) {
z <- dplyr::left_join(x = z, y = mhDB.RH, by = c("ID", "month"))
z[is.na(z)] <- 0L
z$absence <- z$maxReg - z$mh
if (any(z$absence) < 0)
stop("Absence must not be less than 0!")
tempIndex <- which(tempID == z$ID[1])
LC <- listR[[tempIndex]]@leaveHours
z$LH <- 0
for (i in 1:12) {
if (LC > 0) {
minus <- min(z$absence[i], LC)
z$LH[i] <- minus
LC <- LC - minus
} else {
break
}
}
if ((sum(z$LH) + LC) != listR[[tempIndex]]@leaveHours)
stop("Leave hours do not match!")
return(z)
})
maxRegDB <- data.table::rbindlist(maxRegDB, use.names = TRUE) %>%
dplyr::left_join(dplyr::select(wageEmp, -c(salM, isRF)),
by = c("ID", "sal")) %>%
dplyr::mutate(LC = salH * LH)
### Filter-out months with full absences but with leave
vacationMode <- dplyr::filter(maxRegDB, LC > 0, mh < 1)
if (nrow(vacationMode) > 0) {
if (is.null(absenteeList))
stop("Absentees present but without cost centers distribution.")
absenteeID <- unique(vacationMode$ID)
absenteeIDAbsent <- absenteeID[!absenteeID %in% absenteeList$ID]
if (length(absenteeIDAbsent) > 0)
stop(paste0("No distribution absentee for ", absenteeIDAbsent, "."))
absenteeCost <- vacationMode %>%
dplyr::select(ID, month, LC) %>%
dplyr::inner_join(absenteeList, by = "ID") %>%
dplyr::group_by(ID, month) %>%
dplyr::mutate(n = dplyr::n()) %>%
dplyr::mutate(cost = round(LC / n, digits = 2)) %>%
dplyr::group_by(month, costCenters, ID) %>%
dplyr::summarise(cost = sum(cost))
}
### Distribute LC cost for regular employees
mhDB.LC.R <- dplyr::filter(mhDB, mhType %in% distType, status == "reg") %>%
dplyr::group_by(ID, month, costCenter, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID, month) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::ungroup() %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::left_join(dplyr::select(maxRegDB, ID, month, LC),
by = c("ID", "month")) %>%
dplyr::mutate(cost = round(X * LC, digits = 2))
if (nrow(vacationMode) > 0 &&
!is.null(absenteeCost) &&
nrow(absenteeCost) > 0) {
mhDB.LC.R <- dplyr::select(
mhDB.LC.R, ID, month, costCenter, equipment, cost
) %>%
dplyr::bind_rows(
dplyr::select(
absenteeCost, ID, month, costCenter = costCenters, equipment, cost)
)
}
} else {
mhDB.LC.R <- NULL
}
## Separate seasonal and agency employees
##- These must be separated since they are not entitled to negotiated
##- holiday premium.
##- Probationary employees have no leave commutation.
### Get leave hours
LH <- lapply(listR[sapply(listR, FUN = function(x) {
x@status %in% c("sea", "age")
})], FUN = function(x) {
data.frame(ID = x@ID, LH = x@leaveHours, sal = "a")
}) %>% data.table::rbindlist(use.names = TRUE)
if (nrow(LH) > 0) {
### Get LC cost per employee for the whole year
LH <- dplyr::left_join(x = LH,
y = dplyr::select(wageEmp, -c(salM, isRF)),
by = c("ID", "sal")) %>%
dplyr::mutate(LC = LH * salH)
### Distribute LC throughout the year
mhDB.LC.S <- dplyr::filter(mhDB,
status %in% c("sea", "age"),
mhType %in% distType) %>%
dplyr::group_by(ID, month, costCenter, status, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::ungroup() %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::left_join(dplyr::select(LH, ID, LC), by = "ID") %>%
dplyr::mutate(cost = round(X * LC, digits = 2))
} else {
mhDB.LC.S <- data.table::data.table(ID = character(),
status = character(),
costCenter = character(),
month = integer(),
equipment = character(),
cost = numeric())
}
## Get cost
mhDB.LC <- dplyr::filter(mhDB.LC.S, status == "sea") %>%
dplyr::select(costCenter, month, equipment, cost)
mhDB.LC.A <- dplyr::filter(mhDB.LC.S, status == "age") %>%
dplyr::select(costCenter, month, equipment, cost)
##### Compute for SSS contribution of employer ####
cat("\nComputing SSS contribution.\n")
#- SSS Contribution is based on gross salary
SSSdb <- data.frame(
ID = c(hol.mhDB.d.A$ID,
hol.mhDB.d.R$ID,
hol.mhDB.d.S$ID,
mhDB.d.A$ID,
mhDB.d.A$ID,
mhDB.d.P.OT$ID,
mhDB.d.P.OT$ID,
mhDB.d.P.Reg$ID,
mhDB.d.P.Reg$ID,
mhDB.d.R.OT$ID,
mhDB.d.R.OT$ID,
mhDB.d.R.Reg$ID,
mhDB.d.R.Reg$ID,
mhDB.d.S.OT$ID,
mhDB.d.S.OT$ID,
mhDB.d.S.Reg$ID,
mhDB.d.S.Reg$ID,
mhDB.m.P.OT$ID,
mhDB.m.P.OT$ID,
mhDB.m.P.Reg$ID,
mhDB.m.P.Reg$ID,
mhDB.m.R.OT$ID,
mhDB.m.R.OT$ID,
mhDB.m.R.Reg$ID,
mhDB.m.R.Reg$ID,
mhDB.m.S.OT$ID,
mhDB.m.S.OT$ID,
mhDB.m.S.Reg$ID,
mhDB.m.S.Reg$ID,
mhDB.LC.R$ID),
costCenter = c(hol.mhDB.d.A$costCenter,
hol.mhDB.d.R$costCenter,
hol.mhDB.d.S$costCenter,
mhDB.d.A$costCenter,
mhDB.d.A$costCenter,
mhDB.d.P.OT$costCenter,
mhDB.d.P.OT$costCenter,
mhDB.d.P.Reg$costCenter,
mhDB.d.P.Reg$costCenter,
mhDB.d.R.OT$costCenter,
mhDB.d.R.OT$costCenter,
mhDB.d.R.Reg$costCenter,
mhDB.d.R.Reg$costCenter,
mhDB.d.S.OT$costCenter,
mhDB.d.S.OT$costCenter,
mhDB.d.S.Reg$costCenter,
mhDB.d.S.Reg$costCenter,
mhDB.m.P.OT$costCenter,
mhDB.m.P.OT$costCenter,
mhDB.m.P.Reg$costCenter,
mhDB.m.P.Reg$costCenter,
mhDB.m.R.OT$costCenter,
mhDB.m.R.OT$costCenter,
mhDB.m.R.Reg$costCenter,
mhDB.m.R.Reg$costCenter,
mhDB.m.S.OT$costCenter,
mhDB.m.S.OT$costCenter,
mhDB.m.S.Reg$costCenter,
mhDB.m.S.Reg$costCenter,
mhDB.LC.R$costCenter),
month = c(hol.mhDB.d.A$month,
hol.mhDB.d.R$month,
hol.mhDB.d.S$month,
mhDB.d.A$month,
mhDB.d.A$month,
mhDB.d.P.OT$month,
mhDB.d.P.OT$month,
mhDB.d.P.Reg$month,
mhDB.d.P.Reg$month,
mhDB.d.R.OT$month,
mhDB.d.R.OT$month,
mhDB.d.R.Reg$month,
mhDB.d.R.Reg$month,
mhDB.d.S.OT$month,
mhDB.d.S.OT$month,
mhDB.d.S.Reg$month,
mhDB.d.S.Reg$month,
mhDB.m.P.OT$month,
mhDB.m.P.OT$month,
mhDB.m.P.Reg$month,
mhDB.m.P.Reg$month,
mhDB.m.R.OT$month,
mhDB.m.R.OT$month,
mhDB.m.R.Reg$month,
mhDB.m.R.Reg$month,
mhDB.m.S.OT$month,
mhDB.m.S.OT$month,
mhDB.m.S.Reg$month,
mhDB.m.S.Reg$month,
mhDB.LC.R$month),
equipment = c(hol.mhDB.d.A$equipment,
hol.mhDB.d.R$equipment,
hol.mhDB.d.S$equipment,
mhDB.d.A$equipment,
mhDB.d.A$equipment,
mhDB.d.P.OT$equipment,
mhDB.d.P.OT$equipment,
mhDB.d.P.Reg$equipment,
mhDB.d.P.Reg$equipment,
mhDB.d.R.OT$equipment,
mhDB.d.R.OT$equipment,
mhDB.d.R.Reg$equipment,
mhDB.d.R.Reg$equipment,
mhDB.d.S.OT$equipment,
mhDB.d.S.OT$equipment,
mhDB.d.S.Reg$equipment,
mhDB.d.S.Reg$equipment,
mhDB.m.P.OT$equipment,
mhDB.m.P.OT$equipment,
mhDB.m.P.Reg$equipment,
mhDB.m.P.Reg$equipment,
mhDB.m.R.OT$equipment,
mhDB.m.R.OT$equipment,
mhDB.m.R.Reg$equipment,
mhDB.m.R.Reg$equipment,
mhDB.m.S.OT$equipment,
mhDB.m.S.OT$equipment,
mhDB.m.S.Reg$equipment,
mhDB.m.S.Reg$equipment,
mhDB.LC.R$equipment),
cost = c(hol.mhDB.d.A$XcostWage,
hol.mhDB.d.R$XcostWage,
hol.mhDB.d.S$XcostWage,
mhDB.d.A$costNP,
mhDB.d.A$costWage,
mhDB.d.P.OT$costNP,
mhDB.d.P.OT$costWage,
mhDB.d.P.Reg$costNP,
mhDB.d.P.Reg$costWage,
mhDB.d.R.OT$costNP,
mhDB.d.R.OT$costWage,
mhDB.d.R.Reg$costNP,
mhDB.d.R.Reg$costWage,
mhDB.d.S.OT$costNP,
mhDB.d.S.OT$costWage,
mhDB.d.S.Reg$costNP,
mhDB.d.S.Reg$costWage,
mhDB.m.P.OT$costNP,
mhDB.m.P.OT$costWage,
mhDB.m.P.Reg$costNP,
mhDB.m.P.Reg$costWage,
mhDB.m.R.OT$costNP,
mhDB.m.R.OT$costWage,
mhDB.m.R.Reg$costNP,
mhDB.m.R.Reg$costWage,
mhDB.m.S.OT$costNP,
mhDB.m.S.OT$costWage,
mhDB.m.S.Reg$costNP,
mhDB.m.S.Reg$costWage,
mhDB.LC.R$cost)
) %>%
dplyr::group_by(ID, month, costCenter, equipment) %>%
dplyr::summarise(cost = sum(cost)) %>%
dplyr::filter(cost > 0) %>%
dplyr::group_by(ID, month) %>%
dplyr::mutate(totalCost = round(sum(cost), digits = 2)) %>%
dplyr::mutate(X = cost / totalCost)
SSSdb$SSSRate <- sapply(SSSdb$totalCost, function(x) {
SSS$c[which(SSS$r1 <= x & SSS$r2 >= x)]
})
SSSdb$SSS <- SSSdb$X * SSSdb$SSSRate
mhDB.SSS <- dplyr::group_by(SSSdb, ID, month, costCenter, equipment) %>%
dplyr::summarise(cost = round(sum(SSS), digits = 2)) %>%
dplyr::left_join(empStatus) %>%
dplyr::ungroup()
mhDB.SSS.A <- dplyr::filter(mhDB.SSS, status == "age")
mhDB.SSS <- dplyr::filter(mhDB.SSS, status != "age")
#### Compute for Hospital and Medical Expenses ####
cat("\nComputing hospital and medical expenses.\n")
hm <- data.table::rbindlist(lapply(listR, getHM), use.names = TRUE)
mhDB.HM <- dplyr::filter(mhDB, mhType %in% distType) %>%
dplyr::group_by(ID, month, costCenter, status, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID, month, status) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::ungroup() %>%
dplyr::left_join(hm, by = c("ID", "month")) %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::mutate(cost = round(X * HM, digits = 2))
mhDB.HM.A <- dplyr::filter(mhDB.HM, status == "age")
mhDB.HM <- dplyr::filter(mhDB.HM, status != "age")
#### Compute for 13th month pay ####
cat("\nComputing 13th month pay.\n")
mp13 <- data.table::rbindlist(lapply(listR, FUN = function(x) {
tempIndex <- which(wageEmp$ID == x@ID)
tempSal <- wageEmp$salM[tempIndex]
tempData <- get13mp(theObject = x, sal = tempSal)
return(tempData)
}), use.names = TRUE)
mhDB.13mp <- dplyr::filter(mhDB, mhType %in% distType) %>%
dplyr::group_by(ID, month, costCenter, status, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID, month, status) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::ungroup() %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::left_join(mp13, by = c("ID", "month")) %>%
dplyr::mutate(cost = round(X * mp, digits = 2)) %>%
dplyr::group_by(costCenter, status, month, equipment) %>%
dplyr::summarise(cost = sum(cost)) %>%
dplyr::ungroup()
mhDB.13mp.A <- dplyr::filter(mhDB.13mp, status == "age")
mhDB.13mp <- dplyr::filter(mhDB.13mp, status != "age")
## Separate 13th month pay for regular and non-regular in-house as requested
## by accounting
accr.13mp <- dplyr::group_by(
mhDB.13mp, status, costCenter, month, equipment
) %>%
dplyr::summarise(cost = sum(cost)) %>%
tidyr::spread(month, cost, fill = 0)
# Sum all man-hours
mhDB.mh1 <- dplyr::group_by(mhDB, costCenter, month, equipment, status) %>%
dplyr::summarise(cost = sum(mh))
mhDB.mh2 <- dplyr::group_by(
hol.mhDB.m, costCenter, month, equipment, status
) %>%
dplyr::summarise(cost = sum(XholHours))
mhDB.mh3 <- dplyr::group_by(
hol.mhDB.d, costCenter, month, equipment, status
) %>%
dplyr::summarise(cost = sum(XholHours))
mhDB.mh <- data.table::rbindlist(list(mhDB.mh1, mhDB.mh2, mhDB.mh3),
use.names = TRUE)
#### Compute for Mid-year and Year-end bonus ####
cat("\nComputing bonus.\n")
# FIXME: Bonus must pro-rated
# The date hired (probationary or regular, which ever came first) of the
# employee is used in pro-rating.
# The to fully enjoy the bonus for the year, the date of hiring must be not
# not later than January 01.
bonus <- lapply(listR, FUN = function(x) {
if (!isReg(x))
return(NULL)
tempData <- getCM(x)
if (isRF(x)) {
tempData <- dplyr::left_join(x = tempData, y = payB, by = "month") %>%
dplyr::left_join(
y = dplyr::filter(wageEmp, isRF) %>% dplyr::select(-c(salH, isRF)),
by = c("ID", "sal")
) %>%
dplyr::mutate(salM = round(salM * 26, digits = 2))
} else {
tempData <- dplyr::left_join(x = tempData, y = payA, by = "month") %>%
dplyr::left_join(
dplyr::filter(wageEmp, !isRF) %>% dplyr::select(-c(salH, isRF)),
by = c("ID", "sal")
)
}
tempData$salG <- round(tempData$salM * tempData$allow, digits = 2)
tempData$bonus <-
tempData$salG * c(0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, bonusFactorYearEnd)
tempData <- tempData[, colnames(tempData) %in% c("month", "ID", "bonus")]
tempData <- as.data.frame(tempData)
return(tempData)
}) %>%
data.table::rbindlist(use.names = TRUE)
if (length(bonus) > 0) {
# Distribute mid-year bonus to all manhours from January to May.
# TODO: in forecast, use actual manhours per employee.
# If forecasting, temporarily drop man-hours before the start of forecasted
# month so the the cost center "0-0" is not given bonus
mhDB.bonusMid <- dplyr::filter(mhDB,
mhType %in% distType,
month < 6,
month >= monthStart,
status == "reg") %>%
dplyr::group_by(ID, costCenter, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID) %>%
dplyr::mutate(totMH = sum(mh), month = 5L) %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::left_join(bonus, by = c("ID", "month"))
# Distribute year-and bonus to all manhours from January to December
# TODO: in forecast, use actual manhours per employee.
# If forecasting, temporarily drop man-hours before the start of forecasted
# month so the the cost center "0-0" is not given bonus
mhDB.bonusEnd <- dplyr::filter(
mhDB, mhType %in% distType, month >= monthStart, status == "reg"
) %>%
dplyr::group_by(ID, costCenter, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID) %>%
dplyr::mutate(totMH = sum(mh), month = 12L) %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::left_join(bonus, by = c("ID", "month"))
mhDB.bonus <- data.table::rbindlist(list(mhDB.bonusMid, mhDB.bonusEnd),
use.names = TRUE) %>%
dplyr::mutate(cost = round(X * bonus, digits = 2)) %>%
dplyr::filter(!is.na(cost)) %>%
dplyr::group_by(costCenter, month, equipment) %>%
dplyr::summarise(cost = sum(cost))
} else {
mhDB.bonus <- data.table::data.table(costCenter = character(),
month = integer(),
equipment = character(),
cost = numeric())
}
#### Compute for Leave Conversion of Regular Employees ####
cat("\nComputing leave conversion.\n")
leaveConversion <- lapply(listR, FUN = function(x) {
if (!isReg(x))
return(NULL)
tempData <- getCM(x)
if (isRF(x)) {
tempData <- dplyr::left_join(x = tempData, y = payB, by = "month") %>%
dplyr::left_join(
y = dplyr::filter(wageEmp, isRF) %>% dplyr::select(-c(salH, isRF)),
by = c("ID", "sal")
) %>%
dplyr::mutate(salM = round(salM * 26, digits = 2))
} else {
tempData <- dplyr::left_join(x = tempData, y = payA, by = "month") %>%
dplyr::left_join(
dplyr::filter(wageEmp, !isRF) %>% dplyr::select(-c(salH, isRF)),
by = c("ID", "sal")
)
}
tempData$salG <- round(tempData$salM * tempData$allow, digits = 2)
tempData$conversion <-
tempData$salG * c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, leaveConversionFactor)
tempData <- tempData[, colnames(tempData) %in% c("month", "ID", "conversion")]
tempData <- as.data.frame(tempData)
return(tempData)
}) %>%
data.table::rbindlist(use.names = TRUE)
if (length(leaveConversion) > 0) {
# Distribute leave conversion to all manhours from January to December
mhDB.leaveConversion <- dplyr::filter(
mhDB, mhType %in% distType, month >= monthStart, status == "reg"
) %>%
dplyr::group_by(ID, costCenter, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::mutate(month = 12L, X = mh / totMH) %>%
dplyr::left_join(leaveConversion, by = c("ID", "month")) %>%
dplyr::mutate(cost = round(X * conversion, digits = 2)) %>%
dplyr::filter(!is.na(cost)) %>%
dplyr::group_by(costCenter, month, equipment) %>%
dplyr::summarise(cost = sum(cost))
} else {
mhDB.leaveConversion <- data.table::data.table(costCenter = character(),
month = integer(),
equipment = character(),
cost = numeric())
}
#### Compute for Seasonal Employees Bonuses ####
cat("\nComputing signing bonus for seasonal employees.\n")
signingBonusSea <- lapply(listR, getSigningBonusSea) %>%
data.table::rbindlist(use.names = TRUE)
# Distribute seasonal signing bonus
mhDB.signingBonusSea <- dplyr::filter(mhDB, status == "sea") %>%
dplyr::group_by(ID, costCenter, month, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID, month) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::left_join(signingBonusSea, by = c("ID", "month")) %>%
dplyr::mutate(benefits = signingBonus * X) %>%
dplyr::group_by(costCenter, month, equipment) %>%
dplyr::summarise(cost = round(sum(benefits), digits = 2))
cat("\nComputing retention bonus for seasonal employees.\n")
retentionBonusSea <- lapply(listR, getRetentionBonus) %>%
data.table::rbindlist(use.names = TRUE)
# Distribute seasonal retention bonus
mhDB.retentionBonusSea <- dplyr::filter(mhDB, status == "sea") %>%
dplyr::group_by(ID, costCenter, month, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::group_by(ID, costCenter) %>%
dplyr::mutate(totMHCostCenter = sum(mh)) %>%
dplyr::mutate(X = totMHCostCenter / totMH) %>%
dplyr::left_join(retentionBonusSea, by = c("ID", "month")) %>%
dplyr::mutate(benefits = retentionBonus * X) %>%
dplyr::group_by(costCenter, month, equipment) %>%
dplyr::summarise(cost = round(sum(benefits), digits = 2))
# Combine Bonuses
mhDB.RB <- data.table::rbindlist(list(mhDB.signingBonusSea,
mhDB.retentionBonusSea),
use.names = TRUE) %>%
dplyr::group_by(costCenter, month, equipment) %>%
dplyr::summarise(cost = sum(cost))
#### Compute for Rice Subsidy for Agency ####
cat("\nComputing rice subsidy (agency).\n")
listR.A <- listR[sapply(listR, function(x) {return(x@status == "age")})]
if (length(listR.A) > 0) {
## Get rice subsidy per month per employee
riceSub.A <- lapply(listR.A, FUN = getRiceSub) %>%
data.table::rbindlist(use.names = TRUE)
## Distribute rice subsidy
mhDB.riceSub.A <- dplyr::filter(mhDB,
mhType %in% distType,
status == "age") %>%
dplyr::group_by(ID, month, costCenter, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::group_by(ID, month) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::ungroup() %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::left_join(riceSub.A, by = c("ID", "month")) %>%
dplyr::mutate(cost = round(X * riceSub, digits = 2))
} else {
mhDB.riceSub.A <- NULL
}
##### Compute for Rice Subsidy for in-house ####
cat("\nComputing rice subsidy (in-house).\n")
listR.I <- listR[sapply(listR, function(x) {return(x@status != "age")})]
if (length(listR.I) > 0) {
## Get rice subsidy per month per employee
riceSub.I <- lapply(listR.I, FUN = getRiceSub) %>%
data.table::rbindlist(use.names = TRUE)
## Distribute rice subsidy
mhDB.riceSub.I <- dplyr::filter(mhDB,
mhType %in% distType,
status != "age") %>%
dplyr::group_by(ID, month, costCenter, status, equipment) %>%
dplyr::summarise(mh = sum(mh)) %>%
dplyr::bind_rows(mhDBdummy) %>%
dplyr::group_by(ID, month) %>%
dplyr::mutate(totMH = sum(mh)) %>%
dplyr::ungroup() %>%
dplyr::mutate(X = mh / totMH) %>%
dplyr::left_join(riceSub.I, by = c("ID", "month")) %>%
dplyr::mutate(cost = round(X * riceSub, digits = 2))
} else {
mhDB.riceSub.I <- tidyr::tibble(costCenter = character(),
month = integer(),
equipment = character(),
cost = numeric())
}
#### Merged Costs ####
cat("\nMerging costs.\n")
c60300000 <- dplyr::bind_rows(
data.frame(costCenter = mhDB.m.R.Reg$costCenter,
month = mhDB.m.R.Reg$month,
equipment = mhDB.m.R.Reg$equipment,
cost = mhDB.m.R.Reg$costWage),
data.frame(costCenter = mhDB.d.R.Reg$costCenter,
month = mhDB.d.R.Reg$month,
equipment = mhDB.d.R.Reg$equipment,
cost = mhDB.d.R.Reg$costWage),
data.frame(costCenter = hol.mhDB.d.R$costCenter,
month = hol.mhDB.d.R$month,
equipment = hol.mhDB.d.R$equipment,
cost = hol.mhDB.d.R$XcostWage),
data.frame(costCenter = mhDB.m.P.Reg$costCenter,
month = mhDB.m.P.Reg$month,
equipment = mhDB.m.P.Reg$equipment,
cost = mhDB.m.P.Reg$costWage),
data.frame(costCenter = mhDB.d.P.Reg$costCenter,
month = mhDB.d.P.Reg$month,
equipment = mhDB.d.P.Reg$equipment,
cost = mhDB.d.P.Reg$costWage),
data.frame(costCenter = mhDB.LC.R$costCenter,
month = mhDB.LC.R$month,
equipment = mhDB.LC.R$equipment,
cost = mhDB.LC.R$cost)
) %>%
dplyr::mutate(description = "Payroll - Salaries (Regular)",
status = "reg")
c60300001 <- dplyr::bind_rows(
data.frame(costCenter = mhDB.m.S.Reg$costCenter,
month = mhDB.m.S.Reg$month,
equipment = mhDB.m.S.Reg$equipment,
cost = mhDB.m.S.Reg$costWage),
data.frame(costCenter = mhDB.d.S.Reg$costCenter,
month = mhDB.d.S.Reg$month,
equipment = mhDB.d.S.Reg$equipment,
cost = mhDB.d.S.Reg$costWage),
data.frame(costCenter = hol.mhDB.d.S$costCenter,
month = hol.mhDB.d.S$month,
equipment = hol.mhDB.d.S$equipment,
cost = hol.mhDB.d.S$XcostWage)
) %>%
dplyr::mutate(description = "Payroll - Salaries (Seasonal)",
status = "sea")
c60300004 <- dplyr::bind_rows(
data.frame(costCenter = mhDB.m.R.Reg$costCenter,
month = mhDB.m.R.Reg$month,
equipment = mhDB.m.R.Reg$equipment,
cost = mhDB.m.R.Reg$costNP),
data.frame(costCenter = mhDB.m.R.OT$costCenter,
month = mhDB.m.R.OT$month,
equipment = mhDB.m.R.OT$equipment,
cost = mhDB.m.R.OT$costWage),
data.frame(costCenter = mhDB.m.R.OT$costCenter,
month = mhDB.m.R.OT$month,
equipment = mhDB.m.R.OT$equipment,
cost = mhDB.m.R.OT$costNP),
data.frame(costCenter = mhDB.d.R.Reg$costCenter,
month = mhDB.d.R.Reg$month,
equipment = mhDB.d.R.Reg$equipment,
cost = mhDB.d.R.Reg$costNP),
data.frame(costCenter = mhDB.d.R.OT$costCenter,
month = mhDB.d.R.OT$month,
equipment = mhDB.d.R.OT$equipment,
cost = mhDB.d.R.OT$costWage),
data.frame(costCenter = mhDB.d.R.OT$costCenter,
month = mhDB.d.R.OT$month,
equipment = mhDB.d.R.OT$equipment,
cost = mhDB.d.R.OT$costNP),
data.frame(costCenter = mhDB.m.P.Reg$costCenter,
month = mhDB.m.P.Reg$month,
equipment = mhDB.m.P.Reg$equipment,
cost = mhDB.m.P.Reg$costNP),
data.frame(costCenter = mhDB.m.P.OT$costCenter,
month = mhDB.m.P.OT$month,
equipment = mhDB.m.P.OT$equipment,
cost = mhDB.m.P.OT$costWage),
data.frame(costCenter = mhDB.m.P.OT$costCenter,
month = mhDB.m.P.OT$month,
equipment = mhDB.m.P.OT$equipment,
cost = mhDB.m.P.OT$costNP),
data.frame(costCenter = mhDB.d.P.Reg$costCenter,
month = mhDB.d.P.Reg$month,
equipment = mhDB.d.P.Reg$equipment,
cost = mhDB.d.P.Reg$costNP),
data.frame(costCenter = mhDB.d.P.OT$costCenter,
month = mhDB.d.P.OT$month,
equipment = mhDB.d.P.OT$equipment,
cost = mhDB.d.P.OT$costWage),
data.frame(costCenter = mhDB.d.P.OT$costCenter,
month = mhDB.d.P.OT$month,
equipment = mhDB.d.P.OT$equipment,
cost = mhDB.d.P.OT$costNP)
) %>%
dplyr::mutate(description = "Payroll - Overtime (Regular)",
status = "reg")
c60300005 <- dplyr::bind_rows(
data.frame(costCenter = mhDB.m.S.Reg$costCenter,
month = mhDB.m.S.Reg$month,
equipment = mhDB.m.S.Reg$equipment,
cost = mhDB.m.S.Reg$costNP),
data.frame(costCenter = mhDB.m.S.OT$costCenter,
month = mhDB.m.S.OT$month,
equipment = mhDB.m.S.OT$equipment,
cost = mhDB.m.S.OT$costWage),
data.frame(costCenter = mhDB.m.S.OT$costCenter,
month = mhDB.m.S.OT$month,
equipment = mhDB.m.S.OT$equipment,
cost = mhDB.m.S.OT$costNP),
data.frame(costCenter = mhDB.d.S.Reg$costCenter,
month = mhDB.d.S.Reg$month,
equipment = mhDB.d.S.Reg$equipment,
cost = mhDB.d.S.Reg$costNP),
data.frame(costCenter = mhDB.d.S.OT$costCenter,
month = mhDB.d.S.OT$month,
equipment = mhDB.d.S.OT$equipment,
cost = mhDB.d.S.OT$costWage),
data.frame(costCenter = mhDB.d.S.OT$costCenter,
month = mhDB.d.S.OT$month,
equipment = mhDB.d.S.OT$equipment,
cost = mhDB.d.S.OT$costNP)
) %>%
dplyr::mutate(description = "Payroll - Overtime (Seasonal)",
status = "sea")
c60300008 <- dplyr::bind_rows(
dplyr::filter(mhDB.13mp, status != "sea") %>%
dplyr::select(costCenter, month, equipment, cost),
dplyr::select(mhDB.bonus, costCenter, month, equipment, cost),
dplyr::select(mhDB.signingBonus, costCenter, month, equipment, cost)
) %>%
dplyr::mutate(
description = "Payroll - 13th Month and Other Bonuses (Regular)",
status = "reg"
)
c60300009 <- dplyr::bind_rows(
dplyr::filter(mhDB.13mp, status == "sea") %>%
dplyr::select(costCenter, month, equipment, cost),
dplyr::select(mhDB.RB, costCenter, month, equipment, cost)
) %>%
dplyr::mutate(
description = "Payroll - 13th Month and Other Bonuses (Seasonal)",
status = "sea"
)
c60300011 <- dplyr::select(
mhDB.leaveConversion, costCenter, month, equipment, cost
) %>%
dplyr::mutate(description = "Payroll - Leave Commutation (Regular)",
status = "reg")
c60300012 <- dplyr::select(mhDB.LC, costCenter, month, equipment, cost) %>%
dplyr::mutate(description = "Payroll - Leave Commutation (Seasonal)",
status = "sea")
c60300014 <- dplyr::bind_rows(
dplyr::filter(mhDB.benefits, status != "sea") %>%
dplyr::select(costCenter, month, equipment, cost),
dplyr::filter(mhDB.riceSub.I, status != "sea") %>%
dplyr::select(costCenter, month, equipment, cost)
) %>%
dplyr::mutate(description = "Payroll - De Minimis Benefits (Regular)",
status = "reg")
c60300015 <- dplyr::bind_rows(
dplyr::filter(mhDB.benefits, status == "sea") %>%
dplyr::select(costCenter, month, equipment, cost),
dplyr::filter(mhDB.riceSub.I, status == "sea") %>%
dplyr::select(costCenter, month, equipment, cost)
) %>%
dplyr::mutate(description = "Payroll - De Minimis Benefits (Seasonal)",
status = "sea")
c60300017 <- dplyr::filter(mhDB.SSS, status != "sea") %>%
dplyr::select(costCenter, month, equipment, cost) %>%
dplyr::mutate(description = "SSS Contributions (Regular)",
status = "reg")
c60300018 <- dplyr::filter(mhDB.SSS, status == "sea") %>%
dplyr::select(costCenter, month, equipment, cost) %>%
dplyr::mutate(description = "SSS Contributions (Seasonal)",
status = "sea")
c60300020 <- dplyr::filter(mhDB.PHIC, status != "sea") %>%
dplyr::select(costCenter, month, equipment, cost) %>%
dplyr::mutate(description = "PHIC Contributions (Regular)",
status = "reg")
c60300021 <- dplyr::filter(mhDB.PHIC, status == "sea") %>%
dplyr::select(costCenter, month, equipment, cost) %>%
dplyr::mutate(description = "PHIC Contributions (Seasonal)",
status = "sea")
c60300023 <- dplyr::filter(mhDB.PI, status != "sea") %>%
dplyr::select(costCenter, month, equipment, cost) %>%
dplyr::mutate(description = "HDMF Contributions (Regular)",
status = "reg")
c60300024 <- dplyr::filter(mhDB.PI, status == "sea") %>%
dplyr::select(costCenter, month, equipment, cost) %>%
dplyr::mutate(description = "HDMF Contributions (Seasonal)",
status = "sea")
c60300036 <- dplyr::select(mhDB.SB, -c(mh, costCenterNew)) %>%
dplyr::mutate(description = "Awards and Prizes")
c60300029 <- dplyr::group_by(
mhDB.allow, costCenter, month, equipment, status
) %>%
dplyr::summarise(cost = sum(cost)) %>%
dplyr::mutate(description = "Other Employee Allowances")
c60300033 <- dplyr::select(
mhDB.HM, costCenter, month, equipment, cost, status
) %>%
dplyr::mutate(description = "Hospital and Medical Expenses - Employees")
c60900000 <- dplyr::bind_rows(
dplyr::group_by(mhDB.hmo, costCenter, month, equipment) %>%
dplyr::summarise(cost = sum(cost)),
dplyr::group_by(mhDB.groupLife, costCenter, month, equipment) %>%
dplyr::summarise(cost = sum(cost))
) %>%
dplyr::mutate(description = "Life and Medical Insurance - Employees",
status = "reg")
c61100000 <- dplyr::bind_rows(
data.frame(costCenter = mhDB.d.A$costCenter,
month = mhDB.d.A$month,
equipment = mhDB.d.A$equipment,
cost = mhDB.d.A$cost),
data.frame(costCenter = mhDB.d.A$costCenter,
month = mhDB.d.A$month,
equipment = mhDB.d.A$equipment,
cost = mhDB.d.A$costNP),
data.frame(costCenter = hol.mhDB.d.A$costCenter,
month = hol.mhDB.d.A$month,
equipment = hol.mhDB.d.A$equipment,
cost = hol.mhDB.d.A$XcostWage),
data.frame(costCenter = mhDB.SSS.A$costCenter,
month = mhDB.SSS.A$month,
equipment = mhDB.SSS.A$equipment,
cost = mhDB.SSS.A$cost),
data.frame(costCenter = mhDB.PI.A$costCenter,
month = mhDB.PI.A$month,
equipment = mhDB.PI.A$equipment,
cost = mhDB.PI.A$cost),
data.frame(costCenter = mhDB.PHIC.A$costCenter,
month = mhDB.PHIC.A$month,
equipment = mhDB.PHIC.A$equipment,
cost = mhDB.PHIC.A$cost),
data.frame(costCenter = mhDB.LC.A$costCenter,
month = mhDB.LC.A$month,
equipment = mhDB.LC.A$equipment,
cost = mhDB.LC.A$cost),
data.frame(costCenter = mhDB.HM.A$costCenter,
month = mhDB.HM.A$month,
equipment = mhDB.HM.A$equipment,
cost = mhDB.HM.A$cost),
data.frame(costCenter = mhDB.13mp.A$costCenter,
month = mhDB.13mp.A$month,
equipment = mhDB.13mp.A$equipment,
cost = mhDB.13mp.A$cost)
) %>%
dplyr::mutate(cost = round(cost * 1.3117, digits = 2)) %>%
dplyr::bind_rows(
data.frame(costCenter = mhDB.riceSub.A$costCenter,
month = mhDB.riceSub.A$month,
equipment = mhDB.riceSub.A$equipment,
cost = mhDB.riceSub.A$cost)
) %>%
dplyr::mutate(description = "Contract Fee - Agency Services",
status = "age")
c61300016 <- dplyr::group_by(
mhDB.safetyGadgets, costCenter, month, equipment, status
) %>%
dplyr::summarise(cost = sum(cost)) %>%
dplyr::mutate(description = "Safety Equipment and Supplies")
c99999999 <- as.data.frame(mhDB.mh) %>%
dplyr::mutate(description = "TMC Tools - Man-hours")
costDBraw <- dplyr::bind_rows(c60300000,
c60300001,
c60300004,
c60300005,
c60300008,
c60300009,
c60300011,
c60300012,
c60300014,
c60300015,
c60300017,
c60300018,
c60300020,
c60300021,
c60300023,
c60300024,
c60300036,
c60300029,
c60300033,
c60900000,
c61100000,
c61300016,
c99999999)
costDB <- dplyr::group_by(
costDBraw, costCenter, description, month, equipment
) %>%
dplyr::summarise(cost = sum(cost)) %>%
dplyr::left_join(y = mansched::acSAP, by = "description") %>%
tidyr::spread(month, cost, fill = 0) %>%
as.data.frame()
costDBbyStatus <- dplyr::group_by(
costDBraw, costCenter, description, month, equipment, status
) %>%
dplyr::summarise(cost = sum(cost)) %>%
dplyr::left_join(y = mansched::acSAP, by = "description") %>%
tidyr::spread(month, cost, fill = 0) %>%
as.data.frame()
cat("\nExporting data.\n")
missingCols <- (1:12)[which(!1:12 %in% colnames(costDB))]
for (i in missingCols) {
cmd <- paste0("costDB$`", i, "` <- 0")
eval(parse(text = cmd))
}
costDB <- costDB[, c("costCenter",
"description",
"equipment",
"code",
as.character(1:12))]
missingCols <- (1:12)[which(!1:12 %in% colnames(costDBbyStatus))]
for (i in missingCols) {
cmd <- paste0("costDBbyStatus$`", i, "` <- 0")
eval(parse(text = cmd))
}
costDBbyStatus <- costDBbyStatus[, c("costCenter",
"description",
"equipment",
"code",
"status",
as.character(1:12))]
export.mh <- dplyr::filter(costDB, code == 99999999L) %>%
dplyr::select(-c(description, code)) %>%
dplyr::arrange(costCenter, equipment) %>%
as.data.frame()
missingCols <- (1:12)[which(!1:12 %in% colnames(export.mh))]
for (i in missingCols) {
cmd <- paste0("export.mh$`", i, "` <- 0")
eval(parse(text = cmd))
}
export.mh <- export.mh[, c("costCenter", "equipment", as.character(1:12))]
export.mh$SUM <- apply(export.mh[, 3:14], MARGIN = 1, FUN = sum)
return(list(costDB, export.mh, accr.13mp, mhDB.bonus, costDBbyStatus))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.