deliveredtechnologies / rulebook

100% Java, Lambda Enabled, Lightweight Rules Engine with a Simple and Intuitive DSL
http://www.deliveredtechnologies.com
Apache License 2.0
721 stars 124 forks source link

adding asAuditor() to megabank Sample application doesn't produce Audit #142

Closed mgrouch closed 5 years ago

mgrouch commented 6 years ago

adding asAuditor() to megabank Sample application doesn't produce Audit

        RuleBook<Double> homeLoanRateRuleBook =
                RuleBookBuilder.create(HomeLoanRateRuleBook.class)
                    .withResultType(Double.class)
                    .withDefaultResult(4.5)
                    .asAuditor()
                    .build();
Clayton7510 commented 5 years ago

Hmm... I'll look into this and update the example to show auditing with Megabank example.

Clayton7510 commented 5 years ago

Ok, I checked out the example. And you're right, it was never setup for auditing. A RuleBookAuditor is a decorator for a RuleBook that allows AuditableRules to be added. Since HomeLoadRuleBook is not a RuleBookAuditor, when it adds rules, they cannot be tracked for Auditing. In addition, there isn't currently any good way to audit rules created using the defineRules() method. I guess I didn't really realize that until you brought it up. So, thanks for opening up this issue.

Clayton7510 commented 5 years ago

I just pushed a small update to 0.11-SNAPSHOT. The code below shows how the MegaBank example that defines the rules in the defineRules method can audit its rule execution.

public class HomeLoanRateRuleBook extends RuleBookAuditor<Double> {

  public HomeLoanRateRuleBook() {
    this(new CoRRuleBook<>());
  }

  public HomeLoanRateRuleBook(RuleBook<Double> ruleBook) {
    super(ruleBook);
  }

  @Override
  public void defineRules() {
    //credit score under 600 gets a 4x rate increase
    addRule(RuleBuilder.create().withResultType(Double.class).withName("Under 600 FICO")
      .when(facts -> facts.getIntVal("Credit Score") < 600)
      .then((facts, result) -> result.setValue(result.getValue() * 4))
      .stop()
      .build());

    //credit score between 600 and 700 pays a 1 point increase
    addRule(RuleBuilder.create().withResultType(Double.class).withName("Between 600 and 700 FICO")
      .when(facts -> facts.getIntVal("Credit Score") < 700)
      .then((facts, result) -> result.setValue(result.getValue() + 1))
      .build());

    //credit score is 700 and they have at least $25,000 cash on hand
    addRule(RuleBuilder.create().withResultType(Double.class).withName("Over 700 FICO with 25000")
      .when(facts ->
        facts.getIntVal("Credit Score") >= 700 &&
        facts.getDblVal("Cash on Hand") >= 25000)
      .then((facts, result) -> result.setValue(result.getValue() - 0.25))
      .build());

    //first time home buyers get 20% off their rate (except if they have a creditScore < 600)
    addRule(RuleBuilder.create().withFactType(Boolean.class).withResultType(Double.class).withName("First time home buyer")
      .when(facts -> facts.getOne())
      .then((facts, result) -> result.setValue(result.getValue() * 0.80))
      .build());
  }
}
public static void main(String[] args) {
    RuleBook homeLoanRateRuleBook = RuleBookBuilder.create(HomeLoanRateRuleBook.class).withResultType(Double.class)
      .withDefaultResult(4.5)
      .build();

    NameValueReferableMap facts = new FactMap();
    facts.setValue("Credit Score", 650);
    facts.setValue("Cash on Hand", 20000);
    facts.setValue("First Time Homebuyer", true);

    homeLoanRateRuleBook.run(facts);

    homeLoanRateRuleBook.getResult().ifPresent(result -> System.out.println("Applicant qualified for the following rate: " + result));

    Auditor auditor = (Auditor)homeLoanRateRuleBook;
    System.out.println("Under 600 FICO: " + auditor.getRuleStatus("Under 600 FICO"));
    System.out.println("Between 600 and 700 FICO: " + auditor.getRuleStatus("Between 600 and 700 FICO"));
    System.out.println("Over 700 FICO with 25000: " + auditor.getRuleStatus("Over 700 FICO with 25000"));
    System.out.println("Over 700 FICO with 25000: " + auditor.getRuleStatus("First time home buyer"));
  }
Clayton7510 commented 5 years ago

Something to note is that when using the RuleBuilder to build rules, withName() makes the Rule auditable. So, in the context of a RuleBookAuditor, any Rule created using withName() will be audited.

Clayton7510 commented 5 years ago

Closing due to inactivity