36  Convert inventories to coverage

37 Upload libraries

# ETL
library(tidyverse)

# Supply Chain
library(planr)

38 Objective

We’re going to explain here how to use the function inv_to_cov() from the R package planr.

This function aims to convert projected inventories into their related coverages based on the :

  • the demand forecasts.

  • the projected inventories

It’s the opposite of the function proj_cov(), which converts a projected coverage into inventories.

39 Create a demo dataset

Let’s create a dataframe with the 4 variables we need for our calculation:

  • a DFU : 3 Products, A, B and C.

  • a Period of time : in monthly bucket.

  • some Projected Inventories : the monthy ending inventories of each product.

  • some Demand forecasts : some (monthly) sales forecasts for each product.

# create the variables
DFU <- c("Product_A", "Product_B", "Product_C")
Period <- format(seq(as.Date("2026-09-01"), by = "month", length.out = 24))

# merge and create a dataframe
set.seed(42)

df1 <- crossing(DFU, Period) |>
  mutate(
    Inventories = sample(100:300, n(), replace = TRUE),
    Demand = sample(50:200, n(), replace = TRUE)
    )

# format the Period as a Date
df1$Period <- as.Date(df1$Period, format = "%Y-%m-%d")
  
# keep results
inventories_data <- df1
  
glimpse(df1)  
Rows: 72
Columns: 4
$ DFU         <chr> "Product_A", "Product_A", "Product_A", "Product_A", "Produ…
$ Period      <date> 2026-09-01, 2026-10-01, 2026-11-01, 2026-12-01, 2027-01-0…
$ Inventories <int> 148, 164, 252, 173, 245, 221, 148, 227, 146, 123, 170, 199…
$ Demand      <int> 84, 65, 150, 118, 167, 179, 131, 162, 195, 118, 159, 153, …

40 Apply function

Now we apply the function inv_to_cov() to this dataframe.

The output is a dataframe with 6 variables. We get 2 additional ones:

  • Projected.Inventories.Qty : which is actually equal to the initial input [Inventories].

  • Calculated.Coverage.in.Periods : the conversion of those projected inventories into coverages, considering the Demand Forecasts.

# apply function 
df1 <- planr::inv_to_cov(inventories_data)

# keep results
calculated_data <- df1

glimpse(df1)
Rows: 72
Columns: 6
$ DFU                            <chr> "Product_A", "Product_A", "Product_A", …
$ Period                         <date> 2026-09-01, 2026-10-01, 2026-11-01, 20…
$ Demand                         <dbl> 84, 65, 150, 118, 167, 179, 131, 162, 1…
$ Opening                        <dbl> 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
$ Projected.Inventories.Qty      <dbl> 148, 164, 252, 173, 245, 221, 148, 227,…
$ Calculated.Coverage.in.Periods <dbl> 1.6, 1.1, 1.8, 1.0, 1.5, 1.6, 0.9, 1.3,…

Let’s analyze the results

We select the “Product_A” and look at the results:

  • at the end of the 1st Period “2026-09-01”, we have 1.6 months of coverage. 148 units indeed cover the Demand of “2026-10-01” and part of the next one of “2026-11-01”.
  • the same mechanism applies to the following Periods of time.
# filter on DFU
df1 <- calculated_data |> filter(DFU == "Product_A")


print(df1)
         DFU     Period Demand Opening Projected.Inventories.Qty
1  Product_A 2026-09-01     84      64                       148
2  Product_A 2026-10-01     65       0                       164
3  Product_A 2026-11-01    150       0                       252
4  Product_A 2026-12-01    118       0                       173
5  Product_A 2027-01-01    167       0                       245
6  Product_A 2027-02-01    179       0                       221
7  Product_A 2027-03-01    131       0                       148
8  Product_A 2027-04-01    162       0                       227
9  Product_A 2027-05-01    195       0                       146
10 Product_A 2027-06-01    118       0                       123
11 Product_A 2027-07-01    159       0                       170
12 Product_A 2027-08-01    153       0                       199
13 Product_A 2027-09-01     89       0                       188
14 Product_A 2027-10-01    198       0                       264
15 Product_A 2027-11-01    106       0                       209
16 Product_A 2027-12-01    149       0                       119
17 Product_A 2028-01-01     91       0                       253
18 Product_A 2028-02-01    195       0                       213
19 Product_A 2028-03-01    140       0                       210
20 Product_A 2028-04-01     62       0                       230
21 Product_A 2028-05-01    103       0                       140
22 Product_A 2028-06-01    132       0                       188
23 Product_A 2028-07-01     81       0                       126
24 Product_A 2028-08-01    109       0                       263
   Calculated.Coverage.in.Periods
1                             1.6
2                             1.1
3                             1.8
4                             1.0
5                             1.5
6                             1.6
7                             0.9
8                             1.3
9                             1.2
10                            0.8
11                            1.2
12                            1.6
13                            0.9
14                            2.1
15                            1.7
16                            1.1
17                            1.4
18                            2.1
19                            2.3
20                            2.0
21                            1.1
22                            2.0
23                           99.0
24                           99.0