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.io.ByteArrayOutputStream;
019    import java.sql.Date;
020    import java.text.MessageFormat;
021    import java.util.Collection;
022    import java.util.HashMap;
023    import java.util.List;
024    
025    import org.apache.commons.lang.StringUtils;
026    import org.apache.log4j.Logger;
027    import org.kuali.rice.kns.exception.ValidationException;
028    import org.kuali.rice.kns.service.DateTimeService;
029    import org.kuali.rice.kns.service.DocumentService;
030    import org.kuali.rice.kns.service.KualiConfigurationService;
031    import org.kuali.rice.kns.service.NoteService;
032    import org.kuali.rice.kns.util.GlobalVariables;
033    import org.kuali.rice.kns.util.ObjectUtils;
034    import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument;
035    import org.kuali.rice.kns.workflow.service.WorkflowDocumentService;
036    import org.kuali.kfs.module.purap.PurapConstants;
037    import org.kuali.kfs.module.purap.PurapKeyConstants;
038    import org.kuali.kfs.module.purap.PurapWorkflowConstants.PurchaseOrderDocument.NodeDetailEnum;
039    import org.kuali.kfs.module.purap.document.BulkReceivingDocument;
040    import org.kuali.kfs.module.purap.document.PurchaseOrderDocument;
041    import org.kuali.kfs.module.purap.document.CorrectionReceivingDocument;
042    import org.kuali.kfs.module.purap.document.ReceivingDocument;
043    import org.kuali.kfs.module.purap.document.LineItemReceivingDocument;
044    import org.kuali.kfs.module.purap.document.dataaccess.BulkReceivingDao;
045    import org.kuali.kfs.module.purap.document.service.BulkReceivingService;
046    import org.kuali.kfs.module.purap.document.service.PrintService;
047    import org.kuali.kfs.module.purap.document.service.PurapService;
048    import org.kuali.kfs.module.purap.document.service.PurchaseOrderService;
049    import org.kuali.kfs.module.purap.document.validation.event.AttributedContinuePurapEvent;
050    import org.kuali.kfs.sys.KFSConstants;
051    import org.kuali.kfs.sys.KFSPropertyConstants;
052    import org.kuali.kfs.sys.context.SpringContext;
053    import org.springframework.transaction.annotation.Transactional;
054    
055    import org.kuali.rice.kew.exception.WorkflowException;
056    
057    @Transactional
058    public class BulkReceivingServiceImpl implements BulkReceivingService {
059    
060        private static final Logger LOG = Logger.getLogger(BulkReceivingServiceImpl.class);
061        
062        private DateTimeService dateTimeService;
063        private PurchaseOrderService purchaseOrderService;
064        private BulkReceivingDao bulkReceivingDao;
065        private DocumentService documentService;
066        private WorkflowDocumentService workflowDocumentService;
067        private KualiConfigurationService configurationService;    
068        private PurapService purapService;
069        private NoteService noteService;
070        private KualiConfigurationService kualiConfigurationService;
071        private PrintService printService;
072        
073        public boolean canPrintReceivingTicket(BulkReceivingDocument blkRecDoc) {
074    
075            boolean canCreate = false;
076            KualiWorkflowDocument workflowDocument = null;
077            
078            try{
079                workflowDocument = workflowDocumentService.createWorkflowDocument(Long.valueOf(blkRecDoc.getDocumentNumber()), GlobalVariables.getUserSession().getPerson());
080            }catch(WorkflowException we){
081                throw new RuntimeException(we);
082            }
083    
084            if( workflowDocument.stateIsFinal()){            
085                canCreate = true;
086            }
087            
088            return canCreate;
089        }
090        
091        public void populateAndSaveBulkReceivingDocument(BulkReceivingDocument blkRecDoc) 
092        throws WorkflowException {
093            try {            
094                documentService.saveDocument(blkRecDoc, AttributedContinuePurapEvent.class);
095            }
096            catch (WorkflowException we) {
097                String errorMsg = "Error saving document # " + blkRecDoc.getDocumentHeader().getDocumentNumber() + " " + we.getMessage();
098                throw new RuntimeException(errorMsg, we);
099            }
100        }
101        
102        public HashMap<String, String> bulkReceivingDuplicateMessages(BulkReceivingDocument blkRecDoc) {
103            HashMap<String, String> msgs;
104            msgs = new HashMap<String, String>();
105            Integer poId = blkRecDoc.getPurchaseOrderIdentifier();
106            StringBuffer currentMessage = new StringBuffer("");
107            List<String> docNumbers = null;
108            
109            //check vendor date for duplicates
110            if( blkRecDoc.getShipmentReceivedDate() != null ){
111                docNumbers = bulkReceivingDao.duplicateVendorDate(poId, blkRecDoc.getShipmentReceivedDate());
112                if( hasDuplicateEntry(docNumbers) ){
113                    appendDuplicateMessage(currentMessage, PurapKeyConstants.MESSAGE_DUPLICATE_RECEIVING_LINE_VENDOR_DATE, blkRecDoc.getPurchaseOrderIdentifier());                                
114                }
115            }
116            
117            //check packing slip number for duplicates
118            if( !StringUtils.isEmpty(blkRecDoc.getShipmentPackingSlipNumber()) ){
119                docNumbers = bulkReceivingDao.duplicatePackingSlipNumber(poId, blkRecDoc.getShipmentPackingSlipNumber());
120                if( hasDuplicateEntry(docNumbers) ){
121                    appendDuplicateMessage(currentMessage, PurapKeyConstants.MESSAGE_DUPLICATE_RECEIVING_LINE_PACKING_SLIP_NUMBER, blkRecDoc.getPurchaseOrderIdentifier());                                
122                }
123            }
124            
125            //check bill of lading number for duplicates
126            if( !StringUtils.isEmpty(blkRecDoc.getShipmentBillOfLadingNumber()) ){
127                docNumbers = bulkReceivingDao.duplicateBillOfLadingNumber(poId, blkRecDoc.getShipmentBillOfLadingNumber());
128                if( hasDuplicateEntry(docNumbers) ){
129                    appendDuplicateMessage(currentMessage, PurapKeyConstants.MESSAGE_DUPLICATE_RECEIVING_LINE_BILL_OF_LADING_NUMBER, blkRecDoc.getPurchaseOrderIdentifier());                
130                }
131            }
132            
133           //add message if one exists
134           if(currentMessage.length() > 0){
135               //add suffix
136               appendDuplicateMessage(currentMessage, PurapKeyConstants.MESSAGE_DUPLICATE_RECEIVING_LINE_SUFFIX, blkRecDoc.getPurchaseOrderIdentifier() );
137               
138               //add msg to map
139               msgs.put(PurapConstants.BulkReceivingDocumentStrings.DUPLICATE_BULK_RECEIVING_DOCUMENT_QUESTION, currentMessage.toString());
140           }
141           
142           return msgs;
143        }
144    
145        /**
146         * Looks at a list of doc numbers, but only considers an entry duplicate
147         * if the document is in a Final status.
148         * 
149         * @param docNumbers
150         * @return
151         */
152        protected boolean hasDuplicateEntry(List<String> docNumbers){
153            
154            boolean isDuplicate = false;
155            KualiWorkflowDocument workflowDocument = null;
156            
157            for (String docNumber : docNumbers) {
158            
159                try{
160                    workflowDocument = workflowDocumentService.createWorkflowDocument(Long.valueOf(docNumber), GlobalVariables.getUserSession().getPerson());
161                }catch(WorkflowException we){
162                    throw new RuntimeException(we);
163                }
164                
165                //if the doc number exists, and is in final status, consider this a dupe and return
166                if(workflowDocument.stateIsFinal()){
167                    isDuplicate = true;
168                    break;
169                }
170            }
171            
172            return isDuplicate;
173    
174        }
175        
176        protected void appendDuplicateMessage(StringBuffer currentMessage, 
177                                            String duplicateMessageKey, 
178                                            Integer poId){
179            
180            //append prefix if this is first call
181            if(currentMessage.length() == 0){
182                String messageText = configurationService.getPropertyString(PurapKeyConstants.MESSAGE_BULK_RECEIVING_DUPLICATE_PREFIX);
183                String prefix = MessageFormat.format(messageText, poId.toString() );
184                
185                currentMessage.append(prefix);
186            }
187            
188            //append message
189            currentMessage.append( configurationService.getPropertyString(duplicateMessageKey) );                
190        }
191        
192        public String getBulkReceivingDocumentNumberInProcessForPurchaseOrder(Integer poId, 
193                                                                              String bulkReceivingDocumentNumber){
194            
195            String docNumberInProcess = StringUtils.EMPTY;
196            
197            List<String> docNumbers = bulkReceivingDao.getDocumentNumbersByPurchaseOrderId(poId);
198            KualiWorkflowDocument workflowDocument = null;
199                    
200            for (String docNumber : docNumbers) {
201            
202                try{
203                    workflowDocument = workflowDocumentService.createWorkflowDocument(Long.valueOf(docNumber), 
204                                                                                      GlobalVariables.getUserSession().getPerson());
205                }catch(WorkflowException we){
206                    throw new RuntimeException(we);
207                }
208                
209                if(!(workflowDocument.stateIsCanceled() ||
210                     workflowDocument.stateIsException() ||
211                     workflowDocument.stateIsFinal()) &&
212                     !docNumber.equals(bulkReceivingDocumentNumber)){
213                         
214                    docNumberInProcess = docNumber;
215                    break;
216                }
217            }
218    
219            return docNumberInProcess;
220        }
221    
222        public void populateBulkReceivingFromPurchaseOrder(BulkReceivingDocument blkRecDoc) {
223            
224            if (blkRecDoc != null){
225                PurchaseOrderDocument poDoc = purchaseOrderService.getCurrentPurchaseOrder(blkRecDoc.getPurchaseOrderIdentifier());
226                if(poDoc != null){
227                    blkRecDoc.populateBulkReceivingFromPurchaseOrder(poDoc);
228                }
229            }
230            
231        }
232    
233        public BulkReceivingDocument getBulkReceivingByDocumentNumber(String documentNumber){
234            
235            if (ObjectUtils.isNotNull(documentNumber)) {
236                try {
237                    BulkReceivingDocument doc = (BulkReceivingDocument) documentService.getByDocumentHeaderId(documentNumber);
238                    if (ObjectUtils.isNotNull(doc)) {
239                        KualiWorkflowDocument workflowDocument = doc.getDocumentHeader().getWorkflowDocument();
240                        doc.refreshReferenceObject(KFSPropertyConstants.DOCUMENT_HEADER);
241                        doc.getDocumentHeader().setWorkflowDocument(workflowDocument);
242                    }
243                    return doc;
244                }
245                catch (WorkflowException e) {
246                    String errorMessage = "Error getting bulk receiving document from document service";
247                    throw new RuntimeException(errorMessage, e);
248                }
249            }
250            return null;
251        }
252        
253        public void performPrintReceivingTicketPDF(String blkDocId, 
254                                                   ByteArrayOutputStream baosPDF){
255            
256            BulkReceivingDocument blkRecDoc = getBulkReceivingByDocumentNumber(blkDocId);
257            Collection<String> generatePDFErrors = printService.generateBulkReceivingPDF(blkRecDoc, baosPDF);
258            
259            if (!generatePDFErrors.isEmpty()) {
260                addStringErrorMessagesToErrorMap(PurapKeyConstants.ERROR_BULK_RECEIVING_PDF, generatePDFErrors);
261                throw new ValidationException("printing bulk receiving ticket failed");
262            }
263            
264        }
265        
266        protected void addStringErrorMessagesToErrorMap(String errorKey, 
267                                                      Collection<String> errors) {
268            
269            if (ObjectUtils.isNotNull(errors)) {
270                for (String error : errors) {
271                    LOG.error("Adding error message using error key '" + errorKey + "' with text '" + error + "'");
272                    GlobalVariables.getMessageMap().putError(KFSConstants.GLOBAL_ERRORS, errorKey, error);
273                }
274            }
275            
276        }
277        
278        public KualiConfigurationService getKualiConfigurationService() {
279            return kualiConfigurationService;
280        }
281    
282        public void setKualiConfigurationService(KualiConfigurationService kualiConfigurationService) {
283            this.kualiConfigurationService = kualiConfigurationService;
284        }
285    
286        public PrintService getPrintService() {
287            return printService;
288        }
289    
290        public void setPrintService(PrintService printService) {
291            this.printService = printService;
292        }
293        
294        public void setPurchaseOrderService(PurchaseOrderService purchaseOrderService) {
295            this.purchaseOrderService = purchaseOrderService;
296        }
297    
298        public void setBulkReceivingDao(BulkReceivingDao bulkReceivingDao) {
299            this.bulkReceivingDao = bulkReceivingDao;
300        }
301    
302        public void setDocumentService(DocumentService documentService){
303            this.documentService = documentService;
304        }
305    
306        public void setWorkflowDocumentService(WorkflowDocumentService workflowDocumentService){
307            this.workflowDocumentService = workflowDocumentService;
308        }
309    
310        public void setConfigurationService(KualiConfigurationService configurationService) {
311            this.configurationService = configurationService;
312        }
313    
314        public void setPurapService(PurapService purapService) {
315            this.purapService = purapService;
316        }
317    
318        public void setNoteService(NoteService noteService) {
319            this.noteService = noteService;
320        }
321    
322        public DateTimeService getDateTimeService() {
323            return dateTimeService;
324        }
325    
326        public void setDateTimeService(DateTimeService dateTimeService) {
327            this.dateTimeService = dateTimeService;
328        }
329    }
330