View Javadoc
1   /*
2    * Copyright 2006 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.module.purap.document.service.impl;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.ole.integration.cab.CapitalAssetBuilderModuleService;
20  import org.kuali.ole.integration.purap.CapitalAssetSystem;
21  import org.kuali.ole.module.purap.PurapConstants;
22  import org.kuali.ole.module.purap.PurapPropertyConstants;
23  import org.kuali.ole.module.purap.PurapRuleConstants;
24  import org.kuali.ole.module.purap.businessobject.*;
25  import org.kuali.ole.module.purap.document.PurchaseOrderDocument;
26  import org.kuali.ole.module.purap.document.PurchasingDocument;
27  import org.kuali.ole.module.purap.document.RequisitionDocument;
28  import org.kuali.ole.module.purap.document.dataaccess.RequisitionDao;
29  import org.kuali.ole.module.purap.document.service.PurapService;
30  import org.kuali.ole.module.purap.document.service.RequisitionService;
31  import org.kuali.ole.select.businessobject.OlePurchaseOrderItem;
32  import org.kuali.ole.select.businessobject.OleRequisitionItem;
33  import org.kuali.ole.select.document.OleRequisitionDocument;
34  import org.kuali.ole.sys.context.SpringContext;
35  import org.kuali.ole.sys.service.PostalCodeValidationService;
36  import org.kuali.ole.sys.service.UniversityDateService;
37  import org.kuali.ole.vnd.businessobject.VendorCommodityCode;
38  import org.kuali.ole.vnd.businessobject.VendorContract;
39  import org.kuali.ole.vnd.businessobject.VendorDetail;
40  import org.kuali.ole.vnd.document.service.VendorService;
41  import org.kuali.rice.core.api.config.property.ConfigurationService;
42  import org.kuali.rice.core.api.datetime.DateTimeService;
43  import org.kuali.rice.core.api.util.type.KualiDecimal;
44  import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
45  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
46  import org.kuali.rice.kew.actiontaken.ActionTakenValue;
47  import org.kuali.rice.kew.api.KewApiServiceLocator;
48  import org.kuali.rice.kew.api.document.DocumentStatus;
49  import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
50  import org.kuali.rice.kew.api.document.search.DocumentSearchResult;
51  import org.kuali.rice.kew.api.document.search.DocumentSearchResults;
52  import org.kuali.rice.kew.api.exception.WorkflowException;
53  import org.kuali.rice.kew.service.KEWServiceLocator;
54  import org.kuali.rice.kim.api.identity.Person;
55  import org.kuali.rice.kim.api.identity.PersonService;
56  import org.kuali.rice.krad.bo.Note;
57  import org.kuali.rice.krad.service.BusinessObjectService;
58  import org.kuali.rice.krad.service.DocumentService;
59  import org.kuali.rice.krad.service.KualiRuleService;
60  import org.kuali.rice.krad.service.SequenceAccessorService;
61  import org.kuali.rice.krad.util.ObjectUtils;
62  import org.springframework.transaction.annotation.Transactional;
63  
64  import java.math.BigDecimal;
65  import java.util.*;
66  
67  
68  /**
69   * Implementation of RequisitionService
70   */
71  @Transactional
72  public class RequisitionServiceImpl implements RequisitionService {
73      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(RequisitionServiceImpl.class);
74  
75      private BusinessObjectService businessObjectService;
76      private CapitalAssetBuilderModuleService capitalAssetBuilderModuleService;
77      private DateTimeService dateTimeService;
78      private DocumentService documentService;
79      private KualiRuleService ruleService;
80      private ConfigurationService kualiConfigurationService;
81      private ParameterService parameterService;
82      private PersonService personService;
83      private PostalCodeValidationService postalCodeValidationService;
84      private PurapService purapService;
85      private RequisitionDao requisitionDao;
86      private UniversityDateService universityDateService;
87      private VendorService vendorService;
88  
89      @Override
90      public PurchasingCapitalAssetItem createCamsItem(PurchasingDocument purDoc, PurApItem purapItem) {
91          PurchasingCapitalAssetItem camsItem = new RequisitionCapitalAssetItem();
92          camsItem.setItemIdentifier(purapItem.getItemIdentifier());
93          // If the system type is INDIVIDUAL then for each of the capital asset items, we need a system attached to it.
94          if (purDoc.getCapitalAssetSystemTypeCode().equals(PurapConstants.CapitalAssetTabStrings.INDIVIDUAL_ASSETS)) {
95              CapitalAssetSystem resultSystem = new RequisitionCapitalAssetSystem();
96              camsItem.setPurchasingCapitalAssetSystem(resultSystem);
97          }
98          camsItem.setPurchasingDocument(purDoc);
99  
100         return camsItem;
101     }
102 
103     @Override
104     public CapitalAssetSystem createCapitalAssetSystem() {
105         CapitalAssetSystem resultSystem = new RequisitionCapitalAssetSystem();
106         return resultSystem;
107     }
108 
109     /**
110      * @see org.kuali.ole.module.purap.document.service.RequisitionService#getRequisitionById(java.lang.Integer)
111      */
112     @Override
113     public RequisitionDocument getRequisitionById(Integer id) {
114         String documentNumber = requisitionDao.getDocumentNumberForRequisitionId(id);
115         if (ObjectUtils.isNotNull(documentNumber)) {
116             try {
117                 RequisitionDocument doc = (RequisitionDocument) documentService.getByDocumentHeaderId(documentNumber);
118 
119                 return doc;
120             } catch (WorkflowException e) {
121                 String errorMessage = "Error getting requisition document from document service";
122                 LOG.error("getRequisitionById() " + errorMessage, e);
123                 throw new RuntimeException(errorMessage, e);
124             }
125         }
126 
127         return null;
128     }
129 
130     private boolean isReqCreatedByPo(String routeHeaderId) {
131         List<ActionTakenValue> result = (List<ActionTakenValue>) KEWServiceLocator.getActionTakenService().getActionsTaken(routeHeaderId);
132         if (result != null && result.size() > 0) {
133             for (ActionTakenValue val : result) {
134                 if (val.getAnnotation() != null &&
135                         val.getAnnotation().trim().equals("Automatic Approval From PO")) {
136                     return true;
137                 }
138             }
139         }
140         return false;
141     }
142 
143     /**
144      * @see org.kuali.ole.module.purap.document.service.RequisitionService#isAutomaticPurchaseOrderAllowed(org.kuali.ole.module.purap.document.RequisitionDocument)
145      */
146     @Override
147     public boolean isAutomaticPurchaseOrderAllowed(RequisitionDocument requisition) {
148         LOG.debug("isAutomaticPurchaseOrderAllowed() started");
149 
150         /*
151          * The private checkAutomaticPurchaseOrderRules method contains rules to check if a requisition can become an APO (Automatic
152          * Purchase Order). The method returns a string containing the reason why this method should return false. Save the reason
153          * as a note on the requisition.
154          */
155         String note = checkAutomaticPurchaseOrderRules(requisition);
156         if (StringUtils.isNotEmpty(note)) {
157             note = PurapConstants.REQ_REASON_NOT_APO + note;
158             try {
159                 Note apoNote = documentService.createNoteFromDocument(requisition, note);
160                 requisition.addNote(apoNote);
161                 documentService.saveDocumentNotes(requisition);
162             } catch (Exception e) {
163                 throw new RuntimeException(PurapConstants.REQ_UNABLE_TO_CREATE_NOTE + " " + e);
164             }
165 
166             if (LOG.isDebugEnabled()) {
167                 LOG.debug("isAutomaticPurchaseOrderAllowed() return false; " + note);
168             }
169             return false;
170         }
171 
172         LOG.debug("isAutomaticPurchaseOrderAllowed() You made it!  Your REQ can become an APO; return true.");
173         return true;
174     }
175 
176     public Collection<String> getAPORules() {
177         return CoreFrameworkServiceLocator.getParameterService().getParameterValuesAsString(
178                 PurchaseOrderDocument.class, "APORules");
179     }
180 
181     /**
182      * Checks the rule for Automatic Purchase Order eligibility of the requisition and return a String containing the reason why the
183      * requisition was not eligible to become an APO if it was not eligible, or return an empty String if the requisition is
184      * eligible to become an APO
185      *
186      * @param requisition the requisition document to be checked for APO eligibility.
187      * @return String containing the reason why the requisition was not eligible to become an APO if it was not eligible, or an
188      *         empty String if the requisition is eligible to become an APO.
189      */
190     protected String checkAutomaticPurchaseOrderRules(RequisitionDocument requisition) {
191         Collection<String> APORules = getAPORules();
192         String requisitionSource = requisition.getRequisitionSourceCode();
193         KualiDecimal reqTotal = requisition.getTotalDollarAmount();
194         KualiDecimal apoLimit = purapService.getApoLimit(requisition.getVendorContractGeneratedIdentifier(), requisition.getChartOfAccountsCode(), requisition.getOrganizationCode());
195         requisition.setOrganizationAutomaticPurchaseOrderLimit(apoLimit);
196 
197         if (LOG.isDebugEnabled()) {
198             LOG.debug("isAPO() reqId = " + requisition.getPurapDocumentIdentifier() + "; apoLimit = " + apoLimit + "; reqTotal = " + reqTotal);
199         }
200         if (apoLimit == null) {
201             return "APO limit is empty.";
202         } else {
203             if (APORules.contains(PurapConstants.APO_LIMIT)) {
204                 if (reqTotal.compareTo(apoLimit) == 1) {
205                     return "Requisition total is greater than the APO limit.";
206                 }
207             }
208         }
209        /* if (APORules.contains(PurapConstants.REQ_TOT)) {
210             if (reqTotal.compareTo(KualiDecimal.ZERO) <= 0) {
211                 return "Requisition total is not greater than zero.";
212             }
213         }*/
214 
215         if (this.isReqCreatedByPo(requisition.getDocumentNumber())) {
216             return "Requsiusion is created by PO";
217         }
218 
219         LOG.debug("isAPO() vendor #" + requisition.getVendorHeaderGeneratedIdentifier() + "-" + requisition.getVendorDetailAssignedIdentifier());
220         if (APORules.contains(PurapConstants.VEN_NOT_SEL)) {
221             if (requisition.getVendorHeaderGeneratedIdentifier() == null || requisition.getVendorDetailAssignedIdentifier() == null) {
222                 return "Vendor was not selected from the vendor database.";
223             }
224         } else {
225             VendorDetail vendorDetail = vendorService.getVendorDetail(requisition.getVendorHeaderGeneratedIdentifier(), requisition.getVendorDetailAssignedIdentifier());
226             if (APORules.contains(PurapConstants.ERR_RTV_VENDOR)) {
227                 if (vendorDetail == null) {
228                     return "Error retrieving vendor from the database.";
229                 }
230             }
231             if (StringUtils.isBlank(requisition.getVendorLine1Address()) ||
232                     StringUtils.isBlank(requisition.getVendorCityName()) ||
233                     StringUtils.isBlank(requisition.getVendorCountryCode())) {
234                 return "Requisition does not have all of the vendor address fields that are required for Purchase Order.";
235             }
236             requisition.setVendorRestrictedIndicator(vendorDetail.getVendorRestrictedIndicator());
237             if (APORules.contains(PurapConstants.VENDOR_RESTRICTED)) {
238                 if (requisition.getVendorRestrictedIndicator() != null && requisition.getVendorRestrictedIndicator()) {
239                     return "Selected vendor is marked as restricted.";
240                 }
241                 if (vendorDetail.isVendorDebarred()) {
242                     return "Selected vendor is marked as a debarred vendor";
243                 }
244                 requisition.setVendorDetail(vendorDetail);
245 
246                 if ((!PurapConstants.RequisitionSources.B2B.equals(requisitionSource)) && ObjectUtils.isNull(requisition.getVendorContractGeneratedIdentifier())) {
247                     Person initiator = getPersonService().getPerson(requisition.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId());
248                     VendorContract b2bContract = vendorService.getVendorB2BContract(vendorDetail, initiator.getCampusCode());
249                     if (APORules.contains(PurapConstants.REQ_WITH_NO_CONTRACT)) {
250                         if (b2bContract != null) {
251                             return "Standard requisition with no contract selected but a B2B contract exists for the selected vendor.";
252                         }
253                     }
254                 }
255             }
256 
257             //if vendor address isn't complete, no APO
258             if (StringUtils.isBlank(requisition.getVendorLine1Address()) ||
259                     StringUtils.isBlank(requisition.getVendorCityName()) ||
260                     StringUtils.isBlank(requisition.getVendorCountryCode()) ||
261                     !postalCodeValidationService.validateAddress(requisition.getVendorCountryCode(), requisition.getVendorStateCode(), requisition.getVendorPostalCode(), "", "")) {
262                 return "Requistion does not contain a complete vendor address";
263             }
264 
265             // These are needed for commodity codes. They are put in here so that
266             // we don't have to loop through items too many times.
267             String purchaseOrderRequiresCommodityCode = parameterService.getParameterValueAsString(PurchaseOrderDocument.class, PurapRuleConstants.ITEMS_REQUIRE_COMMODITY_CODE_IND);
268             boolean commodityCodeRequired = purchaseOrderRequiresCommodityCode.equals("Y");
269 
270             for (Iterator iter = requisition.getItems().iterator(); iter.hasNext(); ) {
271                 RequisitionItem item = (RequisitionItem) iter.next();
272                 if (APORules.contains(PurapConstants.ITM_RESTRICTED)) {
273                     if (item.isItemRestrictedIndicator()) {
274                         return "Requisition contains an item that is marked as restricted.";
275                     }
276                 }
277 
278                 //We only need to check the commodity codes if this is an above the line item.
279                 if (item.getItemType().isLineItemIndicator()) {
280                     String commodityCodesReason = "";
281                     List<VendorCommodityCode> vendorCommodityCodes = commodityCodeRequired ? requisition.getVendorDetail().getVendorCommodities() : null;
282                     commodityCodesReason = checkAPORulesPerItemForCommodityCodes(item, vendorCommodityCodes, commodityCodeRequired);
283                     if (StringUtils.isNotBlank(commodityCodesReason)) {
284                         return commodityCodesReason;
285                     }
286                 }
287 
288                 if (PurapConstants.ItemTypeCodes.ITEM_TYPE_ORDER_DISCOUNT_CODE.equals(item.getItemType().getItemTypeCode())
289                         || PurapConstants.ItemTypeCodes.ITEM_TYPE_TRADE_IN_CODE.equals(item.getItemType().getItemTypeCode())) {
290                     if (APORules.contains(PurapConstants.REQ_CON_TRADEIN)) {
291                         if ((item.getItemUnitPrice() != null) && ((BigDecimal.ZERO.compareTo(item.getItemUnitPrice())) != 0)) {
292                             // discount or trade-in item has unit price that is not empty or zero
293                             return "Requisition contains a " + item.getItemType().getItemTypeDescription() + " item, so it does not qualify as an APO.";
294                         }
295                     }
296                 }
297                 if (APORules.contains(PurapConstants.REQ_CON_ACC_LINE)) {
298                     if (!PurapConstants.RequisitionSources.B2B.equals(requisitionSource)) {
299                         for (PurApAccountingLine accountingLine : item.getSourceAccountingLines()) {
300                             if (capitalAssetBuilderModuleService.doesAccountingLineFailAutomaticPurchaseOrderRules(accountingLine)) {
301                                 return "Requisition contains accounting line with capital object level";
302                             }
303                         }
304                     }
305                 }
306             }
307 
308         }// endfor items
309         if (APORules.contains(PurapConstants.RECUR_REQ_TYPE)) {
310             if (capitalAssetBuilderModuleService.doesDocumentFailAutomaticPurchaseOrderRules(requisition)) {
311                 return "Requisition contains capital asset items.";
312             }
313         }
314         if (APORules.contains(PurapConstants.RECUR_PAY_TYPE)) {
315             if (StringUtils.isNotEmpty(requisition.getRecurringPaymentTypeCode())) {
316                 return "Payment type is marked as recurring.";
317             }
318         }
319         if (APORules.contains(PurapConstants.PO_TOT_NOT_EXCEED)) {
320             if ((requisition.getPurchaseOrderTotalLimit() != null) && (KualiDecimal.ZERO.compareTo(requisition.getPurchaseOrderTotalLimit()) != 0)) {
321                 LOG.debug("isAPO() po total limit is not null and not equal to zero; return false.");
322                 return "The 'PO not to exceed' amount has been entered.";
323             }
324         }
325         if (APORules.contains(new String("ALT_VEN_NAM"))) {
326             if (StringUtils.isNotEmpty(requisition.getAlternate1VendorName()) || StringUtils.isNotEmpty(requisition.getAlternate2VendorName()) || StringUtils.isNotEmpty(requisition.getAlternate3VendorName()) || StringUtils.isNotEmpty(requisition.getAlternate4VendorName()) || StringUtils.isNotEmpty(requisition.getAlternate5VendorName())) {
327                 LOG.debug("isAPO() alternate vendor name exists; return false.");
328                 return "Requisition contains additional suggested vendor names.";
329             }
330         }
331         if (APORules.contains(PurapConstants.ALT_VEN_NAME_EXISTS)) {
332             if (requisition.isPostingYearNext() && !purapService.isTodayWithinApoAllowedRange()) {
333                 return "Requisition is set to encumber next fiscal year and approval is not within APO allowed date range.";
334             }
335         }
336 
337         return "";
338     }
339 
340     /**
341      * Checks the APO rules for Commodity Codes.
342      * The rules are as follow:
343      * 1. If an institution does not require a commodity code on a requisition but
344      * does require a commodity code on a purchase order:
345      * a. If the requisition qualifies for an APO and the commodity code is blank
346      * on any line item then the system should use the default commodity code
347      * for the vendor.
348      * b. If there is not a default commodity code for the vendor then the
349      * requisition is not eligible to become an APO.
350      * 2. The commodity codes where the restricted indicator is Y should disallow
351      * the requisition from becoming an APO.
352      * 3. If the commodity code is Inactive when the requisition is finally approved
353      * do not allow the requisition to become an APO.
354      *
355      * @param purItem
356      * @param vendorCommodityCodes
357      * @param commodityCodeRequired
358      * @return
359      */
360     protected String checkAPORulesPerItemForCommodityCodes(RequisitionItem purItem, List<VendorCommodityCode> vendorCommodityCodes, boolean commodityCodeRequired) {
361         // If the commodity code is blank on any line item and a commodity code is required,
362         // then the system should use the default commodity code for the vendor
363         if (purItem.getCommodityCode() == null && commodityCodeRequired) {
364             for (VendorCommodityCode vcc : vendorCommodityCodes) {
365                 if (vcc.isCommodityDefaultIndicator()) {
366                     purItem.setCommodityCode(vcc.getCommodityCode());
367                     purItem.setPurchasingCommodityCode(vcc.getPurchasingCommodityCode());
368                 }
369             }
370         }
371         if (purItem.getCommodityCode() == null) {
372             // If there is not a default commodity code for the vendor then the requisition is not eligible to become an APO.
373             if (commodityCodeRequired) {
374                 return "There are missing commodity code(s).";
375             }
376         } else if (!purItem.getCommodityCode().isActive()) {
377             return "Requisition contains inactive commodity codes.";
378         } else if (purItem.getCommodityCode().isRestrictedItemsIndicator()) {
379             return "Requisition contains an item with a restricted commodity code.";
380         }
381         return "";
382     }
383 
384     /**
385      * @see org.kuali.ole.module.purap.document.service.RequisitionService#getRequisitionsAwaitingContractManagerAssignment()
386      */
387     @Override
388     public List<RequisitionDocument> getRequisitionsAwaitingContractManagerAssignment() {
389         List<RequisitionDocument> unassignedRequisitions = new ArrayList<RequisitionDocument>();
390         List<RequisitionDocument> requisitions = new ArrayList<RequisitionDocument>();
391 
392         List<String> documentsNumbersAwaitingContractManagerAssignment = getDocumentsNumbersAwaitingContractManagerAssignment();
393 
394         for (String documentNumber : documentsNumbersAwaitingContractManagerAssignment) {
395             Map fieldValues = new HashMap();
396             fieldValues.put(PurapPropertyConstants.DOCUMENT_NUMBER, documentNumber);
397 
398             requisitions = (List<RequisitionDocument>) businessObjectService.findMatching(RequisitionDocument.class, fieldValues);
399 
400             for (RequisitionDocument req : requisitions) {
401                 unassignedRequisitions.add(req);
402             }
403         }
404 
405         return unassignedRequisitions;
406     }
407 
408     /**
409      * Gets a list of strings of document numbers from workflow documents where
410      * document status = 'P', 'F'  and document type = 'REQS'.  If appDocStatus status
411      * of 'Awaiting Contract Manager Assignment' then the document number is added to the list
412      * <p/>
413      * NOTE: simplify using DocSearch lookup with AppDocStatus
414      *
415      * @return list of documentNumbers to retrieve requisitions.
416      */
417     protected List<String> getDocumentsNumbersAwaitingContractManagerAssignment() {
418         List<String> requisitionDocumentNumbers = new ArrayList<String>();
419 
420         DocumentSearchCriteria.Builder documentSearchCriteriaDTO = DocumentSearchCriteria.Builder.create();
421         //Search for status of P and F and "Awaiting Contract Manager Assignment" application document status
422         documentSearchCriteriaDTO.setDocumentStatuses(Arrays.asList(DocumentStatus.PROCESSED, DocumentStatus.FINAL));
423         documentSearchCriteriaDTO.setDocumentTypeName(PurapConstants.REQUISITION_DOCUMENT_TYPE);
424         documentSearchCriteriaDTO.setApplicationDocumentStatus(PurapConstants.RequisitionStatuses.APPDOC_AWAIT_CONTRACT_MANAGER_ASSGN);
425         documentSearchCriteriaDTO.setSaveName(null);
426 
427         DocumentSearchResults results = KewApiServiceLocator.getWorkflowDocumentService().documentSearch(null, documentSearchCriteriaDTO.build());
428 
429         String documentHeaderId = null;
430 
431         for (DocumentSearchResult result : results.getSearchResults()) {
432             requisitionDocumentNumbers.add(result.getDocument().getDocumentId());
433         }
434 
435         return requisitionDocumentNumbers;
436     }
437 
438     /**
439      * @see org.kuali.ole.module.purap.document.service.RequisitionService#getCountOfRequisitionsAwaitingContractManagerAssignment()
440      */
441     @Override
442     public int getCountOfRequisitionsAwaitingContractManagerAssignment() {
443         List<RequisitionDocument> unassignedRequisitions = getRequisitionsAwaitingContractManagerAssignment();
444         if (ObjectUtils.isNotNull(unassignedRequisitions)) {
445             return unassignedRequisitions.size();
446         } else {
447             return 0;
448         }
449     }
450 
451     /**
452      * Create Purchase Order and populate with data from Purchase Order and other default data
453      *
454      * @param reqDocument The requisition document from which we create the purchase order document.
455      * @return The purchase order document created by this method.
456      * @throws WorkflowException
457      */
458     @Override
459     public OleRequisitionDocument generateRequisitionFromPurchaseOrder(PurchaseOrderDocument purDocument) throws WorkflowException {
460 
461         OleRequisitionDocument rdoc = null;
462         rdoc = (OleRequisitionDocument) documentService.getNewDocument("OLE_REQS");
463         rdoc = populateRequisitionFromPurchaseOrder(rdoc, purDocument);
464 
465 //        rdoc.setStatusCode(PurchaseOrderStatuses.IN_PROCESS);
466         if (ObjectUtils.isNotNull(purDocument.getVendorContract())) {
467             rdoc.setVendorPaymentTermsCode(purDocument.getVendorContract().getVendorPaymentTermsCode());
468             rdoc.setVendorShippingPaymentTermsCode(purDocument.getVendorContract().getVendorShippingPaymentTermsCode());
469             rdoc.setVendorShippingTitleCode(purDocument.getVendorContract().getVendorShippingTitleCode());
470         } else {
471             VendorDetail vendor = vendorService.getVendorDetail(purDocument.getVendorHeaderGeneratedIdentifier(), purDocument.getVendorDetailAssignedIdentifier());
472             if (ObjectUtils.isNotNull(vendor)) {
473                 rdoc.setVendorPaymentTermsCode(vendor.getVendorPaymentTermsCode());
474                 rdoc.setVendorShippingPaymentTermsCode(vendor.getVendorShippingPaymentTermsCode());
475                 rdoc.setVendorShippingTitleCode(vendor.getVendorShippingTitleCode());
476             }
477         }
478 
479         if (!PurapConstants.RequisitionSources.B2B.equals(purDocument.getRequisitionSourceCode())) {
480             purapService.addBelowLineItems(rdoc);
481         }
482         // rdoc.fixItemReferences();
483 
484         return rdoc;
485     }
486 
487 
488     public OleRequisitionDocument populateRequisitionFromPurchaseOrder(OleRequisitionDocument requisitionDocument, PurchaseOrderDocument pdoc) {
489 
490         requisitionDocument.getDocumentHeader().setOrganizationDocumentNumber(pdoc.getDocumentHeader().getOrganizationDocumentNumber());
491         requisitionDocument.getDocumentHeader().setDocumentDescription(pdoc.getDocumentHeader().getDocumentDescription());
492         requisitionDocument.getDocumentHeader().setExplanation(pdoc.getDocumentHeader().getExplanation());
493 
494         requisitionDocument.setBillingName(pdoc.getBillingName());
495         requisitionDocument.setBillingLine1Address(pdoc.getBillingLine1Address());
496         requisitionDocument.setBillingLine2Address(pdoc.getBillingLine2Address());
497         requisitionDocument.setBillingCityName(pdoc.getBillingCityName());
498         requisitionDocument.setBillingStateCode(pdoc.getBillingStateCode());
499         requisitionDocument.setBillingPostalCode(pdoc.getBillingPostalCode());
500         requisitionDocument.setBillingCountryCode(pdoc.getBillingCountryCode());
501         requisitionDocument.setBillingPhoneNumber(pdoc.getBillingPhoneNumber());
502 
503         requisitionDocument.setReceivingName(pdoc.getReceivingName());
504         requisitionDocument.setReceivingCityName(pdoc.getReceivingCityName());
505         requisitionDocument.setReceivingLine1Address(pdoc.getReceivingLine1Address());
506         requisitionDocument.setReceivingLine2Address(pdoc.getReceivingLine2Address());
507         requisitionDocument.setReceivingStateCode(pdoc.getReceivingStateCode());
508         requisitionDocument.setReceivingPostalCode(pdoc.getReceivingPostalCode());
509         requisitionDocument.setReceivingCountryCode(pdoc.getReceivingCountryCode());
510         requisitionDocument.setAddressToVendorIndicator(pdoc.getAddressToVendorIndicator());
511 
512         requisitionDocument.setDeliveryBuildingCode(pdoc.getDeliveryBuildingCode());
513         requisitionDocument.setDeliveryBuildingRoomNumber(pdoc.getDeliveryBuildingRoomNumber());
514         requisitionDocument.setDeliveryBuildingName(pdoc.getDeliveryBuildingName());
515         requisitionDocument.setDeliveryCampusCode(pdoc.getDeliveryCampusCode());
516         requisitionDocument.setDeliveryCityName(pdoc.getDeliveryCityName());
517         requisitionDocument.setDeliveryCountryCode(pdoc.getDeliveryCountryCode());
518         requisitionDocument.setDeliveryInstructionText(pdoc.getDeliveryInstructionText());
519         requisitionDocument.setDeliveryBuildingLine1Address(pdoc.getDeliveryBuildingLine1Address());
520         requisitionDocument.setDeliveryBuildingLine2Address(pdoc.getDeliveryBuildingLine2Address());
521         requisitionDocument.setDeliveryPostalCode(pdoc.getDeliveryPostalCode());
522         requisitionDocument.setDeliveryRequiredDate(pdoc.getDeliveryRequiredDate());
523         requisitionDocument.setDeliveryRequiredDateReasonCode(pdoc.getDeliveryRequiredDateReasonCode());
524         requisitionDocument.setDeliveryStateCode(pdoc.getDeliveryStateCode());
525         requisitionDocument.setDeliveryToEmailAddress(pdoc.getDeliveryToEmailAddress());
526         requisitionDocument.setDeliveryToName(pdoc.getDeliveryToName());
527         requisitionDocument.setDeliveryToPhoneNumber(pdoc.getDeliveryToPhoneNumber());
528         requisitionDocument.setDeliveryBuildingOtherIndicator(pdoc.isDeliveryBuildingOtherIndicator());
529 
530         requisitionDocument.setPurchaseOrderBeginDate(pdoc.getPurchaseOrderBeginDate());
531         requisitionDocument.setPurchaseOrderCostSourceCode(pdoc.getPurchaseOrderCostSourceCode());
532         requisitionDocument.setPostingYear(pdoc.getPostingYear());
533         requisitionDocument.setPurchaseOrderEndDate(pdoc.getPurchaseOrderEndDate());
534         requisitionDocument.setChartOfAccountsCode(pdoc.getChartOfAccountsCode());
535         requisitionDocument.setDocumentFundingSourceCode(pdoc.getDocumentFundingSourceCode());
536         requisitionDocument.setInstitutionContactEmailAddress(pdoc.getInstitutionContactEmailAddress());
537         requisitionDocument.setInstitutionContactName(pdoc.getInstitutionContactName());
538         requisitionDocument.setInstitutionContactPhoneNumber(pdoc.getInstitutionContactPhoneNumber());
539         requisitionDocument.setNonInstitutionFundAccountNumber(pdoc.getNonInstitutionFundAccountNumber());
540         requisitionDocument.setNonInstitutionFundChartOfAccountsCode(pdoc.getNonInstitutionFundChartOfAccountsCode());
541         requisitionDocument.setNonInstitutionFundOrgChartOfAccountsCode(pdoc.getNonInstitutionFundOrgChartOfAccountsCode());
542         requisitionDocument.setNonInstitutionFundOrganizationCode(pdoc.getNonInstitutionFundOrganizationCode());
543         requisitionDocument.setOrganizationCode(pdoc.getOrganizationCode());
544         requisitionDocument.setRecurringPaymentTypeCode(pdoc.getRecurringPaymentTypeCode());
545         requisitionDocument.setRequestorPersonEmailAddress(pdoc.getRequestorPersonEmailAddress());
546         requisitionDocument.setRequestorPersonName(pdoc.getRequestorPersonName());
547         requisitionDocument.setRequestorPersonPhoneNumber(pdoc.getRequestorPersonPhoneNumber());
548 //        requisitionDocument.setPurapDocumentIdentifier(pdoc.getRequisitionIdentifier());
549         requisitionDocument.setPurchaseOrderTotalLimit(pdoc.getPurchaseOrderTotalLimit());
550         requisitionDocument.setPurchaseOrderTransmissionMethodCode(pdoc.getPurchaseOrderTransmissionMethodCode());
551         requisitionDocument.setUseTaxIndicator(pdoc.isUseTaxIndicator());
552         requisitionDocument.setPurchaseOrderTypeId(pdoc.getPurchaseOrderTypeId());
553         /*requisitionDocument.setLicensingRequirementIndicator(pdoc.isLicensingRequirementIndicator());*/
554         /*requisitionDocument.setLicensingRequirementCode(pdoc.getLicensingRequirementCode());*/
555         requisitionDocument.setVendorCityName(pdoc.getVendorCityName());
556         requisitionDocument.setVendorContractGeneratedIdentifier(pdoc.getVendorContractGeneratedIdentifier());
557         requisitionDocument.setVendorCountryCode(pdoc.getVendorCountryCode());
558         requisitionDocument.setVendorCustomerNumber(pdoc.getVendorCustomerNumber());
559         requisitionDocument.setVendorAttentionName(pdoc.getVendorAttentionName());
560         requisitionDocument.setVendorDetailAssignedIdentifier(pdoc.getVendorDetailAssignedIdentifier());
561         requisitionDocument.setVendorFaxNumber(pdoc.getVendorFaxNumber());
562         requisitionDocument.setVendorHeaderGeneratedIdentifier(pdoc.getVendorHeaderGeneratedIdentifier());
563         requisitionDocument.setVendorLine1Address(pdoc.getVendorLine1Address());
564         requisitionDocument.setVendorLine2Address(pdoc.getVendorLine2Address());
565         requisitionDocument.setVendorAddressInternationalProvinceName(pdoc.getVendorAddressInternationalProvinceName());
566         requisitionDocument.setVendorName(pdoc.getVendorName());
567         requisitionDocument.setVendorNoteText(pdoc.getVendorNoteText());
568         requisitionDocument.setVendorPhoneNumber(pdoc.getVendorPhoneNumber());
569         requisitionDocument.setVendorPostalCode(pdoc.getVendorPostalCode());
570         requisitionDocument.setVendorStateCode(pdoc.getVendorStateCode());
571         requisitionDocument.setVendorRestrictedIndicator(pdoc.getVendorRestrictedIndicator());
572 
573         requisitionDocument.setExternalOrganizationB2bSupplierIdentifier(pdoc.getExternalOrganizationB2bSupplierIdentifier());
574         requisitionDocument.setRequisitionSourceCode(pdoc.getRequisitionSourceCode());
575         requisitionDocument.setAccountsPayablePurchasingDocumentLinkIdentifier(pdoc.getAccountsPayablePurchasingDocumentLinkIdentifier());
576         requisitionDocument.setReceivingDocumentRequiredIndicator(pdoc.isReceivingDocumentRequiredIndicator());
577         requisitionDocument.setPaymentRequestPositiveApprovalIndicator(pdoc.isPaymentRequestPositiveApprovalIndicator());
578         /*requisitionDocument.setLicensingRequirementIndicator(pdoc.isLicensingRequirementIndicator());*/
579         /*requisitionDocument.setLicensingRequirementCode(pdoc.getLicensingRequirementCode());*/
580 
581 //        requisitionDocument.setStatusCode(PurapConstants.PurchaseOrderStatuses.IN_PROCESS);
582 
583         // Copy items from requisition (which will copy the item's accounts and capital assets)
584         List<OleRequisitionItem> items = new ArrayList();
585         for (OlePurchaseOrderItem reqItem : (List<OlePurchaseOrderItem>) pdoc.getItems()) {
586             PurchasingCapitalAssetItem reqCamsItem = null;
587             OleRequisitionItem ritem = getRequisitionItem(reqItem, requisitionDocument, reqCamsItem);
588 
589             reqCamsItem = pdoc.
590                     getPurchasingCapitalAssetItemByItemIdentifier(reqItem.getItemIdentifier().intValue());
591             ritem = populateCapitalAssetItem(ritem, requisitionDocument, reqCamsItem);
592             items.add(ritem);
593         }
594         requisitionDocument.setItems(items);
595 
596         // Copy capital asset information that is directly off the document.
597         requisitionDocument.setCapitalAssetSystemTypeCode(pdoc.getCapitalAssetSystemTypeCode());
598         requisitionDocument.setCapitalAssetSystemStateCode(pdoc.getCapitalAssetSystemStateCode());
599         requisitionDocument.setStatusCode(PurapConstants.RequisitionStatuses.APPDOC_CLOSED);
600 
601 
602         for (CapitalAssetSystem capitalAssetSystem : pdoc.getPurchasingCapitalAssetSystems()) {
603             RequisitionCapitalAssetSystem item = new RequisitionCapitalAssetSystem(capitalAssetSystem);
604             item.setPurapDocumentIdentifier(requisitionDocument.getPurapDocumentIdentifier());
605             requisitionDocument.getPurchasingCapitalAssetSystems().add(new RequisitionCapitalAssetSystem(capitalAssetSystem));
606         }
607 
608 //        requisitionDocument.fixItemReferences();
609         return requisitionDocument;
610     }
611 
612     private OleRequisitionItem getRequisitionItem(OlePurchaseOrderItem pitem, RequisitionDocument requisitionDocument, PurchasingCapitalAssetItem reqCamsItem) {
613         OleRequisitionItem ritem = new OleRequisitionItem();
614         ritem.setRequisition(requisitionDocument);
615         SequenceAccessorService sas = SpringContext.getBean(SequenceAccessorService.class);
616         Integer itemIdentifier = sas.getNextAvailableSequenceNumber("REQS_ITM_ID", RequisitionDocument.class).intValue();
617         ritem.setItemIdentifier(itemIdentifier);
618         ritem.setItemLineNumber(pitem.getItemLineNumber());
619         ritem.setItemUnitOfMeasureCode(pitem.getItemUnitOfMeasureCode());
620         ritem.setItemQuantity(pitem.getItemQuantity());
621         ritem.setItemCatalogNumber(pitem.getItemCatalogNumber());
622         ritem.setItemDescription(pitem.getItemDescription());
623         ritem.setItemUnitPrice(pitem.getItemUnitPrice());
624         ritem.setItemAuxiliaryPartIdentifier(pitem.getItemAuxiliaryPartIdentifier());
625         ritem.setItemAssignedToTradeInIndicator(pitem.getItemAssignedToTradeInIndicator());
626         ritem.setItemTaxAmount(pitem.getItemTaxAmount());
627         ritem.setItemTitleId(pitem.getItemTitleId());
628 
629         for (PurApItemUseTax useTaxItem : pitem.getUseTaxItems()) {
630             useTaxItem.setItemIdentifier(itemIdentifier);
631             ritem.getUseTaxItems().add(useTaxItem);
632         }
633 
634         ritem.setExternalOrganizationB2bProductReferenceNumber(pitem.getExternalOrganizationB2bProductReferenceNumber());
635         ritem.setExternalOrganizationB2bProductTypeName(pitem.getExternalOrganizationB2bProductTypeName());
636         ritem.setItemTypeCode(pitem.getItemTypeCode());
637 
638         if (pitem.getSourceAccountingLines() != null && pitem.getSourceAccountingLines().size() > 0 &&
639                 !StringUtils.equals(PurapConstants.ItemTypeCodes.ITEM_TYPE_ORDER_DISCOUNT_CODE, pitem.getItemType().getItemTypeCode())) {
640             List accounts = new ArrayList();
641             for (PurApAccountingLine account : pitem.getSourceAccountingLines()) {
642                 PurApAccountingLineBase poAccount = (PurApAccountingLineBase) account;
643                 RequisitionAccount acc = convertAccount(poAccount, ritem);
644                 accounts.add(acc);
645             }
646             ritem.setSourceAccountingLines(accounts);
647         }
648         ritem.setPurchasingCommodityCode(pitem.getPurchasingCommodityCode());
649         ritem.setCommodityCode(pitem.getCommodityCode());
650 
651         if (ObjectUtils.isNotNull(reqCamsItem)) {
652             RequisitionCapitalAssetItem item = new RequisitionCapitalAssetItem(reqCamsItem, ritem.getItemIdentifier());
653             requisitionDocument.getPurchasingCapitalAssetItems().add(item);
654         }
655         return ritem;
656     }
657 
658     private OleRequisitionItem populateCapitalAssetItem(OleRequisitionItem ritem, RequisitionDocument requisitionDocument, PurchasingCapitalAssetItem reqCamsItem) {
659         if (ObjectUtils.isNotNull(reqCamsItem)) {
660             RequisitionCapitalAssetItem item = new RequisitionCapitalAssetItem(reqCamsItem, ritem.getItemIdentifier());
661             requisitionDocument.getPurchasingCapitalAssetItems().add(item);
662         }
663         return ritem;
664     }
665 
666     private RequisitionAccount convertAccount(PurApAccountingLine account, RequisitionItem requisitionItem) {
667         RequisitionAccount result = new RequisitionAccount();
668         result.setAccountLinePercent(account.getAccountLinePercent());
669         result.setAccountNumber(account.getAccountNumber());
670         result.setChartOfAccountsCode(account.getChartOfAccountsCode());
671         result.setFinancialObjectCode(account.getFinancialObjectCode());
672         result.setFinancialSubObjectCode(account.getFinancialSubObjectCode());
673         result.setOrganizationReferenceId(account.getOrganizationReferenceId());
674         result.setProjectCode(account.getProjectCode());
675         result.setSubAccountNumber(account.getSubAccountNumber());
676         result.setRequisitionItem(requisitionItem);
677         return result;
678     }
679 
680     private RequisitionCapitalAssetItem convert(PurchaseOrderCapitalAssetItem pitem) {
681         RequisitionCapitalAssetItem result = new RequisitionCapitalAssetItem();
682         result.setCapitalAssetItemIdentifier(pitem.getCapitalAssetItemIdentifier());
683         result.setCapitalAssetSystemIdentifier(pitem.getCapitalAssetSystemIdentifier());
684         result.setCapitalAssetTransactionTypeCode(pitem.getCapitalAssetTransactionTypeCode());
685         result.setItemIdentifier(pitem.getItemIdentifier());
686         result.setPurapDocumentIdentifier(pitem.getPurchasingDocument().getPurapDocumentIdentifier());
687         return result;
688     }
689 
690 
691     public void setBusinessObjectService(BusinessObjectService boService) {
692         this.businessObjectService = boService;
693     }
694 
695     public void setDocumentService(DocumentService documentService) {
696         this.documentService = documentService;
697     }
698 
699     public void setRequisitionDao(RequisitionDao requisitionDao) {
700         this.requisitionDao = requisitionDao;
701     }
702 
703     public void setPurapService(PurapService purapService) {
704         this.purapService = purapService;
705     }
706 
707     public KualiRuleService getRuleService() {
708         return ruleService;
709     }
710 
711     public void setRuleService(KualiRuleService ruleService) {
712         this.ruleService = ruleService;
713     }
714 
715     public void setParameterService(ParameterService parameterService) {
716         this.parameterService = parameterService;
717     }
718 
719     public void setDateTimeService(DateTimeService dateTimeService) {
720         this.dateTimeService = dateTimeService;
721     }
722 
723     public void setUniversityDateService(UniversityDateService universityDateService) {
724         this.universityDateService = universityDateService;
725     }
726 
727     public void setVendorService(VendorService vendorService) {
728         this.vendorService = vendorService;
729     }
730 
731     public void setConfigurationService(ConfigurationService kualiConfigurationService) {
732         this.kualiConfigurationService = kualiConfigurationService;
733     }
734 
735     public void setCapitalAssetBuilderModuleService(CapitalAssetBuilderModuleService capitalAssetBuilderModuleService) {
736         this.capitalAssetBuilderModuleService = capitalAssetBuilderModuleService;
737     }
738 
739     public void setPostalCodeValidationService(PostalCodeValidationService postalCodeValidationService) {
740         this.postalCodeValidationService = postalCodeValidationService;
741     }
742 
743     /**
744      * @return Returns the personService.
745      */
746     protected PersonService getPersonService() {
747         if (personService == null) {
748             personService = SpringContext.getBean(PersonService.class);
749         }
750         return personService;
751     }
752 
753 }