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.service; 017 018 import java.util.List; 019 import java.util.SortedSet; 020 021 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionFundingLock; 022 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionHeader; 023 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionLockStatus; 024 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionLockSummary; 025 import org.kuali.kfs.module.bc.businessobject.BudgetConstructionPosition; 026 import org.kuali.kfs.module.bc.businessobject.PendingBudgetConstructionAppointmentFunding; 027 import org.kuali.kfs.module.bc.exception.BudgetConstructionLockUnavailableException; 028 import org.kuali.kfs.module.bc.BCConstants.LockStatus; 029 import org.kuali.rice.kim.bo.Person; 030 031 032 /** 033 * This interface defines the methods that a LockService must provide. LockServiceImpl consists of methods that manage the various 034 * locks used in the Budget module. Locks are needed to serialize user updates since a BC Edoc is potentially editable by many users 035 * simultaneously and the default Optimistic locking scheme used by KFS would produce an inconsistent set of data. <B>Accountlock</B> 036 * controls exclusive access to the BC Edoc <B>Positionlock</B> controls exclusive access to a BC Position <B>Fundinglock</B> 037 * controls shared funding access. An associated Positionlock must exist before attempting to get a Fundinglock. Accountlock and 038 * Fundinglock are mutex. <B>Transactionlock</B> controls exclusive access to serialize updates to the accounting lines in the BC 039 * Edoc. A Fundinglock must exist before creating a Transactionlock. The Transactionlock lifecycle is short, required only for the 040 * duration of the accounting line update. 041 */ 042 public interface LockService { 043 044 /** 045 * This method attempts to lock the given Account for the passed in uuid. Finding an exising account lock for the uuid returns 046 * success without having to relock After setting an accountlock, if any funding locks are found, it releases the accountlock 047 * and sets BCLockStatus with LockStatus.FLOCK_FOUND. Accountlocks and Fundinglocks are mutex 048 * 049 * @param bcHeader 050 * @param principalId 051 * @return BudgetConstructionLockStatus with lockStatus.SUCCESS, OPTIMISTIC_EX (lost optimistic lock), FLOCK_FOUND (also sets 052 * fundingLocks), BY_OTHER (also sets accountLockOwner), NO_DOOR (null bcHeader) 053 */ 054 public BudgetConstructionLockStatus lockAccount(BudgetConstructionHeader bcHeader, String principalId); 055 056 /** 057 * This method checks the database for an accountlock. It assumes a valid bcHeader parameter 058 * 059 * @param bcHeader 060 * @return Returns true if locked, false if not locked or not found in the database 061 */ 062 public boolean isAccountLocked(BudgetConstructionHeader bcHeader); 063 064 /** 065 * This method checks the database for an accountlock according to the given appointment funding. It assumes a valid 066 * appointmentFunding parameter 067 * 068 * @param appointmentFunding the given appointment funding 069 * @return Returns true if locked, false if not locked or not found in the database 070 */ 071 public boolean isAccountLocked(PendingBudgetConstructionAppointmentFunding appointmentFunding); 072 073 /** 074 * Checks the given user has an account lock for the given document. 075 * 076 * @param chartOfAccountsCode - chart code of account lock 077 * @param accountNumber - account number of account lock 078 * @param subAccountNumber - sub account number of account lock 079 * @param fiscalYear - fiscal year of account lock 080 * @param principalId - lock user id 081 * @return true if locked, false if not locked or not found in the database 082 */ 083 public boolean isAccountLockedByUser(String chartOfAccountsCode, String accountNumber, String subAccountNumber, Integer fiscalYear, String principalId); 084 085 /** 086 * This method attempts to unlock the given BudgetConstructionHeader. 087 * 088 * @param bcHeader 089 * @return LockStatus.SUCCESS, NO_DOOR (not found), OPTIMISTIC_EX (lost optimistic lock) 090 */ 091 public LockStatus unlockAccount(BudgetConstructionHeader bcHeader); 092 093 /** 094 * This returns the set of BCFundingLocks associated with a BCHeader. The set is sorted by the Person name 095 * 096 * @param bcHeader 097 * @return SortedSet<BudgetConstructionFundingLock> 098 */ 099 public SortedSet<BudgetConstructionFundingLock> getFundingLocks(BudgetConstructionHeader bcHeader); 100 101 /** 102 * This method sets a funding lock associated to the header. It tests for an accountlock before/after to ensure there is no 103 * locking conflict. Finding an accountlock after setting a fundinglock causes the fundinglock to be released. account locks and 104 * funding locks are mutex. Finding a funding lock for the passed in uuid returns success without having to relock 105 * 106 * @param bcHeader 107 * @param principalId 108 * @return BudgetConstructionLockStatus with lockStatus.SUCCESS, BY_OTHER (accountlock found) 109 */ 110 public BudgetConstructionLockStatus lockFunding(BudgetConstructionHeader bcHeader, String principalId); 111 112 /** 113 * acquire a lock for the given appointment funding 114 * 115 * @param appointmentFunding the given appointment funding 116 * @param person the specified user 117 * @return BudgetConstructionLockStatus with lockStatus.SUCCESS, BY_OTHER (accountlock found) 118 */ 119 public BudgetConstructionLockStatus lockFunding(PendingBudgetConstructionAppointmentFunding appointmentFunding, Person person); 120 121 /** 122 * This removes the fundinglock for the account and user 123 * 124 * @param chartOfAccountsCode 125 * @param accountNumber 126 * @param subAccountNumber 127 * @param fiscalYear 128 * @param principalId 129 * @return LockStatus.SUCCESS, NO_DOOR (no fundinglock found) 130 */ 131 public LockStatus unlockFunding(String chartOfAccountsCode, String accountNumber, String subAccountNumber, Integer fiscalYear, String principalId); 132 133 /** 134 * release the lock for the given appointment funding if any 135 * 136 * @param appointmentFunding the given appointment funding that could have lock 137 * @param person the user who owns the lock on the given appointment funding 138 */ 139 public LockStatus unlockFunding(PendingBudgetConstructionAppointmentFunding appointmentFunding, Person person); 140 141 /** 142 * release the locks for the given appointment fundings if any 143 * 144 * @param lockedFundings the given appointment fundings that could have locks 145 * @param person the user who owns the locks on the given appointment fundings 146 */ 147 public void unlockFunding(List<PendingBudgetConstructionAppointmentFunding> lockedFundings, Person person); 148 149 /** 150 * Checks if the given user has a funding lock for the given accounting key. 151 * 152 * @param chartOfAccountsCode - chart code of funding lock 153 * @param accountNumber - account number of funding lock 154 * @param subAccountNumber - sub account number of funding lock 155 * @param fiscalYear - fiscal year of funding lock 156 * @param principalId - lock user id 157 * @return true if locked, false if not locked or not found in the database 158 */ 159 public boolean isFundingLockedByUser(String chartOfAccountsCode, String accountNumber, String subAccountNumber, Integer fiscalYear, String principalId); 160 161 /** 162 * This locks the position, meaning it sets the position lock id field with the puid. Finding the position already locked by the 163 * same user simply returns success. 164 * 165 * @param positionNumber 166 * @param fiscalYear 167 * @param principalId 168 * @return BudgetConstructionLockStatus with lockStatus.SUCCESS, OPTIMISTIC_EX (lost optimistic lock), BY_OTHER (also sets 169 * positionLockOwner), NO_DOOR (BudgetConstructionPosition found) 170 */ 171 public BudgetConstructionLockStatus lockPosition(String positionNumber, Integer fiscalYear, String principalId); 172 173 /** 174 * acquire a lock for the given budget position 175 * 176 * @param position the given position 177 * @param person the specified user 178 * @return BudgetConstructionLockStatus with lockStatus.SUCCESS, OPTIMISTIC_EX (lost optimistic lock), BY_OTHER (also sets 179 * positionLockOwner), NO_DOOR (BudgetConstructionPosition found) 180 */ 181 public BudgetConstructionLockStatus lockPosition(BudgetConstructionPosition position, Person person); 182 183 /** 184 * This checks the database for an existing positionlock 185 * 186 * @param positionNumber 187 * @param fiscalYear 188 * @return true or false (not locked or BudgetConstructionPosition not found) 189 */ 190 public boolean isPositionLocked(String positionNumber, Integer fiscalYear); 191 192 /** 193 * Checks the given user has an position lock for the given position number. 194 * 195 * @param positionNumber - position number of position record 196 * @param fiscalYear - fiscal year of position record 197 * @param principalId - lock user id 198 * @return true if locked, false if not locked or not found in the database 199 */ 200 public boolean isPositionLockedByUser(String positionNumber, Integer fiscalYear, String principalId); 201 202 /** 203 * Checks the given user has an position/funding lock for the given position number and accounting key. 204 * 205 * @param positionNumber - position number of position record 206 * @param chartOfAccountsCode - chart code of funding lock 207 * @param accountNumber - account number of funding lock 208 * @param subAccountNumber - sub account number of funding lock 209 * @param fiscalYear - fiscal year of position and funding record 210 * @param principalId - lock user id 211 * @return true if locked, false if not locked or not found in the database 212 */ 213 public boolean isPositionFundingLockedByUser(String positionNumber, String chartOfAccountsCode, String accountNumber, String subAccountNumber, Integer fiscalYear, String principalId); 214 215 /** 216 * This removes an existing positionlock 217 * 218 * @param positionNumber 219 * @param fiscalYear 220 * @return LockStatus.SUCCESS (success or already unlocked), OPTIMISTIC_EX (lost optimistic lock - unlikely), NO_DOOR 221 * (BudgetConstructionPosition not found) 222 */ 223 public LockStatus unlockPosition(String positionNumber, Integer fiscalYear); 224 225 /** 226 * release the locks on a positions with the given information 227 * 228 * @param positionNumber the given position number of a position 229 * @param fiscalYear the given fiscal year of a position 230 * @param person the specified user who owns the locks on the position 231 * @return LockStatus.SUCCESS (success or already unlocked), OPTIMISTIC_EX (lost optimistic lock - unlikely), NO_DOOR 232 * (BudgetConstructionPosition not found) 233 */ 234 public LockStatus unlockPosition(String positionNumber, Integer fiscalYear, String principalId); 235 236 /** 237 * release the lock for the given position if any 238 * 239 * @param position the given budget construction position that could have locks 240 * @param person the specified user who owns the lock on the given position 241 */ 242 public LockStatus unlockPostion(BudgetConstructionPosition position, Person person); 243 244 /** 245 * release the locks for the given positions if any 246 * 247 * @param lockedPositions the given budget construction positions that could have locks 248 * @param person the specified user who owns the locks on the given positions 249 */ 250 public void unlockPostion(List<BudgetConstructionPosition> lockedPositions, Person person); 251 252 /** 253 * This attempts a transactionlock on a BC Edoc for a pUId. It retries based on the setting of 254 * BCConstants.maxLockRetry. 255 * 256 * @param chartOfAccountsCode 257 * @param accountNumber 258 * @param subAccountNumber 259 * @param fiscalYear 260 * @param principalId 261 * @return BudgetConstructionLockStatus with lockStatus.SUCCESS, OPTIMISTIC_EX (lost optimistic lock - unlikely) BY_OTHER 262 * (retries exhausted, also sets transactionLockOwner), NO_DOOR (BudgetConstructionHeader not found) 263 */ 264 public BudgetConstructionLockStatus lockTransaction(String chartOfAccountsCode, String accountNumber, String subAccountNumber, Integer fiscalYear, String principalId); 265 266 /** 267 * attemps to have a transaction lock based on the information provided by the given funding line 268 * 269 * @param appointmentFunding the given appointment funding 270 * @param person the specified user 271 */ 272 public BudgetConstructionLockStatus lockTransaction(PendingBudgetConstructionAppointmentFunding appointmentFunding, Person person); 273 274 /** 275 * This checks the database for an existing transactionlock for the BC EDoc (account). 276 * 277 * @param chartOfAccountsCode 278 * @param accountNumber 279 * @param subAccountNumber 280 * @param fiscalYear 281 * @return true or false (not locked or BudgetConstructionHeader not found) 282 */ 283 public boolean isTransactionLocked(String chartOfAccountsCode, String accountNumber, String subAccountNumber, Integer fiscalYear); 284 285 /** 286 * Checks the given user has an transaction lock for the given document. 287 * 288 * @param chartOfAccountsCode - chart code of transaction lock 289 * @param accountNumber - account number of transaction lock 290 * @param subAccountNumber - sub account number of transaction lock 291 * @param fiscalYear - fiscal year of transaction lock 292 * @param principalId - lock user id 293 * @return true if locked, false if not locked or not found in the database 294 */ 295 public boolean isTransactionLockedByUser(String chartOfAccountsCode, String accountNumber, String subAccountNumber, Integer fiscalYear, String principalId); 296 297 /** 298 * This removes an existing transactionlock for a BC EDoc (account). 299 * 300 * @param chartOfAccountsCode 301 * @param accountNumber 302 * @param subAccountNumber 303 * @param fiscalYear 304 * @return LockStatus.SUCCESS (success or already unlocked), OPTIMISTIC_EX (lost optimistic lock - unlikely), NO_DOOR 305 * (BudgetConstructionHeader not found) 306 */ 307 public LockStatus unlockTransaction(String chartOfAccountsCode, String accountNumber, String subAccountNumber, Integer fiscalYear); 308 309 /** 310 * attemps to unlock a transaction based on the information provided by the given funding line 311 * 312 * @param appointmentFunding the given appointment funding 313 * @param person the specified user 314 */ 315 public void unlockTransaction(PendingBudgetConstructionAppointmentFunding appointmentFunding, Person person); 316 317 /** 318 * Retrieves all current account locks for the given user (or all locks if user is null/empty). 319 * 320 * @param lockUnivId - universal id that will be used in lock query 321 * @return budget headers that are locked 322 */ 323 public List<BudgetConstructionHeader> getAllAccountLocks(String lockUnivId); 324 325 /** 326 * Retrieves all current transaction locks for the given user (or all locks if user is null/empty). 327 * 328 * @param lockUnivId - universal id that will be used in lock query 329 * @return budget headers that are locked 330 */ 331 public List<BudgetConstructionHeader> getAllTransactionLocks(String lockUnivId); 332 333 /** 334 * Retrieves all funding locks that do not have a corresponding position lock for the given user (or all locks if user is 335 * null/empty). 336 * 337 * @param lockUnivId - universal id that will be used in lock query 338 * @return funding locks records 339 */ 340 public List<BudgetConstructionFundingLock> getOrphanedFundingLocks(String lockUnivId); 341 342 /** 343 * Retrieves all current position/funding locks for the given user (or all locks if user is null/empty). 344 * 345 * @param lockUnivId - universal id that will be used in lock query 346 * @return position/funding records that are locked. 347 */ 348 public List<PendingBudgetConstructionAppointmentFunding> getAllPositionFundingLocks(String lockUnivId); 349 350 /** 351 * Retrieves all current position locks without a funding lock for the given user (or all locks if user is null/empty). 352 * 353 * @param lockUnivId universal id that will be used in lock query 354 * @return positions that are locked. 355 */ 356 public List<BudgetConstructionPosition> getOrphanedPositionLocks(String lockUnivId); 357 358 /** 359 * Helper method to check if a lock exists for the given parameters. 360 * 361 * @param lockSummary - contains information about the record to unlock 362 * @return boolean true if lock exists, false otherwise 363 */ 364 public boolean checkLockExists(BudgetConstructionLockSummary lockSummary); 365 366 /** 367 * Helper method to check the lock type and do the unlock with the lock summary fields. 368 * 369 * @param lockSummary - contains information about the record to unlock 370 * @return LockStatus.SUCCESS, NO_DOOR (not found), OPTIMISTIC_EX (lost optimistic lock) 371 */ 372 public LockStatus doUnlock(BudgetConstructionLockSummary lockSummary); 373 374 /** 375 * determine whether the account lock on the given budget document is held by the the specified user 376 * 377 * @param budgetConstructionHeader the given budget document 378 * @param person the specified user 379 * @return true if the account lock on the given budget document is held by the the specified user; otherwise, false 380 */ 381 public boolean isAccountLockedByUser(BudgetConstructionHeader budgetConstructionHeader, Person person); 382 383 /** 384 * Retrieves account locks for funding records, for use in the payrate import process. Throws 385 * BudgetConstructionLockUnavailableException if new account lock is unavailable 386 * 387 * @param fundingRecords 388 * @param user 389 * @return 390 * @throws BudgetConstructionLockUnavailableException 391 */ 392 public List<PendingBudgetConstructionAppointmentFunding> lockPendingBudgetConstructionAppointmentFundingRecords(List<PendingBudgetConstructionAppointmentFunding> fundingRecords, Person user) throws BudgetConstructionLockUnavailableException; 393 394 /** 395 * Retrives an account lock (@see 396 * org.kuali.kfs.module.bc.document.service.LockService#lockAccount(org.kuali.kfs.module.bc.businessobject.BudgetConstructionHeader, 397 * java.lang.String) and commits the lock. Used by the request import process. 398 * 399 * @param bcHeader 400 * @param principalId 401 * @return 402 */ 403 public BudgetConstructionLockStatus lockAccountAndCommit(BudgetConstructionHeader bcHeader, String principalId); 404 405 /** 406 * Locks the position record for the given key if not already locked. Then retrieves all active funding lines for the position 407 * that are not marked as delete and attempts to lock each one. 408 * 409 * @param universityFiscalYear budget fiscal year, primary key field for position record 410 * @param positionNumber position number, primary key field for position record 411 * @param principalId current user requesting the lock 412 * @return <code>BudgetConstructionLockStatus</code> indicating the status of the lock attempt. Success is returned if all lock attempts were successful, else one of the Failure status codes are returned 413 */ 414 public BudgetConstructionLockStatus lockPositionAndActiveFunding(Integer universityFiscalYear, String positionNumber, String principalId); 415 416 /** 417 * Unlocks the position and all associated funding lines not marked as delete. 418 * 419 * @param universityFiscalYear budget fiscal year, primary key field for position record 420 * @param positionNumber position number, primary key field for position record 421 * @param principalId current user requesting the unlock 422 * @return <code>LockStatus</code> indicating the status of the unlock attempt. 423 */ 424 public LockStatus unlockPositionAndActiveFunding(Integer universityFiscalYear, String positionNumber, String principalId); 425 }