  # DT.cleaned
  # DT.manual
  # DT.ancillary_from_rev_summary


## --------------------- ##
## DT.mgmtr_summary will be a copy of DT.cleaned, but with the store details aggregated out (as per designations)
## Note that this means the perc splits do not apply and will need to be recalculated
## Also, we can expect NAs in the permeated columns, specifically when is.na(music_vs_video) == TRUE
## --------------------- ##


if (FALSE)
{
  ## NOTE TO SELF:  
  "Thie is how merges work in data.table"
  
  ## SAMPLE DATA
  DT1 <- data.table(A=paste0("A", 1:3), B=11:13)
  DT1 <- rbind(DT1, DT1)[, D := letters[1:3]] [, source := "DT1"]
  DT2 <- data.table(A=paste0("A", 3:4), B=13:14)
  DT2 <- rbind(DT2, DT2)[, C := 1:4] [, source := "DT2"]
  matchKey(DT1, DT2, c("A", "B"))


  merge(DT1, DT2, all=FALSE, allow=TRUE)
  merge(DT1, DT2, all=TRUE, allow=TRUE)
  DT1[DT2, allow=TRUE]
  DT2[DT1, allow=TRUE]
}

  
# mgmtr_summary_tall
# c("accounting_month, store, label_sc_group, release_is_compilation, music_vs_video, musicbucket, videobucket, ancillaryline
#      , GL_netOfSC_forDS, budget, gross_is_estimate, gross_last_modified, budget_last_modified")
#
# mgmtr_summary
# c("accounting_month, store, label_sc_group, release_is_compilation, music_vs_video, musicbucket, videobucket, ancillaryline
#      , GL_netOfSC_forDS, gross_yago, budget, budget_yago, gross_is_estimate, gross_yago_is_estimate, gross_last_modified, budget_last_modified, budget_yago_last_modified")



## ------ BEGIN HERE ------- ##

## CREATE DT.mgmtr_summary FROM  DT.cleaned
{
  DT.mgmtr_summary <- copy(DT.cleaned.OSC) 
  DT.mgmtr_summary[, zz_hasData := TRUE]
  invisible()
}

## CLEANUP DT.mgmtr_summary -- ie, drop certain columns
{
  matchKey(DT.mgmtr_summary, DT.manl_crop, kCols.smry, organize=TRUE)

  ## Confirm budget is $0 in summary
  stopifnot(DT.mgmtr_summary[, sumn(budget)==0])

  ## Any column that is store-specific or cannot be summed must be dropped.
  ##  ie, "GL_gross_forDS" is unique to each date-store
  ##      "perc_split"  will need to be recalculated for the new groups
  cols.dropping.from.smry <- c("budget", "gross_last_modified", "budget_last_modified", "music_vs_video_by_dmv", "id_is_in_GL", "storeid_char", "GL_firstDate_forS", "perc_split") # "GL_gross_forDS", 
  suppressWarnings(DT.mgmtr_summary[, (cols.dropping.from.smry) := NULL])

  ## CONFIRM:  There is no overlap in column names, except for the keys
  stopifnot(!length(setdiff(intersect(names(DT.mgmtr_summary), names(DT.manl_crop)), kCols.smry)))
}

## Identify which stores will be aggregated out and which will remain
{
  ## Most stores will be aggregated out, except for a few handpicked stores
  matchKey(DT.mgmtr_summary, DT.manl_crop, kCols.store, organize=TRUE)

  ## CONFIRM THERE ARE ROWS IN THE MERGE
  stopifnot(nrow(merge(DT.mgmtr_summary, DT.manl_crop, all=FALSE, allow=TRUE)) > 0)

  ## Only those stores specifically in DT.manl_crop will be agg'd individually. The rest will be grouped together
  DT.mgmtr_summary[DT.manl_crop, `:=`(storeid_agg=storeid, store_name_agg=store_name), allow=TRUE]
  DT.mgmtr_summary[is.na(storeid_agg),    storeid_agg := -1]
  DT.mgmtr_summary[is.na(store_name_agg), store_name_agg := "OtherStores"]

  ## replace the original storeid, store_name with the agg'd version, drop the agg'd
  DT.mgmtr_summary[, storeid    := storeid_agg]  [, storeid_agg := NULL]
  DT.mgmtr_summary[, store_name := store_name_agg]  [, store_name_agg := NULL]

  ## backup for dev'ing
  DT.mgmtr_summary.bak <- copy(DT.mgmtr_summary)
  invisible()
}

BackUpOrRestore("DT.mgmtr_summary")

### HARD COPY TAKEN HERE -- TWICE ####
### Aggregate out all the stores that will not remain
{
  ## Aggregate the GL_gross_forDS before the others, since this requires unique()
  DT.mgmtr_summary[, GL_gross_forDSagg := sumn(unique(GL_gross_forDS)), by=kCols.smry]
  DT.mgmtr_summary[, GL_gross_forDS := NULL]

  ## CONFIRM:  The 'as reported' values should be unique by kCols.smry
  ##           Note that the calculated splits need not be, and will be recalculated post aggregation
  uniqCols <- c("zz_hasData", "margin_for_perc_split", "perc_split_as_reported", "GL_gross_forDSagg")
  stopifnot( isUniqueByGroup(DT.mgmtr_summary, colsToCheck=uniqCols, by=kCols.smry) )

## TODO:  create a separate kCols with uniquCols
  
  ## Aggregate the info
  DT.mgmtr_summary <- DT.mgmtr_summary[, lapply(.SD, sumn), keyby=c(kCols.smry, uniqCols)]

  ## the perc_split_ofOA_byDSO is no longer valid, after aggregating. Thuse drop it
  DT.mgmtr_summary[, perc_split_ofOA_byDSO := NULL]

  ## TODO:  Why did these rows even make it here? 
  ## Drop any rows where all the cols.to.spliton are NA and the GL_netOfSC_forDS is zero
  DT.mgmtr_summary <- DT.mgmtr_summary[!(GL_netOfSC_forDS == 0 & DT.mgmtr_summary[, rowSums(is.na(.SD))==length(cols.to.spliton), .SDcols=cols.to.spliton])]

  ## There should be no duplicates... namely zz_hasData should be unique by group
  stopifnot(!any(duplicated(DT.mgmtr_summary, by=kCols.smry)))

  ## I dont think we need the monthly_gross or perc_split info 
  if (FALSE) {
      ## Calculate new perc_splits
      DT.mgmtr_summary[, monthly_gross := sumn(GL_netOfSC_forDS), by=date]
      DT.mgmtr_summary[, perc_split := GL_netOfSC_forDS / monthly_gross]

      ## CONFIRM:  The perc_split sum to one
      stopifnot(DT.mgmtr_summary[, equals1(sum(perc_split)), by=date][, V1])
  }
}


## Merge in the DT.manl_crop info 
{
  matchKey(DT.mgmtr_summary, DT.manl_crop, kCols.smry, organize=TRUE, superset.ok=FALSE)

  ## MERGE THE MANUAL INFO WITH THE GL/OA SUMMARY INFO
  DT.mgmtr_summary_manual <- merge(DT.mgmtr_summary, DT.manl_crop, all=TRUE, allow=TRUE)

  ## Simultaneously convert zz_hasData back to logical while also filling the NAs to FALSE
  # DT.mgmtr_summary_manual[, zz_hasData := !is.na(zz_hasData)]
  ## .... actually... back to normal
  DT.mgmtr_summary_manual[is.na(zz_hasData), zz_hasData := FALSE]

  ## Create a copy of the GL_netOfSC_forDS column
  DT.mgmtr_summary_manual[, gross_before_adj := GL_netOfSC_forDS]


  ## FOR NOW, DROP THE gross_last_modified  COLUMN
  DT.mgmtr_summary_manual[, gross_last_modified := NULL]


  ## We expect NAs GL_netOfSC_forDS for a few combinations, set the GL_netOfSC_forDS to $0 
  ## There are no streaming OtherStores
  DT.mgmtr_summary_manual[is.na(GL_netOfSC_forDS) & store_musicbucket=="Streaming" & store_name == "OtherStores", GL_netOfSC_forDS := 0]
  ## There are no 'Retail Video' OtherStores
  DT.mgmtr_summary_manual[is.na(GL_netOfSC_forDS) & store_videobucket=="Retail Video" & store_name == "OtherStores", GL_netOfSC_forDS := 0]

  ## CONFIRM: All rows either have a GL_netOfSC_forDS or have a manual estimate ... assuming we dont have budget info for a month for which we do not yet have data for
  warning("   ****   RICK  ******  SOME ROWS ARE FAILING IN THE:   is.na(GL_netOfSC_forDS) iff ! is.na(estimate_current_month)  **")
  if (FALSE) {
    stopifnot(DT.mgmtr_summary_manual[, !(is.na(GL_netOfSC_forDS) & is.na(estimate_current_month) & date <= lastDateClosed)])
    DT.mgmtr_summary_manual[!(DT.mgmtr_summary_manual[, !(is.na(GL_netOfSC_forDS) & is.na(estimate_current_month) & date <= lastDateClosed)])]
  }


  ## fill in the manual estimate for the GL_netOfSC_forDS
  DT.mgmtr_summary_manual[is.na(GL_netOfSC_forDS), GL_netOfSC_forDS := estimate_current_month]
  DT.mgmtr_summary_manual[!is.na(estimate_current_month)]

  ## Add in manual adjustments
  DT.mgmtr_summary_manual[!is.na(manual_addition), GL_netOfSC_forDS := GL_netOfSC_forDS + manual_addition]

  ## We can drop the estimate column & the manual adjustment column
  DT.mgmtr_summary_manual[, c("estimate_current_month", "manual_addition") := NULL]



  ## TEMP FIX  "2013-01-01" PROBLEM -----------------
  {
    warning("\t *** RICK *** Fix the '2013-01-01' issue\n")
    ## TODO:  Figure out why No '2013-01-01' for RED / SelectO ? 
    if (DT.mgmtr_summary_manual[date == "2013-01-01", list(!is.na(margin_for_perc_split), !is.na(perc_split_as_reported)), keyby=label_sc_group][.(c("Allegro", "Orchard"))][, all(V1) && all(V2)]) {
   
      ## Manually place the missing values
      DT.mgmtr_summary_manual[date == "2013-01-01" & label_sc_group %in% c("RED", "SelectO") & is.na(perc_split_as_reported), perc_split_as_reported := 0]
      DT.mgmtr_summary_manual[date == "2013-01-01" & label_sc_group == "RED" & is.na(margin_for_perc_split), margin_for_perc_split := 0.06]
      DT.mgmtr_summary_manual[date == "2013-01-01" & label_sc_group == "SelectO" & is.na(margin_for_perc_split), margin_for_perc_split := 0.12]
    }
    invisible()
  }
  ## // end:  TEMP FIX  "2013-01-01" PROBLEM -----------------

  ## permeate the as-reproted values, first confirming they are unique (less any NAs) by group. 
  ## Note that there can be some NAs but an entire group cannot be all-NA
  {
    ## CONFRIM: margin is uniform by date-sc
    stopifnot(isUniqueByGroup(DT.mgmtr_summary_manual[!is.na(margin_for_perc_split)], colsToCheck=c("margin_for_perc_split", "perc_split_as_reported"), by=kCols.SC_date))

    ## There are some NAs, but the NAs should not take ALLL of the sc-date group
    stopifnot(DT.mgmtr_summary_manual[, !all(is.na(margin_for_perc_split)), by=kCols.SC_date] [, V1])

    ## Permeate those values by sc-date
    permeate_ (DT.mgmtr_summary_manual, "margin_for_perc_split",  by=kCols.SC_date, na.rm=TRUE)
    permeate_ (DT.mgmtr_summary_manual, "perc_split_as_reported", by=kCols.SC_date, na.rm=TRUE)

    ## CONFIRM: No NAs
    stopifnot(DT.mgmtr_summary_manual [, !is.na(margin_for_perc_split)] )
    stopifnot(DT.mgmtr_summary_manual[date <= lastDateClosed] [, !is.na(perc_split_as_reported)] )
  }


  ## COMPUTE THE GROSS, NET OF SC
  {
    ## < SEE > 
    DT.mgmtr_summary_manual[GL_netOfSC_forDS != 0 & perc_split_as_reported == 0]

    for (.osc in names(oscMargins)) {
      DT.mgmtr_summary_manual[label_sc_group == .osc, gross_statement := GL_netOfSC_forDS * oscMargins[[.osc]]  ]
    }

    DT.mgmtr_summary_manual[, gross_asreported := GL_netOfSC_forDS * margin_for_perc_split * perc_split_as_reported]
  }

  ## FOR DEV'ing
  DT.mgmtr_summary_manual.bak <- copy(DT.mgmtr_summary_manual)

  invisible()
}

## ---------------------------------------------------------------- ##

## FOR DEV'ing
DT.mgmtr_summary_manual <- copy(DT.mgmtr_summary_manual.bak)


## SEE -- these are the totals so far. 
DT.mgmtr_summary_manual[date >="2014-01-01" & date <= lastDateClosed, formnumb(lapply(.SD, sumn)), by=date, .SDcols=c("GL_netOfSC_forDS", "gross_asreported", "gross_statement")]

DT.mgmtr_summary_manual[date >="2014-01-01" & date <= lastDateClosed, formnumb(sum(GL_netOfSC_forDS * margin_for_perc_split)), by=date]

"
&&& LEFT OFF HERE 
"

## WAY OFF. 
dd  <- as.Date("2014-03-01")
targ <- 17485042
DT.mgmtr_summary_manual[.(dd)][GL_netOfSC_forDS != 0]
DT.mgmtr_summary_manual[.(dd), sumf(GL_netOfSC_forDS), by=label_sc_group]
DT.mgmtr_summary_manual[.(dd), sumf(GL_gross_forDSagg*margin_for_perc_split*perc_split_as_reported, na.rm=TRUE), by=label_sc_group]
DT.mgmtr_summary_manual[.(dd), sumf(unique(GL_gross_forDSagg), na.rm=TRUE), by=label_sc_group]


 # $17,255,905.01 
 # $167,122.66 
 # $62,014.00 

# DT.mainline_group_subtotals_from_rev_summary[date >="2014-01-01", formnumb(sum(reported_gross)), by=date]
#          date         V1
# 1: 2014-01-01 18,902,799
# 2: 2014-02-01 16,778,225
# 3: 2014-03-01 17,485,042
# 4: 2014-04-01 18,439,878
# 5: 2014-05-01 17,098,407


### AFTER TAKING NET OF OSC MARGINS, RBIND FILL THE  * EXPECTED REVENUE *  TABLE
{
  ## set keys for merging
  matchKey(DT.mainline_group_subtotals_from_rev_summary, DT.mgmtr_summary_manual, kCols.smry)

  ## CONFIRM: no NAs in GL_netOfSC_forDS prior to rbind -- this is important for taking sum(GL_netOfSC_forDS) and not mixing NAs with Values
  stopifnot(DT.mgmtr_summary_manual[, !is.na(GL_netOfSC_forDS)])

  # stopifnot(0 == nrow(merge(DT.mgmtr_summary_manual, DT.mainline_group_subtotals_from_rev_summary)))
  # merge(DT.mgmtr_summary_manual, DT.mainline_group_subtotals_from_rev_summary, keyby=c(setdiff(kColsa.smry, kCols.store)))

  ## RBIND
  temp_DT.rbound <- rbind(DT.mgmtr_summary_manual, DT.mainline_group_subtotals_from_rev_summary, fill=TRUE)
  setkeyIfNot(temp_DT.rbound, kCols.smry_nostore, verbose=FALSE)

  ## CONFIRM: Values add up
  .Expected_2 <- (.Expected_Rev_Jan_to_April_2014 - DT.ancillary_from_rev_summary[date >= "2014-01-01" & date <= "2014-04-01", sum(reported_gross)])
  stopifnot(equals(temp_DT.rbound[date >= "2014-01-01" & date <= "2014-04-01"][, sumn(reported_gross)], .Expected_2, tol=1.5))

  ## FIND WHATS MISSING
  {
    temp_DT.sums <- temp_DT.rbound[, lapply(.SD, sumn), keyby=kCols.smry_nostore, .SDcols=c("GL_netOfSC_forDS", "reported_gross")]
    equals(temp_DT.sums[date >= "2014-01-01" & date <= "2014-04-01", sum(reported_gross)], .Expected_2, tol=1.5)

    ## INVESTIGATE AT SOME FURTHER POINT
    if (any(temp_DT.sums[, 0!=reported_gross & (0==GL_netOfSC_forDS)])) {
      temp_DT.zero_gross <- temp_DT.sums[0!=reported_gross & (0==GL_netOfSC_forDS)]
      warning ("There are ", nrow(temp_DT.zero_gross), " rows with $0 GL_netOfSC_forDS yet non-$0 expected revenue. They appear in the months of ", pasteQand(unique(temp_DT.zero_gross$date)), if (all(temp_DT.zero_gross$music_vs_video == "Music")) paste(" for musicbuckets:", pasteQand(unique(temp_DT.zero_gross$store_musicbucket))))
      rm(temp_DT.zero_gross)
    }

    temp_DT.sums[, rev_in_summary_not_in_GL := reported_gross - GL_netOfSC_forDS]
    ## CONFIRM: All $0 for reported_gross for dates not in the GL
    stopifnot(temp_DT.sums[date %in% dates_not_in_GL, reported_gross == 0])
    temp_DT.sums[date %in% dates_not_in_GL, rev_in_summary_not_in_GL := 0]

    ## TODO:    
    ##  < EXPLORE >  ##
        temp_DT.sums[, lapply(.SD, sumn), .SDcols=c("GL_netOfSC_forDS", "reported_gross", "rev_in_summary_not_in_GL"), by=list(store_musicbucket,date)]
        temp_DT.sums[, lapply(.SD, sumn), .SDcols=c("GL_netOfSC_forDS", "reported_gross", "rev_in_summary_not_in_GL"), by=list(store_videobucket,date)]

        ## just in final months
        temp_DT.sums[, lapply(.SD, sumn), .SDcols=c("GL_netOfSC_forDS", "reported_gross", "rev_in_summary_not_in_GL"), by=list(release_product_type,date)]
        temp_DT.sums[, lapply(.SD, sumn), .SDcols=c("GL_netOfSC_forDS", "reported_gross", "rev_in_summary_not_in_GL"), by=list(label_sc_group,date)]
    ##  < EXPLORE >  ##

    
    ## Only keep rows where rev_in_summary_not_in_GL is none-zero
    DT.rev_in_summary_not_in_GL <- temp_DT.sums[(0!=rev_in_summary_not_in_GL)]

    ## Cleanup the meta
    DT.rev_in_summary_not_in_GL[,  GL_netOfSC_forDS := NULL]
    DT.rev_in_summary_not_in_GL[,  `:=`(storeid= -1, store_name="zzz_Mainline_Revenue")]
    setnames(DT.rev_in_summary_not_in_GL, "rev_in_summary_not_in_GL", "GL_netOfSC_forDS")

    # rm(temp_DT.sums, temp_DT.rbound)
  }

  # --------------
  matchKey(DT.mgmtr_summary_manual, DT.rev_in_summary_not_in_GL, kCols.smry, organize=TRUE, verbose=FALSE)
  DT.mgmtr_summary_manual <- rbind(DT.mgmtr_summary_manual, DT.rev_in_summary_not_in_GL, fill=TRUE) [is.na(GL_netOfSC_forDS), GL_netOfSC_forDS := rev_in_summary_not_in_GL]

  setkeyIfNot(DT.mgmtr_summary_manual, kCols.smry)
  stopifnot(equals(.Expected_2, DT.mgmtr_summary_manual[date >= "2014-01-01" & date <= "2014-04-01"][, sum(GL_netOfSC_forDS)], tol=1.5))
}


### ------------------------------------------------- ###

{
  suppressWarnings(DT.mgmtr_summary_manual[, gross_yago := NULL])
  ## Put in last months GL_netOfSC_forDS
  DT.yago <- copy(DT.mgmtr_summary_manual)
  ## This year's GL_netOfSC_forDS is next year's gross_yago
  DT.yago[, date := date %m+% months(12)]
  ## Merge it in
  matchKey(DT.mgmtr_summary_manual, DT.yago, kCols.smry)
  DT.mgmtr_summary_manual[DT.yago, gross_yago := i.GL_netOfSC_forDS, allow=TRUE]

  ## NOTE: Taking the mean across year's will not necessarilly line up, since there will be groups in current year not in yago (and possibly vice versa, but unlikely).  To check, we must sort by splitgroups and remove NAs


  ## CONFRIM: GL_netOfSC_forDS lines up with gross_yago (Two methods)
  {
    ## Method 1:  ordering by split group cols, then by month then year, gross_yago will be offset from GL_netOfSC_forDS by one row. Shifting up, they should line up and be equal
    stopifnot(DT.mgmtr_summary_manual[TRUE][, .month := month(date)][, .year := year(date)][, lapply(.SD, mean, na.rm=TRUE), .SDcols=c("GL_netOfSC_forDS", "gross_yago"), keyby=c(setdiff(kCols.smry, "date"), ".month", ".year")][, gyago := shiftUp(gross_yago)][!is.na(gyago), all(GL_netOfSC_forDS == gyago)])
    ## Method 2:  More manual procedure. Specifically, *leave* the NAs in the sum, ie do NOT use 'sumn'.  This will take care of categroies not matching up one year with the next
    stopifnot({
        merge(
        DT.mgmtr_summary_manual[year(date) == year(max(date)-1), list(.gross_last_year=sum(GL_netOfSC_forDS)), keyby=kCols.smry]
        , 
        DT.mgmtr_summary_manual[year(date) == year(max(date)), list(.gross_this_year=sum(GL_netOfSC_forDS)), keyby=kCols.smry]
        )[, equals(.gross_this_year, .gross_last_year, na.check=TRUE) & !all(is.na(.gross_this_year))]
      })
  }
  

  ## Cleanup Budget: 
  ## Budget may not properly be distributed across all the different subgroups
  ## Therefore, any parent group with *some* rows with budget, will have all NAs in budget treated as zeros. 
  ## ** The question is, what is a parent group?? **   For now, we will use date
  setkeyIfNot(DT.mgmtr_summary_manual, "date", superset.ok=TRUE, verbose=FALSE, warnForColNameInEnv=FALSE)
  DT.mgmtr_summary_manual[DT.mgmtr_summary_manual[, any(!is.na(budget)), keyby=kCols.main][(V1)], budget := removeNA(budget, replace=0)]

  DT.mgmtr_summary_manual[, var_gross_vs_budget_raw  := GL_netOfSC_forDS - budget]

  ## Compute growth and variance
  ## WHICH ONE?  ALLOW NAs or NO?
  DT.mgmtr_summary_manual[, yoy_growth_no_NA           := GL_netOfSC_forDS - gross_yago]
  DT.mgmtr_summary_manual[, var_gross_vs_budget_no_NA  := GL_netOfSC_forDS - budget]

  DT.mgmtr_summary_manual[, yoy_growth           := removeNA(GL_netOfSC_forDS, 0) - removeNA(gross_yago, 0)]
  DT.mgmtr_summary_manual[, var_gross_vs_budget  := removeNA(GL_netOfSC_forDS, 0) - removeNA(budget, 0)]

  ## If we do not yet have GL_netOfSC_forDS for a given month (ie, we received budget figures before OA or GL figures)
  ##  Then make those  var_gross_vs_budget  rows NA
  ##  note that there will be values in the GL_netOfSC_forDS for those where manually estimating
  ##
  ## This line identifies offending dates
  {
    .offendingDates <- DT.mgmtr_summary_manual[is.na(ancillaryline), all(GL_netOfSC_forDS[!is.na(GL_netOfSC_forDS)]==0), keyby=date][(V1), date]
    DT.mgmtr_summary_manual[date %in% .offendingDates, var_gross_vs_budget := NA]
    rm(.offendingDates)
  }

  ## CONFIRM Budget variabce
  {  
    ## CONFIRM:  The sum of the var_gross_vs_budget should be equal to the diff of the sum(GL_netOfSC_forDS) - sum(budget);
    ##             except where (zz_hasData == FALSE) sumn(var_gross_vs_budget) == 0  *this last part assumes we will never be exactly spot on budget to revenue.  CAREFUL! 
    ##             except where sumn(var_gross_vs_budget) == 0  *this last part assumes we will never be exactly spot on budget to revenue.  CAREFUL! 
## ?????
## TODO:  What is the correct filter for [i = ..] in each of these? 
# ---------------------------- #
# ? stopifnot(merge(DT.mgmtr_summary_manual[!(zz_hasData == FALSE), list(auto_var = sumn(var_gross_vs_budget)), keyby=kCols.main], DT.mgmtr_summary_manual[!is.na(budget), lapply(.SD, sumn), keyby=kCols.main, .SDcols=c("GL_netOfSC_forDS", "budget")][, list(man_var=GL_netOfSC_forDS-budget), keyby=kCols.main]    ) [auto_var != 0, equals(auto_var, man_var)])
stopifnot(merge(DT.mgmtr_summary_manual[!(zz_hasData == FALSE), list(auto_var = sumn(var_gross_vs_budget)), keyby=kCols.main], DT.mgmtr_summary_manual[!(zz_hasData == FALSE), lapply(.SD, sumn), keyby=kCols.main, .SDcols=c("GL_netOfSC_forDS", "budget")][, list(man_var=GL_netOfSC_forDS-budget), keyby=kCols.main]    ) [auto_var != 0, equals(auto_var, man_var)])
stopifnot(merge(DT.mgmtr_summary_manual[!is.na(budget), list(auto_var = sumn(var_gross_vs_budget)), keyby=kCols.main], DT.mgmtr_summary_manual[!is.na(budget), lapply(.SD, sumn), keyby=kCols.main, .SDcols=c("GL_netOfSC_forDS", "budget")][, list(man_var=GL_netOfSC_forDS-budget), keyby=kCols.main]    ) [auto_var != 0, equals(auto_var, man_var)])
# ---------------------------- #

    ## CONFIRM:  The only month when the entire sumn(var_gross_vs_budget) == 0 should be the last month. (ie, we got budget before transactions)
    stopifnot(DT.mgmtr_summary_manual[!is.na(budget), list(auto_var = sumn(var_gross_vs_budget)), keyby=date][auto_var==0, date == max(DT.mgmtr_summary_manual$date)])
  }
 
  ## drop the 'last modified' columns.  We won't use them in this table
  suppressWarnings( DT.mgmtr_summary_manual[, paste0(c("budget", "GL_netOfSC_forDS"), "_last_modified") := NULL] )

  invisible()
}

message("Done creating  'DT.mgmtr_summary_manual' ")



