001/*
002 * Copyright 2007 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 */
016package org.kuali.ole.coa.businessobject;
017
018import java.sql.Date;
019import java.util.ArrayList;
020import java.util.Collection;
021import java.util.HashMap;
022import java.util.Iterator;
023import java.util.LinkedHashMap;
024import java.util.List;
025import java.util.Map;
026
027import org.apache.commons.lang.StringUtils;
028import org.kuali.ole.sys.OLEPropertyConstants;
029import org.kuali.ole.sys.context.SpringContext;
030import org.kuali.rice.core.api.util.type.KualiDecimal;
031import org.kuali.rice.krad.bo.GlobalBusinessObject;
032import org.kuali.rice.krad.bo.GlobalBusinessObjectDetail;
033import org.kuali.rice.krad.bo.PersistableBusinessObject;
034import org.kuali.rice.krad.bo.PersistableBusinessObjectBase;
035import org.kuali.rice.krad.service.BusinessObjectService;
036import org.kuali.rice.krad.service.PersistenceStructureService;
037
038/**
039 * This class simply acts as a container to hold the List of Delegate Changes and the list of Account entries, for the Global
040 * Delegate Change Document.
041 */
042public class AccountDelegateGlobal extends PersistableBusinessObjectBase implements GlobalBusinessObject {
043
044    protected String documentNumber;
045
046    protected String modelName;
047    protected String modelChartOfAccountsCode;
048    protected String modelOrganizationCode;
049
050    protected AccountDelegateModel model;
051
052    protected List<AccountGlobalDetail> accountGlobalDetails;
053    protected List<AccountDelegateGlobalDetail> delegateGlobals;
054
055    /**
056     * Constructs a DelegateGlobal.java.
057     */
058    public AccountDelegateGlobal() {
059        super();
060        accountGlobalDetails = new ArrayList<AccountGlobalDetail>();
061        delegateGlobals = new ArrayList<AccountDelegateGlobalDetail>();
062    }
063
064    /**
065     * This method adds a single AccountGlobalDetail instance to the list. If one is already present in the list with the same
066     * chartCode and accountNumber, then this new one will not be added.
067     * 
068     * @param accountGlobalDetail - populated AccountGlobalDetail instance
069     */
070    public void addAccount(AccountGlobalDetail accountGlobalDetail) {
071
072        // validate the argument
073        if (accountGlobalDetail == null) {
074            throw new IllegalArgumentException("The accountGlobalDetail instanced passed in was null.");
075        }
076        else if (StringUtils.isBlank(accountGlobalDetail.getChartOfAccountsCode())) {
077            throw new IllegalArgumentException("The chartOfAccountsCode member of the accountGlobalDetail object was not populated.");
078        }
079        else if (StringUtils.isBlank(accountGlobalDetail.getAccountNumber())) {
080            throw new IllegalArgumentException("The accountNumber member of the accountGlobalDetail object was not populated.");
081        }
082
083        // add the object if one doesnt already exist, otherwise silently do nothing
084        AccountGlobalDetail testObject = getAccount(accountGlobalDetail.getChartOfAccountsCode(), accountGlobalDetail.getAccountNumber());
085        if (testObject == null) {
086            this.accountGlobalDetails.add(accountGlobalDetail);
087        }
088    }
089
090    /**
091     * This method retrieves the specific AccountGlobalDetail object that corresponds to your requested chartCode and accountNumber
092     * (or a null object if there is no match).
093     * 
094     * @param chartCode
095     * @param accountNumber
096     * @return returns the AccountGlobalDetail instance matching the chartCode & accountNumber passed in, or Null if none match
097     */
098    public AccountGlobalDetail getAccount(String chartCode, String accountNumber) {
099
100        // validate the argument
101        if (StringUtils.isBlank(chartCode)) {
102            throw new IllegalArgumentException("The chartCode argument was null or empty.");
103        }
104        else if (StringUtils.isBlank(accountNumber)) {
105            throw new IllegalArgumentException("The accountNumber argument was null or empty.");
106        }
107
108        // walk the list of AccountGlobalDetail objects
109        for (Iterator iter = this.accountGlobalDetails.iterator(); iter.hasNext();) {
110            AccountGlobalDetail accountGlobalDetail = (AccountGlobalDetail) iter.next();
111
112            // if this one is a match, then quit
113            if (chartCode.equalsIgnoreCase(accountGlobalDetail.getChartOfAccountsCode()) && accountNumber.equalsIgnoreCase(accountGlobalDetail.getAccountNumber())) {
114                return accountGlobalDetail;
115            }
116        }
117
118        // we return null if one is not found
119        return null;
120    }
121
122    /**
123     * @see org.kuali.rice.krad.document.GlobalBusinessObject#getGlobalChangesToDelete()
124     */
125    public List<PersistableBusinessObject> generateDeactivationsToPersist() {
126        BusinessObjectService boService = SpringContext.getBean(BusinessObjectService.class);
127
128        // retreive all the existing delegates for these accounts
129        List<AccountDelegate> bosToDeactivate = new ArrayList();
130        Map<String, Object> fieldValues;
131        Collection existingDelegates;
132        for (AccountGlobalDetail accountDetail : getAccountGlobalDetails()) {
133            fieldValues = new HashMap();
134            fieldValues.put("chartOfAccountsCode", accountDetail.getChartOfAccountsCode());
135            fieldValues.put("accountNumber", accountDetail.getAccountNumber());
136            fieldValues.put("active", true);
137            existingDelegates = boService.findMatching(AccountDelegate.class, fieldValues);
138            bosToDeactivate.addAll(existingDelegates);
139        }
140
141        // mark all the delegates as inactive
142        for (AccountDelegate accountDelegate : bosToDeactivate) {
143            accountDelegate.setActive(false);
144        }
145        return new ArrayList<PersistableBusinessObject>(bosToDeactivate);
146    }
147
148    /**
149     * @see org.kuali.rice.krad.document.GlobalBusinessObject#applyGlobalChanges(org.kuali.rice.krad.bo.BusinessObject)
150     */
151    @SuppressWarnings("deprecation")
152    public List<PersistableBusinessObject> generateGlobalChangesToPersist() {
153
154        BusinessObjectService boService = SpringContext.getBean(BusinessObjectService.class);
155        List<AccountDelegate> persistables = new ArrayList();
156
157        List<AccountDelegateGlobalDetail> changeDocuments = this.getDelegateGlobals();
158        List<AccountGlobalDetail> accountDetails = this.getAccountGlobalDetails();
159
160        for (AccountDelegateGlobalDetail changeDocument : changeDocuments) {
161            for (AccountGlobalDetail accountDetail : accountDetails) {
162
163                Account account = (Account) boService.findByPrimaryKey(Account.class, accountDetail.getPrimaryKeys());
164
165                // if the account doesnt exist, fail fast, as this should never happen,
166                // the busines rules for this document should have caught this.
167                if (account == null) {
168                    throw new RuntimeException("Account [" + accountDetail.getChartOfAccountsCode() + "-" + accountDetail.getAccountNumber() + "] was not present in the database. " + "This should never happen under normal circumstances, as an invalid account should have " + "been caught by the Business Rules infrastructure.");
169                }
170
171                // attempt to load the existing Delegate from the DB, if it exists. we do this to avoid
172                // versionNumber conflicts if we tried to just insert a new record that already existed.
173                Map pkMap = new HashMap();
174                pkMap.putAll(accountDetail.getPrimaryKeys()); // chartOfAccountsCode & accountNumber
175                pkMap.put("financialDocumentTypeCode", changeDocument.getFinancialDocumentTypeCode());
176                pkMap.put("accountDelegateSystemId", changeDocument.getAccountDelegateUniversalId());
177                AccountDelegate delegate = (AccountDelegate) boService.findByPrimaryKey(AccountDelegate.class, pkMap);
178
179                // if there is no existing Delegate with these primary keys, then we're creating a new one,
180                // so lets populate it with the primary keys
181                if (delegate == null) {
182                    delegate = new AccountDelegate();
183                    delegate.setChartOfAccountsCode(accountDetail.getChartOfAccountsCode());
184                    delegate.setAccountNumber(accountDetail.getAccountNumber());
185                    delegate.setAccountDelegateSystemId(changeDocument.getAccountDelegateUniversalId());
186                    delegate.setFinancialDocumentTypeCode(changeDocument.getFinancialDocumentTypeCode());
187                    delegate.setActive(true);
188                }
189                else {
190                    delegate.setActive(true);
191                }
192
193                // APPROVAL FROM AMOUNT
194                if (changeDocument.getApprovalFromThisAmount() != null) {
195                    if (!changeDocument.getApprovalFromThisAmount().equals(KualiDecimal.ZERO)) {
196                        delegate.setFinDocApprovalFromThisAmt(changeDocument.getApprovalFromThisAmount());
197                    }
198                }
199
200                // APPROVAL TO AMOUNT
201                if (changeDocument.getApprovalToThisAmount() != null) {
202                    if (!changeDocument.getApprovalToThisAmount().equals(KualiDecimal.ZERO)) {
203                        delegate.setFinDocApprovalToThisAmount(changeDocument.getApprovalToThisAmount());
204                    }
205                }
206
207                // PRIMARY ROUTING
208                delegate.setAccountsDelegatePrmrtIndicator(changeDocument.getAccountDelegatePrimaryRoutingIndicator());
209
210                // START DATE
211                if (changeDocument.getAccountDelegateStartDate() != null) {
212                    delegate.setAccountDelegateStartDate(new Date(changeDocument.getAccountDelegateStartDate().getTime()));
213                }
214
215                persistables.add(delegate);
216
217            }
218        }
219
220        return new ArrayList<PersistableBusinessObject>(persistables);
221    }
222
223    /**
224     * @see org.kuali.rice.krad.bo.BusinessObjectBase#toStringMapper()
225     */
226    
227    protected LinkedHashMap toStringMapper_RICE20_REFACTORME() {
228
229        LinkedHashMap m = new LinkedHashMap();
230
231        m.put(OLEPropertyConstants.DOCUMENT_NUMBER, this.documentNumber);
232        return m;
233    }
234
235    /**
236     * @see org.kuali.rice.krad.document.GlobalBusinessObject#getDocumentNumber()
237     */
238    public String getDocumentNumber() {
239        return documentNumber;
240    }
241
242    /**
243     * @see org.kuali.rice.krad.document.GlobalBusinessObject#setDocumentNumber(java.lang.String)
244     */
245    public void setDocumentNumber(String documentNumber) {
246        this.documentNumber = documentNumber;
247
248    }
249
250    /**
251     * Gets the accountGlobalDetails attribute.
252     * 
253     * @return Returns the accountGlobalDetails.
254     */
255    public final List<AccountGlobalDetail> getAccountGlobalDetails() {
256        return accountGlobalDetails;
257    }
258
259    /**
260     * Sets the accountGlobalDetails attribute value.
261     * 
262     * @param accountGlobalDetails The accountGlobalDetails to set.
263     */
264    public final void setAccountGlobalDetails(List<AccountGlobalDetail> accountGlobalDetails) {
265        this.accountGlobalDetails = accountGlobalDetails;
266    }
267
268    /**
269     * Gets the delegateGlobals attribute.
270     * 
271     * @return Returns the delegateGlobals.
272     */
273    public final List<AccountDelegateGlobalDetail> getDelegateGlobals() {
274        return delegateGlobals;
275    }
276
277    /**
278     * Sets the delegateGlobals attribute value.
279     * 
280     * @param delegateGlobals The delegateGlobals to set.
281     */
282    public final void setDelegateGlobals(List<AccountDelegateGlobalDetail> delegateGlobals) {
283        this.delegateGlobals = delegateGlobals;
284    }
285
286    /**
287     * @see org.kuali.rice.krad.document.GlobalBusinessObject#isPersistable()
288     */
289    public boolean isPersistable() {
290        PersistenceStructureService persistenceStructureService = SpringContext.getBean(PersistenceStructureService.class);
291
292        // fail if the PK for this object is emtpy
293        if (StringUtils.isBlank(documentNumber)) {
294            return false;
295        }
296
297        // fail if the PKs for any of the contained objects are empty
298        for (AccountDelegateGlobalDetail delegateGlobals : getDelegateGlobals()) {
299            if (!persistenceStructureService.hasPrimaryKeyFieldValues(delegateGlobals)) {
300                return false;
301            }
302        }
303        for (AccountGlobalDetail account : getAccountGlobalDetails()) {
304            if (!persistenceStructureService.hasPrimaryKeyFieldValues(account)) {
305                return false;
306            }
307        }
308
309        // otherwise, its all good
310        return true;
311    }
312
313    public String getModelName() {
314        return modelName;
315    }
316
317    public void setModelName(String loadModelName) {
318        this.modelName = loadModelName;
319    }
320
321    public String getModelChartOfAccountsCode() {
322        return modelChartOfAccountsCode;
323    }
324
325    public void setModelChartOfAccountsCode(String loadModelChartOfAccountsCode) {
326        this.modelChartOfAccountsCode = loadModelChartOfAccountsCode;
327    }
328
329    public String getModelOrganizationCode() {
330        return modelOrganizationCode;
331    }
332
333    public void setModelOrganizationCode(String loadModelOrganizationCode) {
334        this.modelOrganizationCode = loadModelOrganizationCode;
335    }
336
337    public AccountDelegateModel getModel() {
338        return model;
339    }
340
341    public void setModel(AccountDelegateModel loadModel) {
342        this.model = loadModel;
343    }
344
345    public List<? extends GlobalBusinessObjectDetail> getAllDetailObjects() {
346        ArrayList<GlobalBusinessObjectDetail> details = new ArrayList<GlobalBusinessObjectDetail>(accountGlobalDetails.size() + delegateGlobals.size());
347        details.addAll(accountGlobalDetails);
348        details.addAll(delegateGlobals);
349        return details;
350    }
351
352    @Override
353    public void linkEditableUserFields() {
354        super.linkEditableUserFields();
355        if (this == null) {
356            throw new IllegalArgumentException("globalDelegate parameter passed in was null");
357        }
358        List<PersistableBusinessObject> bos = new ArrayList<PersistableBusinessObject>();
359        bos.addAll(getDelegateGlobals());
360        SpringContext.getBean(BusinessObjectService.class).linkUserFields(bos);
361    }
362
363    /**
364     * @see org.kuali.rice.krad.bo.PersistableBusinessObjectBase#buildListOfDeletionAwareLists()
365     */
366    @Override
367    public List<Collection<PersistableBusinessObject>> buildListOfDeletionAwareLists() {
368        List<Collection<PersistableBusinessObject>> managedLists = super.buildListOfDeletionAwareLists();
369
370        managedLists.add( new ArrayList<PersistableBusinessObject>( getAccountGlobalDetails() ) );
371        managedLists.add( new ArrayList<PersistableBusinessObject>( getDelegateGlobals() ) );
372
373        return managedLists;
374    }
375}