Customizing kuali a technical perspective
This presentation is the property of its rightful owner.
Sponsored Links
1 / 73

Customizing Kuali: A Technical Perspective PowerPoint PPT Presentation


  • 119 Views
  • Uploaded on
  • Presentation posted in: General

Customizing Kuali: A Technical Perspective. Naser Alavi (Michigan State University) Warren Liang (University of California, Irvine). Customizing Kuali. Outline: System Parameters Business Rules Authorization class Pre-Rules. Customizing Kuali.

Download Presentation

Customizing Kuali: A Technical Perspective

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Customizing kuali a technical perspective

Customizing Kuali:A Technical Perspective

Naser Alavi (Michigan State University)

Warren Liang (University of California, Irvine)


Customizing kuali

Customizing Kuali

Outline:

  • System Parameters

  • Business Rules

  • Authorization class

  • Pre-Rules


Customizing kuali1

Customizing Kuali

  • Which aspects of Kuali are we customizing in this presentation?

    • Customizing business rules

    • Customizing authorization

    • Customizing system parameters


System parameters rules

System Parameters/Rules

Purpose:

  • Externalizing constants out of code

  • They may be maintained by a non-developer via a maintenance document.

  • The code must be programmed to access the constant value(s) by its unique key.


System parameters use cases

System Parameters Use Cases

Where they may be used:

  • Business rule checks

  • Any place where runtime changes to values displayed within the application will be needed without a restart of the application server


System parameters

System Parameters

The System Parameters can be used in the following manners:

  • Key-value constants

    • (key=DEBIT, value=D)

  • Key-value group constants

    • (key=VALID_OBJECT_CODES_FOR_XYZ, value=5000;5001;3400;2300)


System parameters use cases1

System Parameters Use Cases

Where they may not / should not be used:

  • System configuration values that can’t be represented as constants/literals in the code

  • Core constants that will not change no matter what the installation

  • Spring XML configuration files - you cannot have XML files use this mechanism

  • OJB XML configuration or descriptor files - you cannot have XML files use this mechanism


System parameters table

System Parameters Table

  • A single parameter record has a composite key made up of:

    • Parameter Name

    • Parameter Security Grouping

  • This composite key helps to categorize our constants.

    • As an enhancement for next phase to further modularize these parameters a new “Module Code” field will be added to this table


Using system parameters

Using System Parameters

  • Using the System Parameters for Key-Value Constants:

    String MANDATORY_TRANSFER = kualiConfigurationService

    .getApplicationParameter("TransactionProcessingEDocs", "Chart.SubObjectCode.MandatoryTransfer");

    if (financialSubObjectCode.equals(MANDATORY_TRANSFER)) {

    ...


Using system parameters1

Using System Parameters

  • Using the System Parameters for Key-Value Lists of Constants (array of values)

    String[] VALID_OBJ_SUB_TYPES_FOR_TOF = SpringServiceLocator.getKualiConfigurationService()

    .getApplicationParameters("TransactionProcessing",

    "ValidObjectSubTypeCodesForTofAccountingLines");

    if(ArrayUtils.contains(VALID_OBJ_SUB_TYPES_FOR_TOF, accountingLine.getFinancialSubObjectCode())) { ...


System parameter security class table

System Parameter Security Class/Table

  • The following class represents a security grouping which is identified by its security group name.

  • Each security grouping has a workgroup associated with it for authorization purposes.


System parameter security class table1

System Parameter Security Class/Table

publicclass FinancialSystemParameterSecurity extends PersistableBusinessObjectBase {

// script name is the security group

private String financialSystemScriptName;

private String workgroupName;

private String financialSystemScriptDescription;

private List financialSystemParameters;


System parameter attributes

System Parameter Attributes

  • The following class represents a KFS parameter with an associated text value.

  • This text value can be interpreted as a single value or a semicolon delimited list of values

  • The parameter name and the security group name make up the primary key for this business object

  • The security group name is the link to the System Parameter Security Table


System parameter attributes1

System Parameter Attributes

publicclass FinancialSystemParameter extends PersistableBusinessObjectBase {

private String financialSystemScriptName;

private String financialSystemParameterName;

private String financialSystemParameterText;

private String financialSystemParameterDescription;

privatebooleanfinancialSystemMultipleValueIndicator;

private FinancialSystemParameterSecurity financialSystemParameterSecurity;


Business rules

Business Rules

  • Maintained by Business Rules Tables

  • Allows Functional Users to maintain and create business rules (to some extent).

  • Allows institutions to customize out of the box business rules based on their codes and policies.


Business rules1

Business Rules

  • Uses KualiParameterRule object for evaluating business rules

  • This object holds the underlying rule record values and provides a conveniencemethod for the evaluation of the rule

  • You can retrieve the values of a rule record as a KualiParameterRule by using the KualiConfigurationService method:

    KualiParameterRule getApplicationParameterRule(String scriptName, String parameter)


Business rule from administration tab

Business Rule From Administration Tab


Business rule security example

Business Rule Security Example


Business rule example

Business Rule Example


Business rule examples

Business Rule Examples


Sample code using business rule in taxnumberservice

Sample Code Using Business Rule inTaxNumberService

/**

*Splitsthesetoftaxnumberformatswhicharereturned * fromtheruleserviceasasemicolon-delimitedString

* into aStringarray.

*

[email protected]

*/

public String[] parseSSNFormats() {

if(taxNumberFormats == null) {

taxNumberFormats = SpringServiceLocator.getKualiConfigurationService().getApplicationRule("PurapAdminGroup","PURAP.TAX_NUMBER_FORMATS");

}

String taxFormats = taxNumberFormats.getRuleText();

return taxFormats.split(";");

}


Sample code using business rule in taxnumberservice1

Sample Code Using Business Rule inTaxNumberService

publicboolean isValidTaxNumber( String taxNbr, String taxType ) {

String[] ssnFormats = parseSSNFormats();

String[] feinFormats = parseFEINFormats();

Integer defaultTaxNbrDigits =

new Integer (SpringServiceLocator

.getKualiConfigurationService()

.getApplicationParameterValue("PurapAdminGroup",

"PURAP.DEFAULT_TAX_NUM_DIGITS"));

if (taxNbr.length() != defaultTaxNbrDigits

|| !isStringAllNumbers(taxNbr)) {

returnfalse;

}


Business rule attributes

Business Rule Attributes

package org.kuali.core.bo;

publicclass BusinessRule extends PersistableBusinessObjectBase {

private String ruleGroupName;

private String ruleName;

private String ruleText;

private String ruleDescription;

private String ruleOperatorCode;

privatebooleanfinancialSystemMultipleValueIndicator;

privatebooleanfinancialSystemParameterActiveIndicator;

BusinessRuleSecurity ruleGroup;


System parameters rules1

System Parameters/Rules

Summary:

  • Create and populate workgroup that should have maintenance permission

  • Create corresponding security group

  • Create parameter (value to control runtime system behavior) or rule (definition of legal/illegal values)


Customizing kuali2

Customizing Kuali

Outline:

  • System Parameters

  • Business Rules

  • Authorization class

  • Pre-Rules


Putting it all together

Putting It All Together

  • Defining a Transactional Document

    • Payment Request Doc DD XML

    • Payment Request Rule

    • Payment Request Authorizer

    • Payment Request Pre-Rule (using question framework)

    • Demo New Payment Request Document functionality and sample code


Plugging business rules class

Plugging Business Rules Class

  • “Pluggable” business rules

    • Specify business rule implementation in document’s data dictionary file

    • Registering your business rule class with a document type.

    • The fully qualified classname of the business rule class must be specified with the <businessRuleClass> tag in the document's data dictionary file.


Plugging business rules class1

Plugging Business Rules Class

Example, KualiPaymentRequestDocument.xml:

<documentClass>

org.kuali.module.purap.document.PaymentRequestDocument

</documentClass>

<businessRulesClass>

org.kuali.module.purap.rules.PaymentRequestDocumentRule

</businessRulesClass>


Plugging business rules class2

Plugging Business Rules Class

  • “Pluggable” business rules

    • Normally used to detect errors on a form

    • Since these are written in Java, it is much more expressive than just matching

    • Has access to all Kuali services

    • The rules framework creates a copy of the document so that any changes made during rule application will not affect the document when it is persisted.


Payment request rule hierarchy

Payment Request Rule Hierarchy


Business rule framework

Business Rule Framework


Documentrulebase

DocumentRuleBase

  • DocumentRuleBase implements common checks that should be run after every event, and rule implementations should extend this class

  • Instead of overriding the methods defined by the *DocumentRule interfaces, override the processCustom* methods defined in this class (e.g. to define new save rules, override processCustomSaveDocumentBusinessRules instead of processSaveDocument)


Associating rules with events save example

Associating Rules with Events(Save Example)

package org.kuali.core.rule;

/**

*Definesarulewhichgetsinvokedimmediatelybeforeadocumentgetssaved.

*/

publicinterface SaveDocumentRule extends BusinessRule {

/**

[email protected]

[email protected]

*/

publicboolean processSaveDocument(Document document);

}


Associating rules with events and using common services

Associating Rules with Events and Using Common Services

/**

*Thisclasscontainsallofthebusinessrulesthatarecommontoalldocuments.

*/

publicabstractclass DocumentRuleBase implements SaveDocumentRule, RouteDocumentRule, ApproveDocumentRule, AddNoteRule, AddAdHocRoutePersonRule, AdHocRouteWorkgroupRule {

privatestatic UniversalUserService universalUserService;

privatestatic KualiModuleService kualiModuleService;

privatestatic DictionaryValidationService dictionaryValidationService;

privatestatic KualiWorkflowInfo workflowInfoService;

privatestatic KualiConfigurationService kualiConfigurationService;


Documentrulebase rule implementation

DocumentRuleBase Rule Implementation

publicabstractclassDocumentRuleBaseimplements

SaveDocumentRule, … {

publicboolean processSaveDocument(Document document) {

boolean isValid = true;

isValid &= isDocumentOverviewValid(document);

if (isValid) {

isValid &=

processCustomSaveDocumentBusinessRules(document);

}

return isValid;

}

protectedboolean processCustomSaveDocumentBusinessRules

(Document document) {

returntrue;

}

}


Documentrule sample

DocumentRule Sample

publicclass PaymentRequestDocumentRule extends AccountsPayableDocumentRuleBase {

@Override

protectedboolean

processCustomSaveDocumentBusinessRules

(Document document) {

PaymentRequestDocument

paymentRequestDocument =

(PaymentRequestDocument) document;

return

processValidation(paymentRequestDocument);

}


Documentrule sample1

DocumentRule Sample

publicclass PaymentRequestDocumentRule extends AccountsPayableDocumentRuleBase {

….

@Override

publicboolean processValidation(PurchasingAccountsPayableDocument purapDocument) {

boolean valid = super.processValidation(purapDocument);

valid &= processInvoiceValidation((PaymentRequestDocument)purapDocument);

valid &= processPurchaseOrderIDValidation((PaymentRequestDocument)purapDocument);

valid &= processPaymentRequestDateValidation((PaymentRequestDocument)purapDocument);

return valid;

}


Customizing kuali3

Customizing Kuali

Outline:

  • System Parameters

  • Business Rules

  • Authorization class

  • Pre-Rules


Plugging authorizer class

Plugging Authorizer Class

  • Modifying Authorizations for a Document Type

    • Payment Request Document

      • Initiators in Doc DD XML

      • Complex Rules in Document Authorizer Class

      • Approvals in Workflow


Plugging authorizer class1

Plugging Authorizer Class

Authorization DD File Code Sample:

<documentClass>

org.kuali.module.purap.document.PaymentRequestDocument

</documentClass>

<documentAuthorizerClass>

org.kuali.module.purap.document.PaymentRequestDocumentAuthorizer

</documentAuthorizerClass>

<authorizations>

<authorization action="initiate">

<workgroups>

<workgroup>kualiUniversalGroup</workgroup>

</workgroups>

</authorization>

</authorizations>

<documentTypeName>KualiPaymentRequestDocument</documentTypeName>

<documentTypeCode>PREQ</documentTypeCode>


Document authorizer

Document Authorizer

  • The document authorizer framework:

    • Determines a user can initiate a document

    • How document fields are rendered

    • What buttons are displayed


Create new payment request

Create New Payment Request


Checking for duplication

Checking for Duplication


Showing other action buttons

Showing Other Action Buttons


Code modules for paymentrequest

Code Modules for PaymentRequest

The functionality demoed was accomplished through codes in:

  • PaymentRequestDocumentAuthorizer

  • PaymentRequestDocumentRule (already discussed)

  • PaymentRequestAction


Paymentrequestdocumentauthorizer

PaymentRequestDocumentAuthorizer

Overrode these methods:

  • hasInitiateAuthorization

    • Simple true/false value

  • getEditMode

    • A map of mode -> value mappings. The JSP layer uses these mappings to determine how it should render the document

  • getDocumentActionFlags

    • Returns an object with numerous boolean flags, indicating whether a button may be rendered


Paymentrequestdocumentauthorizer1

PaymentRequestDocumentAuthorizer

@Override

publicboolean hasInitiateAuthorization(Document document, UniversalUser user) {

String authorizedWorkgroup = SpringServiceLocator.getKualiConfigurationService().getApplicationParameterValue(PurapRuleConstants.PURAP_ADMIN_GROUP, PurapRuleConstants.PURAP_DOCUMENT_PO_ACTIONS);

try {

return SpringServiceLocator.getKualiGroupService().getByGroupName(authorizedWorkgroup).hasMember(user);

}

catch (GroupNotFoundException e) {

thrownew RuntimeException("Workgroup " + authorizedWorkgroup + " not found",e);

}

}


Paymentrequestdocumentauthorizer2

PaymentRequestDocumentAuthorizer

@Override

public Map getEditMode(Document document, UniversalUser user, List sourceAccountingLines, List targetAccountingLines) {

Map editModeMap = super.getEditMode(document, user, sourceAccountingLines, targetAccountingLines);

PaymentRequestDocument paymentRequestDocument = (PaymentRequestDocument)document;

if (StringUtils.equals(paymentRequestDocument.getStatusCode(),PurapConstants.PaymentRequestStatuses.INITIATE)){

editModeMap.put(PurapAuthorizationConstants.PaymentRequestEditMode.DISPLAY_INIT_TAB, "TRUE");

} else {

editModeMap.put(PurapAuthorizationConstants.PaymentRequestEditMode.DISPLAY_INIT_TAB, "FALSE");

}

return editModeMap;

}


Paymentrequestdocumentauthorizer3

PaymentRequestDocumentAuthorizer

The JSP uses the values in the edit mode map to determine how to render the document.

Example from PaymentRequest.jsp

<c:if test="${not KualiForm.editingMode['displayInitTab']}" >

<kul:documentOverview editingMode="${KualiForm.editingMode}" includePostingYear="true“ />

</c:if>

<c:if test="${KualiForm.editingMode['displayInitTab']}" >

<purap:paymentRequestInit documentAttributes="${DataDictionary.KualiPaymentRequestDocument.attributes}“ />

</c:if>


Paymentrequestdocumentauthorizer4

PaymentRequestDocumentAuthorizer

@Override

public DocumentActionFlags getDocumentActionFlags(Document document, UniversalUser user) {

DocumentActionFlags flags =

super.getDocumentActionFlags(document, user);

KualiWorkflowDocument workflowDocument =

document.getDocumentHeader().getWorkflowDocument();

PaymentRequestDocument paymentRequestDocument =

(PaymentRequestDocument)document;

if (StringUtils.equals(paymentRequestDocument

.getStatusCode(), INITIATE)){

flags.setCanSave(false);

flags.setCanClose(false);

flags.setCanCancel(true);

} else {

flags.setCanSave(true);

}

return flags;

}


Payment request duplication scenario

Payment Request Duplication Scenario

  • Needed to check for Payment Request duplication before even validating business rules

  • In case of duplication give the user a warning and the option of override the warning and continue or to cancel

  • We used the question framework for this

  • Demo this in action in Payment Request

  • Demo the code (paymentRequestAction.continuePREQ())


Paymentrequestaction

PaymentRequestAction

public ActionForward continuePREQ(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {

PaymentRequestForm preqForm = (PaymentRequestForm) form;

PaymentRequestDocument paymentRequestDocument = (PaymentRequestDocument) preqForm.getDocument();

Map editMode = preqForm.getEditingMode();

Object question = request.getParameter(KFSConstants.QUESTION_INST_ATTRIBUTE_NAME);

PaymentRequestService paymentRequestService = SpringServiceLocator.getPaymentRequestService();

HashMap<String, String> duplicateMessages = paymentRequestService.paymentRequestDuplicateMessages(paymentRequestDocument);


Paymentrequestaction continued

PaymentRequestAction (Continued)

if (!duplicateMessages.isEmpty()){

if (question == null) {

// ask question if not already asked

returnthis.performQuestionWithoutInput(mapping, form, request, response, PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION, duplicateMessages.get(PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION) , KFSConstants.CONFIRMATION_QUESTION, KFSConstants.ROUTE_METHOD, "");

}

Object buttonClicked = request.getParameter(KFSConstants.QUESTION_CLICKED_BUTTON);

if ((PurapConstants.PREQDocumentsStrings.DUPLICATE_INVOICE_QUESTION.equals(question)) && ConfirmationQuestion.NO.equals(buttonClicked)) {

// if no button clicked just reload the doc in the

// INITIATE status and let the user to change the

// input values

paymentRequestDocument.setStatusCode(PurapConstants.PaymentRequestStatuses.INITIATE);

return mapping.findForward(KFSConstants.MAPPING_BASIC);

}

}


Customizing kuali4

Customizing Kuali

Outline:

  • System Parameters

  • Business Rules

  • Authorization class

  • Pre-Rules


Pre rules use cases

Pre-Rules Use Cases

  • Pre-Rules allow

    • Modification of values after form submission (e.g. auto-fill values, possibly based on other values on the form)

    • Switching to another page after clicking the button (e.g. go to a confirmation page)


Pre rules configuration

Pre-Rules Configuration

  • Pre-rules for documents are configured in the data dictionary by specifying a class name for the implementation

  • Example: in UniversalUserMaintenanceDocument.xml

    <preRulesCheckClass>

    org.kuali.core.rules.UniversalUserPreRules

    </preRulesCheckClass>


Pre rule checks architecture

Pre Rule Checks Architecture


Prerulescheck interface

PreRulesCheck Interface

publicinterface PreRulesCheck {

/**

*CallbackmethodfromMaintenanceactionthatallowscheckstobedoneandresponseredirectedviathePreRulesCheckEvent

*

[email protected]

[email protected]

[email protected]

[email protected]

*/

publicboolean processPreRuleChecks(ActionForm form, HttpServletRequest request, PreRulesCheckEvent event);

}


Prerulescontinuationbase

PreRulesContinuationBase

  • This class simplifies requesting clarifying user input prior to applying business rules.

  • It mostly shields the classes that extend it from being aware of the web layer, even though the input is collected via a series of one or more request/response cycles.


Prerulescontinuationbase1

PreRulesContinuationBase


Prerulescontinuationbase2

PreRulesContinuationBase

publicabstractclass PreRulesContinuationBase implements PreRulesCheck {

protected String question;

protected String buttonClicked;

protected PreRulesCheckEvent event;

protected KualiForm form;

publicabstractboolean doRules(Document document);


Prerulescontinuationbase3

PreRulesContinuationBase

publicbooleanprocessPreRuleChecks(ActionForm form, HttpServletRequest request, PreRulesCheckEvent event) {

try {

result = doRules(event.getDocument());

}

catch (IsAskingException e) {

returnfalse;

}

if (isAborting) {

returnfalse;

}

return result;

}


Prerulescheckevent

PreRulesCheckEvent


Putting prerules in action

Putting PreRules* in Action

  • Pre-rules are invoked automatically by the framework before routing, approving, and blanket approving a document.

  • Can also force the invocation of a pre-rule by overriding the Struts action handler of the document.


Example 1 adding a pre rule check

Example 1: Adding a pre-rule check

public class BudgetParametersAction extends BudgetAction {

public ActionForward deletePeriodLine(ActionMapping mapping,

ActionForm form, HttpServletRequest request,

HttpServletResponse response) throws Exception {

// do some processing

ActionForward preRulesForward = preRulesCheck(mapping, form,

request, response);

if (preRulesForward != null) {

return preRulesForward;

}

return mapping.findForward(KFSConstants.MAPPING_BASIC);

}


Example 2 universaluserprerules

Example 2: UniversalUserPreRules

publicclass UniversalUserPreRules extends PreRulesContinuationBase {

publicboolean doRules(Document document) {

MaintenanceDocument maintenanceDocument = (MaintenanceDocument) document;

UniversalUser newUser = (UniversalUser) maintenanceDocument.getNewMaintainableObject().getBusinessObject();

Field nameField = FieldUtils.getPropertyField( UniversalUser.class, PropertyConstants.PERSON_NAME, false );

ControlDefinition controlDef = KNSServiceLocator.getDataDictionaryService().getAttributeControlDefinition(UniversalUser.class, PropertyConstants.PERSON_NAME );


Example 2 universaluserprerules continued

Example 2: UniversalUserPreRules (continued)

if ( controlDef.isHidden() || nameField.isReadOnly() || StringUtils.isBlank( newUser.getPersonName() ) ){

if ( !StringUtils.isBlank( newUser.getPersonFirstName() ) && !StringUtils.isBlank( newUser.getPersonLastName() ) ){

if ( !StringUtils.isBlank( newUser.getPersonMiddleName() ) ) {

newUser.setPersonName( newUser.getPersonLastName()+"," +newUser.getPersonFirstName() + " " + newUser.getPersonMiddleName() );

} else {

newUser.setPersonName( newUser.getPersonLastName()+"," +newUser.getPersonFirstName() );

}

}

}

boolean success = true;

List<KualiModule> modules = KNSServiceLocator.getKualiModuleService().getInstalledModules();

PreRulesContinuationBase rule = null;

for ( KualiModule module : modules ) {

rule = (PreRulesContinuationBase) module.getModuleUserPreRules();

if ( rule != null ) {

success &= rule.doRules( document );

}

}


Pre rule scenario sample 3

Pre-Rule Scenario Sample 3

  • Pre-Rules could be used to derive values based on other values, or

  • Setting a default value where needed and the user didn’t enter any value

    • See next sample code


Example 3 set unconditional defaults

Example 3: Set Unconditional Defaults

publicclass DelegateChangePreRules implements PreRulesCheck {

...

privatevoid setUnconditionalDefaults(DelegateChangeContainer newDelegateChangeContainer) {

for (DelegateChangeDocument newDelegateChange : newDelegateChangeContainer.getDelegateChanges()) {

// FROM amount defaults to zero

if (newDelegateChange.getApprovalFromThisAmount()==null) {

newDelegateChange.setApprovalFromThisAmount(new KualiDecimal(0));

}

// TO amount defaults to zero

if (newDelegateChange.getApprovalToThisAmount()==null) {

newDelegateChange.setApprovalToThisAmount(new KualiDecimal(0));

}

}

}


Summary

Summary

  • System parameters

    • Provides on-the-fly configuration of certain components

  • Business Rules

    • Provides business rules based on matching values


Summary1

Summary

  • “Pluggable” business rules

    • Java-based implementation of rules that are more complicated than simple matching

  • Pre-rules

    • Allows modification of form values prior to processing

    • Allows “redirection” to a different page


Customizing kuali a technical perspective

Questions?

[email protected]


References

References

  • System parameters/ business rules

    https://test.kuali.org/confluence/x/-kw

  • Pluggable business rules

    https://test.kuali.org/confluence/x/5l

  • Pre-rules

    https://test.kuali.org/confluence/x/WFE

  • Kuali Nervous System (KNS)

    https://test.kuali.org/confluence/x/EU8


  • Login