/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.pdp.batch.service.impl; import java.sql.Date; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.kuali.kfs.integration.purap.PurchasingAccountsPayableModuleService; import org.kuali.kfs.pdp.PdpConstants; import org.kuali.kfs.pdp.batch.service.ProcessPdpCancelPaidService; import org.kuali.kfs.pdp.businessobject.ExtractionUnit; import org.kuali.kfs.pdp.businessobject.PaymentDetail; import org.kuali.kfs.pdp.service.PaymentDetailService; import org.kuali.kfs.pdp.service.PaymentGroupService; import org.kuali.kfs.sys.KFSParameterKeyConstants; import org.kuali.kfs.sys.batch.service.PaymentSourceToExtractService; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.document.PaymentSource; import org.kuali.kfs.sys.service.impl.KfsParameterConstants; import org.kuali.rice.core.api.datetime.DateTimeService; import org.kuali.rice.coreservice.framework.parameter.ParameterService; import org.kuali.rice.kew.api.exception.WorkflowException; import org.kuali.rice.krad.service.DocumentService; import org.springframework.transaction.annotation.Transactional; /** * Implementation of ProcessPdpCancelPaidService */ @Transactional public class ProcessPdpCancelPaidServiceImpl implements ProcessPdpCancelPaidService { private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ProcessPdpCancelPaidServiceImpl.class); protected PaymentGroupService paymentGroupService; protected PaymentDetailService paymentDetailService; protected ParameterService parameterService; protected DateTimeService dateTimeService; protected PurchasingAccountsPayableModuleService purchasingAccountsPayableModuleService; protected DocumentService documentService; protected volatile Set<String> paymentSourceCheckACHDocumentTypes; protected volatile List<PaymentSourceToExtractService<PaymentSource>> paymentSourceToExtractServices; /** * @see org.kuali.kfs.module.purap.service.ProcessPdpCancelPaidService#processPdpCancels() */ @Override public void processPdpCancels() { LOG.debug("processPdpCancels() started"); Date processDate = dateTimeService.getCurrentSqlDate(); final List<ExtractionUnit> extractionUnits = getExtractionUnits(); Iterator<PaymentDetail> details = paymentDetailService.getUnprocessedCancelledDetails(extractionUnits); while (details.hasNext()) { PaymentDetail paymentDetail = details.next(); String documentTypeCode = paymentDetail.getFinancialDocumentTypeCode(); String documentNumber = paymentDetail.getCustPaymentDocNbr(); boolean primaryCancel = paymentDetail.getPrimaryCancelledPayment(); boolean disbursedPayment = PdpConstants.PaymentStatusCodes.CANCEL_DISBURSEMENT.equals(paymentDetail.getPaymentGroup().getPaymentStatusCode()); if(purchasingAccountsPayableModuleService.isPurchasingBatchDocument(documentTypeCode)) { purchasingAccountsPayableModuleService.handlePurchasingBatchCancels(documentNumber, documentTypeCode, primaryCancel, disbursedPayment); } else { PaymentSourceToExtractService<PaymentSource> extractService = getPaymentSourceToExtractService(paymentDetail); if (extractService != null) { try { PaymentSource dv = (PaymentSource)getDocumentService().getByDocumentHeaderId(documentNumber); if (dv != null) { if (disbursedPayment || primaryCancel) { extractService.cancelPayment(dv, processDate); } else { extractService.resetFromExtraction(dv); } } } catch (WorkflowException we) { throw new RuntimeException("Could not retrieve document #"+documentNumber, we); } } else { LOG.warn("processPdpCancels() Unknown document type (" + documentTypeCode + ") for document ID: " + documentNumber); continue; } } paymentGroupService.processCancelledGroup(paymentDetail.getPaymentGroup(), processDate); } } /** * @see org.kuali.kfs.module.purap.service.ProcessPdpCancelPaidService#processPdpPaids() */ @Override public void processPdpPaids() { LOG.debug("processPdpPaids() started"); Date processDate = dateTimeService.getCurrentSqlDate(); final List<ExtractionUnit> extractionUnits = getExtractionUnits(); Iterator<PaymentDetail> details = paymentDetailService.getUnprocessedPaidDetails(extractionUnits); while (details.hasNext()) { PaymentDetail paymentDetail = details.next(); String documentTypeCode = paymentDetail.getFinancialDocumentTypeCode(); String documentNumber = paymentDetail.getCustPaymentDocNbr(); if(purchasingAccountsPayableModuleService.isPurchasingBatchDocument(documentTypeCode)) { purchasingAccountsPayableModuleService.handlePurchasingBatchPaids(documentNumber, documentTypeCode, processDate); } else { PaymentSourceToExtractService<PaymentSource> extractService = getPaymentSourceToExtractService(paymentDetail); if (extractService != null) { try { PaymentSource dv = (PaymentSource)getDocumentService().getByDocumentHeaderId(documentNumber); extractService.markAsPaid(dv, processDate); } catch (WorkflowException we) { throw new RuntimeException("Could not retrieve document #"+documentNumber, we); } } else { LOG.warn("processPdpPaids() Unknown document type (" + documentTypeCode + ") for document ID: " + documentNumber); continue; } } paymentGroupService.processPaidGroup(paymentDetail.getPaymentGroup(), processDate); } } /** * @see org.kuali.kfs.module.purap.service.ProcessPdpCancelPaidService#processPdpCancelsAndPaids() */ @Override public void processPdpCancelsAndPaids() { LOG.debug("processPdpCancelsAndPaids() started"); processPdpCancels(); processPdpPaids(); } /** * @return a List of all available PaymentSourceToExtractService implementations */ protected List<PaymentSourceToExtractService<PaymentSource>> getPaymentSourceToExtractServices() { if (paymentSourceToExtractServices == null) { paymentSourceToExtractServices = new ArrayList<PaymentSourceToExtractService<PaymentSource>>(); Map<String, PaymentSourceToExtractService> extractionServices = SpringContext.getBeansOfType(PaymentSourceToExtractService.class); for (PaymentSourceToExtractService<PaymentSource> extractionService : extractionServices.values()) { paymentSourceToExtractServices.add(extractionService); } } return paymentSourceToExtractServices; } /** * Looks up the PaymentSourceToExtractService which can act upon the given PaymentDetail, based on the PaymentDetail's document type * @param paymentDetail the payment detail to find an extraction service to act upon * @return the matching PaymentSourceToExtractService, or null if a matching service could not be found (which would be weird, because _something_ created this PaymentDetail, but...whatever) */ protected PaymentSourceToExtractService<PaymentSource> getPaymentSourceToExtractService(PaymentDetail paymentDetail) { for (PaymentSourceToExtractService<PaymentSource> extractionService : getPaymentSourceToExtractServices()) { if (extractionService.handlesAchCheckDocumentType(paymentDetail.getFinancialDocumentTypeCode())) { return extractionService; } } return null; } /** * Loops through the PaymentSourceToExtractService List and builds ExtractionUnits for each * @return a List of ExtractionUnits for each customer profile organization and sub-organization handled by PaymentSourceToExtractServices */ protected List<ExtractionUnit> getExtractionUnitsForPaymentSourceToExtractServices() { List<ExtractionUnit> extractionUnits = new ArrayList<ExtractionUnit>(); for (PaymentSourceToExtractService<PaymentSource> extractionService : getPaymentSourceToExtractServices()) { final ExtractionUnit extractionUnit = new ExtractionUnit(extractionService.getPreDisbursementCustomerProfileUnit(), extractionService.getPreDisbursementCustomerProfileSubUnit()); if (!extractionUnits.contains(extractionUnit)) { extractionUnits.add(extractionUnit); } } return extractionUnits; } /** * @return a List of all known ExtractionUnits */ protected List<ExtractionUnit> getExtractionUnits() { List<ExtractionUnit> extractionUnits = getExtractionUnitsForPaymentSourceToExtractServices(); final String purapOrg = parameterService.getParameterValueAsString(KfsParameterConstants.PURCHASING_BATCH.class, KFSParameterKeyConstants.PurapPdpParameterConstants.PURAP_PDP_ORG_CODE); final String purapSubUnit = parameterService.getParameterValueAsString(KfsParameterConstants.PURCHASING_BATCH.class, KFSParameterKeyConstants.PurapPdpParameterConstants.PURAP_PDP_SUB_UNIT_CODE); final ExtractionUnit purapExtractionUnit = new ExtractionUnit(purapOrg, purapSubUnit); extractionUnits.add(purapExtractionUnit); return Collections.unmodifiableList(extractionUnits); } public void setPaymentDetailService(PaymentDetailService paymentDetailService) { this.paymentDetailService = paymentDetailService; } public void setPaymentGroupService(PaymentGroupService paymentGroupService) { this.paymentGroupService = paymentGroupService; } public void setParameterService(ParameterService parameterService) { this.parameterService = parameterService; } public void setPurchasingAccountsPayableModuleService(PurchasingAccountsPayableModuleService purchasingAccountsPayableModuleService) { this.purchasingAccountsPayableModuleService = purchasingAccountsPayableModuleService; } public void setDateTimeService(DateTimeService dts) { this.dateTimeService = dts; } /** * @return the implementation of the DocumentService to use */ public DocumentService getDocumentService() { return documentService; } /** * Sets the implementation of the DocumentService to use * @param documentService the implementation of the DocumentService to use */ public void setDocumentService(DocumentService documentService) { this.documentService = documentService; } }