001: /*
002: * Copyright 2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.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/ecl1.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.module.vendor.maintenance;
017:
018: import java.util.ArrayList;
019: import java.util.HashMap;
020: import java.util.Iterator;
021: import java.util.List;
022: import java.util.Map;
023:
024: import org.apache.commons.lang.StringUtils;
025: import org.kuali.RiceConstants;
026: import org.kuali.core.bo.Note;
027: import org.kuali.core.bo.PersistableBusinessObject;
028: import org.kuali.core.bo.user.AuthenticationUserId;
029: import org.kuali.core.bo.user.UniversalUser;
030: import org.kuali.core.document.MaintenanceDocument;
031: import org.kuali.core.document.MaintenanceLock;
032: import org.kuali.core.exceptions.UserNotFoundException;
033: import org.kuali.core.maintenance.KualiMaintainableImpl;
034: import org.kuali.core.maintenance.Maintainable;
035: import org.kuali.core.service.BusinessObjectService;
036: import org.kuali.core.service.NoteService;
037: import org.kuali.core.service.UniversalUserService;
038: import org.kuali.core.util.GlobalVariables;
039: import org.kuali.core.util.ObjectUtils;
040: import org.kuali.core.web.ui.Field;
041: import org.kuali.core.web.ui.Row;
042: import org.kuali.core.web.ui.Section;
043: import org.kuali.kfs.context.SpringContext;
044: import org.kuali.kfs.service.ParameterService;
045: import org.kuali.module.purap.PurapParameterConstants;
046: import org.kuali.module.vendor.VendorConstants;
047: import org.kuali.module.vendor.VendorPropertyConstants;
048: import org.kuali.module.vendor.bo.VendorContract;
049: import org.kuali.module.vendor.bo.VendorDetail;
050: import org.kuali.module.vendor.bo.VendorHeader;
051: import org.kuali.module.vendor.service.VendorService;
052:
053: public class VendorMaintainableImpl extends KualiMaintainableImpl {
054: private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
055: .getLogger(VendorMaintainableImpl.class);
056:
057: /**
058: * @see org.kuali.core.maintenance.KualiMaintainableImpl#setGenerateDefaultValues(boolean)
059: */
060: @Override
061: public void setGenerateDefaultValues(boolean generateDefaultValues) {
062: super .setGenerateDefaultValues(generateDefaultValues);
063: if (this .getBusinessObject().getBoNotes().isEmpty()) {
064: setVendorCreateAndUpdateNote(VendorConstants.VendorCreateAndUpdateNotePrefixes.ADD);
065: }
066: }
067:
068: /**
069: * Overrides the kuali default documents title with a Vendor-specific document title style
070: *
071: * @see org.kuali.core.maintenance.KualiMaintainableImpl#getDocumentTitle(org.kuali.core.document.MaintenanceDocument)
072: */
073: @Override
074: public String getDocumentTitle(MaintenanceDocument document) {
075: String documentTitle = "";
076: // Check if we are choosing to override the Kuali default document title.
077: String specificTitle = SpringContext
078: .getBean(ParameterService.class)
079: .getParameterValue(
080: VendorDetail.class,
081: PurapParameterConstants.PURAP_OVERRIDE_VENDOR_DOC_TITLE);
082:
083: if (StringUtils.equals(specificTitle, Boolean.TRUE.toString())) {
084: // We are overriding the standard with a Vendor-specific document title style.
085: if (document.isOldBusinessObjectInDocument()) {
086: documentTitle = "Edit Vendor - ";
087: } else {
088: documentTitle = "New Vendor - ";
089: }
090:
091: try {
092: UniversalUser initUser = SpringContext.getBean(
093: UniversalUserService.class).getUniversalUser(
094: new AuthenticationUserId(document
095: .getDocumentHeader()
096: .getWorkflowDocument()
097: .getInitiatorNetworkId()));
098: documentTitle += initUser.getCampusCode();
099: } catch (UserNotFoundException e) {
100: throw new RuntimeException(
101: "Document Initiator not found "
102: + e.getMessage());
103: }
104:
105: VendorDetail newBo = (VendorDetail) document
106: .getNewMaintainableObject().getBusinessObject();
107:
108: if (StringUtils.isNotBlank(newBo.getVendorName())) {
109: documentTitle += " '" + newBo.getVendorName() + "'";
110: }
111:
112: if (newBo.getVendorHeader().getVendorForeignIndicator()) {
113: documentTitle += " (F)";
114: }
115:
116: if (!newBo.isVendorParentIndicator()) {
117: documentTitle += " (D)";
118: }
119: } else { // We are using the Kuali default document title.
120: documentTitle = super .getDocumentTitle(document);
121: }
122: return documentTitle;
123: }
124:
125: /**
126: * Refreshes the vendorDetail. Currently we need this mainly for refreshing the soldToVendor object after returning from the
127: * lookup for a sold to vendor.
128: *
129: * @see org.kuali.core.maintenance.KualiMaintainableImpl#refresh(java.lang.String, java.util.Map,
130: * org.kuali.core.document.MaintenanceDocument)
131: */
132: @Override
133: public void refresh(String refreshCaller, Map fieldValues,
134: MaintenanceDocument document) {
135: PersistableBusinessObject oldBo = (PersistableBusinessObject) document
136: .getOldMaintainableObject().getBusinessObject();
137: if (ObjectUtils.isNotNull(oldBo)) {
138: oldBo.refreshNonUpdateableReferences();
139: }
140: VendorDetail newBo = (VendorDetail) document
141: .getNewMaintainableObject().getBusinessObject();
142: // Here we have to temporarily save vendorHeader into a temp object, then put back
143: // the vendorHeader into the newBo after the refresh, so that we don't lose the
144: // values
145: VendorHeader tempHeader = newBo.getVendorHeader();
146: newBo.refreshNonUpdateableReferences();
147: newBo.setVendorHeader(tempHeader);
148: super .refresh(refreshCaller, fieldValues, document);
149: }
150:
151: /**
152: * Temporarily saves vendorHeader into a temp object, then put back the vendorHeader into the VendorDetail after the refresh, so
153: * that we don't lose the values
154: */
155: public void refreshBusinessObject() {
156: VendorDetail vd = (VendorDetail) getBusinessObject();
157: // Here we have to temporarily save vendorHeader into a temp object, then put back
158: // the vendorHeader into the VendorDetail after the refresh, so that we don't lose the
159: // values
160: VendorHeader tempHeader = vd.getVendorHeader();
161: vd.refreshNonUpdateableReferences();
162: vd.setVendorHeader(tempHeader);
163: }
164:
165: /**
166: * Checks whether the vendor has already had a vendor detail assigned id. If not, it will call the private method to set the
167: * detail assigned id. The method will also call the vendorService to determine whether it should save the vendor header (i.e.
168: * if this is a parent) and will save the vendor header accordingly. This is because we are not going to save vendor header
169: * automatically along with the saving of vendor detail, so if the vendor is a parent, we have to save the vendor header
170: * separately. Restriction-related information will be changed based on whether the Vendor Restricted Indicator was changed. If
171: * the Tax Number or Tax Type code have changed, the fact will be recorded with a new record in the Tax Change table. Finally
172: * the method will call the saveBusinessObject( ) of the super class to save the vendor detail.
173: *
174: * @see org.kuali.core.maintenance.KualiMaintainableImpl#saveBusinessObject()
175: */
176: @Override
177: public void saveBusinessObject() {
178: VendorDetail vendorDetail = (VendorDetail) super
179: .getBusinessObject();
180: VendorHeader vendorHeader = vendorDetail.getVendorHeader();
181:
182: // Update miscellaneous information and save the Vendor Header if this is a parent vendor.
183: setVendorName(vendorDetail);
184: vendorHeader.setVendorHeaderGeneratedIdentifier(vendorDetail
185: .getVendorHeaderGeneratedIdentifier());
186: if (ObjectUtils.isNull(vendorDetail
187: .getVendorDetailAssignedIdentifier())) {
188: setDetailAssignedId(vendorDetail);
189: }
190: if (vendorDetail.isVendorParentIndicator()) {
191: SpringContext.getBean(VendorService.class)
192: .saveVendorHeader(vendorDetail);
193: }
194: super .saveBusinessObject();
195: }
196:
197: /**
198: * @see org.kuali.core.maintenance.KualiMaintainableImpl#processAfterEdit()
199: */
200: @Override
201: public void processAfterEdit() {
202: setVendorCreateAndUpdateNote(VendorConstants.VendorCreateAndUpdateNotePrefixes.CHANGE);
203: }
204:
205: /**
206: * Checks whether the previous note was an "Add" with the same document number as this one
207: *
208: * @param prefix String to determine if it is a note "Add" or a note "Change"
209: */
210: private void setVendorCreateAndUpdateNote(String prefix) {
211: boolean shouldAddNote = true;
212: if (prefix
213: .equals(VendorConstants.VendorCreateAndUpdateNotePrefixes.CHANGE)) {
214: // Check whether the previous note was an "Add" with the same document number as this one
215: if (!this .getBusinessObject().getBoNotes().isEmpty()) {
216: Note previousNote = this .getBusinessObject()
217: .getBoNote(
218: this .getBusinessObject().getBoNotes()
219: .size() - 1);
220: if (previousNote.getNoteText().contains(
221: this .documentNumber)) {
222: shouldAddNote = false;
223: }
224: }
225: }
226: if (shouldAddNote) {
227: Note newBONote = new Note();
228: newBONote.setNoteText(prefix + " vendor document ID "
229: + this .documentNumber);
230: try {
231: newBONote = SpringContext
232: .getBean(NoteService.class)
233: .createNote(newBONote, this .getBusinessObject());
234: } catch (Exception e) {
235: throw new RuntimeException(
236: "Caught Exception While Trying To Add Note to Vendor",
237: e);
238: }
239: this .getBusinessObject().getBoNotes().add(newBONote);
240: }
241: }
242:
243: /**
244: * Concatenates the vendorLastName and a delimiter and the vendorFirstName fields into vendorName field of the vendorDetail
245: * object.
246: *
247: * @param vendorDetail VendorDetail The vendor whose name field we are trying to assign
248: */
249: private void setVendorName(VendorDetail vendorDetail) {
250: if (vendorDetail.isVendorFirstLastNameIndicator()) {
251: vendorDetail.setVendorName(vendorDetail.getVendorLastName()
252: + VendorConstants.NAME_DELIM
253: + vendorDetail.getVendorFirstName());
254: }
255: }
256:
257: /**
258: * If the vendorFirstLastNameIndicator is true, this method will set the vendor first name and vendor last name fields from the
259: * vendorName field, then set the vendorName field to null. Then it sets the businessObject of this maintainable to the
260: * VendorDetail object that contains our modification to the name fields.
261: *
262: * @see org.kuali.core.maintenance.Maintainable#saveBusinessObject()
263: */
264: @Override
265: public void setBusinessObject(PersistableBusinessObject bo) {
266: VendorDetail originalBo = (VendorDetail) bo;
267: String vendorName = originalBo.getVendorName();
268: if (originalBo.isVendorFirstLastNameIndicator()
269: && ObjectUtils.isNotNull(vendorName)) {
270: int start = vendorName.indexOf(VendorConstants.NAME_DELIM);
271: if (start >= 0) {
272: String lastName = vendorName.substring(0, start);
273: String firstName = new String();
274: if (start + VendorConstants.NAME_DELIM.length() <= vendorName
275: .length()) {
276: firstName = vendorName.substring(start
277: + VendorConstants.NAME_DELIM.length(),
278: vendorName.length());
279: }
280:
281: originalBo.setVendorFirstName((ObjectUtils
282: .isNotNull(firstName) ? firstName.trim()
283: : firstName));
284: originalBo.setVendorLastName((ObjectUtils
285: .isNotNull(lastName) ? lastName.trim()
286: : lastName));
287: originalBo.setVendorName(null);
288: }
289: }
290: this .businessObject = originalBo;
291: }
292:
293: /**
294: * Sets a valid detail assigned id to a vendor if the vendor has not had a detail assigned id yet. If this is a new parent whose
295: * header id is also null, this method will assign 0 as the detail assigned id. If this is a new division vendor, it will look
296: * for the count of vendor details in the database whose vendor header id match with the vendor header id of this new division,
297: * then look for the count of vendor details in the database, in a while loop, to find if a vendor detail with the same header
298: * id and detail id as the count has existed. If a vendor with such criteria exists, this method will increment the count
299: * by 1 and look up in the database again. If it does not exist, assign the count as the vendor detail id and change the
300: * boolean flag to stop the loop, because we have already found the valid detail assigned id that we were looking for
301: *
302: * @param vendorDetail VendorDetail The vendor whose detail assigned id we're trying to assign.
303: */
304: private void setDetailAssignedId(VendorDetail vendorDetail) {
305: // If this is a new parent, let's set the detail id to 0.
306: if (ObjectUtils.isNull(vendorDetail
307: .getVendorHeaderGeneratedIdentifier())) {
308: vendorDetail.setVendorDetailAssignedIdentifier(new Integer(
309: 0));
310: } else {
311: // Try to get the count of all the vendor whose header id is the same as this header id.
312: Map criterias = new HashMap();
313: criterias.put(
314: VendorPropertyConstants.VENDOR_HEADER_GENERATED_ID,
315: vendorDetail.getVendorHeaderGeneratedIdentifier());
316: BusinessObjectService boService = SpringContext
317: .getBean(BusinessObjectService.class);
318: int count = boService.countMatching(VendorDetail.class,
319: criterias);
320: boolean validId = false;
321: while (!validId) {
322: criterias
323: .put(
324: VendorPropertyConstants.VENDOR_DETAIL_ASSIGNED_ID,
325: count);
326: int result = boService.countMatching(
327: VendorDetail.class, criterias);
328: if (result > 0) {
329: // increment the detail id by 1
330: count++;
331: } else {
332: // count is a validId, so we'll use count as our vendor detail assigned id
333: validId = true;
334: vendorDetail
335: .setVendorDetailAssignedIdentifier(new Integer(
336: count));
337: }
338: }
339: }
340: }
341:
342: /**
343: * Returns the locking representation of the vendor. If the vendor detail id is not null, call the super class
344: * implementation of generateMaintenanceLocks which will set the locking key to be the header and detail ids. However, if the
345: * detail id is null, that means this is a new vendor (parent or division) and we should ignore locking.
346: *
347: * @see org.kuali.core.maintenance.Maintainable#generateMaintenanceLocks()
348: */
349: @Override
350: public List<MaintenanceLock> generateMaintenanceLocks() {
351:
352: if (ObjectUtils.isNotNull(((VendorDetail) getBusinessObject())
353: .getVendorDetailAssignedIdentifier())) {
354: return super .generateMaintenanceLocks();
355: } else {
356: return new ArrayList();
357: }
358: }
359:
360: /**
361: * Create a new division vendor if the user clicks on the "Create a new division" link. By default, the vendorParentIndicator is
362: * set to true in the constructor of VendorDetail, but if we're creating a new division, it's not a parent, so we need to set
363: * the vendorParentIndicator to false in this case.
364: *
365: * @see org.kuali.core.maintenance.Maintainable#setupNewFromExisting()
366: */
367: @Override
368: public void setupNewFromExisting() {
369: ((VendorDetail) super .getBusinessObject())
370: .setVendorParentIndicator(false);
371: ((VendorDetail) super .getBusinessObject())
372: .setActiveIndicator(true);
373:
374: setVendorCreateAndUpdateNote(VendorConstants.VendorCreateAndUpdateNotePrefixes.ADD);
375: }
376:
377: /**
378: * Overrides the section implementation to turn off the include add line property unless the user
379: * is in the vendor contract workgroup.
380: *
381: * Also, unless this is a vendor parent, don't show the vendor diversity add line.
382: *
383: * @see org.kuali.core.maintenance.KualiMaintainableImpl#getSections(org.kuali.core.maintenance.Maintainable)
384: */
385: @Override
386: public List getSections(Maintainable oldMaintainable) {
387: List<Section> sections = super .getSections(oldMaintainable);
388: UniversalUser currentUser = (UniversalUser) GlobalVariables
389: .getUserSession().getUniversalUser();
390: String vendorContractWorkgroup = SpringContext.getBean(
391: ParameterService.class).getParameterValue(
392: VendorContract.class,
393: VendorConstants.Workgroups.WORKGROUP_VENDOR_CONTRACT);
394: boolean isVendorParent = ((VendorDetail) getBusinessObject())
395: .isVendorParentIndicator();
396: boolean isInVendorContractGroup = currentUser
397: .isMember(vendorContractWorkgroup);
398: if (!isVendorParent || !isInVendorContractGroup) {
399: for (Section section : sections) {
400: if (!isVendorParent) {
401: if (section
402: .getContainedCollectionNames()
403: .contains(
404: VendorPropertyConstants.VENDOR_HEADER_PREFIX
405: + VendorPropertyConstants.VENDOR_SUPPLIER_DIVERSITIES)) {
406: Iterator<Row> rows = section.getRows()
407: .iterator();
408: while (rows.hasNext()) {
409: Row row = rows.next();
410: if (row.getFields().size() > 0) {
411: Field field = row.getFields().get(0);
412: if (StringUtils
413: .equals(
414: field.getPropertyName(),
415: VendorPropertyConstants.VENDOR_HEADER_PREFIX
416: + VendorPropertyConstants.VENDOR_SUPPLIER_DIVERSITIES)) {
417: rows.remove();
418: }
419: }
420: }
421: }
422: }
423: // If the user is not in vendor contract workgroup, don't include add line for vendor contract and vendor contract
424: // organization
425: if (!isInVendorContractGroup) {
426: if (section.getContainedCollectionNames().contains(
427: VendorPropertyConstants.VENDOR_CONTRACT)
428: || section
429: .getContainedCollectionNames()
430: .contains(
431: VendorPropertyConstants.VENDOR_CONTRACT_ORGANIZATION)) {
432: Iterator<Row> rows = section.getRows()
433: .iterator();
434: while (rows.hasNext()) {
435: Row row = rows.next();
436: if (row.getFields().size() > 0) {
437: Field field = row.getFields().get(0);
438: if (StringUtils
439: .equals(
440: field.getPropertyName(),
441: VendorPropertyConstants.VENDOR_CONTRACT)) {
442: rows.remove();
443: continue;
444: }
445: if (StringUtils.equals(field
446: .getFieldType(), "container")
447: && field
448: .getContainerName()
449: .startsWith(
450: VendorPropertyConstants.VENDOR_CONTRACT
451: + "[")) {
452: Iterator<Row> cRows = field
453: .getContainerRows()
454: .iterator();
455: while (cRows.hasNext()) {
456: Field cField = cRows.next()
457: .getFields().get(0);
458: if (StringUtils
459: .equals(
460: cField
461: .getPropertyName(),
462: VendorPropertyConstants.VENDOR_CONTRACT_ORGANIZATION)) {
463: cRows.remove();
464: continue;
465: }
466: }
467: }
468: }
469: }
470: }
471: }
472: }
473: }
474:
475: return sections;
476: }
477:
478: /**
479: * @see org.kuali.core.maintenance.KualiMaintainableImpl#isRelationshipRefreshable(java.lang.Class, java.lang.String)
480: */
481: @Override
482: protected boolean isRelationshipRefreshable(Class boClass,
483: String relationshipName) {
484: if (VendorDetail.class.isAssignableFrom(boClass)
485: && VendorConstants.VENDOR_HEADER_ATTR
486: .equals(relationshipName)) {
487: return false;
488: }
489: return super.isRelationshipRefreshable(boClass,
490: relationshipName);
491: }
492:
493: }
|