Skip to content

Commit

Permalink
Allow guess_types in sf_run_report and fix date and datetime column bug
Browse files Browse the repository at this point in the history
Salesforce returns dates and datetimes in UTC but
sometimes as YYYY-MM-DD or MM/DD/YYYY in the case of
reports, so we will convert using the anytime package
rather than trusting type_convert()'s behavior.

Allow users to pass guess_types directly to sf_run_report()
in case they still want to do that and parse the character
strings on their own

Closes #93
  • Loading branch information
StevenMMortimer committed Jul 3, 2021
1 parent 9cdbd2d commit f415b49
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 9 deletions.
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Imports:
tibble (>= 3.0.3),
readr (>= 1.3.1),
lubridate (>= 1.7.8),
anytime (>= 0.3.9),
rlang (>= 0.4.7),
httr (>= 1.4.1),
curl (>= 4.3),
Expand Down
3 changes: 3 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,8 @@ importFrom(XML,xmlSApply)
importFrom(XML,xmlSize)
importFrom(XML,xmlToList)
importFrom(XML,xmlValue)
importFrom(anytime,anydate)
importFrom(anytime,anytime)
importFrom(base64enc,base64encode)
importFrom(curl,form_data)
importFrom(curl,form_file)
Expand Down Expand Up @@ -359,6 +361,7 @@ importFrom(purrr,transpose)
importFrom(readr,col_character)
importFrom(readr,col_guess)
importFrom(readr,cols)
importFrom(readr,locale)
importFrom(readr,parse_datetime)
importFrom(readr,read_csv)
importFrom(readr,type_convert)
Expand Down
13 changes: 12 additions & 1 deletion R/analytics-report.R
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,9 @@ sf_get_report_instance_results <- function(report_id,
#' report finish running so that data can be obtained. Otherwise, return the
#' report instance details which can be used to retrieve the results when the
#' async report has finished.
#' @template guess_types
#' @template bind_using_character_cols
#' @template fact_map_key
#' @template verbose
#' @return \code{tbl_df}
#' @family Report functions
Expand Down Expand Up @@ -1017,6 +1020,9 @@ sf_run_report <- function(report_id,
interval_seconds = 3,
max_attempts = 200,
wait_for_results = TRUE,
guess_types = TRUE,
bind_using_character_cols = FALSE,
fact_map_key = "T!T",
verbose = FALSE){

# build out the body of the request based on the inputted arguments by starting
Expand Down Expand Up @@ -1090,7 +1096,9 @@ sf_run_report <- function(report_id,

results <- sf_execute_report(report_id,
async = async,
report_metadata = request_body,
report_metadata = request_body,
guess_types = guess_types,
bind_using_character_cols = bind_using_character_cols,
verbose = verbose)

# request the report results (still wait if async is specified)
Expand Down Expand Up @@ -1123,6 +1131,9 @@ sf_run_report <- function(report_id,
}
results <- sf_get_report_instance_results(report_id,
results$id,
guess_types = guess_types,
bind_using_character_cols = bind_using_character_cols,
fact_map_key = "T!T",
verbose = verbose)
}
}
Expand Down
28 changes: 21 additions & 7 deletions R/utils-query.R
Original file line number Diff line number Diff line change
Expand Up @@ -733,32 +733,46 @@ sf_reorder_cols <- function(df){
contains("."))
}

#' Reorder resultset columns to prioritize \code{sObject} and \code{Id}
#' Parse resultset columns to a known datatype in R
#'
#' This function accepts a \code{tbl_df} with columns rearranged.
#'
#' @importFrom dplyr mutate across
#' @importFrom readr type_convert cols col_guess
#' @importFrom anytime anytime anydate
#' @importFrom readr type_convert cols col_guess locale
#' @param df \code{tbl_df}; the data frame to rearrange columns in
#' @return \code{tbl_df} the formatted data frame
#' @note This function is meant to be used internally. Only use when debugging.
#' @keywords internal
#' @export
sf_guess_cols <- function(df, guess_types=TRUE, dataType=NULL){
if(guess_types){
if(is.null(dataType) || any(is.na(dataType)) || (length(dataType)== 0)){
if(is.null(dataType) || any(is.na(dataType)) || (length(dataType) == 0)){
df <- df %>%
type_convert(col_types = cols(.default = col_guess()))
type_convert(col_types = cols(.default = col_guess()), locale=locale(tz="UTC"))
} else {
col_spec <- sf_build_cols_spec(dataType)
# if numeric but contains Salesforce "-" then preemptively change to NA
# if numeric Salesforce will flag N/A as "-" so we need to preemptively change to NA
# TODO: Does it use "-" for NA or zero? Or both?
if(grepl('i|n', col_spec)){
numeric_col_idx <- which(strsplit(col_spec, split=character(0))[[1]] %in% c("i", "n"))
df <- df %>%
mutate(across(all_of(numeric_col_idx), ~ifelse(.x == "-", NA_character_, .x)))
}
df <- df %>%
type_convert(col_types = col_spec)
# Salesforce returns dates and datetimes in UTC but sometimes as YYYY-MM-DD
# or MM/DD/YYYY in the case of reports, so we will convert using the
# anytime package rather than trusting type_convert's behavior
if(grepl('D', col_spec)){
date_col_idx <- which(strsplit(col_spec, split=character(0))[[1]] == "D")
df <- df %>%
mutate(across(all_of(date_col_idx), ~as.character(anydate(.x, tz="UTC", asUTC=TRUE))))
}
if(grepl('T', col_spec)){
datetime_col_idx <- which(strsplit(col_spec, split=character(0))[[1]] == "T")
df <- df %>%
mutate(across(all_of(datetime_col_idx), ~as.character(anytime(.x, tz="UTC", asUTC=TRUE))))
}
df <- df %>% type_convert(col_types = col_spec, locale=locale(tz="UTC"))
}
}
return(df)
Expand Down
2 changes: 1 addition & 1 deletion man/sf_guess_cols.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 46 additions & 0 deletions man/sf_run_report.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f415b49

Please sign in to comment.