[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi] Variables synthesized in 'pdf_command_wx.cpp'
From: |
Greg Chicares |
Subject: |
[lmi] Variables synthesized in 'pdf_command_wx.cpp' |
Date: |
Sat, 2 Feb 2019 23:52:56 +0000 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.4.0 |
In 'pdf_command_wx.cpp', several dozen string variables are synthesized
from members of the ledger classes, for use in MST files from which PDFs
are generated. Most are benign, transparent workarounds for the deliberate
limitations of MST templates. However, these:
"GroupCarveout"
"ModifiedSinglePremium"
"ModifiedSinglePremium0"
"ModifiedSinglePremiumOrModifiedSinglePremium0"
"SinglePremium"
"GroupExperienceRating"
"UWTypeIsGuaranteedIssueInTexasWithFootnote"
were introduced in the XSL templates of yesteryear for bad reasons, and
must now be exterminated. They (ab)use LedgerInvariant::PolicyLegalName
to divine various product properties, much as one might ascertain whether
a country has the second-largest land area by testing for "nada" at the
end of its name and disallowing any name beginning with "G" to eliminate
Grenada. Such a method easily breaks when the set of names grows and
shrinks and its elements mutate; and it's obscure at best--investigating
whether "UWTypeIsGuaranteedIssueInTexasWithFootnote" does the right thing
today took us quite a lot of work yesterday.
The new 'DB_ErNotionallyPaysTerm' that was added last week might turn out
to be a synonym for "GroupCarveout". I'll add new entities to the product
database to replace the other variables above.
Here's a complete current list of the other variables synthesized in
'pdf_command_wx.cpp', sorted into categories, with some comments:
nbsp strings:
"Space1"
"Space2"
"Space4"
"Space8"
"Space16"
"Space32"
"Space64"
Vadim--Only the last two are actually used, and only in very special
contexts. Is there a strong reason for keeping the others? Could html's
'width=' attribute be used in place of all of these?
shortened strings:
add_abbreviated_variable("CorpName", 60);
add_abbreviated_variable("CorpName", 50);
add_abbreviated_variable("CorpName", 140);
add_abbreviated_variable("Insured1", 30);
add_abbreviated_variable("Insured1", 50);
add_abbreviated_variable("Insured1", 140);
add_abbreviated_variable("ContractNumber", full_abbrev_length);
add_abbreviated_variable("ContractNumber", full_abbrev_length / 2);
add_abbreviated_variable("MasterContractNumber", full_abbrev_length);
add_abbreviated_variable("MasterContractNumber", full_abbrev_length / 2);
Similarly, could a 'width=' attribute be used here?
The rest seem quite safe...
empty-or-not booleans:
"HasMasterContract"
"HasPolicyNumber"
"HasScaleUnit"
"HasProducerCity"
"HasInterestDisclaimer"
boolean compounds:
"HasTermOrSupplSpecAmt"
enumerator-test booleans:
"DefnLifeInsIsGPT"
"UWTypeIsMedical"
"UWClassIsRated"
"StateIsCarolina"
"StateIsMaryland"
"StateIsIllinois"
"StateIsTexas"
"StateIsIllinoisOrTexas"
"StateIsNewYork"
trivial arithmetic:
"MecYearPlus1"
"HasGuarPrem"
"InforceYearLT5"
"LapseYear_Guaranteed_LT_MaxDuration"
"LapseYear_Guaranteed_Plus1"
"LapseYear_Midpoint_LT_MaxDuration"
"LapseYear_Midpoint_Plus1"
"LapseYear_Current_LT_MaxDuration"
"LapseYear_Current_Plus1"
"MecYearIs0"
We want the ledger classes to be nearly minimal: e.g., they record
which US state has jurisdiction, as an enumeration, and we wouldn't
add fifty booleans like IsNewYork to those classes; if MST needs
something like that, then it does belong here.
However, I wonder whether the business logic behind some of these
variables is actually sound. For example, "MecYearIs0" is used
only as follows, to say that a contract...
{{#IsMec}}
{{^MecYearIs0}}
becomes a Modified Endowment Contract (MEC) in policy year
{{MecYearPlus1}}.
{{/MecYearIs0}}
{{#MecYearIs0}}
is a Modified Endowment Contract (MEC).
{{/MecYearIs0}}
Apparently that prints:
"becomes a [MEC] in policy year 1."
if it fails the seven-pay test at any time before the end of the first
year, or just
"is a [MEC]."
if it fails at any other time. That's weird in several ways:
- normally we'd distinguish between failure on the first day
and failure later--as opposed to failure before or after the
365th day;
- in the snippet above, {{MecYearPlus1}} could be replaced by
the constant "1" because it isn't used when it has any other
value; but
- if the duration of failure is relevant when it's zero, then
it's also relevant when it's not zero; and
- this logic is used only for one ledger type, but the same
tax law applies equally to other ledger types.
We won't touch this now, but later in 2019 we hope to rework
the contents of all these templates. (I should again point out
that the MSTs are faithful translations of the XSL originals,
and I'm taking issue with the original design.)
exotic booleans:
"HasComplianceTrackingNumber"
What is this intended to accomplish? Its apparent function is to insert
'imprimatur.mst' iff its contents are not empty:
{{#HasComplianceTrackingNumber}}
<p>
Compliance tracking number: {{>imprimatur}}
</p>
{{/HasComplianceTrackingNumber}}
but the definition seems more elaborate than that function requires:
add_variable
("HasComplianceTrackingNumber"
,expand_template("imprimatur")
.as_html().find_first_not_of(" \n")
!= std::string::npos
);
Or is that just another satanic verse that was inserted in the XSL?
The list concludes with handful that I'll probably reimplement:
concatenation:
"date_prepared"
It looks like the ledger classes parse a single date datum into
separate {Y,M,D} strings only for use by the code here, which then
recombines them into a single string. It would be simpler to pass
a single string and just use it as such.
indexing:
"PresentCreditingRate"
We have ledger members representing "initial" values of certain
vectors, so maybe we should have this single "present" one.
string manipulations:
"ErModeLCWithArticle"
"ContractNameCap"
If a contract is a "Life Insurance Policy", then I'm not sure there's
a good reason to lowercase the whole string and then capitalize the
first letter of the phrase, turning it into a "Life insurance policy";
but if that's truly necessary, maybe we should have two distinct strings
in the '.policy' file. And instead of
Premiums are assumed to be paid on {{ErModeLCWithArticle}}
we could say
The assumed frequency of premium payment is [mode]
and omit the complex rule for transforming the frequency:
Annual --> an annual
Monthly --> a monthly
because lmi is not a word processor after all; but if this exact wording
is important, I'd prefer to do the transformation in a lookup table, or
to store distinct strings with the indefinite article--anything to avoid
"AEIOU sometimes Y" logic. (The present code looks like it would handle
"a yearly" correctly, and "a hebdomadal", but not "a UCT nychthemeral";
and I know of a product that had a "bifortnightly" mode, so actually
anything is possible.)
- [lmi] Variables synthesized in 'pdf_command_wx.cpp',
Greg Chicares <=