From e01a4b05977e8f05283ebfa65ccdc390f1355157 Mon Sep 17 00:00:00 2001
From: Reinhold Kainhofer <reinhold@kainhofer.com>
Date: Fri, 26 Nov 2021 23:51:43 +0100
Subject: [PATCH] Add hooks (adjustCosts, adjustMinCosts) to allow modifying
 costs per contract (i.e. modifying existing cost definitions from the
 tariff); Add function costs.scsaleAlpha

---
 NAMESPACE                                  |  1 +
 R/InsuranceParameters.R                    | 23 ++++++++++++++++++++++
 R/InsuranceTarif.R                         |  2 ++
 man/InsuranceContract.ParameterDefaults.Rd |  2 ++
 man/InsuranceContract.Rd                   |  4 +++-
 man/costs.scaleAlpha.Rd                    | 20 +++++++++++++++++++
 6 files changed, 51 insertions(+), 1 deletion(-)
 create mode 100644 man/costs.scaleAlpha.Rd

diff --git a/NAMESPACE b/NAMESPACE
index 5bf4308..688dc8d 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -57,6 +57,7 @@ export(applyHook)
 export(contractGrid)
 export(contractGridPremium)
 export(costs.baseAlpha)
+export(costs.scaleAlpha)
 export(costsDisplayTable)
 export(deathBenefit.annuityDecreasing)
 export(deathBenefit.linearDecreasing)
diff --git a/R/InsuranceParameters.R b/R/InsuranceParameters.R
index 79a4937..77e788e 100644
--- a/R/InsuranceParameters.R
+++ b/R/InsuranceParameters.R
@@ -163,6 +163,25 @@ costs.baseAlpha = function(alpha) {
   }
 }
 
+#' Helper function to modify alpha costs of an insurance contract individually
+#'
+#' Returns a function that modifies alpha (and Zillmer) costs by the given scale,
+#' but otherwise uses the full costs defined by the Costs parameter.
+#'
+#' This function can be set as adjustCosts or adjustMinCosts hook parameters
+#' for a tariff or contract and can be used to apply cost adjustments on a
+#' per-contract basis.
+#'
+#' @param scale The scale for  alpha / Zillmer cost
+#'
+#' @export
+costs.scaleAlpha = function(scale) {
+  function(costs, ...) {
+    costs[c("alpha", "Zillmer"),,] = costs[c("alpha", "Zillmer"),,] * scale
+    costs
+  }
+}
+
 
 #' Helper function to display all cost definitions in a concise table
 #'
@@ -492,6 +511,8 @@ InsuranceContract.Values = list(
 #' \describe{
 #'     \item{\code{$adjustCashFlows}}{Function with signature \code{function(x, params, values, ...)} to adjust the benefit/premium cash flows after their setup.}
 #'     \item{\code{$adjustCashFlowsCosts}}{Function with signature \code{function(x, params, values, ...)} to adjust the costs cash flows after their setup.}
+#'     \item{\code{$adjustCosts}}{Function with signature \code{function(costs, params, values, ...)} to adjust the tariff costs after their setup (e.g. contract-specific conditions/waivers, etc.).}
+#'     \item{\code{$adjustMinCosts}}{Function with signature \code{function(minCosts, costs, params, values, ...)} to adjust the tariff minimum (unwaivable) costs after their setup (e.g. contract-specific conditions/waivers, etc.).}
 #'     \item{\code{$adjustPremiumCoefficients}}{Function with signature \code{function(coeff, type, premiums, params, values, premiumCalculationTime)} to adjust the coefficients for premium calculation after their default setup. Use cases are e.g. term-fix tariffs where the Zillmer premium term contains the administration cost over the whole contract, but not other gamma- or beta-costs.}
 #' }
 #'
@@ -604,6 +625,8 @@ InsuranceContract.ParameterDefaults = list(
       # Functions with signature function(x, params, values, ...), default NULL is equivalent to function(x, ...) {x}
       adjustCashFlows = NULL,
       adjustCashFlowsCosts = NULL,
+      adjustCosts = NULL,
+      adjustMinCosts = NULL,
       adjustPremiumCoefficients = NULL # function(coeff, type = type, premiums = premiums, params = params, values = values, premiumCalculationTime = premiumCalculationTime)
     )
 );
diff --git a/R/InsuranceTarif.R b/R/InsuranceTarif.R
index ec977de..85b231c 100644
--- a/R/InsuranceTarif.R
+++ b/R/InsuranceTarif.R
@@ -372,7 +372,9 @@ InsuranceTarif = R6Class(
         browser();
       }
       costs = valueOrFunction(params$Costs, params = params, values = NULL)
+            costs = applyHook(params$Hooks$adjustCosts, costs, params = params, values = NULL);
       baseCost = valueOrFunction(params$minCosts, params = params, values = NULL, costs = costs)
+            baseCost = applyHook(params$Hooks$adjustMinCosts, baseCost, costs = costs, params = params, values = NULL);
       if (!is.null(baseCost)) {
         costWaiver = valueOrFunction(params$ContractData$costWaiver, params = params, values = NULL, costs = costs, minCosts = baseCost)
         if (is.numeric(costWaiver)) {
diff --git a/man/InsuranceContract.ParameterDefaults.Rd b/man/InsuranceContract.ParameterDefaults.Rd
index a501407..1fc6fd8 100644
--- a/man/InsuranceContract.ParameterDefaults.Rd
+++ b/man/InsuranceContract.ParameterDefaults.Rd
@@ -292,6 +292,8 @@ participation rates are defined at the level of profit classes.}
 \describe{
 \item{\code{$adjustCashFlows}}{Function with signature \code{function(x, params, values, ...)} to adjust the benefit/premium cash flows after their setup.}
 \item{\code{$adjustCashFlowsCosts}}{Function with signature \code{function(x, params, values, ...)} to adjust the costs cash flows after their setup.}
+\item{\code{$adjustCosts}}{Function with signature \code{function(costs, params, values, ...)} to adjust the tariff costs after their setup (e.g. contract-specific conditions/waivers, etc.).}
+\item{\code{$adjustMinCosts}}{Function with signature \code{function(minCosts, costs, params, values, ...)} to adjust the tariff minimum (unwaivable) costs after their setup (e.g. contract-specific conditions/waivers, etc.).}
 \item{\code{$adjustPremiumCoefficients}}{Function with signature \code{function(coeff, type, premiums, params, values, premiumCalculationTime)} to adjust the coefficients for premium calculation after their default setup. Use cases are e.g. term-fix tariffs where the Zillmer premium term contains the administration cost over the whole contract, but not other gamma- or beta-costs.}
 }
 }
diff --git a/man/InsuranceContract.Rd b/man/InsuranceContract.Rd
index aa65807..aeb37c4 100644
--- a/man/InsuranceContract.Rd
+++ b/man/InsuranceContract.Rd
@@ -632,13 +632,15 @@ that time will be left unchanged.}
 \subsection{Method \code{premiumWaiver()}}{
 Stop premium payments and re-calculate sumInsured of the paid-up contract
 \subsection{Usage}{
-\if{html}{\out{<div class="r">}}\preformatted{InsuranceContract$premiumWaiver(t)}\if{html}{\out{</div>}}
+\if{html}{\out{<div class="r">}}\preformatted{InsuranceContract$premiumWaiver(t, ...)}\if{html}{\out{</div>}}
 }
 
 \subsection{Arguments}{
 \if{html}{\out{<div class="arguments">}}
 \describe{
 \item{\code{t}}{Time of the premium waiver.}
+
+\item{\code{...}}{Further parameters (currently unused)}
 }
 \if{html}{\out{</div>}}
 }
diff --git a/man/costs.scaleAlpha.Rd b/man/costs.scaleAlpha.Rd
new file mode 100644
index 0000000..36e3ff2
--- /dev/null
+++ b/man/costs.scaleAlpha.Rd
@@ -0,0 +1,20 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/InsuranceParameters.R
+\name{costs.scaleAlpha}
+\alias{costs.scaleAlpha}
+\title{Helper function to modify alpha costs of an insurance contract individually}
+\usage{
+costs.scaleAlpha(scale)
+}
+\arguments{
+\item{scale}{The scale for  alpha / Zillmer cost}
+}
+\description{
+Returns a function that modifies alpha (and Zillmer) costs by the given scale,
+but otherwise uses the full costs defined by the Costs parameter.
+}
+\details{
+This function can be set as adjustCosts or adjustMinCosts hook parameters
+for a tariff or contract and can be used to apply cost adjustments on a
+per-contract basis.
+}
-- 
GitLab