001 /*
002 * Copyright 2011 The Kuali Foundation.
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.kfs.module.bc.document.web.struts;
017
018 import java.util.ArrayList;
019 import java.util.HashMap;
020 import java.util.HashSet;
021 import java.util.List;
022 import java.util.Set;
023
024 import javax.servlet.http.HttpServletRequest;
025
026 import org.kuali.kfs.coa.businessobject.Account;
027 import org.kuali.kfs.coa.businessobject.Organization;
028 import org.kuali.kfs.module.bc.BCConstants;
029 import org.kuali.kfs.module.bc.BCKeyConstants;
030 import org.kuali.kfs.module.bc.BCPropertyConstants;
031 import org.kuali.kfs.module.bc.BCConstants.LockStatus;
032 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionLockStatus;
033 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionPosition;
034 import org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding;
035 import org.kuali.kfs.module.bc.document.service.BudgetConstructionProcessorService;
036 import org.kuali.kfs.module.bc.document.service.BudgetDocumentService;
037 import org.kuali.kfs.module.bc.document.service.LockService;
038 import org.kuali.kfs.module.bc.document.service.SalarySettingService;
039 import org.kuali.kfs.module.bc.util.SalarySettingFieldsHolder;
040 import org.kuali.kfs.sys.KFSConstants;
041 import org.kuali.kfs.sys.KFSPropertyConstants;
042 import org.kuali.kfs.sys.ObjectUtil;
043 import org.kuali.kfs.sys.context.SpringContext;
044 import org.kuali.kfs.sys.identity.KfsKimAttributes;
045 import org.kuali.rice.kim.bo.types.dto.AttributeSet;
046 import org.kuali.rice.kim.service.PermissionService;
047 import org.kuali.rice.kim.service.RoleManagementService;
048 import org.kuali.rice.kns.service.BusinessObjectService;
049 import org.kuali.rice.kns.util.ErrorMap;
050 import org.kuali.rice.kns.util.MessageMap;
051
052 /**
053 * the base struts form for the detail salary setting: by position or by incumbent
054 */
055 public abstract class DetailSalarySettingForm extends SalarySettingBaseForm {
056 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DetailSalarySettingForm.class);
057
058 private PendingBudgetConstructionAppointmentFunding newBCAFLine;
059 private boolean addLine;
060
061 private String positionNumber;
062 private String emplid;
063 private String name;
064
065 private SalarySettingService salarySettingService = SpringContext.getBean(SalarySettingService.class);
066 private BudgetDocumentService budgetDocumentService = SpringContext.getBean(BudgetDocumentService.class);
067 private PermissionService permissionService = SpringContext.getBean(PermissionService.class);
068 private LockService lockService = SpringContext.getBean(LockService.class);
069 private BusinessObjectService businessObjectService = SpringContext.getBean(BusinessObjectService.class);
070
071 private static final List<String> comparableFields = getComparableFields();
072
073 /**
074 * Constructs a DetailSalarySettingForm.java.
075 */
076 public DetailSalarySettingForm() {
077 super();
078
079 this.setEditingMode(new HashMap<String, String>());
080 this.setNewBCAFLine(new PendingBudgetConstructionAppointmentFunding());
081 }
082
083 /**
084 * @see org.kuali.rice.kns.web.struts.form.KualiForm#populate(javax.servlet.http.HttpServletRequest)
085 */
086 @Override
087 public void populate(HttpServletRequest request) {
088 super.populate(request);
089
090 this.setSingleAccountMode(this.resetSingleAccountModeFlag());
091
092 this.populateBCAFLines();
093 }
094
095 /**
096 * @see org.kuali.kfs.module.bc.document.web.struts.SalarySettingBaseForm#populateBCAFLines()
097 */
098 @Override
099 public void populateBCAFLines() {
100 super.populateBCAFLines();
101
102 this.refreshBCAFLine(this.getNewBCAFLine());
103 }
104
105 /**
106 * @see org.kuali.kfs.module.bc.document.web.struts.SalarySettingBaseForm#refreshBCAFLine(org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding)
107 */
108 @Override
109 public void refreshBCAFLine(PendingBudgetConstructionAppointmentFunding appointmentFunding) {
110 super.refreshBCAFLine(appointmentFunding);
111
112 appointmentFunding.refreshReferenceObject(BCPropertyConstants.BUDGET_CONSTRUCTION_INTENDED_INCUMBENT);
113 appointmentFunding.refreshReferenceObject(BCPropertyConstants.BUDGET_CONSTRUCTION_POSITION);
114 appointmentFunding.refreshReferenceObject(BCPropertyConstants.BUDGET_CONSTRUCTION_ADMINISTRATIVE_POST);
115 }
116
117 /**
118 * acquire position and funding locks for all appointment fundings
119 */
120 public boolean acquirePositionAndFundingLocks(MessageMap errorMap) {
121 List<PendingBudgetConstructionAppointmentFunding> appointmentFundings = this.getAppointmentFundings();
122 for (PendingBudgetConstructionAppointmentFunding appointmentFunding : appointmentFundings) {
123 boolean gotLocks = this.acquirePositionAndFundingLocks(appointmentFunding, errorMap);
124
125 if (!gotLocks) {
126 return false;
127 }
128 }
129 return true;
130 }
131
132 /**
133 * acquire position and funding locks for the given appointment funding
134 *
135 * @param appointmentFunding the given appointment funding
136 * @return true if the position and funding locks for the given appointment funding are acquired successfully, otherwise, false
137 */
138 public boolean acquirePositionAndFundingLocks(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
139 LOG.info("acquirePositionAndFundingLocks() started");
140
141 try {
142 // not to acquire any lock for the display-only and non-budgetable funding line
143 if (appointmentFunding.isDisplayOnlyMode() || !appointmentFunding.isBudgetable()) {
144 return true;
145 }
146
147 // acquire position lock for the current funding line
148 BudgetConstructionPosition position = appointmentFunding.getBudgetConstructionPosition();
149 String positionNumber = position.getPositionNumber();
150 Integer universityFiscalYear = position.getUniversityFiscalYear();
151 String principalId = this.getPerson().getPrincipalId();
152 Boolean positionWasAlreadyLocked = lockService.isPositionLockedByUser(positionNumber, universityFiscalYear, principalId);
153 if (!positionWasAlreadyLocked) {
154 BudgetConstructionLockStatus positionLockingStatus = lockService.lockPosition(position, this.getPerson());
155 if (!LockStatus.SUCCESS.equals(positionLockingStatus.getLockStatus())) {
156 errorMap.putError(BCPropertyConstants.NEW_BCAF_LINE, BCKeyConstants.ERROR_FAIL_TO_LOCK_POSITION, position.toString());
157
158 // gwp - added if test, unlock all others only when initially loading the screen
159 // not during the add line action
160 if (!appointmentFunding.isNewLineIndicator()) {
161 this.releasePositionAndFundingLocks();
162 }
163 return false;
164 }
165 }
166
167 // acquire funding lock for the current funding line
168 BudgetConstructionLockStatus fundingLockingStatus = this.getLockStatusForBudgetByAccountMode(appointmentFunding);
169 if (fundingLockingStatus == null) {
170 fundingLockingStatus = lockService.lockFunding(appointmentFunding, this.getPerson());
171 }
172
173 if (!LockStatus.SUCCESS.equals(fundingLockingStatus.getLockStatus())) {
174 errorMap.putError(BCPropertyConstants.NEW_BCAF_LINE, BCKeyConstants.ERROR_FAIL_TO_LOCK_FUNDING, appointmentFunding.getAppointmentFundingString());
175
176 // gwp - added if test, unlock all others only when initially loading the screen
177 // not during the add line action
178 if (!appointmentFunding.isNewLineIndicator()) {
179 this.releasePositionAndFundingLocks();
180 }
181 else {
182 // adding a new line, just release the earlier position lock
183 // if we just issued it above, not from other line
184 if (!positionWasAlreadyLocked) {
185 lockService.unlockPosition(positionNumber, universityFiscalYear, principalId);
186 }
187 }
188 return false;
189 }
190 }
191 catch (Exception e) {
192 this.releasePositionAndFundingLocks();
193
194 String errorMessage = "Failed when acquiring position/funding lock for " + appointmentFunding;
195 LOG.error(errorMessage, e);
196 throw new RuntimeException(errorMessage, e);
197 }
198
199 return true;
200 }
201
202 /**
203 * update the access modes of all appointment fundings
204 */
205 public boolean updateAccessMode(MessageMap errorMap) {
206 List<PendingBudgetConstructionAppointmentFunding> appointmentFundings = this.getAppointmentFundings();
207 for (PendingBudgetConstructionAppointmentFunding appointmentFunding : appointmentFundings) {
208 boolean accessModeUpdated = this.updateAccessMode(appointmentFunding, errorMap);
209
210 if (!accessModeUpdated) {
211 return false;
212 }
213 }
214 return true;
215 }
216
217 /**
218 * update the access mode of the given appointment funding
219 *
220 * @param appointmentFunding the given appointment funding
221 * @return true if the access mode of the given appointment funding are updated successfully, otherwise, false
222 */
223 public boolean updateAccessMode(PendingBudgetConstructionAppointmentFunding appointmentFunding, MessageMap errorMap) {
224 LOG.info("updateAccessMode() started");
225
226 try {
227 SalarySettingFieldsHolder fieldsHolder = this.getSalarySettingFieldsHolder();
228
229 // update the access flags of the current funding line
230 boolean updated = salarySettingService.updateAccessOfAppointmentFunding(appointmentFunding, fieldsHolder, this.isBudgetByAccountMode(), this.isEditAllowed(), this.getPerson());
231 if (!updated) {
232 errorMap.putError(BCPropertyConstants.NEW_BCAF_LINE, BCKeyConstants.ERROR_FAIL_TO_UPDATE_FUNDING_ACCESS, appointmentFunding.getAppointmentFundingString());
233 return false;
234 }
235 }
236 catch (Exception e) {
237 String errorMessage = "Failed to update the access mode of " + appointmentFunding + ".";
238 LOG.error(errorMessage, e);
239 throw new RuntimeException(errorMessage, e);
240 }
241
242 return true;
243 }
244
245 /**
246 * acquire transaction locks for the savable appointment fundings
247 *
248 * @return true if the transaction locks for all savable appointment fundings are acquired successfully, otherwise, false
249 */
250 public boolean acquireTransactionLocks(MessageMap messageMap) {
251 LOG.info("acquireTransactionLocks() started");
252
253 for (PendingBudgetConstructionAppointmentFunding appointmentFunding : this.getSavableAppointmentFundings()) {
254 try {
255 BudgetConstructionLockStatus transactionLockStatus = this.getLockStatusForBudgetByAccountMode(appointmentFunding);
256 if (transactionLockStatus == null) {
257 transactionLockStatus = lockService.lockTransaction(appointmentFunding, this.getPerson());
258 }
259
260 if (!LockStatus.SUCCESS.equals(transactionLockStatus.getLockStatus())) {
261 messageMap.putError(BCPropertyConstants.NEW_BCAF_LINE, BCKeyConstants.ERROR_FAIL_TO_ACQUIRE_TRANSACTION_LOCK, appointmentFunding.getAppointmentFundingString());
262
263 this.releaseTransactionLocks();
264 return false;
265 }
266 }
267 catch (Exception e) {
268 this.releaseTransactionLocks();
269 this.releasePositionAndFundingLocks();
270
271 LOG.error("Failed when acquiring transaction lock for " + appointmentFunding, e);
272 throw new RuntimeException("Failed when acquiring transaction lock for " + appointmentFunding, e);
273 }
274 }
275
276 return true;
277 }
278
279 /**
280 * release all position and funding locks acquired in current action by the current user
281 */
282 public void releasePositionAndFundingLocks() {
283 LOG.info("releasePositionAndFundingLocks() started");
284
285 List<PendingBudgetConstructionAppointmentFunding> releasableAppointmentFundings = this.getReleasableAppointmentFundings();
286 lockService.unlockFunding(releasableAppointmentFundings, this.getPerson());
287
288 Set<BudgetConstructionPosition> lockedPositionSet = new HashSet<BudgetConstructionPosition>();
289 for (PendingBudgetConstructionAppointmentFunding fundingLine : releasableAppointmentFundings) {
290 lockedPositionSet.add(fundingLine.getBudgetConstructionPosition());
291 LOG.info("fundingLine: " + fundingLine);
292 }
293
294 LOG.info("releasePositionAndFundingLocks()" + lockedPositionSet);
295 List<BudgetConstructionPosition> lockedPositions = new ArrayList<BudgetConstructionPosition>();
296 lockedPositions.addAll(lockedPositionSet);
297 lockService.unlockPostion(lockedPositions, this.getPerson());
298 for (BudgetConstructionPosition position : lockedPositionSet) {
299 LOG.info("fundingLine: " + position.getPositionLockUserIdentifier());
300 }
301 }
302
303 /**
304 * release all the transaction locks acquired in current action by the current user
305 */
306 public void releaseTransactionLocks() {
307 LOG.info("releaseTransactionLocks() started");
308
309 List<PendingBudgetConstructionAppointmentFunding> fundingsWithTransactionLocks = this.getReleasableAppointmentFundings();
310 for (PendingBudgetConstructionAppointmentFunding appointmentFunding : fundingsWithTransactionLocks) {
311 lockService.unlockTransaction(appointmentFunding, this.getPerson());
312 }
313 }
314
315 /**
316 * get the appointment fundings that can be saved
317 */
318 public List<PendingBudgetConstructionAppointmentFunding> getSavableAppointmentFundings() {
319 LOG.info("getSavableAppointmentFundings() started");
320
321 // get the funding lines that can be saved
322 List<PendingBudgetConstructionAppointmentFunding> savableAppointmentFundings = new ArrayList<PendingBudgetConstructionAppointmentFunding>();
323 for (PendingBudgetConstructionAppointmentFunding fundingLine : this.getAppointmentFundings()) {
324
325 // save-able line is one that is edit-able
326 // rules should catch attempts to save active, !purged, !isBudgetable lines
327 if (!fundingLine.isDisplayOnlyMode()) {
328 savableAppointmentFundings.add(fundingLine);
329 }
330 }
331 return savableAppointmentFundings;
332 }
333
334 /**
335 * get the appointment fundings for which the position or funding locks can be released
336 */
337 public List<PendingBudgetConstructionAppointmentFunding> getReleasableAppointmentFundings() {
338 LOG.info("getReleasableAppointmentFundings() started");
339
340 List<PendingBudgetConstructionAppointmentFunding> savableAppointmentFundings = this.getSavableAppointmentFundings();
341 List<PendingBudgetConstructionAppointmentFunding> releasableAppointmentFundings = new ArrayList<PendingBudgetConstructionAppointmentFunding>();
342 releasableAppointmentFundings.addAll(savableAppointmentFundings);
343
344 return releasableAppointmentFundings;
345 }
346
347 /**
348 * determine whether there is any active funding line in the given savable appointment funding lines
349 */
350 public List<PendingBudgetConstructionAppointmentFunding> getActiveFundingLines() {
351 LOG.info("getActiveFundingLines() started");
352
353 List<PendingBudgetConstructionAppointmentFunding> activeFundingLines = new ArrayList<PendingBudgetConstructionAppointmentFunding>();
354 for (PendingBudgetConstructionAppointmentFunding appointmentFunding : this.getSavableAppointmentFundings()) {
355 if (!appointmentFunding.isAppointmentFundingDeleteIndicator()) {
356 activeFundingLines.add(appointmentFunding);
357 }
358 }
359 return activeFundingLines;
360 }
361
362 /**
363 * sets the default fields not setable by the user for added lines and any other required initialization
364 *
365 * @param appointmentFunding the given appointment funding line
366 */
367 public PendingBudgetConstructionAppointmentFunding createNewAppointmentFundingLine() {
368 PendingBudgetConstructionAppointmentFunding appointmentFunding = new PendingBudgetConstructionAppointmentFunding();
369
370 if (this.isAddLine() || this.isSingleAccountMode()) {
371 appointmentFunding.setChartOfAccountsCode(this.getChartOfAccountsCode());
372 appointmentFunding.setAccountNumber(this.getAccountNumber());
373
374 // empty field implies dashes and is fixed in add action
375 if (this.getSubAccountNumber().equals(KFSConstants.getDashSubAccountNumber())) {
376 appointmentFunding.setSubAccountNumber(KFSConstants.EMPTY_STRING);
377 }
378 else {
379 appointmentFunding.setSubAccountNumber(this.getSubAccountNumber());
380 }
381 appointmentFunding.setFinancialObjectCode(this.getFinancialObjectCode());
382
383 // empty field implies dashes and is fixed in add action
384 if (this.getFinancialSubObjectCode().equals(KFSConstants.getDashFinancialSubObjectCode())) {
385 appointmentFunding.setFinancialSubObjectCode(KFSConstants.EMPTY_STRING);
386 }
387 else {
388 appointmentFunding.setFinancialSubObjectCode(this.getFinancialSubObjectCode());
389 }
390 }
391
392 appointmentFunding.setUniversityFiscalYear(this.getUniversityFiscalYear());
393 appointmentFunding.setAppointmentFundingDeleteIndicator(false);
394 appointmentFunding.setNewLineIndicator(true);
395 appointmentFunding.setAppointmentFundingDurationCode(BCConstants.AppointmentFundingDurationCodes.NONE.durationCode);
396
397 return appointmentFunding;
398 }
399
400 /**
401 * pick up the appointment fundings belonging to the specified account from a collection of fundings that are associated with a
402 * position/incumbent
403 */
404 public void pickAppointmentFundingsForSingleAccount() {
405 LOG.info("pickAppointmentFundingsForSingleAccount() started");
406
407 List<PendingBudgetConstructionAppointmentFunding> excludedFundings = new ArrayList<PendingBudgetConstructionAppointmentFunding>();
408 for (PendingBudgetConstructionAppointmentFunding appointmentFunding : this.getAppointmentFundings()) {
409 if (!ObjectUtil.equals(appointmentFunding, this, comparableFields)) {
410 excludedFundings.add(appointmentFunding);
411 }
412 }
413
414 this.getAppointmentFundings().removeAll(excludedFundings);
415 }
416
417 /**
418 * Funding/transaction locks are not required for the lines associated with a document already open in budget by account mode
419 */
420 private BudgetConstructionLockStatus getLockStatusForBudgetByAccountMode(PendingBudgetConstructionAppointmentFunding appointmentFunding) {
421 LOG.info("getLockStatusForBudgetByAccountMode() started");
422
423 BudgetConstructionLockStatus transactionLockStatus = null;
424
425 if (this.isBudgetByAccountMode() && ObjectUtil.equals(appointmentFunding, this, comparableFields)) {
426 transactionLockStatus = new BudgetConstructionLockStatus();
427 transactionLockStatus.setLockStatus(LockStatus.SUCCESS);
428 }
429
430 return transactionLockStatus;
431 }
432
433 /**
434 * get the names of comparable fields that are considered to determine a single account, that is, the fundings are considered
435 * being assocated with the given account if they have the same values of the fields as specified.
436 */
437 public static List<String> getComparableFields() {
438 List<String> comparableFields = new ArrayList<String>();
439 comparableFields.add(KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE);
440 comparableFields.add(KFSPropertyConstants.ACCOUNT_NUMBER);
441 comparableFields.add(KFSPropertyConstants.SUB_ACCOUNT_NUMBER);
442
443 return comparableFields;
444 }
445
446 /**
447 * determine whether the editing mode for detail salary setting is in single account mode or not
448 */
449 private boolean resetSingleAccountModeFlag() {
450
451 List<Organization> processorOrgs = SpringContext.getBean(BudgetConstructionProcessorService.class).getProcessorOrgs(this.getPerson());
452 Boolean isOrgApprover = processorOrgs != null && !processorOrgs.isEmpty();
453
454 if (this.isBudgetByAccountMode()) {
455
456 Account account = new Account();
457 account.setAccountNumber(this.getAccountNumber());
458 account.setChartOfAccountsCode(this.getChartOfAccountsCode());
459 account = (Account) businessObjectService.retrieve(account);
460
461 RoleManagementService roleService = SpringContext.getBean(RoleManagementService.class);
462 AttributeSet qualification = new AttributeSet();
463 qualification.put(KfsKimAttributes.CHART_OF_ACCOUNTS_CODE, getChartOfAccountsCode());
464 qualification.put(KfsKimAttributes.ACCOUNT_NUMBER, getAccountNumber());
465 qualification.put(KfsKimAttributes.DOCUMENT_TYPE_NAME, BCConstants.BUDGET_CONSTRUCTION_DOCUMENT_NAME);
466
467 List<String> roleId = new ArrayList<String>();
468 roleId.add(roleService.getRoleIdByName(KFSConstants.ParameterNamespaces.KFS, KFSConstants.SysKimConstants.FISCAL_OFFICER_KIM_ROLE_NAME));
469
470 Boolean isFiscalOfficerOrDelegate = roleService.principalHasRole(getPerson().getPrincipalId(), roleId, qualification);
471
472 return (isFiscalOfficerOrDelegate && !isOrgApprover);
473 }
474
475 // instruct the detail salary setting by multiple account mode if current user is an organization level approver
476 if (isOrgApprover) {
477 return false;
478 }
479 else {
480 throw new RuntimeException("Access denied: not authorized to do the detail salary setting");
481 }
482 }
483
484 /**
485 * Gets the newBCAFLine attribute.
486 *
487 * @return Returns the newBCAFLine.
488 */
489 public PendingBudgetConstructionAppointmentFunding getNewBCAFLine() {
490 return newBCAFLine;
491 }
492
493 /**
494 * Sets the newBCAFLine attribute value.
495 *
496 * @param newBCAFLine The newBCAFLine to set.
497 */
498 public void setNewBCAFLine(PendingBudgetConstructionAppointmentFunding newBCAFLine) {
499 this.newBCAFLine = newBCAFLine;
500 }
501
502 /**
503 * Gets the emplid attribute.
504 *
505 * @return Returns the emplid.
506 */
507 public String getEmplid() {
508 return emplid;
509 }
510
511 /**
512 * Sets the emplid attribute value.
513 *
514 * @param emplid The emplid to set.
515 */
516 public void setEmplid(String emplid) {
517 this.emplid = emplid;
518 }
519
520 /**
521 * Gets the addLine attribute.
522 *
523 * @return Returns the addLine.
524 */
525 public boolean isAddLine() {
526 return addLine;
527 }
528
529 /**
530 * Sets the addLine attribute value.
531 *
532 * @param addLine The addLine to set.
533 */
534 public void setAddLine(boolean addLine) {
535 this.addLine = addLine;
536 }
537
538 /**
539 * Gets the positionNumber attribute.
540 *
541 * @return Returns the positionNumber.
542 */
543 public String getPositionNumber() {
544 return positionNumber;
545 }
546
547 /**
548 * Sets the positionNumber attribute value.
549 *
550 * @param positionNumber The positionNumber to set.
551 */
552 public void setPositionNumber(String positionNumber) {
553 this.positionNumber = positionNumber;
554 }
555
556 /**
557 * Gets the name attribute.
558 *
559 * @return Returns the name.
560 */
561 public String name() {
562 return name;
563 }
564
565 /**
566 * Sets the name attribute value.
567 *
568 * @param name The name to set.
569 */
570 public void setName(String name) {
571 this.name = name;
572 }
573
574 /**
575 * @see org.kuali.rice.kns.web.struts.form.KualiForm#shouldPropertyBePopulatedInForm(java.lang.String,
576 * javax.servlet.http.HttpServletRequest)
577 */
578 @Override
579 public boolean shouldPropertyBePopulatedInForm(String requestParameterName, HttpServletRequest request) {
580
581 if (super.shouldPropertyBePopulatedInForm(requestParameterName, request)) {
582 return true;
583 }
584 else {
585 // make sure special disabled fields are allowed to be populated
586 if (requestParameterName.endsWith(BCPropertyConstants.APPOINTMENT_REQUESTED_CSF_AMOUNT) || requestParameterName.endsWith(BCPropertyConstants.APPOINTMENT_REQUESTED_CSF_TIME_PERCENT) || requestParameterName.endsWith(BCPropertyConstants.APPOINTMENT_FUNDING_REASON_AMOUNT)) {
587 return true;
588 }
589 else {
590 return false;
591 }
592 }
593 }
594 }