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