---
title: "Before-tax by design: scope, portability, and future tax extensions"
author: "Package cre.dcf"
output:
  rmarkdown::html_vignette:
    toc: true
    toc_depth: 3
    number_sections: true
vignette: >
  %\VignetteIndexEntry{Before-tax by design: scope, portability, and future tax extensions}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
bibliography: manual-foundations.bib
link-citations: true
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, message = FALSE, warning = FALSE)
library(cre.dcf)
library(dplyr)
library(tibble)
```

## Purpose

This vignette explains a deliberate scope choice in `cre.dcf`: the package is currently designed as a property-level, before-tax DCF engine.

That choice is methodological and practical at the same time.

- Methodologically, the manuals first structure valuation around operating cash flows, terminal value, and leverage before opening the more jurisdiction-specific after-tax layer [@geltnerChapitre11Nuts_and_Bolts_for_Real_Estate_Valuation_Cash_Flow_Proformas_and_Discount_Rates2014; @hartzellChapter5Basic; @geltnerChapitre14AfterTax_Investment_Analysis_and_Corporate_Real_Estate2014].
- Practically, a before-tax core is much easier to mobilize across countries, vehicles, and investor types.

The portability argument is an implementation choice inferred from those chapters. The textbooks justify a strong before-tax core; the package then keeps that core jurisdiction-agnostic on purpose.

The package now also includes a first generic SPV-level tax helper, `tax_run_spv()`. The important design point is that this tax layer sits on top of the before-tax core rather than replacing it.

## Why the core still stops at the before-tax level

The current public API is strongest where the manuals are most universal:

- build the operating pro forma,
- expose the property-before-tax cash flow (`PBTCF`),
- isolate terminal value,
- layer leverage,
- read underwriting constraints.

This is already a meaningful analytical perimeter. It supports property comparison, financing comparison, exit-dependence diagnostics, and lease analysis without hard-coding any national tax code into the engine.

By contrast, after-tax analysis quickly becomes specific to:

- depreciation lives and asset splits,
- limits on interest deductibility,
- treatment of capital expenditures,
- loss carryforwards,
- exit taxation,
- investor and vehicle structure.

That is exactly why `cre.dcf` does not yet pretend to return a fully jurisdiction-specific after-tax investment value. The new tax helper is intentionally generic and stylized.

## What the core already gives us

The present version already produces most of the building blocks that a future SPV-level tax layer would need.

```{r}
cfg_path <- system.file("extdata", "preset_core.yml", package = "cre.dcf")
cfg <- yaml::read_yaml(cfg_path)
case <- run_case(cfg)

tax_basis_preview <- case$cashflows |>
  select(year, gei, noi, pbtcf, capex, interest, sale_proceeds, equity_flow) |>
  filter(year <= 4 | year == max(year))

knitr::kable(
  tax_basis_preview,
  digits = 0,
  caption = "Current outputs that can feed a future SPV-level tax layer"
)
```

The economic logic is already explicit:

- `gei` captures effective income,
- `noi` captures operating income net of recurring expenses,
- `pbtcf` captures the property-level cash flow before debt and taxes,
- `interest` and `sale_proceeds` are already separated in the consolidated table.

This is one of the main reasons the package can add a fiscal layer later without rewriting the current core.

## What the current `tax_rate` does and does not do

The package still exposes a `tax_rate` inside the WACC-oriented discount-rate blocks.

```{r}
tpl <- dcf_spec_template()

tibble(
  KE = tpl$disc_rate_wacc$KE,
  KD = tpl$disc_rate_wacc$KD,
  tax_rate = tpl$disc_rate_wacc$tax_rate
)
```

That field is part of the discounting convention. It adjusts the debt leg in a WACC-style formula. It is not a cash-tax engine.

In the current version, the following statements are true:

- `disc_rate_wacc$tax_rate` affects discount-rate construction,
- `scr_ratio` can still act as a fallback in some discounting workflows,
- neither of those fields computes annual corporate tax liabilities,
- neither of those fields applies depreciation, loss carryforwards, or tax rules at exit.

So the package already acknowledges tax in the cost-of-capital sense, but not yet in the jurisdictional cash-flow sense.

## Why this helps with multi-jurisdiction portability

A generic before-tax engine travels well because it focuses on the economics that are most stable across jurisdictions:

- rents, vacancy, expenses, capital expenditure,
- financing terms,
- debt service,
- terminal value,
- value composition between operations and exit.

The parts that differ the most from one country to another can then be isolated in a future tax specification instead of being mixed into the core valuation engine.

This is especially important if the same package may later be used for:

- a French SPV,
- a German asset-holding vehicle,
- a UK single-asset company,
- or a teaching case where only stylized tax assumptions are needed.

## The current SPV-level tax helper

The tax layer is optional and leaves `run_case()` untouched.

The intended split is:

```{r}
future_tax_blocks <- tibble::tribble(
  ~block, ~consumes_from_core, ~adds_from_tax_spec, ~target_output,
  "Tax depreciation", "price, capex, holding period", "asset split, depreciation lives, start rule", "tax_depreciation",
  "Interest deductibility", "interest", "deductibility rule", "deductible_interest, interest_disallowed",
  "Simple corporate tax", "taxable base after adjustments", "statutory rate", "cash_is",
  "Loss carryforwards", "negative taxable income", "carryforward rule", "loss_cf_open, loss_cf_used, loss_cf_close"
)

knitr::kable(
  future_tax_blocks,
  caption = "Target blocks for a future SPV-level tax layer"
)
```

For version 1 of that tax layer, the scope should remain intentionally narrow:

- straight-line tax depreciation,
- deductible interest under a simple rule,
- a single corporate income-tax rate,
- loss carryforwards.

That scope is large enough to support realistic teaching cases and comparative illustrations, but still narrow enough to remain portable across stylized jurisdictions.

## A working generic SPV tax run

The key design principle is that the before-tax case is still the source object, and the tax layer consumes it.

```{r}
tax_basis <- tax_basis_spv(case)

tax_spec <- tax_spec_spv(
  corp_tax_rate = 0.25,
  depreciation_spec = depreciation_spec(
    acquisition_split = tibble::tribble(
      ~bucket,    ~share, ~life_years, ~method,          ~depreciable,
      "land",      0.20,        NA,    "none",           FALSE,
      "building",  0.65,        30,    "straight_line",  TRUE,
      "fitout",    0.15,        10,    "straight_line",  TRUE
    ),
    capex_bucket = "fitout",
    start_rule = "full_year"
  ),
  interest_rule = interest_rule(mode = "full"),
  loss_rule = loss_rule(carryforward = TRUE, carryforward_years = Inf)
)

tax_res <- tax_run_spv(tax_basis, tax_spec)

tax_res$tax_table |>
  select(
    year, noi, tax_depreciation, deductible_interest,
    taxable_income_pre_losses, loss_cf_open, loss_cf_used,
    cash_is, after_tax_equity_cf
  ) |>
  filter(year <= 4 | year == max(year))
```

```{r}
tax_res$summary
```

This is enough to show the intended layering:

- the DCF engine still produces the economic case,
- `tax_basis_spv()` extracts a tax basis from that case,
- `tax_run_spv()` adds depreciation, deductible interest, simple CIT, and loss carryforwards.

The yearly tax table now exposes columns such as:

- `tax_depreciation`,
- `deductible_interest`,
- `interest_disallowed`,
- `taxable_income_pre_losses`,
- `loss_cf_open`,
- `loss_cf_used`,
- `loss_cf_close`,
- `cash_is`,
- `after_tax_equity_cf`.

It remains deliberately modest:

- no investor-level taxes,
- no withholding taxes,
- no jurisdiction-specific interest-cap regimes,
- no recapture logic,
- no treaty logic.

## How to read the French fiscal-impact vignette

The package now includes a French investment vignette built on `tax_run_spv()`.

That vignette should be read for what it is:

1. an illustration of one country-like parameterization of the generic engine,
2. a teaching-oriented bridge from before-tax DCF to SPV-level cash taxes,
3. not a complete encoding of French tax law.

In other words, the French vignette is useful precisely because it sits on top of the generic architecture rather than driving the architecture itself.

## Summary

The absence of a full tax engine in the current release is not a methodological weakness. It is a scope decision.

- The package is strongest on the textbook before-tax core.
- That core is explicit enough to feed a generic SPV-level tax layer.
- The current `tax_rate` input is part of discounting, not a fiscal cash-flow model.
- The new `tax_run_spv()` helper stays optional, generic, and jurisdiction-agnostic at the API level.

This keeps `cre.dcf` scientifically defensible today while supporting applied tax vignettes, including the current stylized French investment illustration built on `tax_run_spv()`.
