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.cab.document.service.impl;
017    
018    import java.util.HashMap;
019    import java.util.List;
020    import java.util.Map;
021    
022    import org.kuali.kfs.fp.businessobject.CapitalAssetInformation;
023    import org.kuali.kfs.fp.businessobject.CapitalAssetInformationDetail;
024    import org.kuali.kfs.module.cab.CabConstants;
025    import org.kuali.kfs.module.cab.CabPropertyConstants;
026    import org.kuali.kfs.module.cab.businessobject.GeneralLedgerEntry;
027    import org.kuali.kfs.module.cab.businessobject.GeneralLedgerEntryAsset;
028    import org.kuali.kfs.module.cab.document.service.GlLineService;
029    import org.kuali.kfs.module.cam.CamsConstants;
030    import org.kuali.kfs.module.cam.CamsPropertyConstants;
031    import org.kuali.kfs.module.cam.CamsConstants.DocumentTypeName;
032    import org.kuali.kfs.module.cam.businessobject.Asset;
033    import org.kuali.kfs.module.cam.businessobject.AssetGlobal;
034    import org.kuali.kfs.module.cam.businessobject.AssetGlobalDetail;
035    import org.kuali.kfs.module.cam.businessobject.AssetPaymentAssetDetail;
036    import org.kuali.kfs.module.cam.businessobject.AssetPaymentDetail;
037    import org.kuali.kfs.module.cam.businessobject.defaultvalue.NextAssetNumberFinder;
038    import org.kuali.kfs.module.cam.document.AssetPaymentDocument;
039    import org.kuali.kfs.module.cam.document.service.AssetGlobalService;
040    import org.kuali.kfs.module.cam.util.ObjectValueUtils;
041    import org.kuali.kfs.sys.KFSConstants;
042    import org.kuali.kfs.sys.context.SpringContext;
043    import org.kuali.rice.kew.exception.WorkflowException;
044    import org.kuali.rice.kns.bo.PersistableBusinessObject;
045    import org.kuali.rice.kns.document.Document;
046    import org.kuali.rice.kns.document.MaintenanceDocument;
047    import org.kuali.rice.kns.service.BusinessObjectService;
048    import org.kuali.rice.kns.service.DocumentService;
049    import org.kuali.rice.kns.util.KNSConstants;
050    import org.kuali.rice.kns.util.KualiDecimal;
051    import org.kuali.rice.kns.util.ObjectUtils;
052    
053    public class GlLineServiceImpl implements GlLineService {
054        private static final String CAB_DESC_PREFIX = "CAB created for FP ";
055        protected BusinessObjectService businessObjectService;
056        protected AssetGlobalService assetGlobalService;
057    
058    
059        /**
060         * @see org.kuali.kfs.module.cab.document.service.GlLineService#createAssetGlobalDocument(java.util.List,
061         *      org.kuali.kfs.module.cab.businessobject.GeneralLedgerEntry)
062         */
063        public Document createAssetGlobalDocument(List<GeneralLedgerEntry> entries, GeneralLedgerEntry primary) throws WorkflowException {
064            // initiate a new document
065            DocumentService documentService = SpringContext.getBean(DocumentService.class);
066            MaintenanceDocument document = (MaintenanceDocument) documentService.getNewDocument(DocumentTypeName.ASSET_ADD_GLOBAL);
067            // create asset global
068            AssetGlobal assetGlobal = createAssetGlobal(primary, document);
069            assetGlobal.setCapitalAssetBuilderOriginIndicator(true);
070            assetGlobal.setAcquisitionTypeCode(getAssetGlobalService().getNewAcquisitionTypeCode());
071            updatePreTagInformation(primary, document, assetGlobal);
072            int seq = 0;
073            for (GeneralLedgerEntry generalLedgerEntry : entries) {
074                assetGlobal.getAssetPaymentDetails().add(createAssetPaymentDetail(generalLedgerEntry, document, ++seq));
075            }
076            // save the document
077            document.getNewMaintainableObject().setMaintenanceAction(KNSConstants.MAINTENANCE_NEW_ACTION);
078            document.getDocumentHeader().setDocumentDescription(CAB_DESC_PREFIX + primary.getDocumentNumber());
079            document.getNewMaintainableObject().setBusinessObject(assetGlobal);
080            document.getNewMaintainableObject().setBoClass(assetGlobal.getClass());
081            documentService.saveDocument(document);
082            deactivateGLEntries(entries, document);
083            return document;
084        }
085    
086        /**
087         * De-activate the GL Entries
088         * 
089         * @param entries GL Entries
090         * @param document Document
091         */
092        protected void deactivateGLEntries(List<GeneralLedgerEntry> entries, Document document) {
093            for (GeneralLedgerEntry generalLedgerEntry : entries) {
094                generalLedgerEntry.setTransactionLedgerSubmitAmount(generalLedgerEntry.getTransactionLedgerEntryAmount());
095                generalLedgerEntry.setActivityStatusCode(CabConstants.ActivityStatusCode.ENROUTE);
096                createGeneralLedgerEntryAsset(generalLedgerEntry, document);
097                getBusinessObjectService().save(generalLedgerEntry);
098            }
099        }
100    
101        /**
102         * This method reads the pre-tag information and creates objects for asset global document
103         * 
104         * @param entry GL Line
105         * @param document Asset Global Maintenance Document
106         * @param assetGlobal Asset Global Object
107         */
108        protected void updatePreTagInformation(GeneralLedgerEntry entry, MaintenanceDocument document, AssetGlobal assetGlobal) {
109            CapitalAssetInformation assetInformation = findCapitalAssetInformation(entry);
110            if (ObjectUtils.isNotNull(assetInformation) && assetInformation.getCapitalAssetNumber() == null) {
111                List<CapitalAssetInformationDetail> capitalAssetInformationDetails = assetInformation.getCapitalAssetInformationDetails();
112                for (CapitalAssetInformationDetail capitalAssetInformationDetail : capitalAssetInformationDetails) {
113                    // This is not added to constructor in CAMS to provide module isolation from CAMS
114                    AssetGlobalDetail assetGlobalDetail = new AssetGlobalDetail();
115                    assetGlobalDetail.setDocumentNumber(document.getDocumentNumber());
116                    assetGlobalDetail.setCampusCode(capitalAssetInformationDetail.getCampusCode());
117                    assetGlobalDetail.setBuildingCode(capitalAssetInformationDetail.getBuildingCode());
118                    assetGlobalDetail.setBuildingRoomNumber(capitalAssetInformationDetail.getBuildingRoomNumber());
119                    assetGlobalDetail.setBuildingSubRoomNumber(capitalAssetInformationDetail.getBuildingSubRoomNumber());
120                    assetGlobalDetail.setSerialNumber(capitalAssetInformationDetail.getCapitalAssetSerialNumber());
121                    assetGlobalDetail.setCapitalAssetNumber(NextAssetNumberFinder.getLongValue());
122                    assetGlobalDetail.setCampusTagNumber(capitalAssetInformationDetail.getCapitalAssetTagNumber());
123                    AssetGlobalDetail uniqueAsset = new AssetGlobalDetail();
124                    ObjectValueUtils.copySimpleProperties(assetGlobalDetail, uniqueAsset);
125                    assetGlobalDetail.getAssetGlobalUniqueDetails().add(uniqueAsset);
126                    assetGlobal.getAssetSharedDetails().add(assetGlobalDetail);
127                }
128                assetGlobal.setVendorName(assetInformation.getVendorName());
129                assetGlobal.setInventoryStatusCode(CamsConstants.InventoryStatusCode.CAPITAL_ASSET_ACTIVE_IDENTIFIABLE);
130                assetGlobal.setCapitalAssetTypeCode(assetInformation.getCapitalAssetTypeCode());
131                assetGlobal.setManufacturerName(assetInformation.getCapitalAssetManufacturerName());
132                assetGlobal.setManufacturerModelNumber(assetInformation.getCapitalAssetManufacturerModelNumber());
133                assetGlobal.setCapitalAssetDescription(assetInformation.getCapitalAssetDescription());
134            }
135        }
136    
137        /**
138         * @see org.kuali.kfs.module.cab.document.service.GlLineService#findCapitalAssetInformation(org.kuali.kfs.module.cab.businessobject.GeneralLedgerEntry)
139         */
140        public CapitalAssetInformation findCapitalAssetInformation(GeneralLedgerEntry entry) {
141            Map<String, String> primaryKeys = new HashMap<String, String>();
142            primaryKeys.put(CabPropertyConstants.CapitalAssetInformation.DOCUMENT_NUMBER, entry.getDocumentNumber());
143            CapitalAssetInformation assetInformation = (CapitalAssetInformation) businessObjectService.findByPrimaryKey(CapitalAssetInformation.class, primaryKeys);
144            return assetInformation;
145        }
146    
147        /**
148         * Creates general ledger entry asset
149         * 
150         * @param entry GeneralLedgerEntry
151         * @param maintDoc Document
152         */
153        protected void createGeneralLedgerEntryAsset(GeneralLedgerEntry entry, Document document) {
154            // store the document number
155            GeneralLedgerEntryAsset entryAsset = new GeneralLedgerEntryAsset();
156            entryAsset.setGeneralLedgerAccountIdentifier(entry.getGeneralLedgerAccountIdentifier());
157            entryAsset.setCapitalAssetBuilderLineNumber(1);
158            entryAsset.setCapitalAssetManagementDocumentNumber(document.getDocumentNumber());
159            entry.getGeneralLedgerEntryAssets().add(entryAsset);
160        }
161    
162    
163        /**
164         * Creates asset global
165         * 
166         * @param entry GeneralLedgerEntry
167         * @param maintDoc MaintenanceDocument
168         * @return AssetGlobal
169         */
170        protected AssetGlobal createAssetGlobal(GeneralLedgerEntry entry, MaintenanceDocument maintDoc) {
171            AssetGlobal assetGlobal = new AssetGlobal();
172            assetGlobal.setOrganizationOwnerChartOfAccountsCode(entry.getChartOfAccountsCode());
173            assetGlobal.setOrganizationOwnerAccountNumber(entry.getAccountNumber());
174            assetGlobal.setDocumentNumber(maintDoc.getDocumentNumber());
175            assetGlobal.setConditionCode(CamsConstants.Asset.CONDITION_CODE_E);
176            return assetGlobal;
177        }
178    
179    
180        public Document createAssetPaymentDocument(List<GeneralLedgerEntry> entries, GeneralLedgerEntry primaryGlEntry) throws WorkflowException {
181            // Find out the GL Entry
182            // initiate a new document
183            DocumentService documentService = SpringContext.getBean(DocumentService.class);
184            AssetPaymentDocument document = (AssetPaymentDocument) documentService.getNewDocument(DocumentTypeName.ASSET_PAYMENT);
185            document.setCapitalAssetBuilderOriginIndicator(true);
186            document.getDocumentHeader().setDocumentDescription(CAB_DESC_PREFIX + primaryGlEntry.getDocumentNumber());
187            updatePreTagInformation(primaryGlEntry, document);
188            // Asset Payment Detail
189            int seq = 0;
190            for (GeneralLedgerEntry generalLedgerEntry : entries) {
191                AssetPaymentDetail detail = createAssetPaymentDetail(generalLedgerEntry, document, ++seq);
192                document.getSourceAccountingLines().add(detail);
193            }
194            // Asset payment asset detail
195            // save the document
196            documentService.saveDocument(document);
197            deactivateGLEntries(entries, document);
198            return document;
199        }
200    
201        /**
202         * Updates pre tag information received from FP document
203         * 
204         * @param entry GeneralLedgerEntry
205         * @param document AssetPaymentDocument
206         */
207        protected void updatePreTagInformation(GeneralLedgerEntry entry, AssetPaymentDocument document) {
208            CapitalAssetInformation assetInformation = findCapitalAssetInformation(entry);
209            if (ObjectUtils.isNotNull(assetInformation) && assetInformation.getCapitalAssetNumber() != null) {
210                AssetPaymentAssetDetail assetPaymentAssetDetail = new AssetPaymentAssetDetail();
211                assetPaymentAssetDetail.setDocumentNumber(document.getDocumentNumber());
212                assetPaymentAssetDetail.setCapitalAssetNumber(assetInformation.getCapitalAssetNumber());
213                assetPaymentAssetDetail.refreshReferenceObject(CamsPropertyConstants.AssetPaymentAssetDetail.ASSET);
214                Asset asset = assetPaymentAssetDetail.getAsset();
215                if (ObjectUtils.isNotNull(asset)) {
216                    assetPaymentAssetDetail.setPreviousTotalCostAmount(asset.getTotalCostAmount() != null ? asset.getTotalCostAmount() : KualiDecimal.ZERO);
217                    document.getAssetPaymentAssetDetail().add(assetPaymentAssetDetail);
218                }
219            }
220        }
221    
222        /**
223         * Creates asset payment detail based on GL line. to CAB
224         * 
225         * @param entry GeneralLedgerEntry
226         * @param document Document
227         * @return AssetPaymentDetail
228         */
229        protected AssetPaymentDetail createAssetPaymentDetail(GeneralLedgerEntry entry, Document document, int seqNo) {
230            // This is not added to constructor in CAMS to provide module isolation from CAMS
231            AssetPaymentDetail detail = new AssetPaymentDetail();
232            detail.setDocumentNumber(document.getDocumentNumber());
233            detail.setSequenceNumber(seqNo);
234            detail.setPostingYear(entry.getUniversityFiscalYear());
235            detail.setPostingPeriodCode(entry.getUniversityFiscalPeriodCode());
236            detail.setChartOfAccountsCode(entry.getChartOfAccountsCode());
237            detail.setAccountNumber(replaceFiller(entry.getAccountNumber()));
238            detail.setSubAccountNumber(replaceFiller(entry.getSubAccountNumber()));
239            detail.setFinancialObjectCode(replaceFiller(entry.getFinancialObjectCode()));
240            detail.setProjectCode(replaceFiller(entry.getProjectCode()));
241            detail.setOrganizationReferenceId(replaceFiller(entry.getOrganizationReferenceId()));
242            detail.setAmount(KFSConstants.GL_CREDIT_CODE.equals(entry.getTransactionDebitCreditCode()) ? entry.getTransactionLedgerEntryAmount().negated() : entry.getTransactionLedgerEntryAmount());
243            detail.setExpenditureFinancialSystemOriginationCode(replaceFiller(entry.getFinancialSystemOriginationCode()));
244            detail.setExpenditureFinancialDocumentNumber(entry.getDocumentNumber());
245            detail.setExpenditureFinancialDocumentTypeCode(replaceFiller(entry.getFinancialDocumentTypeCode()));
246            detail.setExpenditureFinancialDocumentPostedDate(entry.getTransactionDate());
247            detail.setPurchaseOrderNumber(replaceFiller(entry.getReferenceFinancialDocumentNumber()));
248            detail.setTransferPaymentIndicator(false);
249            return detail;
250        }
251    
252        /**
253         * If the value contains only the filler characters, then return blank
254         * 
255         * @param val Value
256         * @return blank if value if a filler
257         */
258        protected String replaceFiller(String val) {
259            if (val == null) {
260                return "";
261            }
262            char[] charArray = val.trim().toCharArray();
263            for (char c : charArray) {
264                if (c != '-') {
265                    return val;
266                }
267            }
268            return "";
269        }
270    
271        /**
272         * Gets the businessObjectService attribute.
273         * 
274         * @return Returns the businessObjectService.
275         */
276        public BusinessObjectService getBusinessObjectService() {
277            return businessObjectService;
278        }
279    
280        /**
281         * Sets the businessObjectService attribute value.
282         * 
283         * @param businessObjectService The businessObjectService to set.
284         */
285        public void setBusinessObjectService(BusinessObjectService businessObjectService) {
286            this.businessObjectService = businessObjectService;
287        }
288        
289        private AssetGlobalService getAssetGlobalService() {
290            return assetGlobalService;
291        }
292    
293        public void setAssetGlobalService(AssetGlobalService assetGlobalService) {
294            this.assetGlobalService = assetGlobalService;
295        }
296        
297    }