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    }