customizing kuali a technical perspective n.
Download
Skip this Video
Download Presentation
Customizing Kuali: A Technical Perspective

Loading in 2 Seconds...

play fullscreen
1 / 73

Customizing Kuali: A Technical Perspective - PowerPoint PPT Presentation


  • 171 Views
  • Uploaded on

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.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Customizing Kuali: A Technical Perspective' - lilac


Download Now 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)

sample code using business rule in taxnumberservice
Sample Code Using Business Rule inTaxNumberService

/**

*Splitsthesetoftaxnumberformatswhicharereturned * fromtheruleserviceasasemicolon-delimitedString

* into aStringarray.

*

*@returnAStringarrayofthetaxnumberformatregularexpressions.

*/

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.
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 {

/**

*@paramdocument

*@returnfalseiftherulefails

*/

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
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>

prerulescheck interface
PreRulesCheck Interface

publicinterface PreRulesCheck {

/**

*CallbackmethodfromMaintenanceactionthatallowscheckstobedoneandresponseredirectedviathePreRulesCheckEvent

*

*@paramform

*@paramrequest

*@paramevent

*@returnbooleanindicatingwhetherroutingshouldstoporcontinue

*/

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.
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;

}

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
slide72
Questions?

kualitestdrive@oncourse.iu.edu

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