Skip to content

Commit 79729dd

Browse files
Merge pull request #5 from California-Data-Collaborative/addSewerCharges
1. Added support for sewer_charge that can be tiered or allocation based. Uses sewer_tier_starts and sewer_tier_prices fields. 2. Tier start and tier prices no longer need to appear before commodity_charge and sewer_charge. 3. Some minor cleanup.
2 parents 7e89a2a + 67542a8 commit 79729dd

14 files changed

Lines changed: 128 additions & 57 deletions

DESCRIPTION

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ Date: 2016-10-28
66
Author: Christopher Tull
77
Maintainer: Christopher Tull <chris@argolabs.org>
88
Description: RateParser is designed to parse a machine-readable water rate
9-
structure written using the Open Water Rate Specification (OWRS). In addition
10-
to parsing the rate structure, this package will also apply the rate structure
11-
to properly formatted meter read data in order to calculate water bills.
9+
structure written using the Open Water Rate Specification (OWRS). In addition to
10+
parsing the rate structure, this package will also apply the rate structure to
11+
properly formatted meter read data in order to calculate water bills.
1212
License: MIT
1313
LazyData: TRUE
1414
Imports:
15-
dplyr,
16-
yaml
15+
dplyr,
16+
yaml
1717
Suggests:
18-
testthat,
19-
covr
18+
testthat,
19+
covr
20+
RoxygenNote: 5.0.1

NAMESPACE

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
# Generated by roxygen2 (4.1.1): do not edit by hand
1+
# Generated by roxygen2: do not edit by hand
22

33
export(calculate_bill)
4+
export(is_map)
45
export(read_owrs_file)
56
importFrom(dplyr,"%>%")
67
importFrom(dplyr,bind_cols)
78
importFrom(dplyr,do)
89
importFrom(dplyr,group_by)
10+
importFrom(dplyr,select)
911
importFrom(dplyr,tbl_df)
12+
importFrom(dplyr,ungroup)

R/rateParser.R

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ calculate_class_bill <- function(df, parsed_rate){
7070
return(df)
7171
}
7272

73-
73+
#' Evaluate a rate part and add to the dataframe.
74+
#'
75+
#' @importFrom dplyr %>% tbl_df group_by do bind_cols ungroup select
7476
add_rate_part_to_frame <- function(df, name, name_list, class_rate, cust_class){
7577
rate_part <- class_rate[[name]]
7678

@@ -90,13 +92,26 @@ add_rate_part_to_frame <- function(df, name, name_list, class_rate, cust_class){
9092
}
9193
else if(is_rate_type(rate_part)){
9294

93-
stopif(!(("tier_starts" %in% names(df))&&("tier_prices" %in% names(df))),
94-
paste0("Either tier_starts or tier_prices is not present in the ", cust_class,
95-
" rate structure, or they could appear afterwards."))
96-
9795
rate_type <- rate_part
98-
variable_bills <- df %>% group_by(tier_starts, tier_prices) %>%
99-
do(calculate_variable_bill(., rate_type))
96+
97+
if(name=="commodity_charge"){
98+
stopif(!(("tier_starts" %in% names(df))), "object 'tier_starts' not found")
99+
stopif(!(("tier_prices" %in% names(df))), "object 'tier_prices' not found")
100+
101+
variable_bills <- df %>% group_by(tier_starts, tier_prices) %>%
102+
do(calculate_variable_bill(., rate_type)) %>%
103+
ungroup() %>% select(-tier_starts, -tier_prices)
104+
105+
}else if(name=="sewer_charge"){
106+
stopif(!(("sewer_tier_starts" %in% names(df))), "object 'sewer_tier_starts' not found")
107+
stopif(!(("sewer_tier_prices" %in% names(df))), "object 'sewer_tier_prices' not found")
108+
109+
variable_bills <- df %>% group_by(sewer_tier_starts, sewer_tier_prices) %>%
110+
do(calculate_variable_bill(., rate_type, start_name="sewer_tier_starts",
111+
price_name="sewer_tier_prices", is_sewer=TRUE)) %>%
112+
ungroup() %>% select(-sewer_tier_starts, -sewer_tier_prices)
113+
}
114+
100115
#rename the column
101116
names(variable_bills)[names(variable_bills)=="variable_bill"] <- name
102117
df <- bind_cols( df, variable_bills )

R/tier_calcs.R

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,48 @@
22
#******************************************************************
33
# Calculate the variable portion of a bill
44
#******************************************************************
5-
calculate_variable_bill <- function(data, rate_type){
6-
tier_start_str <- data$tier_starts[1]
7-
tier_price_str <- data$tier_prices[1]
5+
calculate_variable_bill <- function(data, rate_type, start_name="tier_starts",
6+
price_name="tier_prices", is_sewer=FALSE){
7+
if(is_sewer){budget_col <- "sewer_budget"}
8+
else{budget_col <- "budget"}
9+
10+
tier_start_str <- data[[start_name]][1]
11+
tier_price_str <- data[[price_name]][1]
812

913
#call correct bill calculator function
1014
if(rate_type == "Tiered"){
1115
tier_starts <- parse_numerics(tier_start_str)
1216
tier_prices <- parse_numerics(tier_price_str)
1317
#check that prices are same length as tiers
1418
stopifnot(length(tier_starts)==length(tier_prices))
15-
bill_info <- calculate_tiered_charge(data, tier_starts, tier_prices)
19+
bill_info <- calculate_tiered_charge(data, tier_starts, tier_prices, is_sewer=is_sewer)
1620
}
1721
else if(rate_type == "Budget"){
18-
tier_starts <- get_budget_tiers(data, parse_strings(tier_start_str))
22+
tier_starts <- get_budget_tiers(data, parse_strings(tier_start_str), budget_col=budget_col)
1923
tier_prices <- parse_numerics(tier_price_str )
2024
#check that prices are same length as tiers
2125
stopifnot(ncol(tier_starts)==length(tier_prices))
22-
bill_info <- calculate_tiered_charge(data, tier_starts, tier_prices, budget_based=TRUE)
26+
bill_info <- calculate_tiered_charge(data, tier_starts, tier_prices, budget_based=TRUE, is_sewer=is_sewer)
2327
}
2428

2529
return(bill_info)
2630
}
2731

28-
#******************************************************************
29-
# Calculate a flat rate usage charge
30-
#******************************************************************
31-
calculate_flat_charge <- function(data, price){
32-
tmp <- tbl_df(data.frame(X1=data$usage_ccf, XR1= data$usage_ccf*price ,variable_bill=data$usage_ccf*price))
33-
return(tmp)
34-
}
3532

3633
#******************************************************************
3734
# Calculate a tiered usage charge
3835
#******************************************************************
39-
calculate_tiered_charge <- function(data, tier_starts, tier_prices, budget_based=FALSE){
36+
calculate_tiered_charge <- function(data, tier_starts, tier_prices, budget_based=FALSE, is_sewer=FALSE){
37+
if(is_sewer){suffix <- "_sewer"}
38+
else{suffix <- ""}
39+
4040
usage_in_tiers <- get_usage_in_tiers(data, tier_starts, budget_based=budget_based)
4141
revenue_in_tiers <- t(tier_prices*t(usage_in_tiers))
4242

43-
#change name of revenue columns to XR#
44-
colnames(revenue_in_tiers) <- c( paste("XR", 1:ncol(revenue_in_tiers), sep="") )
43+
#change name of usage columns to X#{suffix}
44+
colnames(usage_in_tiers) <- c( paste("X", 1:ncol(usage_in_tiers), suffix, sep="") )
45+
#change name of revenue columns to XR#{suffix}
46+
colnames(revenue_in_tiers) <- c( paste("XR", 1:ncol(revenue_in_tiers), suffix, sep="") )
4547
usage_in_tiers <- tbl_df(data.frame(usage_in_tiers, revenue_in_tiers, variable_bill=usage_in_tiers%*%tier_prices))
4648
return(usage_in_tiers)
4749
}
@@ -114,8 +116,8 @@ parse_numerics <- function(str){
114116
# and converts them to a matrix of CCF tier starting values for
115117
# each customer.
116118
#******************************************************************
117-
get_budget_tiers <- function(data, tier_start_strs){
118-
budget <- data$budget
119+
get_budget_tiers <- function(data, tier_start_strs, budget_col){
120+
budget <- data[[budget_col]]
119121
budget_tiers <- matrix(0, nrow(data), length(tier_start_strs))
120122

121123
for(i in 1:length(tier_start_strs)){

man/add_rate_part_to_frame.Rd

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/calculate_bill.Rd

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/calculate_class_bill.Rd

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/collapse_tiers.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/eval_field_or_formula.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/eval_map.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)