[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] odd/mst-in-product-db 952b242 2/2: Embed {{MST}} and
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] odd/mst-in-product-db 952b242 2/2: Embed {{MST}} and <html> in product database |
Date: |
Thu, 18 Jul 2019 10:39:47 -0400 (EDT) |
branch: odd/mst-in-product-db
commit 952b2428040ddf17e86f77c5588dddeec2308f0d
Author: Gregory W. Chicares <address@hidden>
Commit: Gregory W. Chicares <address@hidden>
Embed {{MST}} and <html> in product database
Motivating example:
"<br><b>Definition #1:</b><br>{{phrase_1a}} some words {{phrase2a}}."
For instance, product_data::GuarMortalityFootnote says essentially:
"This [policy|contract|certificate] has guaranteed COIs
based on the [1980|2001|2017] CSO table"
and at present the database of proprietary products has distinct hard-
coded strings for all possibilities:
guar_mortality_footnote_1980
...
guar_mortality_certificate_footnote_2001
...
guar_mortality_policy_footnote_2017
...
one of which is specified for each of about 140 products. That's
redundant because the product database already has variables that hold
the variant components like "certificate" and "2017":
product_data::ContractName --> LedgerInvariant::ContractName
DBDictionary::CsoEra [to be mapped to a LedgerInvariant member soon]
The goal is to have a single "GuarMortalityFootnote" string for all
products, with the variant parts filled in automatically. There are
about a hundred footnote strings like this, and the evolving practice
(at least for one insurer) is to use exactly the same terminology as the
corresponding policy form, instead of generic wording like:
"This product has guaranteed COIs based on the applicable CSO table"
Often such "footnotes" embody definitions of terms such as
AttainedAgeFootnote = "The [insured|annuitant]'s age at the end of
the illustrated [policy|contract|certificate] year."
and the evolving practice is to format that thus:
<b>End of Year Age:</b> {{AttainedAgeFootnote}}
In theory, such a string could be hard-coded OAOO in each '.mst' file.
In practice, that approach has grown unworkable. For example, suppose
that a PDF resulting from
A.policy + A.database + X.mst --> AX.pdf
is formally filed with regulators; later, when a different product B
B.policy + B.database + X.mst --> BX.pdf
is to be filed, an arbitrary difference such as
- <b>End of Year Age:</b> {{AttainedAgeFootnote}}
+ <b>Age at End of Year:</b> {{AttainedAgeFootnote}}
may be considered necessary, simply because B's contract defined a
trivially different term for the same concept; but modifying template
X.mst potentially changes the already-filed AX.pdf, which is forbidden.
Virtualizing the name:
<b>{{EndOfYearAgeTerminology}}</b> {{AttainedAgeFootnote}}
might seem like a good idea, but really isn't, because that's just one
of an infinitude of possible variations, e.g.:
"...at the end of the illustrated [policy|contract|certificate] year."
"...at the end of the depicted [policy|contract|certificate] year."
which might be demanded for "business reasons".
Instead, ideally, footnotes could be consolidated into a handful of
multiple-paragraph blurbs:
std::string blurb1 = "term0: {{defn0}}<br>term1:{{defn1}}<br>...";
which would be held in '.policy' files, with html markup and mustache
substitutions realized when a PDF is generated. IOW, the vision is to
change the contents of '.policy' files from flat text to something like
mustache "partials" (even if the {{>partial}} syntax isn't used).
Test case:
File | New | Illustration [defaults to 'sample' product']
OK
File | Print to PDF
This appears toward the top of page 3 of 10:
Guaranteed mortality column definition: [only that line in boldface]
Superior Life Insurance Company guarantees that this contract's
mortality charges will never exceed the applicable CSO mortality
tables...blah blah blah.
This demonstration does work, but it's ugly. The de-html-ization code
is terse, but presumably slow; and calling interpolate_string() twice
can't be optimal.
---
pdf_command_wx.cpp | 23 ++++++++++++++++++++++-
product_data.cpp | 6 ++++++
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/pdf_command_wx.cpp b/pdf_command_wx.cpp
index bfcbf95..b5ef4d1 100644
--- a/pdf_command_wx.cpp
+++ b/pdf_command_wx.cpp
@@ -58,6 +58,7 @@
#include <fstream>
#include <map>
#include <memory> // make_unique(), unique_ptr
+#include <regex>
#include <sstream>
#include <stdexcept>
#include <string>
@@ -143,6 +144,14 @@ class html_interpolator
throw std::runtime_error("invalid lookup kind");
}
+ static std::string dehtmlize(std::string const& raw_text)
+ {
+ std::string z = raw_text;
+ z = std::regex_replace(z, std::regex("<"), "<");
+ z = std::regex_replace(z, std::regex(">"), ">");
+ return z;
+ }
+
// A function which can be used to interpolate an HTML string containing
// references to the variables defined for this illustration. The general
// syntax is the same as in the global interpolate_string() function, i.e.
@@ -156,9 +165,21 @@ class html_interpolator
// variables explicitly defined by add_variable() calls.
html::text operator()(char const* s) const
{
+ std::string z =
+ interpolate_string
+ (s
+ ,[this]
+ (std::string const& str
+ ,interpolate_lookup_kind kind
+ )
+ {
+ return interpolation_func(str, kind);
+ }
+ )
+ ;
return html::text::from_html
(interpolate_string
- (s
+ (dehtmlize(z).c_str()
,[this]
(std::string const& str
,interpolate_lookup_kind kind
diff --git a/product_data.cpp b/product_data.cpp
index f0507f3..e6564d9 100644
--- a/product_data.cpp
+++ b/product_data.cpp
@@ -537,6 +537,12 @@ sample::sample()
item("GroupQuoteFooterMandatory") = glossed_string("The employer pays all
premiums.");
item("GroupQuoteFooterVoluntary") = glossed_string("The employee pays all
premiums.");
item("GroupQuoteFooterFusion") = glossed_string("The employer and
employee pay their respective premiums.");
+ // Experimental.
+ item("GuarMortalityFootnote") =
+ "<br><b>Guaranteed mortality column definition:</b><br>{{InsCoName}}"
+ " guarantees that this {{ContractName}}'s mortality charges will"
+ " never exceed the applicable CSO mortality tables...blah blah blah."
+ ;
}
/// The 'sample2*' products are designed to facilitate testing.