lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] Embed {{MST}} and <html> in product database


From: Greg Chicares
Subject: Re: [lmi] Embed {{MST}} and <html> in product database
Date: Thu, 18 Jul 2019 18:24:49 +0000
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.7.1

On 2019-07-18 15:27, Vadim Zeitlin wrote:
> On Thu, 18 Jul 2019 14:46:10 +0000 Greg Chicares <address@hidden> wrote:
[...]
> GC>   odd/mst-in-product-db
[...]
>  Using the "GuarMortalityFootnote" example for reference, it seems to me
> that it's already defined in the product_data, so even though the PDF
> generation code gets it from LedgerInvariant, ultimately it already comes
> from the product database, doesn't it? I.e. I can already see
> GuarMortalityFootnote in sample.policy, it's just empty there currently.

All correct. Class product_data is the ultimate source of
product-specific string data. Strings come from '*.policy',
and numeric parameters from '*.data'. The ledger classes relay
data from those sources (and from  various calculations) to
the PDF generation code.

> Is the problem you're trying to solve that it is only supposed to contain
> text, and not HTML, currently, while you'd like to use HTML inside it?

In part, yes. More generally, I'd also like text substitutions
such as mustache offers.

>  Also, the commit message says
> 
>       IOW, the vision is to change the contents of '.policy' files from
>       flat text to something like mustache "partials"
> 
> but the .policy files are XML, not flat text. Am I even looking at the
> right files here?

Yes, those are the right files. I think of them as XML containers
whose contents are flat text:
  <GuarMortalityFootnote>
    <datum>Only flat text here today.</datum>
  </GuarMortalityFootnote>
I want them to be able to contain both mustache and html markup,
e.g.:

    <datum>
      &lt;br&gt;&lt;b&gt;Guaranteed mortality column 
definition:&lt;/b&gt;&lt;br&gt;
      {{InsCoName}} guarantees that this {{ContractName}}'s mortality charges 
will
      never exceed the applicable CSO mortality tables...blah blah blah.
    </datum>

(In the code that generates this 'sample.policy' file, that would
be written as a C++ string, legibly:

  "<br><b>Guaranteed mortality column definition:</b><br> ..."

but the html is escaped (so that it can be embedded in xml)
when that code is run to generate the '.policy' file.)

>  I think things would become clearer if I could see the final target you
> have in mind. I.e., implementation issues aside, what would you ideally
> like to achieve?

Most generally, I want there to be more than one way to code
variations. At one extreme, we could have a few short strings
in '.policy' files, and use them in '.mst' files: then the
'.policy' files would be small, but the '.mst' files would be
ponderous, and would contain a lot of complex logic. That's
what the original implementation looked like, decades ago
(when generic, one-size-fits-all narrative text was okay;
but those were happier times).

At the other extreme, we could have a few very simple '.mst'
files, and build enormous strings in '.policy' files. Then
the '.mst' files would be very simple, perhaps with only
three parts to each page:

  {{text_preceding_arrays_of_numbers}}
  <!-- numbers go here -->
  {{text_following_arrays_of_numbers}}

but the '.policy' files would be enormous, and the code to
generate them would be complex.

Both extremes are bad, but the first one is worse, and
unfortunately that's the way the current design works.
If we had the flexibility to use html and mustache markup
in '.policy' strings, as well as in '.mst' templates, then
we could reduce overall complexity.

I'll cite a specific example below.

> Should there still be any .mst files at all left or should
> their contents be entirely moved to the product database (the commit
> message speaks about moving them in the product database, but at least this
> commit doesn't actually do this)?

Both '.policy' and '.mst' files would remain. The difference
is that we'd be able to express <html> and {{mustache}} logic
in both places.

Let me repeat the 952b242804 commit message[0] below as a
permanent reference in case that branch is deleted someday.
Its first paragraph gives a concrete example: today, in
code that generates '.policy' files for proprietary products,
we have sixty-two long lines representing just the string
literals for "GuarMortalityFootnote". There are nine of them,
one for each combination of
  [policy|contract|certificate] X [1980|2001|2017]
Then, one of the nine is selected for each of a hundred forty
products:

    item("GuarMortalityFootnote")          = 
guar_mortality_certificate_footnote_1980;
...
    item("GuarMortalityFootnote")          = guar_mortality_footnote_1980;
...
    item("GuarMortalityFootnote")          = 
guar_mortality_policy_footnote_1980;
...

Sixty-two lines to specify the "guar_mortality..." variables,
plus one hundred forty lines to choose the right one for each
product, means two hundred lines just for this one footnote.
Multiply that by about a hundred (the number of footnotes) to
gauge the size of the problem.

But these nine strings are all the same except for the
  [policy|contract|certificate] X [1980|2001|2017]
variant text that's dropped in. If we could write them as

  std::string TheOneAndOnlyMortalityFootnote =
    "This {{ContractName}} has guaranteed COIs
    based on the {{CsoEra}} CSO table...
    ...[plus several lines of mumbo jumbo]..."

then we'd have just a few lines instead of the sixty-two,
and we could make it a universal default with one line of
code instead of one hundred forty.

You might well ask why we don't just write that "one and
only footnote" in each '.mst' file that needs it. The reason
is flexibility. It is crucial to understand that, although
there are only about four sets of '.mst' files (one for each
"ledger type"), our work is subject to emendation by internal
reviewers and also by regulators, who review PDF output one
product at a time rather than one "ledger type" at a time.
If some reviewer demands a one-word change somewhere, that
becomes an absolute business requirement, for that product
only. Product vs. ledger-type is an impedance mismatch.
If we try to do everything in '.mst' files, then we must do:

  {{^WeirdOneWordChangeNumber31416Required}}
    This is an insurance illustration.
  {{/WeirdOneWordChangeNumber31416Required}}
  {{#WeirdOneWordChangeNumber31416Required}}
    This is a life insurance illustration.
  {{/WeirdOneWordChangeNumber31416Required}}

which means we have to define a variable
  WeirdOneWordChangeNumber31416Required
in the product data files, and pass also in the ledger
classes...and that means changing
 - the lmi binary; and
 - one or more '.mst' files; and
 - every product file; and
 - regression-test benchmarks
every time someone changes one word. It would be much less
inconvenient to change that one word in one place, in the
one product file that requires it.

If we can use <html> and {{mustache}} markup in only one
place ('*.mst'), then we have only one degree of freedom.
If we can use those techniques in two places, then we have
two degrees of freedom; that's what we very much want.

---------

[0] "the 952b242804 commit message":

http://git.savannah.nongnu.org/cgit/lmi.git/commit/?h=odd/mst-in-product-db

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> &nbsp; {{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> &nbsp; {{AttainedAgeFootnote}}
+ <b>Age at End of Year:</b> &nbsp; {{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> &nbsp; {{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.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]