R/invoice.R

#' Create an invoice object
#' 
#' @param month specify month for a one-month invoice
#' @param year invoice year
#' @param since if month is not specified, beginning of invoice period
#' @param until end of invoice period
#' @param date invoice date, defaults to the day after until
#' @param client client name
#' @param address client address
#' @param expenses amount of expenses for current month
#' @param template_key the google drive key for the template to use.
#'    must be in your google drive
#' @param inv_number invoice number/code
#' 
#' @return an invoice object, a tibble with the following attributes:
#' \itemize{
#'    \item {fields} {the various invoice-specific values, such as date
#'    and address}
#'    \item {tmpl} {google drive document key of the template}
#'    \item {url} {url of the google sheet generated}
#' }
#' 
#' @examples
#' \dontrun{
#' # create an invoice for the latest complete calendar month using the default
#' # client, address, and template
#' invoice()
#' 
#' # create an invoice for this month to date
#' invoice(
#'   since = lubridate::floor_date(today(),"month"),
#'   until = lubridate::today()
#' )
#' }
#' 
#' @export
#' @importFrom retryr retry


invoice <- function(
  month = NULL,
  year = lubridate::year(lubridate::today()),
  since = if (is.null(month)) {
    d <- lubridate::today()-months(1)
    lubridate::day(d) <- 1
    d
  } else lubridate::ymd(sprintf("%s-%s-01", year, month)),
  until = since+months(1)-lubridate::days(1),
  client = getOption("invoicer_default_client","without client"),
  date = until + lubridate::days(1),
  address = getOption("invoicer_default_address",""),
  expenses = 0,
  template_key = getOption("invoicer_template_key", 
                           stop("template key must be specified")),
  inv_num = 1
){
  smry <- togglr::get_dashboard(since = since, until = until)$synthese
  smry <- smry[!is.na(smry$client),]
  smry <- smry[smry$client == client,]
  if(nrow(smry) == 0){
    message("no results for month ", month)
    return(NULL)
  }
  proj_code <- sub("\\s.+$", "", smry$project)
  proj_desc <- sub("^[A-Z0-9]+\\s+","", smry$project)
  recs <- tibble::tibble(
    inum = 1:nrow(smry), 
    proj_code = proj_code, 
    proj_desc = proj_desc,
    quant = smry$time/24/60/60/1000,
    rate = 50,
    total = 24 * rate * quant
  )
  fields <- list(
    period = sprintf(
      "%s - %s", format(since,"%d.%m.%Y"),
      format(until, "%d.%m.%Y")
    ),
    date = format(date,"%d.%m.%Y"),
    inv_num = str_glue("{client_code(client)}-{inv_num}"),
    client = client,
    address = address,
    fees_total = sum(recs$total),
    expenses = expenses,
    inv_total = expenses + sum(recs$total)
  )
  
  sh <- retry(googlesheets::gs_key)(template_key)
  
  
  # replace keys with field values in tmpl
  tmpl <- googlesheets::gs_read(sh,"Fees",col_names = F)
  tmpl[is.na(tmpl)] <- ""
  for(fn in names(fields)){
    addr <- which(tmpl==sprintf("${%s}",fn),arr.ind = T)
    tmpl[addr[1],addr[2]] <- fields[[fn]]
  }
  
  # create a copy of template and open it into sh
  sh <- retry(googlesheets::gs_key)(
    retry(googledrive::drive_cp)(
      retry(googledrive::as_id)(template_key),
      sprintf("Invoice %s - %s", client, format(date,"%Y%m%d"))
    )$id
  )
  
  # overwrite the copy with tmpl
  sh <- retry(googlesheets::gs_edit_cells)(sh,"Fees",tmpl,col_names = F)
  
  # copy recs into the copy at position "recs_anchor"
  anchor <- which(tmpl == "${recs_anchor}", arr.ind = T)
  anchor <- sprintf("R%dC%d",anchor[1],anchor[2])
  sh <- retry(googlesheets::gs_edit_cells)(
    sh,
    "Fees", 
    recs, 
    anchor = anchor, 
    col_names = F
  )
  browseURL(sh$browser_url)
  sh
}

get_pdf <- function(key,path="."){
  drive_download(as_id(key),paste0(path,'/',as_dribble(as_id(key))$name,'.pdf'))
}

client_code <- function(name)
  name %>% 
  stringr::str_split("") %>%
  getElement(1) %>% 
  map_int(utf8ToInt) %>% sum %>% 
  {. %% 10000}
  
mlgrm/invoicer documentation built on May 20, 2019, 11:59 a.m.