1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.ole.vnd.document.service.impl;
17
18 import java.sql.Date;
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.log4j.Logger;
28 import org.kuali.ole.sys.OLEConstants;
29 import org.kuali.ole.sys.businessobject.Building;
30 import org.kuali.ole.sys.context.SpringContext;
31 import org.kuali.ole.vnd.VendorConstants;
32 import org.kuali.ole.vnd.VendorPropertyConstants;
33 import org.kuali.ole.vnd.businessobject.VendorAddress;
34 import org.kuali.ole.vnd.businessobject.VendorContract;
35 import org.kuali.ole.vnd.businessobject.VendorContractOrganization;
36 import org.kuali.ole.vnd.businessobject.VendorDefaultAddress;
37 import org.kuali.ole.vnd.businessobject.VendorDetail;
38 import org.kuali.ole.vnd.businessobject.VendorHeader;
39 import org.kuali.ole.vnd.businessobject.VendorRoutingComparable;
40 import org.kuali.ole.vnd.dataaccess.VendorDao;
41 import org.kuali.ole.vnd.document.service.VendorService;
42 import org.kuali.rice.core.api.datetime.DateTimeService;
43 import org.kuali.rice.core.api.util.type.KualiDecimal;
44 import org.kuali.rice.kew.api.exception.WorkflowException;
45 import org.kuali.rice.kim.api.identity.Person;
46 import org.kuali.rice.kim.api.identity.PersonService;
47 import org.kuali.rice.kns.document.MaintenanceDocument;
48 import org.kuali.rice.krad.bo.Note;
49 import org.kuali.rice.krad.document.Document;
50 import org.kuali.rice.krad.service.BusinessObjectService;
51 import org.kuali.rice.krad.service.DocumentService;
52 import org.kuali.rice.krad.service.KRADServiceLocator;
53 import org.kuali.rice.krad.service.NoteService;
54 import org.kuali.rice.krad.util.GlobalVariables;
55 import org.kuali.rice.krad.util.KRADConstants;
56 import org.kuali.rice.krad.util.ObjectUtils;
57 import org.springframework.transaction.annotation.Transactional;
58
59 @Transactional
60 public class VendorServiceImpl implements VendorService {
61 private static final Logger LOG = Logger.getLogger(VendorServiceImpl.class);
62
63 protected BusinessObjectService businessObjectService;
64 protected DocumentService documentService;
65 protected DateTimeService dateTimeService;
66 protected VendorDao vendorDao;
67 protected NoteService noteService;
68
69 public BusinessObjectService getBusinessObjectService() {
70 if (businessObjectService == null) {
71 businessObjectService = KRADServiceLocator.getBusinessObjectService();
72 }
73 return businessObjectService;
74 }
75
76
77
78
79 @Override
80 public void saveVendorHeader(VendorDetail vendorDetail) {
81 getBusinessObjectService().save(vendorDetail.getVendorHeader());
82 }
83
84
85
86
87 @Override
88 public VendorDetail getByVendorNumber(String vendorNumber) {
89 return getVendorDetail(vendorNumber);
90 }
91
92
93
94
95 @Override
96 public VendorDetail getVendorDetail(String vendorNumber) {
97 if (LOG.isDebugEnabled()) {
98 LOG.debug("Entering getVendorDetail for vendorNumber: " + vendorNumber);
99 }
100 if (StringUtils.isBlank(vendorNumber)) {
101 return null;
102 }
103
104 int dashInd = vendorNumber.indexOf('-');
105
106 if (dashInd > 0 && dashInd < vendorNumber.length() - 1) {
107 try {
108 Integer headerId = new Integer(vendorNumber.substring(0, dashInd));
109 Integer detailId = new Integer(vendorNumber.substring(dashInd + 1));
110 return getVendorDetail(headerId, detailId);
111 }
112 catch (NumberFormatException e) {
113
114 return null;
115 }
116 }
117
118 return null;
119 }
120
121
122
123
124 @Override
125 public VendorDetail getVendorDetail(Integer headerId, Integer detailId) {
126 if (LOG.isDebugEnabled()) {
127 LOG.debug("Entering getVendorDetail for headerId:" + headerId + ", detailId:" + detailId);
128 }
129 HashMap<String, Integer> keys = new HashMap<String, Integer>();
130 keys.put("vendorHeaderGeneratedIdentifier", headerId);
131 keys.put("vendorDetailAssignedIdentifier", detailId);
132 return getBusinessObjectService().findByPrimaryKey(VendorDetail.class, keys);
133 }
134
135
136
137
138 @Override
139 public KualiDecimal getApoLimitFromContract(Integer contractId, String chart, String org) {
140 if (LOG.isDebugEnabled()) {
141 LOG.debug("Entering getApoLimitFromContract with contractId:" + contractId + ", chart:" + chart + ", org:" + org);
142 }
143
144
145 if (ObjectUtils.isNotNull(contractId) && ObjectUtils.isNotNull(chart) && ObjectUtils.isNotNull(org)) {
146 Map<String,Object> pkFields = new HashMap<String, Object>(3);
147 pkFields.put("vendorContractGeneratedIdentifier", contractId);
148 pkFields.put("chartOfAccountsCode", chart);
149 pkFields.put("organizationCode", org);
150 VendorContractOrganization contractOrg = getBusinessObjectService().findByPrimaryKey(VendorContractOrganization.class, pkFields);
151
152 if (ObjectUtils.isNotNull(contractOrg)) {
153
154 if (!contractOrg.isVendorContractExcludeIndicator()) {
155 return contractOrg.getVendorContractPurchaseOrderLimitAmount();
156 }
157
158 else {
159 return null;
160 }
161 }
162 }
163
164
165
166 if ( contractId != null ) {
167 VendorContract contract = getBusinessObjectService().findBySinglePrimaryKey(VendorContract.class, contractId);
168 if (contract != null) {
169 return contract.getOrganizationAutomaticPurchaseOrderLimit();
170 }
171 }
172
173
174 return null;
175 }
176
177
178
179
180 @Override
181 public VendorDetail getParentVendor(Integer vendorHeaderGeneratedIdentifier) {
182 if (LOG.isDebugEnabled()) {
183 LOG.debug("Entering getParentVendor for vendorHeaderGeneratedIdentifier:" + vendorHeaderGeneratedIdentifier);
184 }
185 Collection<VendorDetail> vendors = getBusinessObjectService().findMatching(VendorDetail.class,
186 Collections.singletonMap("vendorHeaderGeneratedIdentifier", vendorHeaderGeneratedIdentifier));
187 VendorDetail result = null;
188 if (vendors == null || vendors.isEmpty() ) {
189 LOG.warn("Error: No vendors exist with vendor header " + vendorHeaderGeneratedIdentifier + ".");
190 }
191 else {
192 for (VendorDetail vendor : vendors) {
193 if (vendor.isVendorParentIndicator()) {
194 if (ObjectUtils.isNull(result)) {
195 result = vendor;
196 }
197 else {
198 LOG.error("Error: More than one parent vendor for vendor header " + vendorHeaderGeneratedIdentifier + ".");
199 throw new RuntimeException("Error: More than one parent vendor for vendor header " + vendorHeaderGeneratedIdentifier + ".");
200 }
201 }
202 }
203 if (ObjectUtils.isNull(result)) {
204 LOG.error("Error: No parent vendor for vendor header " + vendorHeaderGeneratedIdentifier + ".");
205 throw new RuntimeException("Error: No parent vendor for vendor header " + vendorHeaderGeneratedIdentifier + ".");
206 }
207 }
208 LOG.debug("Exiting getParentVendor normally.");
209 return result;
210 }
211
212
213
214
215 @Override
216 public VendorDetail getVendorByDunsNumber(String vendorDunsNumber) {
217 if (LOG.isDebugEnabled()) {
218 LOG.debug("Entering getVendorByDunsNumber for vendorDunsNumber:" + vendorDunsNumber);
219 }
220 HashMap<String, String> criteria = new HashMap<String, String>();
221 criteria.put(VendorPropertyConstants.VENDOR_DUNS_NUMBER, vendorDunsNumber);
222 Collection<VendorDetail> vds = getBusinessObjectService().findMatching(VendorDetail.class, criteria);
223 LOG.debug("Exiting getVendorByDunsNumber.");
224 if (vds.size() < 1) {
225 return null;
226 }
227 else {
228 return vds.iterator().next();
229 }
230 }
231
232
233
234
235 @Override
236 public VendorAddress getVendorDefaultAddress(Integer vendorHeaderId, Integer vendorDetailId, String addressType, String campus) {
237 if (LOG.isDebugEnabled()) {
238 LOG.debug("Entering getVendorDefaultAddress for vendorHeaderId:" + vendorHeaderId + ", vendorDetailId:" + vendorDetailId + ", addressType:" + addressType + ", campus:" + campus);
239 }
240 HashMap<String, Object> criteria = new HashMap<String, Object>();
241 criteria.put(VendorPropertyConstants.VENDOR_HEADER_GENERATED_ID, vendorHeaderId);
242 criteria.put(VendorPropertyConstants.VENDOR_DETAIL_ASSIGNED_ID, vendorDetailId);
243 criteria.put(VendorPropertyConstants.VENDOR_ADDRESS_TYPE_CODE, addressType);
244 Collection<VendorAddress> addresses = getBusinessObjectService().findMatching(VendorAddress.class, criteria);
245 LOG.debug("Exiting getVendorDefaultAddress.");
246 return getVendorDefaultAddress(addresses, addressType, campus);
247 }
248
249
250
251
252 @Override
253 public VendorAddress getVendorDefaultAddress(Collection<VendorAddress> addresses, String addressType, String campus) {
254 LOG.debug("Entering getVendorDefaultAddress.");
255 VendorAddress allDefaultAddress = null;
256 for (VendorAddress address : addresses) {
257
258 if (addressType.equals(address.getVendorAddressTypeCode())) {
259
260 if (StringUtils.isNotEmpty(campus) && address.getVendorDefaultAddresses() != null) {
261
262 for (VendorDefaultAddress defaultCampus : address.getVendorDefaultAddresses()) {
263 if (campus.equals(defaultCampus.getVendorCampusCode())) {
264
265 LOG.debug("Exiting getVendorDefaultAddress with single campus default.");
266 return address;
267 }
268 }
269 }
270
271
272 if (address.isVendorDefaultAddressIndicator()) {
273 allDefaultAddress = address;
274 }
275 }
276 }
277
278
279 LOG.debug("Exiting getVendorDefaultAddress with default set for all.");
280 return allDefaultAddress;
281 }
282
283
284
285
286 @Override
287 public boolean shouldVendorRouteForApproval(String documentId) {
288 LOG.debug("Entering shouldVendorRouteForApproval.");
289 boolean shouldRoute = true;
290 MaintenanceDocument document = null;
291 try {
292 document = (MaintenanceDocument) documentService.getByDocumentHeaderId(documentId);
293 }
294 catch (WorkflowException we) {
295 throw new RuntimeException("A WorkflowException was thrown which prevented the loading of the comparison document (" + documentId + ")", we);
296 }
297
298 if (document == null) {
299
300 LOG.error( "Unable to retrieve document in workflow: " + documentId);
301 return false;
302 }
303 String maintenanceAction = document.getNewMaintainableObject().getMaintenanceAction();
304 if ( StringUtils.equals(KRADConstants.MAINTENANCE_NEW_ACTION, maintenanceAction)
305 || StringUtils.equals(KRADConstants.MAINTENANCE_NEWWITHEXISTING_ACTION, maintenanceAction)
306 || StringUtils.equals(KRADConstants.MAINTENANCE_COPY_ACTION, maintenanceAction) ) {
307 return true;
308 }
309 VendorDetail oldVendorDetail = (VendorDetail)document.getOldMaintainableObject().getBusinessObject();
310 if ( oldVendorDetail == null ) {
311
312 return true;
313 }
314 VendorHeader oldVendorHeader = oldVendorDetail.getVendorHeader();
315 if ( ObjectUtils.isNull(oldVendorHeader) ) {
316
317 return true;
318 }
319
320 VendorDetail newVendorDetail = (VendorDetail)document.getNewMaintainableObject().getBusinessObject();
321 if ( newVendorDetail == null ) {
322
323 return true;
324 }
325 VendorHeader newVendorHeader = newVendorDetail.getVendorHeader();
326
327 if ( ObjectUtils.isNull(newVendorHeader) ) {
328
329 return true;
330 }
331 return !noRouteSignificantChangeOccurred(newVendorDetail, newVendorHeader, oldVendorDetail, oldVendorHeader);
332 }
333
334
335
336
337
338
339 @Override
340 public boolean noRouteSignificantChangeOccurred(VendorDetail newVDtl, VendorHeader newVHdr, VendorDetail oldVDtl, VendorHeader oldVHdr) {
341 LOG.debug("Entering noRouteSignificantChangeOccurred.");
342
343
344 boolean unchanged = ((oldVHdr.isEqualForRouting(newVHdr))
345 && (equalMemberLists(oldVHdr.getVendorSupplierDiversities(), newVHdr.getVendorSupplierDiversities()))
346 && (oldVDtl.isEqualForRouting(newVDtl))
347 && (equalMemberLists(oldVDtl.getVendorAddresses(), newVDtl.getVendorAddresses()))
348 && (equalMemberLists(oldVDtl.getVendorContracts(), newVDtl.getVendorContracts()))
349 && (equalMemberLists(oldVDtl.getVendorShippingSpecialConditions(), newVDtl.getVendorShippingSpecialConditions())));
350
351 LOG.debug("Exiting noRouteSignificantChangeOccurred.");
352 return unchanged;
353 }
354
355
356
357
358 @Override
359 public boolean equalMemberLists(List<? extends VendorRoutingComparable> list_a, List<? extends VendorRoutingComparable> list_b) {
360 LOG.debug("Entering equalMemberLists.");
361 boolean result = true;
362 int listSize = list_a.size();
363 if (listSize != list_b.size()) {
364 LOG.debug("Exiting equalMemberLists because list sizes are unequal.");
365 return false;
366 }
367 VendorRoutingComparable aMember = null;
368 for (int i = 0; i < listSize; i++) {
369 aMember = list_a.get(i);
370 if (!aMember.isEqualForRouting(list_b.get(i))) {
371 result = false;
372 break;
373 }
374 }
375 LOG.debug("Exiting equalMemberLists.");
376 return result;
377 }
378
379
380
381
382 @Override
383 public boolean isVendorInstitutionEmployee(Integer vendorHeaderGeneratedIdentifier) {
384 VendorDetail vendorToUse = getParentVendor(vendorHeaderGeneratedIdentifier);
385 if (ObjectUtils.isNull(vendorToUse)) {
386 String errorMsg = "Vendor with header generated id '" + vendorHeaderGeneratedIdentifier + "' cannot be found in the system";
387 LOG.error(errorMsg);
388 throw new RuntimeException(errorMsg);
389 }
390 if (VendorConstants.TAX_TYPE_SSN.equals(vendorToUse.getVendorHeader().getVendorTaxTypeCode())) {
391 String ssnTaxId = vendorToUse.getVendorHeader().getVendorTaxNumber();
392 if (StringUtils.isNotBlank(ssnTaxId)) {
393 List<Person> personList = SpringContext.getBean(PersonService.class).getPersonByExternalIdentifier(org.kuali.rice.kim.api.KimConstants.PersonExternalIdentifierTypes.TAX, ssnTaxId);
394 if (personList != null && !personList.isEmpty()) {
395 return ObjectUtils.isNotNull(personList.get(0));
396 }
397 else {
398
399 return false;
400 }
401 }
402 }
403 return false;
404 }
405
406 public void createVendorNote(VendorDetail vendorDetail, String vendorNote) {
407 try {
408 if (StringUtils.isNotBlank(vendorNote)) {
409 Note newBONote = new Note();
410 newBONote.setNoteText(vendorNote);
411 newBONote.setNotePostedTimestampToCurrent();
412 newBONote.setNoteTypeCode(OLEConstants.NoteTypeEnum.BUSINESS_OBJECT_NOTE_TYPE.getCode());
413 Note note = noteService.createNote(newBONote, vendorDetail, GlobalVariables.getUserSession().getPrincipalId());
414 noteService.save(note);
415 }
416 } catch (Exception e){
417 throw new RuntimeException("Problems creating note for Vendor " + vendorDetail);
418 }
419 }
420
421 @Override
422 public List<Note> getVendorNotes(VendorDetail vendorDetail) {
423 List<Note> notes = new ArrayList<Note>();
424 if (ObjectUtils.isNotNull(vendorDetail)) {
425 notes = noteService.getByRemoteObjectId(vendorDetail.getObjectId());
426 }
427 return notes;
428 }
429
430
431
432
433 @Override
434 public boolean isVendorForeign(Integer vendorHeaderGeneratedIdentifier) {
435 VendorDetail vendorToUse = getParentVendor(vendorHeaderGeneratedIdentifier);
436 if (ObjectUtils.isNull(vendorToUse)) {
437 String errorMsg = "Vendor with header generated id '" + vendorHeaderGeneratedIdentifier + "' cannot be found in the system";
438 LOG.error(errorMsg);
439 throw new RuntimeException(errorMsg);
440 }
441 return vendorToUse.getVendorHeader().getVendorForeignIndicator();
442 }
443
444
445
446
447 @Override
448 public boolean isSubjectPaymentVendor(Integer vendorHeaderGeneratedIdentifier) {
449 VendorDetail vendorToUse = getParentVendor(vendorHeaderGeneratedIdentifier);
450 if (ObjectUtils.isNull(vendorToUse)) {
451 String errorMsg = "Vendor with header generated id '" + vendorHeaderGeneratedIdentifier + "' cannot be found in the system";
452 LOG.error(errorMsg);
453 throw new RuntimeException(errorMsg);
454 }
455 return VendorConstants.VendorTypes.SUBJECT_PAYMENT.equals(vendorToUse.getVendorHeader().getVendorTypeCode());
456 }
457
458
459
460
461 @Override
462 public boolean isRevolvingFundCodeVendor(Integer vendorHeaderGeneratedIdentifier) {
463 VendorDetail vendorToUse = getParentVendor(vendorHeaderGeneratedIdentifier);
464 if (ObjectUtils.isNull(vendorToUse)) {
465 String errorMsg = "Vendor with header generated id '" + vendorHeaderGeneratedIdentifier + "' cannot be found in the system";
466 LOG.error(errorMsg);
467 throw new RuntimeException(errorMsg);
468 }
469 return VendorConstants.VendorTypes.REVOLVING_FUND.equals(vendorToUse.getVendorHeader().getVendorTypeCode());
470 }
471
472
473
474
475
476 @Override
477 public Building getBuildingDetails(String campusCode, String buildingCode) {
478
479 Map keys = new HashMap();
480 keys.put("campusCode", campusCode);
481 keys.put("buildingCode", buildingCode);
482 return getBusinessObjectService().findByPrimaryKey(Building.class, keys);
483 }
484
485
486
487
488 @Override
489 public boolean isVendorContractExpired(Document document, VendorDetail vendorDetail) {
490 boolean isExpired = false;
491
492 Date currentDate = SpringContext.getBean(DateTimeService.class).getCurrentSqlDate();
493
494 List<VendorContract> vendorContracts = vendorDetail.getVendorContracts();
495 List<Note> notes = document.getNotes();
496
497 for (VendorContract vendorContract : vendorContracts) {
498 if (currentDate.compareTo(vendorContract.getVendorContractEndDate()) > 0 || !vendorContract.isActive()) {
499 Note newNote = new Note();
500 newNote.setNoteText("Vendor Contract: " + vendorContract.getVendorContractName() + " contract has expired contract end date.");
501 newNote.setNotePostedTimestampToCurrent();
502 newNote.setNoteTypeCode(OLEConstants.NoteTypeEnum.BUSINESS_OBJECT_NOTE_TYPE.getCode());
503 Note note = noteService.createNote(newNote, vendorDetail, GlobalVariables.getUserSession().getPrincipalId());
504 notes.add(note);
505 return true;
506 }
507 }
508
509 return isExpired;
510 }
511
512 @Override
513 public VendorContract getVendorB2BContract(VendorDetail vendorDetail, String campus) {
514 return SpringContext.getBean(org.kuali.ole.vnd.dataaccess.VendorDao.class).getVendorB2BContract(vendorDetail, campus, dateTimeService.getCurrentSqlDate());
515 }
516
517 public void setBusinessObjectService(BusinessObjectService boService) {
518 this.businessObjectService = boService;
519 }
520
521 public void setDocumentService(DocumentService documentService) {
522 this.documentService = documentService;
523 }
524
525 public void setVendorDao(VendorDao vendorDao) {
526 this.vendorDao = vendorDao;
527 }
528
529 public VendorDao getVendorDao() {
530 return this.vendorDao ;
531 }
532
533 public void setDateTimeService(DateTimeService dateTimeService) {
534 this.dateTimeService = dateTimeService;
535 }
536
537 }