R/getSalesReports.R

Defines functions getSalesReport

Documented in getSalesReport

#' Retrieve sales reports.
#'
#' \code{getSalesReport} provides comphrehensive access to sales
#' reports from the appFigures web API. 
#'
#' @param product_ids Numeric. A vector of appFigures-assigned
#' product ids. The default will return sales for all products
#' in the account.
#' 
#' @param end_date Character string or date object. Date of last ranks
#' to be reported. Defaults to today. See Details.
#' 
#' @param start_date Character string or date object. Date of first
#' ranks to be reported. Defaults to the last 31 days. See Details.
#' 
#' @param group_by Character. Choose one or more of:
#' \code{"dates", "products", "store", "countries", or "regions"}
#' 
#' @param country Character. One or more country iso abbreviations.
#' Defaults to all countries.
#' 
#' @param dataset Character. Choose either \code{"none" or
#' "financial"}. Defaults to \code{"none"}. This only applies
#' to Apple products.
#' 
#' @param granularity Character. How should values be aggregated in time.
#' Options include \code{"daily", "weekly", "monthly", or "yearly"}.
#' See Details.
#' 
#' @param format Character. Choose between \code{"flat", "csv",
#'or "json"}. Defaults to \code{"flat"}. See Details
#' 
#' @param include_inapps Logical. If set to \code{TRUE}, any
#' products given in \code{product_ids} will have their
#' children automatically selected as well. Defaults to
#' \code{FALSE}.
#' 
#' @param curlHandle Provide an instance of the CURLHandle-class
#' from the RCurl package. The default will create a curl handle
#' specific to the function call.
#' 
#' @param verbose Logical. Should details of the web request
#' print to the console? Defaults to \code{FALSE}.
#' 
#' @param orgJSON Logical. Should the JSON string be returned
#' without being converted to R objects? Defaults to \code{FALSE}.
#' 
#' @details For \code{start_date} and \code{end_date}, if the
#' supplied argument can be interepreted as a date or POSIX
#' object, any hour, minute, or second is ignored. If a string
#' is supplied, it should have the format: 'yyyy-MM-dd'.
#' 
#' The argument \code{granularity} only matters if \code{group_by}
#' contains \code{"dates"}.
#' 
#' For the \code{format} argument, \code{"csv"} and \code{"flat"}
#' return similar fields. Both values will truncate some of the data
#' returned in the original JSON. A times (i.e. \code{group_by =
#' "products"}),  \code{"csv"} will contain a few more fields
#' than \code{"flat"}. Since different combinations of
#' \code{group_by} arguments will lead to different nested JSON
#' structures, if \code{format} is set to \code{"json"}, the
#' unformatted JSON string will be returned.
#' 
#' @return A data frame containing the requested sales report.
#' 
#' @seealso Official documentation:
#' \url{http://docs.appfigures.com/api/reference/v2/sales}.

getSalesReport <- function(product_ids, end_date, start_date,
                           group_by, country, dataset = c("none", "financial"),
                           granularity = c("daily", "weekly", "monthly", "yearly"),
                           format = c("flat", "csv", "json"), include_inapps = FALSE,
                           curlHandle, verbose = FALSE, orgJSON = FALSE) {
  
  stopifnot(is.logical(include_inapps))
  dataset <- match.arg(dataset)
  granularity <- match.arg(granularity)
  format <- match.arg(format)
  include_inapps <- tolower(deparse(include_inapps))
  uri <- paste(BASE_URI, "reports", "sales", sep = "/")
  if (missing(end_date)) {
    end_date <- as.character(Sys.Date())
  } else {
    end_date <- as.character(as.Date(end_date))
  }
  if (missing(start_date)) {
    start_date <- as.character(Sys.Date() - 31)
  } else {
    start_date <- as.character(as.Date(start_date))
  }
  product_ids <- if (!missing(product_ids)) {
    paste(product_ids, collapse = ";")
  }
  country <- if (!missing(country)) {
    paste(country, collapse = ";")
  }
  group_by <- if (!missing(group_by)) {
    paste(group_by, collapse = ",")
  }
  parList <- c(products = product_ids, end_date = end_date,
               start_date = start_date, granularity = granularity,
               countries = country, dataset = dataset,
               include_inapps = include_inapps, format = format,
               group_by = group_by)
  if (missing(curlHandle)) {
    opts <- list(userpwd = paste(USERNAME, PASSWORD, sep = ":"),
                 httpheader = c('X-Client-Key' = API_KEY),
                 httpauth = 1L, verbose = verbose, ssl.verifypeer = FALSE)
    curlHandle <- getCurlHandle(.opts = opts)
  } else if (!inherits(curlHandle, "CURLHandle")) {
    stop("curlHandle must be of class 'CURLHandle'.")
  } else {
    curlHandle <- curlHandle
  }
  jsonText <- getForm(uri, .opts = opts, .params = parList)
  if (orgJSON || format == "json") {
    if (!validate(jsonText)) {
      stop("appFigures API yielded invalid JSON!")
    }
    return(jsonText) 
  }
  if (format == "csv") {
    conn <- textConnection(jsonText)
    output <- read.csv(file = conn, header = T, stringsAsFactors = F)
    close(conn)
  }
  if (format == "flat") {
    output <- fromJSON(jsonText)
  }
  cont_vars <- c("gross_revenue", "revenue", "gross_returns_amount",
                 "returns_amount", "gross_educational_revenue",
                 "educational_revenue")
  for (cv in intersect(cont_vars, names(output))) {
    output[, cv] <- as.numeric(output[, cv])
  }
  if (all(c("start_date", "end_date") %in% names(output))) {
    output$start_date <- as.Date(output$start_date)
    output$end_date <- as.Date(output$end_date)
  }
  return(output)
}
appfigures/afapi documentation built on Nov. 13, 2022, 9:27 a.m.