Exemple #1
0
void Input::redintegrate_ex_post
    (int                                       file_version
    ,std::map<std::string, std::string> const& detritus_map
    ,std::list<std::string>             const& residuary_names
    )
{
    if(class_version() == file_version)
        {
        return;
        }

    if(0 == file_version)
        {
        // An older version with no distinct 'file_version' didn't
        // have 'DefinitionOfMaterialChange', whose default value is
        // unacceptable for GPT.
        if(contains(residuary_names, "DefinitionOfMaterialChange"))
            {
            DefinitionOfMaterialChange =
                mce_gpt == DefinitionOfLifeInsurance
                ? mce_adjustment_event
                : mce_earlier_of_increase_or_unnecessary_premium
                ;
            }

        operator[]("AgentName"  ) = full_name
            (map_lookup(detritus_map, "AgentFirstName" )
            ,map_lookup(detritus_map, "AgentMiddleName")
            ,map_lookup(detritus_map, "AgentLastName"  )
            );
        operator[]("InsuredName") = full_name
            (map_lookup(detritus_map, "FirstName"      )
            ,map_lookup(detritus_map, "MiddleName"     )
            ,map_lookup(detritus_map, "LastName"       )
            );
        }

    if(file_version < 2)
        {
        // 'UseCurrentDeclaredRate' was introduced 20071017T1454Z; its
        // default value of "Yes" would break backward compatibility.
        if(contains(residuary_names, "UseCurrentDeclaredRate"))
            {
            UseCurrentDeclaredRate = "No";
            }

        // 'LastCoiReentryDate' was introduced 20071017T1454Z; its
        // default value may be inappropriate for files saved earlier.
        LastCoiReentryDate = std::min
            (LastCoiReentryDate.value()
            ,add_years(EffectiveDate.value(), InforceYear.value(), true)
            );
        }

    if(1 == file_version)
        {
        // Solve 'Year' values were saved in solve 'Time' entities,
        // apparently in this version only.
        //
        // However, default values for
        //   SolveTargetTime
        //   SolveEndTime
        // didn't work correctly with contemporary versions of the
        // program. Users had to change them in order to make solves
        // work correctly. For saved cases with unchanged defaults,
        // limiting the two offending variables to the maturity
        // duration produces a result consonant with the palpable
        // intention of the quondam defaults.
        //
        SolveTargetYear = std::min(years_to_maturity(), SolveTargetTime.value());
        SolveBeginYear  =                               SolveBeginTime .value() ;
        SolveEndYear    = std::min(years_to_maturity(), SolveEndTime   .value());

        SolveTargetTime = issue_age() + SolveTargetYear.value();
        SolveBeginTime  = issue_age() + SolveBeginYear .value();
        SolveEndTime    = issue_age() + SolveEndYear   .value();
        }

    if(file_version < 5)
        {
        InforceAsOfDate = add_years_and_months
            (EffectiveDate.value()
            ,InforceYear  .value()
            ,InforceMonth .value()
            ,true
            );
        LastMaterialChangeDate = add_years_and_months
            (EffectiveDate.value()
            ,InforceYear  .value() - InforceContractYear .value()
            ,InforceMonth .value() - InforceContractMonth.value()
            ,true
            );
        }

    // Defectively, some admin-system extracts lack various elements.
    // All deficient extracts happen to lack <AgentPhone>: they don't
    // even have an empty <AgentPhone/>; but that field is present in
    // every input file ever saved by any version of lmi.
    bool const deficient_extract = contains(residuary_names, "AgentPhone");

    // One state governs everything except premium tax, which may be
    // paid to a different state, e.g. on cases with more than five
    // hundred lives with a common (employer) issue state; see:
    //   http://www.naic.org/documents/frs_summit_presentations_03.pdf
    //   http://www.naic.org/documents/committees_e_app_blanks_adopted_2007-42BWG_Modified.pdf
    // Prior to version 6, a single state was used for all purposes,
    // and it was determined as either employee or employer state,
    // depending on the value of DB_PremTaxState. The determination is
    // complex (what if a case was issued with 498 lives and then
    // grew to 502?), and starting with version 6 both states are
    // input fields.
    //
    // 'StateOfJurisdiction' has always been in lmi, but was never
    // meaningfully used prior to version 6.
    //
    // 'FilingApprovalState' and 'PremiumTaxState' were unknown before
    // version 6, and would not ordinarily occur in older versions.
    // However, certain admin-system extracts that are always marked
    // as version 5 were to have been modified to add these two fields
    // (yet were not so modified).
    if(file_version < 6)
        {
        bool const b0 = contains(detritus_map, "FilingApprovalState");
        bool const b1 = !contains(residuary_names, "PremiumTaxState");
        if(b0 || b1)
            {
            fatal_error() << "Unexpected 'state' fields." << LMI_FLUSH; // deficient_extract
            LMI_ASSERT(b0 && b1 && 5 == file_version);
            StateOfJurisdiction = map_lookup(detritus_map, "FilingApprovalState");
            }
        else
            {
            product_database db
                (ProductName          .value()
                ,Gender               .value()
                ,UnderwritingClass    .value()
                ,Smoking              .value()
                ,IssueAge             .value()
                ,GroupUnderwritingType.value()
                ,mce_s_CT // Dummy initialization.
                );

            // Deemed state must not depend on itself.
            if(db.varies_by_state(DB_PremTaxState))
                {
                fatal_error()
                    << "Database invalid: circular dependency."
                    << " State of jurisdiction depends on itself."
                    << LMI_FLUSH
                    ;
                }

            switch(static_cast<int>(db.Query(DB_PremTaxState)))
                {
                case oe_ee_state:
                    {
                    StateOfJurisdiction = State;
                    PremiumTaxState     = State;
                    }
                    break;
                case oe_er_state:
                    {
                    StateOfJurisdiction = CorporationState;
                    PremiumTaxState     = CorporationState;
                    }
                    break;
                default:
                    {
                    fatal_error()
                        << "Cannot determine state of jurisdiction."
                        << LMI_FLUSH
                        ;
                    }
                    break;
                }
            }
        }

    // For "deficient" extracts, these required elements are missing.
    if(file_version < 6 && !deficient_extract)
        {
        LMI_ASSERT(contains(residuary_names, "SolveFromWhich"));
        LMI_ASSERT(contains(residuary_names, "SolveTgtAtWhich"));
        LMI_ASSERT(contains(residuary_names, "SolveToWhich"));
        LMI_ASSERT(contains(residuary_names, "UseDOB"));
        SolveFromWhich  = map_lookup(detritus_map, "DeprecatedSolveFromWhich");
        SolveTgtAtWhich = map_lookup(detritus_map, "DeprecatedSolveTgtAtWhich");
        SolveToWhich    = map_lookup(detritus_map, "DeprecatedSolveToWhich");
        UseDOB          = map_lookup(detritus_map, "DeprecatedUseDOB");
        }

    if(file_version < 7)
        {
        // Version 7 renamed these elements.
        LMI_ASSERT(contains(residuary_names, "ContractNumber"));
        LMI_ASSERT(contains(residuary_names, "External1035ExchangeTaxBasis"));
        LMI_ASSERT(contains(residuary_names, "Inforce7702AAmountsPaidHistory"));
        LMI_ASSERT(contains(residuary_names, "InforceCumulativeNoLapsePayments"));
        LMI_ASSERT(contains(residuary_names, "Internal1035ExchangeTaxBasis"));
        LMI_ASSERT(contains(residuary_names, "MasterContractNumber"));
        LMI_ASSERT(contains(residuary_names, "SolveExpenseGeneralAccountBasis"));
        ContractNumber                   = map_lookup(detritus_map, "PolicyNumber");
        External1035ExchangeTaxBasis     = map_lookup(detritus_map, "External1035ExchangeBasis");
        InforceCumulativeNoLapsePayments = map_lookup(detritus_map, "InforceCumulativePayments");
        Internal1035ExchangeTaxBasis     = map_lookup(detritus_map, "Internal1035ExchangeBasis");
        MasterContractNumber             = map_lookup(detritus_map, "Franchise");
        // Some (but not all) variants of version 0 lacked
        // 'PremiumHistory'; all later versions should include it.
        if(!contains(detritus_map, "PremiumHistory"))
            {
            LMI_ASSERT(0 == file_version);
            }
        else
            {
            Inforce7702AAmountsPaidHistory  = map_lookup(detritus_map, "PremiumHistory");
            }
        // "Deficient" extracts lack 'SolveBasis'.
        if(!deficient_extract)
            {
            SolveExpenseGeneralAccountBasis = map_lookup(detritus_map, "SolveBasis");
            }
        }

    if(file_version < 7)
        {
        // Prior to version 7, 'InforceCumulativePayments' was used
        // for no-lapse, GPT, and ROP, so set them all equal here
        // for backward compatibility. This matters little for new
        // business, but is so cheap that it may as well be done
        // unconditionally.
        InforceCumulativeGptPremiumsPaid = InforceCumulativeNoLapsePayments.value();
        InforceCumulativeRopPayments     = InforceCumulativeNoLapsePayments.value();
        }

    if(file_version < 7 && contains(detritus_map, "SpecamtHistory"))
        {
        // Merge obsolete 'SpecamtHistory' into 'SpecifiedAmount'.
        //
        // Prior to version 7, 'SpecamtHistory' and 'SpecifiedAmount'
        // were distinct. Some version-0 files had the history entity,
        // but others did not; if it's not present, then of course it
        // cannot be merged.
        //
        // Function must_overwrite_specamt_with_obsolete_history(),
        // called below, requires 'InforceYear' and 'InforceMonth',
        // which some "deficient" extracts omit. DoTransmogrify()
        // sets those members downstream (at least before any
        // illustration is produced), but the "obsolete history"
        // function needs them now. This requires version 5, which
        // introduced 'InforceAsOfDate'; no "deficient" extract
        // should have an earlier version.
        //
        // set_inforce_durations_from_dates() does the same and more;
        // but, because it does more, it can't simply be called here.
        if(deficient_extract && EffectiveDate.value() != InforceAsOfDate.value())
            {
            LMI_ASSERT(4 < file_version);
            std::pair<int,int> ym0 = years_and_months_since
                (EffectiveDate  .value()
                ,InforceAsOfDate.value()
                );
            InforceYear  = ym0.first;
            InforceMonth = ym0.second;
            }
        // Requiring 'deficient_extract' here wouldn't be right,
        // because an extract file that has been modified and saved
        // is no longer detectably "deficient".
        //
        // This idiom for distinguishing inforce from new business is
        // avoided in new code, but retained in backward-compatibility
        // code that, by its nature, should rarely be modernized.
        if(0 != InforceYear || 0 != InforceMonth)
            {
            if
                (must_overwrite_specamt_with_obsolete_history
                    (SpecifiedAmount.value()
                    ,map_lookup(detritus_map, "SpecamtHistory")
                    )
                )
                {
                SpecifiedAmount = map_lookup(detritus_map, "SpecamtHistory");
                }
            }
        }

    if(file_version < 7 && EffectiveDate.value() != InforceAsOfDate.value())
        {
        // Version 7 introduced 'InforceSpecAmtLoadBase'; previously,
        // the first element of 'SpecamtHistory' had been used in its
        // place, which would have disregarded any term rider.
        RealizeSpecifiedAmount();
        InforceSpecAmtLoadBase = TermRiderAmount.value() + SpecifiedAmountRealized_[0].value();
        }
}
		inline Gregorian operator + (detail::packaged_year y) { return add_years(*this, y.nYears_); }