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 }