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.purap.document.service.impl;
017    
018    import java.util.HashMap;
019    import java.util.List;
020    import java.util.Map;
021    
022    import org.apache.commons.lang.StringUtils;
023    import org.apache.ojb.broker.metadata.ClassDescriptor;
024    import org.kuali.kfs.integration.cab.CapitalAssetBuilderModuleService;
025    import org.kuali.kfs.integration.purap.CapitalAssetLocation;
026    import org.kuali.kfs.integration.purap.CapitalAssetSystem;
027    import org.kuali.kfs.module.cam.CamsKeyConstants;
028    import org.kuali.kfs.module.cam.CamsPropertyConstants;
029    import org.kuali.kfs.module.purap.PurapConstants;
030    import org.kuali.kfs.module.purap.PurapKeyConstants;
031    import org.kuali.kfs.module.purap.PurapParameterConstants;
032    import org.kuali.kfs.module.purap.PurapPropertyConstants;
033    import org.kuali.kfs.module.purap.businessobject.PurApItem;
034    import org.kuali.kfs.module.purap.businessobject.PurchasingCapitalAssetItem;
035    import org.kuali.kfs.module.purap.document.PurchasingDocument;
036    import org.kuali.kfs.module.purap.document.service.PurchasingDocumentSpecificService;
037    import org.kuali.kfs.module.purap.document.service.PurchasingService;
038    import org.kuali.kfs.module.purap.service.PurapAccountingService;
039    import org.kuali.kfs.sys.KFSPropertyConstants;
040    import org.kuali.kfs.sys.businessobject.Room;
041    import org.kuali.kfs.sys.context.SpringContext;
042    import org.kuali.kfs.sys.service.PostalCodeValidationService;
043    import org.kuali.kfs.sys.service.impl.KfsParameterConstants;
044    import org.kuali.kfs.vnd.businessobject.VendorDetail;
045    import org.kuali.rice.kns.service.BusinessObjectService;
046    import org.kuali.rice.kns.service.DataDictionaryService;
047    import org.kuali.rice.kns.service.ParameterService;
048    import org.kuali.rice.kns.service.SequenceAccessorService;
049    import org.kuali.rice.kns.service.impl.PersistenceServiceStructureImplBase;
050    import org.kuali.rice.kns.util.GlobalVariables;
051    import org.kuali.rice.kns.util.ObjectUtils;
052    import org.kuali.rice.kns.util.RiceKeyConstants;
053    import org.kuali.rice.kns.util.TypedArrayList;
054    import org.springframework.transaction.annotation.Transactional;
055    
056    @Transactional
057    public class PurchasingServiceImpl extends PersistenceServiceStructureImplBase implements PurchasingService {
058        private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(PurchasingServiceImpl.class);
059    
060        private ParameterService parameterService;
061        private SequenceAccessorService sequenceAccessorService;
062        private PurapAccountingService purapAccountingService;
063        private CapitalAssetBuilderModuleService capitalAssetBuilderModuleService;
064        private PostalCodeValidationService postalCodeValidationService;
065        
066        public void setPurapAccountingService(PurapAccountingService purapAccountingService) {
067            this.purapAccountingService = purapAccountingService;
068        }
069    
070        public void setParameterService(ParameterService parameterService) {
071            this.parameterService = parameterService;
072        }
073    
074        public void setSequenceAccessorService(SequenceAccessorService sequenceAccessorService) {
075            this.sequenceAccessorService = sequenceAccessorService;
076        }
077    
078        public void setCapitalAssetBuilderModuleService(CapitalAssetBuilderModuleService capitalAssetBuilderModuleService) {
079            this.capitalAssetBuilderModuleService = capitalAssetBuilderModuleService;
080        }
081    
082        public void setPostalCodeValidationService(PostalCodeValidationService postalCodeValidationService) {
083            this.postalCodeValidationService = postalCodeValidationService;
084        }
085    
086        public void setupCapitalAssetItems(PurchasingDocument purDoc) {
087    
088            List<PurchasingCapitalAssetItem> camsItemsList = purDoc.getPurchasingCapitalAssetItems();
089            List<PurchasingCapitalAssetItem> newCamsItemsList = new TypedArrayList(purDoc.getPurchasingCapitalAssetItemClass());
090    
091            for (PurApItem purapItem : purDoc.getItems()) {
092                if (purapItem.getItemType().isLineItemIndicator() || PurapConstants.ItemTypeCodes.ITEM_TYPE_TRADE_IN_CODE.equals(purapItem.getItemTypeCode())) {
093                    if (capitalAssetBuilderModuleService.doesItemNeedCapitalAsset(purapItem.getItemTypeCode(), purapItem.getSourceAccountingLines())) {
094                        PurchasingCapitalAssetItem camsItem = getItemIfAlreadyInCamsItemsList(purapItem, camsItemsList);
095                        // If either the camsItem is null or if its system is null and the document's system type is IND (this is
096                        // the case when the user tries to switch from ONE system type to IND system type), we'll have to create
097                        // the camsItem again along with its system to prevent the No collection found error.
098                        if (ObjectUtils.isNull(camsItem) || (purDoc.getCapitalAssetSystemTypeCode() != null && purDoc.getCapitalAssetSystemTypeCode().equals(PurapConstants.CapitalAssetSystemTypes.INDIVIDUAL) && ObjectUtils.isNull(camsItem.getPurchasingCapitalAssetSystem()))) {
099                            PurchasingCapitalAssetItem newCamsItem = createCamsItem(purDoc, purapItem);
100                            newCamsItemsList.add(newCamsItem);
101                        }
102                        else {                        
103                            camsItem.setPurchasingDocument(purDoc);
104                            newCamsItemsList.add(camsItem);
105                        }
106                    }
107                    else {
108                        PurchasingCapitalAssetItem camsItem = getItemIfAlreadyInCamsItemsList(purapItem, camsItemsList);
109                        if (camsItem != null && camsItem.isEmpty()) {
110                            camsItemsList.remove(camsItem);
111                        }
112                    }
113                }
114            }
115    
116            purDoc.setPurchasingCapitalAssetItems(newCamsItemsList);
117            
118            if (purDoc.getPurchasingCapitalAssetItems().isEmpty()) {
119                purDoc.setCapitalAssetSystemStateCode(null);
120                purDoc.setCapitalAssetSystemTypeCode(null);
121            }
122        }
123    
124        protected PurchasingCapitalAssetItem createCamsItem(PurchasingDocument purDoc, PurApItem purapItem) {
125            PurchasingDocumentSpecificService purchasingDocumentSpecificService = purDoc.getDocumentSpecificService();
126            if (purapItem.getItemIdentifier() == null) {
127                ClassDescriptor cd = this.getClassDescriptor(purapItem.getClass());
128                String sequenceName = cd.getFieldDescriptorByName(PurapPropertyConstants.ITEM_IDENTIFIER).getSequenceName();
129                            
130                Integer itemIdentifier = sequenceAccessorService.getNextAvailableSequenceNumber(sequenceName, PurApItem.class).intValue();
131                purapItem.setItemIdentifier(itemIdentifier);
132            }
133            PurchasingCapitalAssetItem camsItem = purchasingDocumentSpecificService.createCamsItem(purDoc, purapItem);
134            return camsItem;
135        }
136    
137    
138        protected PurchasingCapitalAssetItem getItemIfAlreadyInCamsItemsList(PurApItem item, List<PurchasingCapitalAssetItem> camsItemsList) {
139            for (PurchasingCapitalAssetItem camsItem : camsItemsList) {
140                if (camsItem.getItemIdentifier() != null && camsItem.getItemIdentifier().equals(item.getItemIdentifier())) {
141                    return camsItem;
142                }
143            }
144    
145            return null;
146        }
147    
148    
149        public void deleteCapitalAssetItems(PurchasingDocument purDoc, Integer itemIdentifier) {
150            // delete the corresponding CAMS items.
151            int index = 0;
152            for (PurchasingCapitalAssetItem camsItem : purDoc.getPurchasingCapitalAssetItems()) {
153                if (camsItem.getItemIdentifier().equals(itemIdentifier)) {
154                    break;
155                }
156                index++;
157            }
158            purDoc.getPurchasingCapitalAssetItems().remove(index);
159        }
160    
161        public void setupCapitalAssetSystem(PurchasingDocument purDoc) {
162            CapitalAssetSystem resultSystem = purDoc.getDocumentSpecificService().createCapitalAssetSystem();
163            if (purDoc.getCapitalAssetSystemTypeCode() != null && (purDoc.getCapitalAssetSystemTypeCode().equals(PurapConstants.CapitalAssetTabStrings.ONE_SYSTEM) || purDoc.getCapitalAssetSystemTypeCode().equals(PurapConstants.CapitalAssetTabStrings.MULTIPLE_SYSTEMS))) {
164                if (purDoc.getPurchasingCapitalAssetSystems().size() == 0) {
165                    purDoc.getPurchasingCapitalAssetSystems().add(resultSystem);
166                }
167            }
168        }
169    
170        public boolean getDefaultUseTaxIndicatorValue(PurchasingDocument purDoc) {
171            
172            purDoc.refreshReferenceObject("vendorDetail");
173            VendorDetail vendor = purDoc.getVendorDetail();        
174            if (vendor != null) {
175                String vendorStateCode = vendor.getDefaultAddressStateCode();
176                String billingStateCode = purDoc.getBillingStateCode();
177                if (StringUtils.equals(vendorStateCode, billingStateCode) || (vendor.isTaxableIndicator())) {
178                    return false;
179                }
180            }
181            else {
182                // don't set use tax if no vendor on req
183                return true;
184            }
185    
186            return true;
187        }
188    
189        public String getDefaultAssetTypeCodeNotThisFiscalYear() {
190            //FIXME (hjs) is this breaking modularization??
191            return parameterService.getParameterValue(KfsParameterConstants.CAPITAL_ASSET_BUILDER_DOCUMENT.class, PurapParameterConstants.CapitalAsset.PURCHASING_DEFAULT_ASSET_TYPE_WHEN_NOT_THIS_FISCAL_YEAR);
192        }
193    
194        public boolean checkCapitalAssetLocation(CapitalAssetLocation location) {
195            // if any of the date fields have a value AND one of them does not have a value...
196            if (ObjectUtils.isNotNull(location) &&
197                    (StringUtils.isEmpty(location.getCapitalAssetLine1Address()) ||
198                    StringUtils.isEmpty(location.getCapitalAssetCityName()) ||
199                    StringUtils.isEmpty(location.getCapitalAssetCountryCode()) )) { 
200                    String missingFields = "";
201                    if (StringUtils.isEmpty(location.getCapitalAssetLine1Address())) {
202                        missingFields = "Address";
203                        addErrorToCapitalAssetLocation(PurapPropertyConstants.CAPITAL_ASSET_LOCATION_ADDRESS_LINE1,missingFields);
204                    }
205                    if (StringUtils.isEmpty(location.getCapitalAssetCityName())) {
206                        missingFields = "City";
207                        addErrorToCapitalAssetLocation(PurapPropertyConstants.CAPITAL_ASSET_LOCATION_CITY,missingFields);
208                    }
209                    if (StringUtils.isEmpty(location.getCapitalAssetCountryCode())) {
210                       missingFields = "Country";
211                       addErrorToCapitalAssetLocation(PurapPropertyConstants.CAPITAL_ASSET_LOCATION_COUNTRY,missingFields);
212                    }
213                    return false;
214            }
215            return true;
216        }
217        
218        
219        public boolean checkValidRoomNumber(CapitalAssetLocation location){
220            boolean valid = true;
221            if (StringUtils.isNotBlank(location.getBuildingCode()) && StringUtils.isNotBlank(location.getBuildingRoomNumber())) {
222                Map objectKeys = new HashMap();
223                objectKeys.put(CamsPropertyConstants.AssetGlobalDetail.CAMPUS_CODE, location.getCampusCode());
224                objectKeys.put(CamsPropertyConstants.AssetGlobalDetail.BUILDING_CODE, location.getBuildingCode());
225                objectKeys.put(CamsPropertyConstants.AssetGlobalDetail.BUILDING_ROOM_NUMBER, location.getBuildingRoomNumber());
226                Room room = (Room) SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(Room.class, objectKeys);
227    
228                if (ObjectUtils.isNull(room)) {
229                    GlobalVariables.getMessageMap().addToErrorPath(PurapPropertyConstants.NEW_PURCHASING_CAPITAL_ASSET_LOCATION_LINE);
230                    GlobalVariables.getMessageMap().putError(PurapPropertyConstants.CAPITAL_ASSET_LOCATION_ROOM, CamsKeyConstants.AssetLocationGlobal.ERROR_INVALID_ROOM_NUMBER,location.getBuildingCode(),location.getBuildingRoomNumber(), location.getCampusCode());
231                    GlobalVariables.getMessageMap().removeFromErrorPath(PurapPropertyConstants.NEW_PURCHASING_CAPITAL_ASSET_LOCATION_LINE);
232                    valid &= false;
233                }
234                else if (!room.isActive()) {
235                    String label = getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(Room.class.getName()).getAttributeDefinition(KFSPropertyConstants.BUILDING_ROOM_NUMBER).getLabel();
236                    //GlobalVariables.getMessageMap().putError(PurapConstants.CAPITAL_ASSET_TAB_ERRORS, RiceKeyConstants.ERROR_INACTIVE, label);
237                    GlobalVariables.getMessageMap().addToErrorPath(PurapPropertyConstants.NEW_PURCHASING_CAPITAL_ASSET_LOCATION_LINE);
238                    GlobalVariables.getMessageMap().putError(PurapPropertyConstants.CAPITAL_ASSET_LOCATION_ROOM, RiceKeyConstants.ERROR_INACTIVE, label);
239                    GlobalVariables.getMessageMap().removeFromErrorPath(PurapPropertyConstants.NEW_PURCHASING_CAPITAL_ASSET_LOCATION_LINE);
240                    valid &= false;
241                }
242            }else if (StringUtils.isBlank(location.getBuildingCode()) && StringUtils.isNotBlank(location.getBuildingRoomNumber())){
243                Map objectKeys = new HashMap();
244                objectKeys.put(CamsPropertyConstants.AssetGlobalDetail.CAMPUS_CODE, location.getCampusCode());
245                objectKeys.put(CamsPropertyConstants.AssetGlobalDetail.BUILDING_ROOM_NUMBER, location.getBuildingRoomNumber());
246                Room room = (Room) SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(Room.class, objectKeys);
247    
248                if (ObjectUtils.isNull(room)) {
249                    GlobalVariables.getMessageMap().addToErrorPath(PurapPropertyConstants.NEW_PURCHASING_CAPITAL_ASSET_LOCATION_LINE);
250                    GlobalVariables.getMessageMap().putError(PurapPropertyConstants.CAPITAL_ASSET_LOCATION_ROOM, CamsKeyConstants.AssetLocationGlobal.ERROR_INVALID_ROOM_NUMBER_FOR_CAMPUS,location.getBuildingRoomNumber(), location.getCampusCode());
251                    GlobalVariables.getMessageMap().removeFromErrorPath(PurapPropertyConstants.NEW_PURCHASING_CAPITAL_ASSET_LOCATION_LINE);
252                    valid &= false;
253                }
254                else if (!room.isActive()) {
255                    String label = getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(Room.class.getName()).getAttributeDefinition(KFSPropertyConstants.BUILDING_ROOM_NUMBER).getLabel();
256                    GlobalVariables.getMessageMap().addToErrorPath(PurapPropertyConstants.NEW_PURCHASING_CAPITAL_ASSET_LOCATION_LINE);
257                    GlobalVariables.getMessageMap().putError(PurapPropertyConstants.CAPITAL_ASSET_LOCATION_ROOM, RiceKeyConstants.ERROR_INACTIVE, label);
258                    GlobalVariables.getMessageMap().removeFromErrorPath(PurapPropertyConstants.NEW_PURCHASING_CAPITAL_ASSET_LOCATION_LINE);
259                    //GlobalVariables.getMessageMap().putError(PurapConstants.CAPITAL_ASSET_TAB_ERRORS, RiceKeyConstants.ERROR_INACTIVE, label);
260                    valid &= false;
261                }
262            }
263            return valid;
264        }
265        
266        /**
267         * Gets the dataDictionaryService attribute.
268         * 
269         * @return an implementation of the dataDictionaryService.
270         */
271        public DataDictionaryService getDataDictionaryService() {
272            return SpringContext.getBean(DataDictionaryService.class);
273        }
274        
275        public void addErrorToCapitalAssetLocation(String path, String field) {
276            
277            GlobalVariables.getMessageMap().addToErrorPath(PurapPropertyConstants.NEW_PURCHASING_CAPITAL_ASSET_LOCATION_LINE);
278            GlobalVariables.getMessageMap().putError(path,PurapKeyConstants.ERROR_CAPITAL_ASSET_INCOMPLETE_ADDRESS,field);
279            GlobalVariables.getMessageMap().removeFromErrorPath(PurapPropertyConstants.NEW_PURCHASING_CAPITAL_ASSET_LOCATION_LINE);
280       }
281        
282        
283    }