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;
017    
018    import java.io.ByteArrayOutputStream;
019    import java.util.ArrayList;
020    import java.util.HashMap;
021    import java.util.List;
022    
023    import org.kuali.kfs.integration.purap.CapitalAssetSystem;
024    import org.kuali.kfs.module.purap.businessobject.PurchaseOrderItem;
025    import org.kuali.kfs.module.purap.businessobject.PurchaseOrderQuoteStatus;
026    import org.kuali.kfs.module.purap.businessobject.PurchaseOrderVendorQuote;
027    import org.kuali.kfs.module.purap.businessobject.PurchasingCapitalAssetItem;
028    import org.kuali.kfs.module.purap.document.ContractManagerAssignmentDocument;
029    import org.kuali.kfs.module.purap.document.PurchaseOrderDocument;
030    import org.kuali.kfs.module.purap.document.PurchaseOrderSplitDocument;
031    import org.kuali.kfs.module.purap.document.RequisitionDocument;
032    import org.kuali.kfs.vnd.businessobject.VendorDetail;
033    import org.kuali.rice.kns.bo.Note;
034    import org.kuali.rice.kns.util.KualiDecimal;
035    
036    /**
037     * Defines methods that must be implemented by classes providing a PurchaseOrderService.
038     */
039    public interface PurchaseOrderService extends PurchasingDocumentSpecificService {
040    
041        public boolean isPurchaseOrderOpenForProcessing(Integer poId);
042        
043        public boolean isPurchaseOrderOpenForProcessing(PurchaseOrderDocument purchaseOrderDocument);
044    
045        /**
046         * Creates an automatic purchase order document using the given requisition document
047         * 
048         * @param reqDocument The requisition document that this method will use to create the Automated Purchase Order (APO).
049         */
050        public void createAutomaticPurchaseOrderDocument(RequisitionDocument reqDocument);
051    
052        /**
053         * Creates a PurchaseOrderDocument from given RequisitionDocument. Both documents need to be saved after this method is called.
054         * 
055         * @param reqDocument The requisition document that this method will use to create the purchase order.
056         * @param newSessionUserId The session user id that we'll use to invoke the performLogicWithFakedUserSession method of
057         *        PurapService.
058         * @param contractManagerCode The contract manager code that we'll need to set on the purchase order.
059         * @return The purchase order document object that is created by this method.
060         */
061        public PurchaseOrderDocument createPurchaseOrderDocument(RequisitionDocument reqDocument, String newSessionUserId, Integer contractManagerCode);
062    
063        /**
064         * Creates and saves the purchase order change document (for example, PurchaseOrderAmendmentDocument) based on an existing
065         * purchase order document.
066         * 
067         * @param documentNumber The document number of the existing purchase order document from which we try to create a new change
068         *        document.
069         * @param docType The document type of the new change document.
070         * @param newDocumentStatusCode The status code that we want to set on the existing purchase order document after the new change
071         *        document is created.
072         * @return The resulting new purchase order change document created by this method.
073         */
074        public PurchaseOrderDocument createAndSavePotentialChangeDocument(String documentNumber, String docType, String newDocumentStatusCode);
075    
076        /**
077         * Creates and routes the purchase order change document (for example, PurchaseOrderCloseDocument) based on an existing purchase
078         * order document.
079         * 
080         * @param
081         * @param documentNumber The document number of the existing purchase order document from which we try to create a new change
082         *        document.
083         * @param docType The document type of the new change document.
084         * @param annotation The annotation that we'll use to invoke the routeDocument method of DocumentService.
085         * @param adhocRoutingRecipients The adhocRoutingRecipients that we'll use to invoke the routeDocument method of
086         *        DocumentService.
087         * @param newDocumentStatusCode The status code that we want to set on the existing purchase order document after the new change
088         *        document is created.
089         * @return The resulting new purchase order change document created by this method.
090         */
091        public PurchaseOrderDocument createAndRoutePotentialChangeDocument(String documentNumber, String docType, String annotation, List adhocRoutingRecipients, String newDocumentStatusCode);
092        
093        /**
094         * Creates and saves a Purchase Order Split document based on the old PO document, and the items from that PO that the 
095         * new Split PO is to contain.
096         * 
097         * @param newPOItems        The List<PurchaseOrderItem> of the items that the new Split PO is to contain
098         * @param currentDocument   The original PurchaseOrderDocument 
099         * @param copyNotes         A boolean.  True if notes are to be copied from the old document to the new.
100         * @param splitNoteText     A String containing the text of the note to be added to the old document.
101         * @return  A PurchaseOrderSplitDocument containing the given list of items
102         */
103        public PurchaseOrderSplitDocument createAndSavePurchaseOrderSplitDocument(List<PurchaseOrderItem> newPOItems, PurchaseOrderDocument currentDocument, boolean copyNotes, String splitNoteText);
104    
105        /**
106         * Obtains the internal purchasing dollar limit amount for a purchase order document.
107         * 
108         * @param po The purchase order document for which this method is obtaining the internal purchasing dollar limit.
109         * @return The internal purchasing dollar limit for the given purchase order document.
110         */
111        public KualiDecimal getInternalPurchasingDollarLimit(PurchaseOrderDocument po);
112    
113        public boolean printPurchaseOrderQuoteRequestsListPDF(String documentNumber, ByteArrayOutputStream baosPDF);
114    
115        public boolean printPurchaseOrderQuotePDF(PurchaseOrderDocument po, PurchaseOrderVendorQuote povq, ByteArrayOutputStream baosPDF);
116    
117        /**
118         * Creates and displays the pdf document for the purchase order, sets the transmit dates, calls the
119         * takeAllActionsForGivenCriteria method in PurApWorkflowIntegrationService to perform all the workflow related steps that are
120         * necessary as part of the document initial print transmission and then performs the setup of initial of open document of the
121         * purchase order.
122         * 
123         * @param documentNumber The document number of the purchase order document that we want to perform the first transmit.
124         * @param baosPDF The ByteArrayOutputStream object that was passed in from the struts action so that we could display the pdf on
125         *        the browser.
126         */
127        public void performPurchaseOrderFirstTransmitViaPrinting(String documentNumber, ByteArrayOutputStream baosPDF);
128    
129        /**
130         * Creates and displays the pdf document for the purchase order with a draft watermark
131         * 
132         * @param documentNumber The document number of the purchase order document that we want to perform the first transmit.
133         * @param baosPDF The ByteArrayOutputStream object that was passed in from the struts action so that we could display the pdf on
134         *        the browser.
135         */
136        public void performPurchaseOrderPreviewPrinting(String documentNumber, ByteArrayOutputStream baosPDF);
137    
138        /**
139         * Generates and displays the purchase order pdf by invoking the generatePurchaseOrderPdf method of the PrintService.
140         * 
141         * @param documentNumber The document number of the purchase order document that we want to print the pdf.
142         * @param baosPDF The ByteArrayOutputStream object that we'll use to display the pdf on the browser.
143         */
144        public void performPrintPurchaseOrderPDFOnly(String documentNumber, ByteArrayOutputStream baosPDF);
145    
146        /**
147         * Generates and displays the purchase order retransmit pdf by invoking the generatePurchaseOrderPdfForRetransmission method of
148         * the PrintService.
149         * 
150         * @param po The purchase order document to be retransmitted.
151         * @param baosPDF The ByteArrayOutputStream object that we'll use to display the pdf on the browser.
152         */
153        public void retransmitPurchaseOrderPDF(PurchaseOrderDocument po, ByteArrayOutputStream baosPDF);
154    
155        /**
156         * Performs the steps needed to complete the newly approved purchase order document, which consists of setting the current and
157         * pending indicators for the purchase order document and if the status is not pending transmission, then calls the
158         * attemptsSetupOfInitialOpenOfDocument to set the statuses, the initial open date and save the document.
159         * 
160         * @param po The newly approved purchase order document that we want to complete.
161         */
162        public void completePurchaseOrder(PurchaseOrderDocument po);
163    
164        public void retransmitB2BPurchaseOrder(PurchaseOrderDocument po);
165        
166        public void completePurchaseOrderAmendment(PurchaseOrderDocument po);
167    
168        /**
169         * Obtains the purchase order document whose current indicator is true, given a purchase order id which is the
170         * purapDocumentIdentifier.
171         * 
172         * @param id The po id (purapDocumentIdentifier) that we'll use to retrieve the current purchase order document.
173         * @return The current purchase order document (the po whose current indicator is true).
174         */
175        public PurchaseOrderDocument getCurrentPurchaseOrder(Integer id);
176    
177        /**
178         * Obtains the purchase order document given the document number.
179         * 
180         * @param documentNumber The document number of the purchase order that we want to retrieve.
181         * @return The purchase order document whose document number is the given document number.
182         */
183        public PurchaseOrderDocument getPurchaseOrderByDocumentNumber(String documentNumber);
184    
185        /**
186         * Sets the current and pending indicators of the new purchase order and the old purchase order as well as its status, then save
187         * the purchase order.
188         * 
189         * @param newPO The new purchase order document that has been approved.
190         */
191        public void setCurrentAndPendingIndicatorsForApprovedPODocuments(PurchaseOrderDocument newPO);
192    
193        /**
194         * Sets the current and pending indicators of the new purchase order and the old purchase order as well as their statuses, then
195         * save the purchase order.
196         * 
197         * @param newPO The new purchase order document that has been disapproved.
198         */
199        public void setCurrentAndPendingIndicatorsForDisapprovedChangePODocuments(PurchaseOrderDocument newPO);
200    
201        /**
202         * Sets the current and pending indicators of the new purchase order and the old purchase order as well as their statuses, then
203         * save the purchase order.
204         * 
205         * @param newPO The new purchase order document that has been canceled.
206         */
207        public void setCurrentAndPendingIndicatorsForCancelledChangePODocuments(PurchaseOrderDocument newPO);
208    
209        /**
210         * Sets the current and pending indicators of the new purchase order and the old purchase order as well as their statuses, then
211         * save the purchase order.
212         * 
213         * @param newPO The new purchase order reopen document that has been canceled.
214         */
215        public void setCurrentAndPendingIndicatorsForCancelledReopenPODocuments(PurchaseOrderDocument newPO);
216    
217        /**
218         * Sets the current and pending indicators of the new purchase order and the old purchase order as well as their statuses, then
219         * save the purchase order.
220         * 
221         * @param newPO The new purchase order reopen document that has been disapproved.
222         */
223        public void setCurrentAndPendingIndicatorsForDisapprovedReopenPODocuments(PurchaseOrderDocument newPO);
224    
225        /**
226         * Sets the current and pending indicators of the new purchase order and the old purchase order as well as their statuses, then
227         * save the purchase order
228         * 
229         * @param newPO The new purchase order remove hold document that has been canceled.
230         */
231        public void setCurrentAndPendingIndicatorsForCancelledRemoveHoldPODocuments(PurchaseOrderDocument newPO);
232    
233        /**
234         * Sets the current and pending indicators of the new purchase order and the old purchase order as well as their statuses, then
235         * save the purchase order.
236         * 
237         * @param newPO The new purchase order remove hold document that has been disapproved.
238         */
239        public void setCurrentAndPendingIndicatorsForDisapprovedRemoveHoldPODocuments(PurchaseOrderDocument newPO);
240    
241        /**
242         * Obtains the oldest purchase order given the purchase order object to be used to search, then calls the updateNotes method to
243         * set the notes on the oldest purchase order and finally return the oldest purchase order.
244         * 
245         * @param po The current purchase order object from which we want to obtain the oldest purchase order.
246         * @param documentBusinessObject The documentBusinessObject of the current purchase order object.
247         * @return The oldest purchase order whose purchase order id is the same as the current purchase order's id.
248         */
249        public PurchaseOrderDocument getOldestPurchaseOrder(PurchaseOrderDocument po, PurchaseOrderDocument documentBusinessObject);
250    
251        /**
252         * Obtains all the notes that belong to this purchase order given the purchase order id.
253         * 
254         * @param id The purchase order id (purapDocumentIdentifier).
255         * @return The list of notes that belong to this purchase order.
256         */
257        public ArrayList<Note> getPurchaseOrderNotes(Integer id);
258    
259        public ArrayList<PurchaseOrderQuoteStatus> getPurchaseOrderQuoteStatusCodes();
260    
261        /**
262         * Performs a threshold check on the purchase order to determine if any attribute on the purchase order
263         * falls within a defined threshold. This check is only perfromed if the receiving required flag is set to N.
264         * 
265         * @param po
266         */
267        public void setReceivingRequiredIndicatorForPurchaseOrder(PurchaseOrderDocument po);
268        
269        /**
270         * If there are commodity codes on the items on the PurchaseOrderDocument that
271         * haven't existed yet on the vendor that the PurchaseOrderDocument is using,
272         * then we will spawn a new VendorDetailMaintenanceDocument automatically to
273         * update the vendor with the commodity codes that aren't already existing on
274         * the vendor.
275         *
276         * @param po The PurchaseOrderDocument containing the vendor that we want to update.
277         */
278        public void updateVendorCommodityCode(PurchaseOrderDocument po);
279        
280        /**
281         * Checks the item list for newly added unordered items.
282         * 
283         * @param po
284         * @return
285         */
286        public boolean hasNewUnorderedItem(PurchaseOrderDocument po);
287     
288        /**
289         * Check whether each of the items contain commodity code, if so then loop
290         * through the vendor commodity codes on the vendor to find out whether the
291         * commodity code on the item has existed on the vendor. While doing that,
292         * also check whether there exists a default commodity code on the vendor, 
293         * although we only need to check this until we find a vendor commodity code
294         * with default indicator set to true. If we didn't find any matching
295         * commodity code in the existing vendor commodity codes, then add the new
296         * commodity code to a List of commodity code, create a new vendor commodity
297         * code and set all of its attributes appropriately, including setting the 
298         * default indicator to true if we had not found any existing default commodity
299         * code on the vendor, then add the newly created vendor commodity code to
300         * the vendor (which is a deep copy of the original vendor on the PO).
301         * After we're done with all of the items, if the List that contains the
302         * commodity code that were being added to the vendor is not empty, then
303         * for each entry on that list, we should create an empty VendorCommodityCode
304         * to be added to the old vendor (the original vendor that is on the PO document).
305         * The reason we're combining all of these processing here is so that we don't
306         * need to loop through items and vendor commodity codes too many times. 
307         * 
308         * @param po  The PurchaseOrderDocument containing the vendor that we want to update.
309         * 
310         * @return VendorDetail the vendorDetail object which is a deep copy of the original
311         *         vendorDetail on the PurchaseOrderDocument, whose commodity codes have
312         *         already been updated based on our findings on the items' commodity codes.
313         */
314        public VendorDetail updateVendorWithMissingCommodityCodesIfNecessary(PurchaseOrderDocument po);
315        
316        /**
317         * Determines if a purchase order item is new unordered item. 
318         * 
319         * @param poItem
320         * @return
321         */
322        public boolean isNewUnorderedItem(PurchaseOrderItem poItem);
323        
324        /**
325         * Determines if a purchase order item is newly added on 
326         * the Purchase Order Amendment Document. 
327         * 
328         * @param poItem
329         * @return
330         */
331        public boolean isNewItemForAmendment(PurchaseOrderItem poItem);
332        
333        /**
334         * Used to provide sublists of the list of the original PO's items according to whether they
335         * are marked to be moved or not.  Retrieving the item from the hash with the key of 'movingPOItems'
336         * will retrieve those Items which should move, using 'remainingPOItems'.
337         * 
338         * @param items     A List<PurchaseOrderItem> from the original PO of a Split.
339         * @return          A HashMap<String, List<PurchaseOrderItem>> of categorized lists of items
340         */
341        public HashMap<String, List<PurchaseOrderItem>> categorizeItemsForSplit(List<PurchaseOrderItem> items);
342    
343        /**
344         * Creates a PurchaseOrderVendorQuote based on the data on the selected vendor and the document number.
345         * 
346         * @param headerId       The vendorHeaderGeneratedIdentifier of the selected vendor.
347         * @param detailId       The vendorDetailAssignedIdentifier of the selected vendor.
348         * @param documentNumber The documentNumber of the PurchaseOrderDocument containing this quote.
349         * @return               The resulting PurchaseOrderVendorQuote object.
350         */
351        public PurchaseOrderVendorQuote populateQuoteWithVendor(Integer headerId, Integer detailId, String documentNumber);
352        
353        /**
354         * 
355         * This method takes care of creating PurchaseOrderDocuments from a list of Requisitions on an ACM
356         * @param acmDoc An assign a contract manager document
357         */
358        public void processACMReq(ContractManagerAssignmentDocument acmDoc);
359        
360        /**
361         * This gets a list of Purchase Orders in Open status and checks to see if their
362         * line item encumbrances are all fully disencumbered and if so then the Purchase
363         * Order is closed and notes added to indicate the change occurred in batch
364         * 
365         * @return boolean true if the job is completed successfully and false otherwise.
366         */
367        public boolean autoCloseFullyDisencumberedOrders();
368        
369    
370        /**
371         * - PO status is OPEN 
372         * - Recurring payment type code is not null 
373         * - Vendor Choice is not Sub-Contract 
374         * - PO End Date <= parm date (comes from system parameter) 
375         * - Verify that the system parameter date entered is not greater than the current date minus three months.
376         *   If the date entered is invalid, the batch process will halt and an error will be generated.
377         * - Close and disencumber all recurring PO's that have end dates less than
378         *   the system parameter date. 
379         * - Set the system parameter date to mm/dd/yyyy after processing. 
380         * - Send email indicating that the job ran and which orders were closed. 
381         *   Mail it to the AUTO_CLOSE_RECURRING_PO_EMAIL_ADDRESSES in system parameter.
382         *   
383         * @return boolean true if the job is completed successfully and false otherwise.
384         */
385        public boolean autoCloseRecurringOrders();
386        
387        
388        /**
389         * Return a list of PurchasingCapitalAssetItems where each item would have a CapitalAssetSystem. The CapitalAssetSystem provides
390         * the capital asset information such as asset numbers and asset type.
391         * 
392         * @param poId Purchase Order ID used to retrieve the asset information for the current PO
393         * @return List of PurchasingCapitalAssetItems (each of which contain a CapitalAssetSystem)
394         */
395        public List<PurchasingCapitalAssetItem> retrieveCapitalAssetItemsForIndividual(Integer poId);
396    
397    
398        /**
399         * Return a CapitalAssetSystem which provides the capital asset information such as asset numbers and asset type.
400         * 
401         * @param poId Purchase Order ID used to retrieve the asset information for the current PO
402         * @return CapitalAssetSystem
403         */
404        public CapitalAssetSystem retrieveCapitalAssetSystemForOneSystem(Integer poId);
405    
406    
407        /**
408         * Return a list of CapitalAssetSystems which provide the capital asset information such as asset numbers and asset type.
409         * 
410         * @param poId Purchase Order ID used to retrieve the asset information for the current PO
411         * @return List of CapitalAssetSystems
412         */
413        public List<CapitalAssetSystem> retrieveCapitalAssetSystemsForMultipleSystem(Integer poId);
414    
415    
416        /**
417         * This method gets all the Purchase orders that are waiting for faxing
418         * @return List of POs
419         */
420        public List<PurchaseOrderDocument> getPendingPurchaseOrderFaxes();
421        
422        /**
423         * Determines whether to display the amend button for the purchase order document.
424         * The document status must be open, the purchase order must be current and not pending and the
425         * user must be in purchasing group. These are the conditions for displaying the payment hold
426         * button. In addition to these conditions, we also have to check that there is no In Process
427         * Payment Requests nor Credit Memos associated with the PO.
428         * 
429         * @return boolean true if the amendment possible for the purchase order.
430         */
431        public boolean canAmendPurchaseOrder(PurchaseOrderDocument purchaseOrder);
432        
433        /**
434         * Determines whether to display the amend and payment hold buttons for the purchase order document.
435         * The document status must be open, the purchase order must be current and not pending and the
436         * user must be in purchasing group.
437         * 
438         * @return boolean true if the payment hold is possible for the purchase order document.
439         */
440        public boolean canHoldPayment(PurchaseOrderDocument purchaseOrder);
441        
442        
443    }