TEST_F(ContributionLadder_Anciennitet_CONTEXT_KI_OSV_25_50, Bidragsstigningsform_Anciennitet_1_Step_POSITIVE) {
	RuleEngine::_printDebugAtValidation = true;
	TA ta { "15124040"}; // KonceptOid 4 - OSV
//	ta.setValue(kUnionAgreementRelationship, kOUTSIDE);
	ta.setValue(kPrivate_Taxed_MK, false);
	ta.setValue(kBidragsstigningsform, "Anciennitet" );
	ta.setValue(kHospitalsdaekning_MK, false);


	auto r = re.validate(ta, false);
	EXPECT_FALSE(r.isAllOk());
//	if (r.isAllOk())
		cout << r;
	EXPECT_EQ(1, r.getValidationResults(kBidragstrappe).size());
	EXPECT_TRUE(r.hasMessages(kBidragstrappe, kProductElementRequired));

	ta.addContributionStep( {0, 1, 1} );
	r = re.validate(ta, false);
	EXPECT_FALSE(r.isAllOk());
//	if (r.isAllOk())
		cout << r;
	EXPECT_EQ(1, r.getValidationResults(kBidragstrappe).size());
	EXPECT_TRUE(r.hasMessages(kBidragstrappe, kValueUnderLimit));

	ta.removeContributionStep( {0, 1, 1} );
	ta.addContributionStep( {0, 3, 3} );
	r = re.validate(ta, false);
	EXPECT_TRUE(r.isAllOk());
//	if (r.isAllOk())
		cout << r;
}
TEST_F(ContributionLadder_Anciennitet_CONTEXT_KI_OSV_25_50, Bidragsstigningsform_Anciennitet_3_Steps_Inkl_POSITIVE) {
	RuleEngine::_printDebugAtValidation = true;
	TA ta { "15124040"}; // KonceptOid 4 - OSV
//	ta.setValue(kUnionAgreementRelationship, kOUTSIDE);
	ta.setValue(kPrivate_Taxed_MK, false);
	ta.setValue(kBidragsstigningsform, "Anciennitet" );
	ta.setValue(kHospitalsdaekning_MK, true);
	ta.setValue(kHospitalsdaekningLeverandoer, "Codan");
	ta.setValue(kHospitalsdaekningFrivillig_MK, false);

	ta.addContributionStep( {0, 2.6, 3} );
	auto r = re.validate(ta, false);
	EXPECT_TRUE(r.isAllOk());
	cout << r;

	ta.addContributionStep( {2, 3, 4} );
	r = re.validate(ta, false);
	EXPECT_TRUE(r.isAllOk());
	cout << r;

	ta.addContributionStep( {5, 4, 3.2} );
	r = re.validate(ta, false);
	EXPECT_TRUE(r.isAllOk());
	cout << r;
}
// Test kIndmeldelsesalder and getting options prior to that
TEST_F(ContributionLadder_Ingen_CONTEXT_KI_OSV_25_50, Bidragsstigningsform_Ingen_No_Hospitalsdaekning)
{
	RuleEngine::_printDebugAtValidation = true;
	TA ta { "15124040"}; // KonceptOid 4 - OSV
	ta.setValue(kPrivate_Taxed_MK, false);
	ta.setValue(kBidragsstigningsform, "Ingen");
//	ta.setValue(kUnionAgreementRelationship, kOUTSIDE);
	ta.setValue(kHospitalsdaekning_MK, false);

	// expecting complains about missing step
	auto r = re.validate(ta, false);
	EXPECT_FALSE(r.isAllOk());
//	if (r.isAllOk())
	cout << r;
	EXPECT_EQ(1, r.getValidationResults(kBidragstrappe).size());
	EXPECT_TRUE(r.hasMessages(kBidragstrappe, kProductElementRequired));

	r = re.validate(ta, (unsigned short) kBidragsstigningsform);
	EXPECT_TRUE(r.isAllOk());
//	if (r.isAllOk())
	cout << r;

	r = re.validate(ta, { kBidragsstigningsform, kBidragstrappe });
	EXPECT_TRUE(r.isAllOk());
//	if (r.isAllOk())
	cout << r;
	EXPECT_EQ(2, r.getWarnings(kBidragstrappe).size());
	EXPECT_TRUE(r.hasWarnings(kBidragstrappe, kProductElementRequired));

	//  now add one step, but let it start from 3 (!=0), and it should fail
	ta.addContributionStep( { 3, 3.4, 5.3 });
	r = re.validate(ta, false);
	EXPECT_FALSE(r.isAllOk());
//	if (r.isAllOk())
	cout << r;
	EXPECT_TRUE(r.hasMessages(kBidragstrappe, kValueNotAllowed));

	//  now remove that step, and add one that starts from 0 and no complains
	ta.removeContributionStep( { 3, 0, 0 });
	ta.addContributionStep( { 0, 3.4, 5.3 });
	r = re.validate(ta, false);
	EXPECT_TRUE(r.isAllOk());
//	if (!r.isAllOk())
	cout << r;

	//  then add one more and it should complain again, that only 1 step is allowed, when "Ingen" is selected in Bidragsstigningsform
	ta.addContributionStep( { 1, 4, 6 });
	r = re.validate(ta, false);
	EXPECT_FALSE(r.isAllOk());
//	if (r.isAllOk())
	cout << r;
	EXPECT_TRUE(r.hasMessages(kBidragstrappe, kValueNotAllowed));

	//  now remove the last step (index!=0), and everything should be fine again
	ta.removeContributionStep( { 1, 0, 0 });
	r = re.validate(ta, false);
	EXPECT_TRUE(r.isAllOk());
//	if (!r.isAllOk())
	cout << r;
}
TEST_F(ContributionLadder_Anciennitet_CONTEXT_KI_OSV_25_50, Bidragsstigningsform_Anciennitet_Over100_NEGATIVE) {
	RuleEngine::_printDebugAtValidation = true;
	TA ta { "15124040"}; // KonceptOid 4 - OSV
//	ta.setValue(kUnionAgreementRelationship, kOUTSIDE);
	ta.setValue(kPrivate_Taxed_MK, false);
	ta.setValue(kBidragsstigningsform, "Anciennitet" );
	ta.setValue(kHospitalsdaekning_MK, true);
	ta.setValue(kHospitalsdaekningLeverandoer, "Codan");
	ta.setValue(kHospitalsdaekningFrivillig_MK, false);

	ta.addContributionStep( {0, 2, 3} );
	auto r = re.validate(ta, false);
	EXPECT_TRUE(r.isAllOk());
	cout << r;

	ta.addContributionStep( {2, 99, 2} ); // add a step where the total is not increasing 1+1 < 2+3
	r = re.validate(ta, false);
	EXPECT_FALSE(r.isAllOk());
	cout << r;
	EXPECT_TRUE(r.hasMessages(kBidragstrappe, kValueOverLimit));
}
TEST_F(ContributionLadder_Anciennitet_CONTEXT_KI_OSV_25_50, Bidragsstigningsform_Anciennitet_1_Step_Ekskl_NEGATIVE) {
	RuleEngine::_printDebugAtValidation = true;
	TA ta { "15124040"}; // KonceptOid 4 - OSV
//	ta.setValue(kUnionAgreementRelationship, kOUTSIDE);
	ta.setValue(kPrivate_Taxed_MK, false);
	ta.setValue(kBidragsstigningsform, "Anciennitet" );
	ta.setValue(kHospitalsdaekning_MK, false);

	ta.addContributionStep( {0, 2, 1} ); // == 3 which is below BidragEksklHispdaekningPctMin == 3
	auto r = re.validate(ta, false);
	EXPECT_FALSE(r.isAllOk());
	cout << r;
	EXPECT_EQ(1, r.getValidationResults(kBidragstrappe).size());
	EXPECT_TRUE(r.hasMessages(kBidragstrappe, kValueUnderLimit));
	EXPECT_EQ("33.1.2.1", r.getValidationResults(kBidragstrappe).at(0).getRuleId());

	ta.removeContributionStep( {0, 2, 1} ); // remove and set new step that equals to 6
	ta.addContributionStep( {0, 2, 4} );
	r = re.validate(ta, false);
	EXPECT_TRUE(r.isAllOk());
	cout << r;
}
TEST_F(ContributionLadder_Ingen_CONTEXT_KI_OSV_25_50, Bidragsstigningsform_Ingen_Over100_NEGATIVE)
{
	RuleEngine::_printDebugAtValidation = true;
	TA ta { "15124040"}; // KonceptOid 4 - OSV
	ta.setValue(kAftaleIkraftdato, 20150701);
//	ta.setValue(kUnionAgreementRelationship, kOUTSIDE);
	ta.setValue(kBidragEjFoesteTrin_MK, false);
	ta.setValue(kBidragsstigningsform, "Ingen");
	ta.setValue(kHospitalsdaekning_MK, false);
	ta.setValue(kHospitalsdaekningFrivillig_MK, false);
	ta.setValue(kPrivate_Taxed_MK, false);

	ta.addContributionStep( {0, 90, 11} );

	auto r = re.validate(ta, false);
	EXPECT_FALSE(r.isAllOk());
	cout << r;
	EXPECT_TRUE(r.hasMessages(kBidragstrappe, kValueOverLimit));

	ta.addContributionStep( {0, 90, 9} );
	r = re.validate(ta, false);
	EXPECT_FALSE(r.isAllOk());
	cout << r;
}
TEST_F(Incremental_TA_CONTEXT_KI_OSV_25_50, Incremental_TA_POSITIVE) {
	RuleEngine::_printDebugAtValidation = true;
	TA ta { "15124040"}; // KonceptOid 4 - OSV
//	ta.setValue(kUnionAgreementRelationship, kOUTSIDE);

	bool full {false};
	auto r = re.validate(ta, full);
	EXPECT_TRUE(r.isAllOk());
	if (!r.isAllOk())
		cout << r;

	//************************************************************
	// GENERAL PAGE
	//************************************************************
	//

	//
	// ***** Date
	//
	// need to calculate Ikraftdato minus rc_Ikraftdato_min number of months and see if todays date is before that.
	// same with rc_Ikraftdato_max
	ta.setValue(kIkraftDato, (long) 11);
//	r = re.validate(ta, full);
//	EXPECT_FALSE(r.isAllOk());
//	if (r.isAllOk()) cout << r;
//	ASSERT_EQ(1, r.getValidationResults(kIkraftDato).size());
//	EXPECT_EQ(sbx::ValidationCode::kProductElementRequired, r.getValidationResults(kIkraftDato).at(0).getValidationCode());


	//
	// ***** Indmeldelseskriterier, age, anciennitet
	//
	ta.setValue(kIndmeldelsesAlder, (long) 5);
	r = re.validate(ta, full);
	EXPECT_FALSE(r.isAllOk());
	if (!r.isAllOk()) cout << r;
	ASSERT_EQ(1, r.getValidationResults(kIndmeldelsesAlder).size());
	EXPECT_EQ(sbx::ValidationCode::kValueUnderLimit, r.getValidationResults(kIndmeldelsesAlder).at(0).getValidationCode());

	ta.setValue(kIndmeldelsesAlder, (long) 31);
	r = re.validate(ta, full);

	EXPECT_FALSE(r.isAllOk());
	if (r.isAllOk()) cout << r;
	ASSERT_EQ(1, r.getValidationResults(kIndmeldelsesAlder).size());
	EXPECT_EQ(sbx::ValidationCode::kValueOverLimit, r.getValidationResults(kIndmeldelsesAlder).at(0).getValidationCode());

	ta.setValue(kIndmeldelsesAlder, (long) 20);
	r = re.validate(ta, full);
	EXPECT_TRUE(r.isAllOk());
	if (!r.isAllOk()) cout << r;


	ta.setValue(kAnciennitet, (long) 30);
	r = re.validate(ta, full);
	ASSERT_EQ(1, r.getValidationResults(kAnciennitet).size());
	EXPECT_EQ(sbx::ValidationCode::kValueOverLimit, r.getValidationResults(kAnciennitet).at(0).getValidationCode());
	ta.setValue(kAnciennitet, (long) 12);
	r = re.validate(ta, full);
	EXPECT_TRUE(r.isAllOk());
	if (!r.isAllOk()) cout << r;


	ta.setValue(kAnciennitetTidlArbejdsplads, true);
	r = re.validate(ta, full);
	EXPECT_TRUE(r.isAllOk());
	if (!r.isAllOk()) cout << r;

	//
	// ***** Fravalg grupper
	//
	ta.setValue(kGrpElever, true);
	ta.setValue(kGrpLaerlinge, true);
	ta.setValue(kGrpStuderende, true);
	r = re.validate(ta, full);
	EXPECT_TRUE(r.isAllOk());
	if (!r.isAllOk()) cout << r;


	//
	//************************************************************
	// PRODUKT PAGE
	//************************************************************
	//
	//
	// ****** Udlobsalder
	//
	ta.setValue(kUdlobsalder_Pension, (long) 67);
	r = re.validate(ta, full);
	EXPECT_TRUE(r.isAllOk());
	if (!r.isAllOk())
		cout << r;


	//
	// ******* Fravalg af risikodaekning
	//
	ta.setValue(kFravalgRisiko_MK, true);
	r = re.validate(ta, full);
	cout << r;

	EXPECT_FALSE(r.isAllOk());
	EXPECT_EQ(1, r.getValidationResults(kFravalgRisikoAlder).size());
	EXPECT_EQ(1, r.getValidationResults(kFravalgRisiko_MK).size());
	EXPECT_EQ(sbx::ValidationCode::kProductElementRequired, r.getValidationResults(kFravalgRisikoAlder).at(0).getValidationCode());
	EXPECT_EQ(sbx::ValidationCode::kValueNotAllowed, r.getValidationResults(kFravalgRisiko_MK).at(0).getValidationCode());
	ta.setValue(kFravalgRisikoAlder, (long) 45);

	// now age is set, so all should be ok
	r = re.validate(ta, full);
	EXPECT_FALSE(r.isAllOk());
	cout << r;
	EXPECT_EQ(1, r.getValidationResults(kFravalgRisiko_MK).size());
	EXPECT_EQ(sbx::ValidationCode::kValueNotAllowed, r.getValidationResults(kFravalgRisiko_MK).at(0).getValidationCode());

	ta.setValue(kFravalgRisiko_MK, false);
	ta.remove(kFravalgRisikoAlder);
	r = re.validate(ta, full);
	cout << r;
	EXPECT_TRUE(r.isAllOk());

	//
	// ****** Opsparingsprodukter
	//
	ta.setValue(kStandardProduct, "Traditionel_MK");
	ta.setValue(kTraditionel_MK, false);
	//    expecting to fail as the standardprodukt hasn't been set on the ta
	r = re.validate(ta, full);
	EXPECT_FALSE(r.isAllOk());
	if (r.isAllOk()) cout << r;

	ta.setValue(kTraditionel_MK, true);
	ta.setValue(kLink_MK, true);
	ta.setValue(kMarkedspension_MK, true);
	ta.setValue(kTidspensionMedGaranti_MK, true);
	ta.setValue(kTidspensionUdenGaranti_MK, true);

	//    now savings products has been set, so everything should be fine
	r = re.validate(ta, full);
	EXPECT_TRUE(r.isAllOk());
	if (!r.isAllOk()) cout << r;

	ta.setValue(kUdbetalingsform, re.getDefaultValue(kUdbetalingsform)->stringValue());
	r = re.validate(ta, full);
	EXPECT_TRUE(r.isAllOk());
	if (!r.isAllOk()) cout << r;

	ta.setValue(kUdbetalingsperiode, re.getDefaultValue(kUdbetalingsperiode)->longValue());
	r = re.validate(ta, full);
	EXPECT_TRUE(r.isAllOk());
	if (!r.isAllOk()) cout << r;

	ta.setValue(kMaxAndelLinkBidragPCT, (double) 5.5);
	r = re.validate(ta, full);
	EXPECT_TRUE(r.isAllOk());
	if (!r.isAllOk()) cout << r;

	ta.setValue(kMaxAndelMarkedspensionBidragPct, (double) 6.1);
	r = re.validate(ta, full);
	EXPECT_TRUE(r.isAllOk());
	if (!r.isAllOk()) cout << r;

	ta.setValue(kLinkKunForEgetBidrag_MK, true);
	r = re.validate(ta, full);
	EXPECT_TRUE(r.isAllOk());
	if (!r.isAllOk()) cout << r;

	//
	// Invaliditetsdaekning
	//
//	ta.setValue(kInvalidesum);



	//
	//************************************************************
	// SALARY PAGE
	//************************************************************
	//
	//
	// ***** Lon og betaling
	//
	ta.setValue(kLoenDefinition, "garbage");
	r = re.validate(ta, full);
	EXPECT_FALSE(r.isAllOk());
	if (r.isAllOk()) cout << r;
	ASSERT_EQ(1, r.getValidationResults(kLoenDefinition).size());
	EXPECT_EQ(sbx::ValidationCode::kValueNotAllowed, r.getValidationResults(kLoenDefinition).at(0).getValidationCode());
	ta.setValue(kLoenDefinition, re.getDefaultValue(kLoenDefinition)->stringValue());

	ta.setValue(kLoenRegulering, "garbage");
	r = re.validate(ta, full);
	EXPECT_FALSE(r.isAllOk());
	if (r.isAllOk()) cout << r;
	ASSERT_EQ(1, r.getValidationResults(kLoenRegulering).size());
	EXPECT_EQ(sbx::ValidationCode::kValueNotAllowed, r.getValidationResults(kLoenRegulering).at(0).getValidationCode());
	ta.setValue(kLoenRegulering, "januar");

	ta.setValue(kLoenreguleringsfrekvens, "garbage");
	r = re.validate(ta, full);
	EXPECT_FALSE(r.isAllOk());
	if (r.isAllOk()) cout << r;
	ASSERT_EQ(1, r.getValidationResults(kLoenreguleringsfrekvens).size());
	EXPECT_EQ(sbx::ValidationCode::kValueNotAllowed, r.getValidationResults(kLoenreguleringsfrekvens).at(0).getValidationCode());
	ta.setValue(kLoenreguleringsfrekvens, re.getDefaultValue(kLoenreguleringsfrekvens)->stringValue());

	ta.setValue(kBidragsstigningsform, "garbage");
	r = re.validate(ta, full);
	EXPECT_FALSE(r.isAllOk());
	if (r.isAllOk()) cout << r;
	ASSERT_EQ(1, r.getValidationResults(kBidragsstigningsform).size());
	EXPECT_EQ(sbx::ValidationCode::kValueNotAllowed, r.getValidationResults(kBidragsstigningsform).at(0).getValidationCode());
	ta.setValue(kBidragsstigningsform, "Ingen");
	ta.addContributionStep({0, 2, 2});

	ta.setValue(kPrivate_Taxed_MK, true); // set privately taxed but no value for premium
	ta.setValue(kPrivate_Taxed_Reguleringskode, "Pristal");
	ta.setValue(kTAEReguleringskode, "Pristal");
	ta.setValue(kTAEBlGrMin, 100000);
	ta.setValue(kTAEBlOblMax, 200000);
	ta.setValue(kDoedReguleringskode, "Pristal");
	ta.setValue(kDoedBlGrMin, 400000);
	ta.setValue(kDoedBlOblMax, 600000);
	r = re.validate(ta, full); // ...and expect to fail
	EXPECT_FALSE(r.isAllOk());
	if (r.isAllOk()) cout << r;
	EXPECT_TRUE(r.hasMessages(kPrivate_Premium_BL, kProductElementRequired));
	EXPECT_TRUE(r.hasMessages(kPrivate_Taxed_SA_Administrated_MK, kProductElementRequired));

	ta.setValue(kPrivate_Taxed_SA_Administrated_MK, true);
	ta.setValue(kPrivate_Premium_BL, (double) 150234.5); // set a premium ...
	ta.setValue(kHospitalsdaekning_MK, false);
	r = re.validate(ta, full); // ... and expect not to fail
	EXPECT_TRUE(r.isAllOk());
	cout << r;

	ta.setValue(kBidragEjFoesteTrin_MK, false); // set the
	r = re.validate(ta, full);
	EXPECT_TRUE(r.isAllOk());
	cout << r;

}