Java tutorial
/* * eGov SmartCity eGovernance suite aims to improve the internal efficiency,transparency, * accountability and the service delivery of the government organizations. * * Copyright (C) 2017 eGovernments Foundation * * The updated version of eGov suite of products as by eGovernments Foundation * is available at http://www.egovernments.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/ or * http://www.gnu.org/licenses/gpl.html . * * In addition to the terms of the GPL license to be adhered to in using this * program, the following additional terms are to be complied with: * * 1) All versions of this program, verbatim or modified must carry this * Legal Notice. * Further, all user interfaces, including but not limited to citizen facing interfaces, * Urban Local Bodies interfaces, dashboards, mobile applications, of the program and any * derived works should carry eGovernments Foundation logo on the top right corner. * * For the logo, please refer http://egovernments.org/html/logo/egov_logo.png. * For any further queries on attribution, including queries on brand guidelines, * please contact contact@egovernments.org * * 2) Any misrepresentation of the origin of the material is prohibited. It * is required that all modified versions of this material be marked in * reasonable ways as different from the original version. * * 3) This license does not grant any rights to any user of the program * with regards to rights under trademark law for use of the trade names * or trademarks of eGovernments Foundation. * * In case of any queries, you can reach eGovernments Foundation at contact@egovernments.org. * */ package org.egov.collection.service; import java.math.BigDecimal; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import org.egov.billsaccounting.services.VoucherConstant; import org.egov.collection.constants.CollectionConstants; import org.egov.collection.entity.AccountPayeeDetail; import org.egov.collection.entity.Challan; import org.egov.collection.entity.CollectionIndex; import org.egov.collection.entity.ReceiptDetail; import org.egov.collection.entity.ReceiptHeader; import org.egov.collection.entity.ReceiptMisc; import org.egov.collection.entity.ReceiptVoucher; import org.egov.collection.integration.models.BillReceiptInfo; import org.egov.collection.integration.models.BillReceiptInfoImpl; import org.egov.collection.integration.models.BillReceiptReq; import org.egov.collection.integration.models.ReceiptCancellationInfo; import org.egov.collection.integration.services.BillingIntegrationService; import org.egov.collection.utils.CollectionsNumberGenerator; import org.egov.collection.utils.CollectionsUtil; import org.egov.collection.utils.FinancialsUtil; import org.egov.collection.utils.es.CollectionIndexUtils; import org.egov.commons.Bankaccount; import org.egov.commons.CFinancialYear; import org.egov.commons.CVoucherHeader; import org.egov.commons.EgwStatus; import org.egov.commons.dao.ChartOfAccountsHibernateDAO; import org.egov.eis.entity.Assignment; import org.egov.eis.entity.Employee; import org.egov.eis.entity.Jurisdiction; import org.egov.eis.service.AssignmentService; import org.egov.eis.service.EmployeeService; import org.egov.infra.admin.master.entity.Boundary; import org.egov.infra.admin.master.entity.Department; import org.egov.infra.admin.master.service.DepartmentService; import org.egov.infra.exception.ApplicationRuntimeException; import org.egov.infra.reporting.engine.ReportFormat; import org.egov.infra.reporting.engine.ReportRequest; import org.egov.infra.security.utils.SecurityUtils; import org.egov.infra.validation.exception.ValidationError; import org.egov.infra.validation.exception.ValidationException; import org.egov.infstr.models.ServiceDetails; import org.egov.infstr.services.PersistenceService; import org.egov.model.instrument.InstrumentHeader; import org.egov.model.instrument.InstrumentType; import org.egov.pims.commons.Designation; import org.egov.pims.commons.Position; import org.hibernate.HibernateException; import org.hibernate.Query; import org.joda.time.DateTime; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; /** * Provides services related to receipt header */ @Transactional(readOnly = true) public class ReceiptHeaderService extends PersistenceService<ReceiptHeader, Long> { private static final Logger LOGGER = Logger.getLogger(ReceiptHeaderService.class); private CollectionsUtil collectionsUtil; private CollectionsNumberGenerator collectionsNumberGenerator; private FinancialsUtil financialsUtil; private PersistenceService persistenceService; @Autowired private EmployeeService employeeService; @Autowired private DepartmentService departmentService; @Autowired private AssignmentService assignmentService; private ChallanService challanService; @Autowired private CollectionIndexService collectionIndexService; @Autowired private CollectionIndexUtils collectionIndexUtils; @Autowired private ChartOfAccountsHibernateDAO chartOfAccountsHibernateDAO; @Autowired protected SecurityUtils securityUtils; public ReceiptHeaderService() { super(ReceiptHeader.class); } public ReceiptHeaderService(final Class<ReceiptHeader> type) { super(type); } /** * @param statusCode Status code of receipts to be fetched. If null or ALL, then receipts with all statuses are fetched * @param userName User name of the user who has created the receipts. If null or ALL, then receipts of all users are fetched * @param counterId Counter id on which the receipts were created. If negative, then receipts from all counters are fetched * @param serviceCode Service code for which the receipts were created. If null or ALL, then receipts of all billing services * are fetched * @return List of all receipts created by given user from given counter id and having given status */ public List<ReceiptHeader> findAllByPositionAndInboxItemDetails(final List<Long> positionIds, final String groupingCriteria) { final StringBuilder query = new StringBuilder( " select distinct (receipt) from org.egov.collection.entity.ReceiptHeader receipt "); String wfAction = null; String serviceCode = null; String userName = null; String receiptDate = null; String receiptType = null; Integer counterId = null; String paymentMode = null; final String params[] = groupingCriteria.split(CollectionConstants.SEPARATOR_HYPHEN, -1); if (params.length == 7) { wfAction = params[0]; serviceCode = params[1]; userName = params[2]; counterId = Integer.valueOf(params[4]); receiptDate = params[3]; receiptType = params[5]; paymentMode = params[6]; } final boolean allCounters = counterId == null || counterId < 0; // final boolean allPositions = positionIds == null || // positionIds.equals(CollectionConstants.ALL); final boolean allServices = serviceCode == null || serviceCode.equals(CollectionConstants.ALL); final boolean allWfAction = wfAction == null || wfAction.equals(CollectionConstants.ALL); final boolean allUserName = userName == null || userName.equals(CollectionConstants.ALL); final boolean allDate = receiptDate == null || receiptDate.equals(CollectionConstants.ALL); final SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy"); Date rcptDate = null; try { rcptDate = formatter.parse(receiptDate); } catch (final ParseException e) { LOGGER.error("Exception while parsing ReceiptDate", e); throw new ApplicationRuntimeException(e.getMessage()); } if (paymentMode.equals(CollectionConstants.INSTRUMENTTYPE_CASH) || paymentMode.equals(CollectionConstants.INSTRUMENTTYPE_CHEQUEORDD)) query.append("join receipt.receiptInstrument as instruments "); query.append(" where 1=1 and receipt.state.value != 'END' and receipt.state.status != 2 "); // if (!allPositions) query.append(" and receipt.state.ownerPosition.id in :positionIds"); if (!allCounters) query.append(" and receipt.location.id = :counterId"); if (!allServices && receiptType.equals(CollectionConstants.SERVICE_TYPE_BILLING)) query.append(" and receipt.service.code = :serviceCode"); if (!allWfAction) query.append(" and receipt.state.nextAction = :wfAction"); if (!allUserName) query.append(" and receipt.createdBy.username = :userName"); if (!allDate) query.append(" and (cast(receipt.receiptdate as date)) = :rcptDate"); if (receiptType.equals(CollectionConstants.SERVICE_TYPE_BILLING)) query.append(" and receipt.receipttype = :receiptType"); else query.append(" and receipt.receipttype in ('A', 'C')"); if (paymentMode.equals(CollectionConstants.INSTRUMENTTYPE_CASH) || paymentMode.equals(CollectionConstants.INSTRUMENTTYPE_CHEQUEORDD)) query.append(" and instruments.instrumentType.type in (:paymentMode )"); query.append(" order by receipt.receiptdate desc"); final Query listQuery = getSession().createQuery(query.toString()); // if (!allPositions) listQuery.setParameterList("positionIds", positionIds); if (!allCounters) listQuery.setInteger("counterId", counterId); if (!allServices && receiptType.equals(CollectionConstants.SERVICE_TYPE_BILLING)) listQuery.setString("serviceCode", serviceCode); if (!allWfAction) listQuery.setString("wfAction", wfAction); if (!allUserName) listQuery.setString("userName", userName); if (!allDate) listQuery.setDate("rcptDate", rcptDate); if (receiptType.equals(CollectionConstants.SERVICE_TYPE_BILLING)) listQuery.setCharacter("receiptType", receiptType.charAt(0)); if (paymentMode.equals(CollectionConstants.INSTRUMENTTYPE_CASH)) listQuery.setString("paymentMode", paymentMode); else if (paymentMode.equals(CollectionConstants.INSTRUMENTTYPE_CHEQUEORDD)) listQuery.setParameterList("paymentMode", new ArrayList<>(Arrays.asList("cheque", "dd"))); return listQuery.list(); } /** * This method is called for voucher creation into the financial system. For each receipt created in the collections module, a * voucher is created. * * @param receiptHeader Receipt header for which the pre-approval voucher is to be created * @param receiptBulkUpload * @return The created voucher */ protected CVoucherHeader createVoucher(final ReceiptHeader receiptHeader) { final HashMap<String, Object> headerdetails = new HashMap<>(0); final List<HashMap<String, Object>> accountCodeList = new ArrayList<>(0); final List<HashMap<String, Object>> subledgerList = new ArrayList<>(0); String fundCode = null; String fundsourceCode = null; String departmentCode = null; Boolean isVoucherApproved = Boolean.FALSE; if (receiptHeader.getService().getIsVoucherApproved() != null) isVoucherApproved = receiptHeader.getService().getIsVoucherApproved(); final ReceiptMisc receiptMisc = receiptHeader.getReceiptMisc(); if (receiptMisc.getFund() != null) fundCode = receiptMisc.getFund().getCode(); if (receiptMisc.getFundsource() != null) fundsourceCode = receiptMisc.getFundsource().getCode(); if (receiptMisc.getDepartment() != null) departmentCode = receiptMisc.getDepartment().getCode(); for (final InstrumentHeader instrumentHeader : receiptHeader.getReceiptInstrument()) if (instrumentHeader.getInstrumentType().getType().equals(CollectionConstants.INSTRUMENTTYPE_CASH) || instrumentHeader.getInstrumentType().getType() .equals(CollectionConstants.INSTRUMENTTYPE_CHEQUE) || instrumentHeader.getInstrumentType().getType().equals(CollectionConstants.INSTRUMENTTYPE_DD) || instrumentHeader.getInstrumentType().getType() .equals(CollectionConstants.INSTRUMENTTYPE_ONLINE) || instrumentHeader.getInstrumentType().getType() .equals(CollectionConstants.INSTRUMENTTYPE_CARD)) { headerdetails.put(VoucherConstant.VOUCHERNAME, CollectionConstants.FINANCIAL_RECEIPTS_VOUCHERNAME); headerdetails.put(VoucherConstant.VOUCHERTYPE, CollectionConstants.FINANCIAL_RECEIPTS_VOUCHERTYPE); } else if (instrumentHeader.getInstrumentType().getType() .equals(CollectionConstants.INSTRUMENTTYPE_BANK)) { headerdetails.put(VoucherConstant.VOUCHERNAME, CollectionConstants.FINANCIAL_CONTRATVOUCHER_VOUCHERNAME); headerdetails.put(VoucherConstant.VOUCHERTYPE, CollectionConstants.FINANCIAL_CONTRAVOUCHER_VOUCHERTYPE); } headerdetails.put(VoucherConstant.DESCRIPTION, CollectionConstants.FINANCIAL_VOUCHERDESCRIPTION); final SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy"); try { String dateString; if (receiptHeader.getVoucherDate() == null) { dateString = format.format(new Date()); headerdetails.put(VoucherConstant.VOUCHERDATE, format.parse(dateString)); } else { dateString = format.format(receiptHeader.getVoucherDate()); headerdetails.put(VoucherConstant.VOUCHERDATE, format.parse(dateString)); } } catch (final ParseException e) { LOGGER.error("Exception while voucher date", e); throw new ApplicationRuntimeException(e.getMessage()); } if (receiptHeader.getVoucherNum() != null && !receiptHeader.getVoucherNum().isEmpty()) headerdetails.put(VoucherConstant.VOUCHERNUMBER, receiptHeader.getVoucherNum()); headerdetails.put(VoucherConstant.FUNDCODE, fundCode); headerdetails.put(VoucherConstant.DEPARTMENTCODE, departmentCode); headerdetails.put(VoucherConstant.FUNDSOURCECODE, fundsourceCode); headerdetails.put(VoucherConstant.MODULEID, CollectionConstants.COLLECTIONS_EG_MODULES_ID); headerdetails.put(VoucherConstant.SOURCEPATH, CollectionConstants.RECEIPT_VIEW_SOURCEPATH + receiptHeader.getId()); Set<ReceiptDetail> receiptDetailSet; /** * Aggregate Amount in case of bill based receipt for account codes appearing more than once in receipt details */ if (receiptHeader.getReceipttype() == 'B') receiptDetailSet = aggregateDuplicateReceiptDetailObject( new ArrayList<ReceiptDetail>(receiptHeader.getReceiptDetails())); else receiptDetailSet = receiptHeader.getReceiptDetails(); for (final ReceiptDetail receiptDetail : receiptDetailSet) if (receiptDetail.getCramount().compareTo(BigDecimal.ZERO) != 0 || receiptDetail.getDramount().compareTo(BigDecimal.ZERO) != 0) { final HashMap<String, Object> accountcodedetailsHashMap = new HashMap<>(0); accountcodedetailsHashMap.put(VoucherConstant.GLCODE, receiptDetail.getAccounthead().getGlcode()); accountcodedetailsHashMap.put(VoucherConstant.DEBITAMOUNT, receiptDetail.getDramount().compareTo(BigDecimal.ZERO) == 0 ? 0 : receiptDetail.getDramount()); accountcodedetailsHashMap.put(VoucherConstant.CREDITAMOUNT, receiptDetail.getCramount().compareTo(BigDecimal.ZERO) == 0 ? 0 : receiptDetail.getCramount()); if (receiptDetail.getFunction() != null) accountcodedetailsHashMap.put(VoucherConstant.FUNCTIONCODE, receiptDetail.getFunction().getCode()); accountCodeList.add(accountcodedetailsHashMap); for (final AccountPayeeDetail accpayeeDetail : receiptDetail.getAccountPayeeDetails()) if (accpayeeDetail.getAmount().compareTo(BigDecimal.ZERO) != 0) { final HashMap<String, Object> subledgerdetailsHashMap = new HashMap<>(0); subledgerdetailsHashMap.put(VoucherConstant.GLCODE, accpayeeDetail.getReceiptDetail().getAccounthead().getGlcode()); subledgerdetailsHashMap.put(VoucherConstant.DETAILTYPEID, accpayeeDetail.getAccountDetailType().getId()); subledgerdetailsHashMap.put(VoucherConstant.DETAILKEYID, accpayeeDetail.getAccountDetailKey().getDetailkey()); if (accpayeeDetail.getReceiptDetail().getCramount().compareTo(BigDecimal.ZERO) != 0) subledgerdetailsHashMap.put(VoucherConstant.CREDITAMOUNT, accpayeeDetail.getAmount().compareTo(BigDecimal.ZERO) == 0 ? 0 : accpayeeDetail.getAmount()); else if (accpayeeDetail.getReceiptDetail().getDramount().compareTo(BigDecimal.ZERO) != 0) subledgerdetailsHashMap.put(VoucherConstant.DEBITAMOUNT, accpayeeDetail.getAmount().compareTo(BigDecimal.ZERO) == 0 ? 0 : accpayeeDetail.getAmount()); subledgerList.add(subledgerdetailsHashMap); } } return financialsUtil.createVoucher(headerdetails, accountCodeList, subledgerList, isVoucherApproved); } /** * Creates voucher for given receipt header and maps it with the same. Also updates the instrument voucher mapping in * financials. * * @param receiptHeader Receipt header for which voucher is to be created * @return The created voucher header */ public CVoucherHeader createVoucherForReceipt(final ReceiptHeader receiptHeader) { CVoucherHeader voucherheader = null; // Additional check for challan Based Receipt, if the receipt cancelled // before remittance // then need to check the instrument status of that receipt in order to // create voucher // as the challan has a 'PENDING' receipt object associated with it boolean isParentReceiptInstrumentDeposited = false; if (receiptHeader.getReceiptHeader() != null) for (final InstrumentHeader instrumentHeader : receiptHeader.getReceiptHeader().getReceiptInstrument()) if (instrumentHeader.getInstrumentType().getType() .equals(CollectionConstants.INSTRUMENTTYPE_CASH)) { if (instrumentHeader.getStatusId().getDescription() .equals(CollectionConstants.INSTRUMENT_RECONCILED_STATUS)) { isParentReceiptInstrumentDeposited = true; break; } } else if (instrumentHeader.getStatusId().getDescription() .equals(CollectionConstants.INSTRUMENT_DEPOSITED_STATUS)) { isParentReceiptInstrumentDeposited = true; break; } if (receiptHeader.getReceiptHeader() == null || receiptHeader.getReceiptHeader() != null && !isParentReceiptInstrumentDeposited) { voucherheader = createVoucher(receiptHeader); if (voucherheader != null) { final ReceiptVoucher receiptVoucher = new ReceiptVoucher(); receiptVoucher.setVoucherheader(voucherheader); receiptVoucher.setReceiptHeader(receiptHeader); receiptHeader.addReceiptVoucher(receiptVoucher); } } updateInstrument(receiptHeader); LOGGER.debug("Created voucher for receipt : " + receiptHeader.getReceiptnumber()); return voucherheader; } /** * Starts workflow for given set of receipt headers. Internally performs the following: 1. Start workflow 2. Transition * workflow state with action "Create Receipt" 3. Create vouchers (if required) 4. If vouchers created, transition workflow * state with action "Create Voucher" * * @param receiptHeaders set of receipt headers on which workflow is to be started * @param receiptBulkUpload */ public void startWorkflow(final ReceiptHeader receiptHeader) { final Boolean createVoucherForBillingService = collectionsUtil.checkVoucherCreation(receiptHeader); Position position; if (!collectionsUtil.isEmployee(this.securityUtils.getCurrentUser())) position = collectionsUtil .getPositionByDeptDesgAndBoundary(receiptHeader.getReceiptMisc().getBoundary()); else position = collectionsUtil.getPositionOfUser(this.securityUtils.getCurrentUser()); if (receiptHeader.getState() == null && !createVoucherForBillingService) receiptHeader.transition().start() .withSenderName(this.securityUtils.getCurrentUser().getUsername() + "::" + this.securityUtils.getCurrentUser().getName()) .withComments(CollectionConstants.WF_STATE_RECEIPT_CREATED) .withStateValue(CollectionConstants.WF_STATE_RECEIPT_CREATED).withOwner(position) .withDateInfo(new Date()).withNextAction(CollectionConstants.WF_ACTION_SUBMIT); else if (createVoucherForBillingService) receiptHeader.transition().start() .withSenderName(this.securityUtils.getCurrentUser().getUsername() + "::" + this.securityUtils.getCurrentUser().getName()) .withComments("Receipt voucher created") .withStateValue(CollectionConstants.WF_ACTION_CREATE_VOUCHER).withOwner(position) .withDateInfo(new Date()).withNextAction(CollectionConstants.WF_ACTION_SUBMIT); persistenceService.applyAuditing(receiptHeader.getState()); LOGGER.debug("Workflow state transition complete"); } /** * Method to check if the given HashMap already exists in the List of HashMap * * @param queryResults * @param objHashMap * @param m * @return index of objHashMap in the queryResults */ public int checkIfMapObjectExist(final List<HashMap<String, Object>> paramList, final Object[] arrayObjectInitialIndexTemp) { int check = -1; for (int m = 0; m < paramList.size(); m++) { final HashMap<String, Object> objHashMapTemp = paramList.get(m); if (arrayObjectInitialIndexTemp[1] != null && arrayObjectInitialIndexTemp[2] != null) if (arrayObjectInitialIndexTemp[1] .equals(objHashMapTemp.get(CollectionConstants.BANKREMITTANCE_RECEIPTDATE)) && arrayObjectInitialIndexTemp[2] .equals(objHashMapTemp.get(CollectionConstants.BANKREMITTANCE_SERVICENAME)) && arrayObjectInitialIndexTemp[6] .equals(objHashMapTemp.get(CollectionConstants.BANKREMITTANCE_FUNDCODE)) && arrayObjectInitialIndexTemp[7] .equals(objHashMapTemp.get(CollectionConstants.BANKREMITTANCE_DEPARTMENTCODE))) { check = m; break; } else continue; } return check; } public int checkIfChequeMapObjectExist(final List<HashMap<String, Object>> paramList, final Object[] arrayObjectInitialIndexTemp) { int check = -1; for (int m = 0; m < paramList.size(); m++) { final HashMap<String, Object> objHashMapTemp = paramList.get(m); if (arrayObjectInitialIndexTemp[1] != null && arrayObjectInitialIndexTemp[2] != null) if (arrayObjectInitialIndexTemp[1] .equals(objHashMapTemp.get(CollectionConstants.BANKREMITTANCE_RECEIPTDATE)) && arrayObjectInitialIndexTemp[2] .equals(objHashMapTemp.get(CollectionConstants.BANKREMITTANCE_RECEIPTNUMBER)) && arrayObjectInitialIndexTemp[11] .equals(objHashMapTemp.get(CollectionConstants.BANKREMITTANCE_INSTRUMENTID))) { check = m; break; } else continue; } return check; } @Transactional public void updateChequeCardRemittance(final Map<String, Object> instrumentDepositeMap, final String voucherWorkflowMsg, final Boolean voucherTypeForChequeDDCard, final Date voucherDate, final Bankaccount depositedBankAccount, final String serviceGlCode, final List<InstrumentHeader> instrumentHeaderListCheque, final CVoucherHeader voucherHeaderCheque) { final EgwStatus instrumentStatusDeposited = collectionsUtil.getStatusForModuleAndCode( CollectionConstants.MODULE_NAME_INSTRUMENTHEADER, CollectionConstants.INSTRUMENT_DEPOSITED_STATUS); int counter = 1; for (InstrumentHeader instrumentHeader : instrumentHeaderListCheque) { instrumentHeader = financialsUtil.updateInstrumentHeaderStatus(instrumentHeader, instrumentStatusDeposited, depositedBankAccount); if (voucherHeaderCheque.getId() != null && serviceGlCode != null) { final Map<String, Object> chequeMap = constructInstrumentMap(instrumentDepositeMap, depositedBankAccount, instrumentHeader, voucherHeaderCheque, voucherDate); if (voucherTypeForChequeDDCard) financialsUtil.updateCheque_DD_Card_Deposit_Receipt(chequeMap); else financialsUtil.updateCheque_DD_Card_Deposit(chequeMap); } if (counter % 20 == 0) { getSession().flush(); getSession().clear(); } counter++; } } @Transactional public void updateCashRemittance(final Map<String, Object> instrumentDepositeMap, final String voucherWorkflowMsg, final Date voucherDate, final Bankaccount depositedBankAccount, final String serviceGlCode, final List<InstrumentHeader> instrumentHeaderListCash, final CVoucherHeader voucherHeaderCash) { int counter = 1; for (final InstrumentHeader instrumentHeader : instrumentHeaderListCash) { if (voucherHeaderCash.getId() != null && serviceGlCode != null) { final Map<String, Object> cashMap = constructInstrumentMap(instrumentDepositeMap, depositedBankAccount, instrumentHeader, voucherHeaderCash, voucherDate); financialsUtil.updateCashDeposit(cashMap); } if (counter % 20 == 0) { getSession().flush(); getSession().clear(); } counter++; } } /** * For Bill Based Receipt, aggregate the amount for same account heads * * @param receiptDetailSetParam * @return Set of Receipt Detail after Aggregating Amounts */ public Set<ReceiptDetail> aggregateDuplicateReceiptDetailObject( final List<ReceiptDetail> receiptDetailSetParam) { final List<ReceiptDetail> newReceiptDetailList = new ArrayList<>(0); int counter = 0; for (final ReceiptDetail receiptDetailObj : receiptDetailSetParam) { if (counter == 0) newReceiptDetailList.add(receiptDetailObj); else { final int checknew = checkIfReceiptDetailObjectExist(newReceiptDetailList, receiptDetailObj); if (checknew == -1) newReceiptDetailList.add(receiptDetailObj); else { final ReceiptDetail receiptDetail = new ReceiptDetail(); final ReceiptDetail newReceiptDetailObj = newReceiptDetailList.get(checknew); newReceiptDetailList.remove(checknew); receiptDetail.setAccounthead(newReceiptDetailObj.getAccounthead()); receiptDetail.setAccountPayeeDetails(newReceiptDetailObj.getAccountPayeeDetails()); receiptDetail .setCramount(newReceiptDetailObj.getCramount().add(receiptDetailObj.getCramount())); receiptDetail.setCramountToBePaid(newReceiptDetailObj.getCramountToBePaid()); receiptDetail.setDescription(newReceiptDetailObj.getDescription()); receiptDetail .setDramount(newReceiptDetailObj.getDramount().add(receiptDetailObj.getDramount())); receiptDetail.setFinancialYear(newReceiptDetailObj.getFinancialYear()); receiptDetail.setFunction(newReceiptDetailObj.getFunction()); receiptDetail.setOrdernumber(newReceiptDetailObj.getOrdernumber()); newReceiptDetailList.add(receiptDetail); } } counter++; } return new HashSet<>(newReceiptDetailList); } /** * API to check if the given receipt detail object already exists in the list passed passed as parameter * * @param newReceiptDetailSet * @param receiptDetailObj * @return */ public int checkIfReceiptDetailObjectExist(final List<ReceiptDetail> newReceiptDetailSet, final ReceiptDetail receiptDetailObj) { int check = -1; for (int m = 0; m < newReceiptDetailSet.size(); m++) { final ReceiptDetail receiptDetail = newReceiptDetailSet.get(m); if (receiptDetailObj.getAccounthead().getId().equals(receiptDetail.getAccounthead().getId())) { check = m; break; } else continue; } return check; } /** * End Work-flow of the given cancelled receipt * * @param receiptHeaders Set of receipt headers to be transitioned * @param actionName Action name for the transition * @param comment Comment for the transition */ public void endReceiptWorkFlowOnCancellation(final ReceiptHeader receiptHeaderToBeCancelled) { // End work-flow for the cancelled receipt Position position; if (!collectionsUtil.isEmployee(receiptHeaderToBeCancelled.getCreatedBy())) position = collectionsUtil .getPositionByDeptDesgAndBoundary(receiptHeaderToBeCancelled.getReceiptMisc().getBoundary()); else position = collectionsUtil.getPositionOfUser(receiptHeaderToBeCancelled.getCreatedBy()); if (position != null) receiptHeaderToBeCancelled.transition().end() .withSenderName(receiptHeaderToBeCancelled.getCreatedBy().getUsername() + "::" + receiptHeaderToBeCancelled.getCreatedBy().getName()) .withComments("Receipt Cancelled - Workflow ends") .withStateValue(CollectionConstants.WF_STATE_END).withOwner(position).withDateInfo(new Date()); } /** * This method persists the given <code>ReceiptPayeeDetails</code> entity. The receipt number for all of the receipts is * generated, if not already present. If the receipt is associated with a challan, and the challan number is not present, the * challan number is generated and set into it. */ @Override @Transactional public ReceiptHeader persist(final ReceiptHeader receiptHeader) throws ApplicationRuntimeException { if (receiptHeader.getReceipttype() != CollectionConstants.RECEIPT_TYPE_CHALLAN && !CollectionConstants.RECEIPT_STATUS_CODE_PENDING.equals(receiptHeader.getStatus().getCode()) && !CollectionConstants.RECEIPT_STATUS_CODE_FAILED.equals(receiptHeader.getStatus().getCode()) && receiptHeader.getReceiptnumber() == null) setReceiptNumber(receiptHeader); if (receiptHeader.getChallan() != null) { final Challan challan = receiptHeader.getChallan(); if (challan.getChallanNumber() == null) setChallanNumber(challan); receiptHeader.setChallan(challan); LOGGER.info("Persisted challan with challan number " + challan.getChallanNumber()); } // Update Billing System regarding cancellation of the existing if (CollectionConstants.RECEIPT_STATUS_CODE_CANCELLED.equals(receiptHeader.getStatus().getCode())) { if (receiptHeader.getState() != null && !receiptHeader.getState().getValue().equals(CollectionConstants.WF_STATE_END)) endReceiptWorkFlowOnCancellation(receiptHeader); if (receiptHeader.getReceipttype() == CollectionConstants.RECEIPT_TYPE_BILL) { if (receiptHeader.getService().getCode().equals(CollectionConstants.SERVICECODE_LAMS)) { // TODO Implement separate API for Microservice billing services final BillReceiptInfo billReceipt = new BillReceiptInfoImpl(receiptHeader, chartOfAccountsHibernateDAO, persistenceService, null); collectionsUtil.updateReceiptDetailsAndGetReceiptAmountInfo(new BillReceiptReq(billReceipt), receiptHeader.getService().getCode()); } else updateBillingSystemWithReceiptInfo(receiptHeader, null, null); } } return super.persist(receiptHeader); } /** * This method persists the given <code>ReceiptPayeeDetails</code> entity. If the receipt number for all of the receipts is * generated, if not already present. */ @Transactional public ReceiptHeader persistChallan(final ReceiptHeader receiptHeader, final Position position, final String actionName, final String approvalRemarks) { final Integer validUpto = Integer .valueOf(collectionsUtil.getAppConfigValue(CollectionConstants.MODULE_NAME_COLLECTIONS_CONFIG, CollectionConstants.APPCONFIG_VALUE_CHALLANVALIDUPTO)); final Challan challan = receiptHeader.getChallan(); DateTime date = new DateTime(challan.getChallanDate()); date = date.plusDays(validUpto); challan.setValidUpto(date.toDate()); if (challan.getChallanNumber() == null) setChallanNumber(challan); challan.setReceiptHeader(receiptHeader); receiptHeader.setChallan(challan); super.persist(receiptHeader); LOGGER.info("Persisting challan with challan number " + challan.getChallanNumber()); challanService.workflowtransition(receiptHeader.getChallan(), position, actionName, approvalRemarks); return receiptHeader; } /** * This method persists the given set of <code>ReceiptPayeeDetails</code> instances with receipt number as Pending * * @param entity a set of <code>ReceiptPayeeDetails</code> instances to be persisted * @return the list of persisted <code>ReceiptPayeeDetails</code> instances */ @Transactional public ReceiptHeader persistReceiptObject(final ReceiptHeader receiptHeader) { return super.persist(receiptHeader); } public void setReceiptNumber(final ReceiptHeader entity) { entity.setReceiptnumber(collectionsNumberGenerator.generateReceiptNumber(entity)); } private void setChallanNumber(final Challan challan) { final CFinancialYear financialYear = collectionsUtil.getFinancialYearforDate(new Date()); challan.setChallanNumber(collectionsNumberGenerator.generateChallanNumber(challan, financialYear)); } public void setCollectionsNumberGenerator(final CollectionsNumberGenerator collectionsNumberGenerator) { this.collectionsNumberGenerator = collectionsNumberGenerator; } private BillingIntegrationService getBillingServiceBean(final String serviceCode) { return (BillingIntegrationService) collectionsUtil .getBean(serviceCode + CollectionConstants.COLLECTIONS_INTERFACE_SUFFIX); } /** * This method looks up the bean to communicate with the billing system and updates the billing system. */ @Transactional public Boolean updateBillingSystem(final ServiceDetails serviceDetails, final Set<BillReceiptInfo> billReceipts, BillingIntegrationService billingService) { if (!serviceDetails.getServiceType().equals(CollectionConstants.SERVICE_TYPE_BILLING)) return true; else if (billingService == null && serviceDetails.getServiceType().equals(CollectionConstants.SERVICE_TYPE_BILLING)) billingService = getBillingServiceBean(serviceDetails.getCode()); if (billingService == null && serviceDetails.getServiceType().equals(CollectionConstants.SERVICE_TYPE_BILLING)) return false; else try { billingService.updateReceiptDetails(billReceipts); return true; } catch (ValidationException e) { LOGGER.error("Validation error occurred while updating receipt details ", e); throw e; } catch (final Exception e) { final String errMsg = "Exception while updating billing system [" + serviceDetails.getCode() + "] with receipt details!"; LOGGER.error(errMsg, e); throw new ApplicationRuntimeException(errMsg, e); } } public String getAdditionalInfoForReceipt(final String serviceCode, final BillReceiptInfo billReceipt) { final BillingIntegrationService billingService = getBillingServiceBean(serviceCode); if (billingService == null) throw new ApplicationRuntimeException("Unable to load bean for billing system: " + serviceCode); else try { return billingService.constructAdditionalInfoForReceipt(billReceipt); } catch (final Exception e) { final String errMsg = "Exception while constructing additional info for receipt [" + serviceCode + "]!"; LOGGER.error(errMsg, e); throw new ApplicationRuntimeException(errMsg, e); } } /** * This method is called for voucher reversal in case of intra-day receipt cancellation. */ public void createReversalVoucher(final ReceiptVoucher receiptVoucher) { final List<HashMap<String, Object>> reversalVoucherInfoList = new ArrayList<>(0); final HashMap<String, Object> reversalVoucherInfo = new HashMap<>(0); if (receiptVoucher.getVoucherheader() != null) { reversalVoucherInfo.put(CollectionConstants.FINANCIALS_VOUCHERREVERSAL_ORIGINALVOUCHERID, receiptVoucher.getVoucherheader().getId()); if (receiptVoucher.getVoucherheader().getType() .equals(CollectionConstants.FINANCIAL_JOURNALVOUCHER_VOUCHERTYPE)) { reversalVoucherInfo.put(CollectionConstants.FINANCIALS_VOUCHERREVERSAL_TYPE, CollectionConstants.FINANCIAL_JOURNALVOUCHER_VOUCHERTYPE); reversalVoucherInfo.put(CollectionConstants.FINANCIALS_VOUCHERREVERSAL_NAME, CollectionConstants.FINANCIAL_JOURNALVOUCHER_VOUCHERNAME); } else if (receiptVoucher.getVoucherheader().getType() .equals(CollectionConstants.FINANCIAL_RECEIPTS_VOUCHERTYPE)) { reversalVoucherInfo.put(CollectionConstants.FINANCIALS_VOUCHERREVERSAL_TYPE, CollectionConstants.FINANCIAL_PAYMENTVOUCHER_VOUCHERTYPE); reversalVoucherInfo.put(CollectionConstants.FINANCIALS_VOUCHERREVERSAL_NAME, CollectionConstants.FINANCIAL_PAYMENTVOUCHER_VOUCHERNAME); } } reversalVoucherInfoList.add(reversalVoucherInfo); try { financialsUtil.getReversalVoucher(reversalVoucherInfoList); } catch (final Exception exp) { final String errorMsg = "Receipt Service Exception while creating reversal voucher!"; LOGGER.error(errorMsg, exp); throw new ApplicationRuntimeException(errorMsg, exp); } } /** * @param receiptPayeeDetails * @return void @ Create instrument voucher list from receiptpayeelist and pass it to financialsutil */ public void updateInstrument(final ReceiptHeader receiptHeader) { final List<Map<String, Object>> instrumentVoucherList = new ArrayList<>(0); if (receiptHeader.getReceiptVoucher() != null && !receiptHeader.getReceiptVoucher().isEmpty()) { final CVoucherHeader voucherHeader = receiptHeader.getReceiptVoucher().iterator().next() .getVoucherheader(); if (voucherHeader != null && receiptHeader.getReceiptInstrument() != null) { for (final InstrumentHeader instrumentHeader : receiptHeader.getReceiptInstrument()) { final Map<String, Object> iVoucherMap = new HashMap<>(0); iVoucherMap.put(CollectionConstants.FINANCIAL_INSTRUMENTSERVICE_INSTRUMENTHEADEROBJECT, instrumentHeader); iVoucherMap.put(CollectionConstants.FINANCIAL_INSTRUMENTSERVICE_VOUCHERHEADEROBJECT, voucherHeader); instrumentVoucherList.add(iVoucherMap); } financialsUtil.updateInstrumentVoucher(instrumentVoucherList); } } } public List<InstrumentHeader> createInstrument(final List<InstrumentHeader> instrumentHeaderList) { final List<Map<String, Object>> instrumentHeaderMapList = new ArrayList<>(0); if (instrumentHeaderList != null) for (final InstrumentHeader instrumentHeader : instrumentHeaderList) { final Map<String, Object> instrumentHeaderMap = new HashMap<>(0); instrumentHeaderMap.put(CollectionConstants.MAP_KEY_INSTRSERVICE_INSTRUMENTNUMBER, instrumentHeader.getInstrumentNumber()); instrumentHeaderMap.put(CollectionConstants.MAP_KEY_INSTRSERVICE_INSTRUMENTDATE, instrumentHeader.getInstrumentDate()); instrumentHeaderMap.put(CollectionConstants.MAP_KEY_INSTRSERVICE_INSTRUMENTAMOUNT, instrumentHeader.getInstrumentAmount()); instrumentHeaderMap.put(CollectionConstants.MAP_KEY_INSTRSERVICE_INSTRUMENTTYPE, instrumentHeader.getInstrumentType().getType()); instrumentHeaderMap.put(CollectionConstants.MAP_KEY_INSTRSERVICE_ISPAYCHEQUE, instrumentHeader.getIsPayCheque()); if (instrumentHeader.getBankId() != null) instrumentHeaderMap.put(CollectionConstants.MAP_KEY_INSTRSERVICE_BANKCODE, instrumentHeader.getBankId().getCode()); instrumentHeaderMap.put(CollectionConstants.MAP_KEY_INSTRSERVICE_BANKBRANCHNAME, instrumentHeader.getBankBranchName()); instrumentHeaderMap.put(CollectionConstants.MAP_KEY_INSTRSERVICE_TRANSACTIONNUMBER, instrumentHeader.getTransactionNumber()); instrumentHeaderMap.put(CollectionConstants.MAP_KEY_INSTRSERVICE_TRANSACTIONDATE, instrumentHeader.getTransactionDate()); if (instrumentHeader.getBankAccountId() != null) instrumentHeaderMap.put(CollectionConstants.MAP_KEY_INSTRSERVICE_BANKACCOUNTID, instrumentHeader.getBankAccountId().getId()); instrumentHeaderMapList.add(instrumentHeaderMap); // should add bankaccount for bank : key = Bank account id; // value = instrumentHeader.getBankAccount.getId() } return financialsUtil.createInstrument(instrumentHeaderMapList); } private Map<String, Object> constructInstrumentMap(final Map<String, Object> instrumentDepositeMap, final Bankaccount bankaccount, final InstrumentHeader instrumentHeader, final CVoucherHeader voucherHeader, final Date voucherDate) { final InstrumentType instrumentType = (InstrumentType) persistenceService .find("select it from InstrumentType it,InstrumentHeader ih where " + "ih.instrumentType=it.id and ih.id=?", instrumentHeader.getId()); instrumentDepositeMap.put("instrumentheader", instrumentHeader.getId()); instrumentDepositeMap.put("bankaccountid", bankaccount.getId()); instrumentDepositeMap.put("instrumentamount", instrumentHeader.getInstrumentAmount()); instrumentDepositeMap.put("instrumenttype", instrumentType.getType()); instrumentDepositeMap.put("depositdate", voucherDate); instrumentDepositeMap.put("createdby", voucherHeader.getCreatedBy().getId()); instrumentDepositeMap.put("ispaycheque", instrumentHeader.getIsPayCheque()); instrumentDepositeMap.put("payinid", voucherHeader.getId()); return instrumentDepositeMap; } @Transactional public void performWorkflow(final String actionName, final ReceiptHeader receiptHeader, final String remarks) { try { Position operatorPosition; Employee employee = employeeService.getEmployeeById(receiptHeader.getCreatedBy().getId()); final Department department = departmentService.getDepartmentByName( collectionsUtil.getAppConfigValue(CollectionConstants.MODULE_NAME_COLLECTIONS_CONFIG, CollectionConstants.COLLECTION_DEPARTMENTFORWORKFLOWAPPROVER)); final Designation designation = collectionsUtil.getDesignationForApprover(); final Boolean isEmployee = collectionsUtil.isEmployee(receiptHeader.getCreatedBy()); if (!isEmployee) employee = employeeService.getEmployeeById(collectionsUtil.getLoggedInUser().getId()); Boundary boundary = null; for (final Jurisdiction jur : employee.getJurisdictions()) boundary = jur.getBoundary(); List<Employee> emp = employeeService.findByDepartmentDesignationAndBoundary(department.getId(), designation.getId(), boundary.getId()); if (emp.isEmpty() && boundary.getParent() != null) { emp = employeeService.findByDepartmentDesignationAndBoundary(department.getId(), designation.getId(), boundary.getParent().getId()); if (emp.isEmpty() && boundary.getParent().getParent() != null) emp = employeeService.findByDepartmentDesignationAndBoundary(department.getId(), designation.getId(), boundary.getParent().getParent().getId()); } if (emp.isEmpty()) throw new ValidationException(Arrays.asList(new ValidationError("Manager does not exists", "submitcollections.validation.error.manager.notexists"))); Position approverPosition = null; final List<Assignment> assignments = assignmentService .getAllActiveEmployeeAssignmentsByEmpId(emp.get(0).getId()); for (final Assignment assign : assignments) if (assign.getDesignation().equals(designation)) approverPosition = assign.getPosition(); if (actionName.equals(CollectionConstants.WF_ACTION_SUBMIT)) perform(receiptHeader, CollectionConstants.WF_ACTION_APPROVE, CollectionConstants.RECEIPT_STATUS_CODE_SUBMITTED, CollectionConstants.WF_ACTION_APPROVE, approverPosition, remarks); else if (actionName.equals(CollectionConstants.WF_ACTION_APPROVE)) perform(receiptHeader, CollectionConstants.WF_STATE_APPROVED, CollectionConstants.RECEIPT_STATUS_CODE_APPROVED, "", approverPosition, remarks); else if (actionName.equals(CollectionConstants.WF_ACTION_REJECT)) { if (!isEmployee) operatorPosition = collectionsUtil .getPositionByDeptDesgAndBoundary(receiptHeader.getReceiptMisc().getBoundary()); else operatorPosition = collectionsUtil.getPositionOfUser(receiptHeader.getCreatedBy()); perform(receiptHeader, CollectionConstants.WF_STATE_REJECTED, CollectionConstants.RECEIPT_STATUS_CODE_TO_BE_SUBMITTED, CollectionConstants.WF_ACTION_SUBMIT, operatorPosition, remarks); } } catch (final Exception e) { final String errorMsg = "Receipt Service Exception while workflow transition!"; LOGGER.error(errorMsg, e); throw new ApplicationRuntimeException(e.getMessage()); } } @Transactional public void performWorkflowForAllReceipts(final String actionName, final List<ReceiptHeader> receiptHeaders, final String remarks) { try { final Position approverPosition = getApproverPosition(receiptHeaders.get(0)); for (final ReceiptHeader receiptHeader : receiptHeaders) if (actionName.equals(CollectionConstants.WF_ACTION_SUBMIT)) perform(receiptHeader, CollectionConstants.WF_ACTION_APPROVE, CollectionConstants.RECEIPT_STATUS_CODE_SUBMITTED, CollectionConstants.WF_ACTION_APPROVE, approverPosition, remarks); else if (actionName.equals(CollectionConstants.WF_ACTION_APPROVE)) perform(receiptHeader, CollectionConstants.WF_STATE_APPROVED, CollectionConstants.RECEIPT_STATUS_CODE_APPROVED, "", approverPosition, remarks); else if (actionName.equals(CollectionConstants.WF_ACTION_REJECT)) { final Position operatorPosition = getOperatorPosition(receiptHeaders.get(0)); perform(receiptHeader, CollectionConstants.WF_STATE_REJECTED, CollectionConstants.RECEIPT_STATUS_CODE_TO_BE_SUBMITTED, CollectionConstants.WF_ACTION_SUBMIT, operatorPosition, remarks); } } catch (final ValidationException e) { final List<ValidationError> errors = new ArrayList<>(); errors.add(new ValidationError("exp", e.getErrors().get(0).getMessage())); LOGGER.error(errors, e); throw new ValidationException(errors); } catch (final Exception e) { final String errorMsg = "Receipt Service Exception while workflow transition!"; LOGGER.error(errorMsg, e); throw new ApplicationRuntimeException(e.getMessage()); } } public Position getApproverPosition(final ReceiptHeader receiptHeader) { Employee employee; final Boolean isEmployee = collectionsUtil.isEmployee(receiptHeader.getCreatedBy()); if (!isEmployee) employee = employeeService.getEmployeeById(collectionsUtil.getLoggedInUser().getId()); else employee = employeeService.getEmployeeById(receiptHeader.getCreatedBy().getId()); final Department department = departmentService.getDepartmentByName( collectionsUtil.getAppConfigValue(CollectionConstants.MODULE_NAME_COLLECTIONS_CONFIG, CollectionConstants.COLLECTION_DEPARTMENTFORWORKFLOWAPPROVER)); final Designation designation = collectionsUtil.getDesignationForApprover(); Boundary boundary = null; for (final Jurisdiction jur : employee.getJurisdictions()) boundary = jur.getBoundary(); List<Employee> emp = employeeService.findByDepartmentDesignationAndBoundary(department.getId(), designation.getId(), boundary.getId()); if (emp.isEmpty() && boundary.getParent() != null) { emp = employeeService.findByDepartmentDesignationAndBoundary(department.getId(), designation.getId(), boundary.getParent().getId()); if (emp.isEmpty() && boundary.getParent().getParent() != null) emp = employeeService.findByDepartmentDesignationAndBoundary(department.getId(), designation.getId(), boundary.getParent().getParent().getId()); } if (emp.isEmpty()) throw new ValidationException(Arrays.asList(new ValidationError("Manager does not exists", "submitcollections.validation.error.manager.notexists"))); Position approverPosition = null; final List<Assignment> assignments = assignmentService .getAllActiveEmployeeAssignmentsByEmpId(emp.get(0).getId()); for (final Assignment assign : assignments) if (assign.getDesignation().equals(designation)) approverPosition = assign.getPosition(); return approverPosition; } public Position getOperatorPosition(final ReceiptHeader receiptHeader) { Position operatorPosition; final Boolean isEmployee = collectionsUtil.isEmployee(receiptHeader.getCreatedBy()); if (!isEmployee) operatorPosition = collectionsUtil .getPositionByDeptDesgAndBoundary(receiptHeader.getReceiptMisc().getBoundary()); else operatorPosition = collectionsUtil.getPositionOfUser(receiptHeader.getCreatedBy()); return operatorPosition; } @Transactional public void perform(final ReceiptHeader receiptHeader, final String wfState, final String newStatusCode, final String nextAction, final Position ownerPosition, final String remarks) { receiptHeader.setStatus(collectionsUtil.getReceiptStatusForCode(newStatusCode)); if (receiptHeader.getStatus().getCode().equals(CollectionConstants.RECEIPT_STATUS_CODE_APPROVED)) // Receipt approved. end workflow for this receipt. receiptHeader.transition().end() .withSenderName(receiptHeader.getCreatedBy().getUsername() + "::" + receiptHeader.getCreatedBy().getName()) .withComments("Receipt Approved - Workflow ends") .withStateValue(CollectionConstants.WF_STATE_END).withOwner(ownerPosition) .withDateInfo(new Date()); else receiptHeader.transition().progressWithStateCopy() .withSenderName(receiptHeader.getCreatedBy().getUsername() + "::" + receiptHeader.getCreatedBy().getName()) .withComments(remarks).withStateValue(wfState).withOwner(ownerPosition).withDateInfo(new Date()) .withNextAction(nextAction); super.persist(receiptHeader); updateCollectionIndexAndPushMail(receiptHeader); } public Set<InstrumentHeader> createOnlineInstrument(final Date transactionDate, final String transactionId, final BigDecimal transactionAmt) { final InstrumentHeader onlineInstrumentHeader = new InstrumentHeader(); Set<InstrumentHeader> instrumentHeaderSet; onlineInstrumentHeader.setInstrumentType( financialsUtil.getInstrumentTypeByType(CollectionConstants.INSTRUMENTTYPE_ONLINE)); onlineInstrumentHeader.setTransactionDate(transactionDate); onlineInstrumentHeader.setIsPayCheque(CollectionConstants.ZERO_INT); onlineInstrumentHeader.setTransactionNumber(transactionId); onlineInstrumentHeader.setInstrumentAmount(transactionAmt); final List<InstrumentHeader> instHeaderList = new ArrayList<>(); instHeaderList.add(onlineInstrumentHeader); instrumentHeaderSet = new HashSet<>(createInstrument(instHeaderList)); return instrumentHeaderSet; } public String getReceiptHeaderforDishonor(final Long mode, final Long bankAccId, final Long bankId, final String chequeDDNo, final String chqueDDDate) { final StringBuilder sb = new StringBuilder(); sb.append( "FROM egcl_collectionheader rpt,egcl_collectioninstrument ci,egf_instrumentheader ih,egw_status status,bank b," + "bankbranch bb,bankaccount ba WHERE rpt.id = ci.collectionheader AND ci.instrumentheader = ih.id AND status.id = ih.id_status " + "AND b.id = bb.bankid AND bb.id = ba.branchid AND ba.id = ih.bankaccountid AND ih.instrumenttype = '" + mode + "' AND ((ih.ispaycheque ='0' AND status.moduletype ='" + CollectionConstants.MODULE_NAME_INSTRUMENTHEADER + "'" + "AND status.description = '" + CollectionConstants.INSTRUMENT_DEPOSITED_STATUS + "'))"); if (bankAccId != null && bankAccId != -1) sb.append(" AND ih.bankaccountid=" + bankAccId + ""); if ((bankAccId == null || bankAccId == -1) && bankId != null && bankId != 0) sb.append(" AND ih.bankid=" + bankId + ""); if (!"".equals(chequeDDNo) && chequeDDNo != null) sb.append(" AND ih.instrumentnumber=trim('" + chequeDDNo + "') "); if (!"".equals(chqueDDDate) && chqueDDDate != null) sb.append(" AND ih.instrumentdate = '" + chqueDDDate + "' "); return sb.toString(); } /** * This method performs the following for receipts to be newly created: * <ol> * <li>The user instrument header details, and actual amount paid by user is captured.</li> * <li>A debit receipt detail account head is created for the total credit collected.</li> * <li>Vouchers are created</li> * </ol> * <p> * The receipts are persisted and work flow is started for these persisted receipts where in the receipt state is set to NEW * The billing system is updated about the persisted receipts. These include details of both newly created as well as * cancelled receipts. If the instrument list and voucher list are not empty, the .... is updated The receipt ids of the newly * created receipts are collectively populated to be shown on the print screen */ @Transactional public void populateAndPersistReceipts(final ReceiptHeader receiptHeader, final List<InstrumentHeader> receiptInstrList) { try { LOGGER.info("Workflow started for newly created receipts"); if (isReceiptCreateApprovedStatus(receiptHeader)) setReceiptApprovedStatus(receiptHeader); else startWorkflow(receiptHeader); LOGGER.info("Persisted receipts"); persist(receiptHeader); // create voucher based on configuration. if (collectionsUtil.checkVoucherCreation(receiptHeader)) createVoucherForReceipt(receiptHeader); if (receiptHeader.getService().getServiceType() .equalsIgnoreCase(CollectionConstants.SERVICE_TYPE_BILLING)) { updateBillingSystemWithReceiptInfo(receiptHeader, null, null); LOGGER.info("Updated billing system "); } else updateCollectionIndexAndPushMail(receiptHeader); } catch (final HibernateException e) { LOGGER.error("Receipt Service HException while persisting ReceiptHeader", e); throw new ApplicationRuntimeException("Receipt Service Exception while persisting ReceiptHeader : ", e); } catch (final ApplicationRuntimeException e) { LOGGER.error("Receipt Service AException while persisting ReceiptHeader!", e); throw new ApplicationRuntimeException("Receipt Service Exception while persisting ReceiptHeader : ", e); } }// end of method public Date getDataEntryCutOffDate() { final SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); Date cutOffDate = null; try { cutOffDate = sdf .parse(collectionsUtil.getAppConfigValue(CollectionConstants.MODULE_NAME_COLLECTIONS_CONFIG, CollectionConstants.APPCONFIG_VALUE_COLLECTIONDATAENTRYCUTOFFDATE)); } catch (final ParseException e) { LOGGER.error("Error parsing Cut Off Date", e); throw new ApplicationRuntimeException(e.getMessage()); } return cutOffDate; } /** * Updates the billing system with receipt information * * @param receiptHeader */ @Transactional public void updateBillingSystemWithReceiptInfo(final ReceiptHeader receiptHeader, final BillingIntegrationService billingService, final InstrumentHeader bouncedInstrumentInfo) { /** * for each receipt created, send the details back to the billing system */ LOGGER.info("$$$$$$ Update Billing system for Service Code :" + receiptHeader.getService().getCode() + (receiptHeader.getConsumerCode() != null ? " and consumer code: " + receiptHeader.getConsumerCode() : "")); final Set<BillReceiptInfo> billReceipts = new HashSet<>(0); billReceipts.add(new BillReceiptInfoImpl(receiptHeader, chartOfAccountsHibernateDAO, persistenceService, bouncedInstrumentInfo)); if (receiptHeader.getService().getCode().equals(CollectionConstants.SERVICECODE_LAMS) || updateBillingSystem(receiptHeader.getService(), billReceipts, billingService)) { receiptHeader.setIsReconciled(true); // the receipts should be persisted again super.persist(receiptHeader); updateCollectionIndexAndPushMail(receiptHeader); } LOGGER.info("$$$$$$ Billing system updated for Service Code :" + receiptHeader.getService().getCode() + (receiptHeader.getConsumerCode() != null ? " and consumer code: " + receiptHeader.getConsumerCode() : "")); } @Transactional public void updateCollectionIndexAndPushMail(final ReceiptHeader receiptHeader) { if (receiptHeader.getPayeeEmail() != null && !receiptHeader.getPayeeEmail().isEmpty() && (receiptHeader .getCollectiontype().equals(CollectionConstants.COLLECTION_TYPE_ONLINECOLLECTION) && receiptHeader.getStatus().getCode().equals(CollectionConstants.RECEIPT_STATUS_CODE_APPROVED) || !receiptHeader.getCollectiontype().equals(CollectionConstants.COLLECTION_TYPE_ONLINECOLLECTION) && receiptHeader.getStatus().getCode() .equals(CollectionConstants.RECEIPT_STATUS_CODE_TO_BE_SUBMITTED))) pushMail(receiptHeader); CollectionIndex collectionIndexObj = collectionIndexUtils .findByReceiptNumber(receiptHeader.getReceiptnumber()); if (collectionIndexObj != null) { collectionIndexObj.setStatus(receiptHeader.getStatus().getDescription()); collectionIndexService.persistCollectionIndex(collectionIndexObj); } else { collectionIndexObj = collectionsUtil.constructCollectionIndex(receiptHeader); collectionIndexService.pushCollectionIndex(collectionIndexObj); } } private void pushMail(final ReceiptHeader receiptHeader) { collectionsUtil.emailReceiptAsAttachment(receiptHeader, collectionsUtil.createReport(getReportRequest(receiptHeader)).getReportOutputData()); } public ReportRequest getReportRequest(final ReceiptHeader receiptHeader) { String additionalMessage = null; final List<BillReceiptInfo> receiptList = new ArrayList<>(0); final Map<String, Object> reportParams = new HashMap<>(0); final String serviceCode = receiptHeader.getService().getCode(); reportParams.put(CollectionConstants.REPORT_PARAM_COLLECTIONS_UTIL, collectionsUtil); final String templateName = collectionsUtil.getReceiptTemplateName(receiptHeader.getReceipttype(), serviceCode); if (receiptHeader.getReceipttype() == CollectionConstants.RECEIPT_TYPE_BILL) { if (!receiptHeader.getService().getCode().equals(CollectionConstants.SERVICECODE_LAMS)) additionalMessage = getAdditionalInfoForReceipt(serviceCode, new BillReceiptInfoImpl(receiptHeader, chartOfAccountsHibernateDAO, persistenceService, null)); if (additionalMessage != null) receiptList.add(new BillReceiptInfoImpl(receiptHeader, additionalMessage, chartOfAccountsHibernateDAO, persistenceService)); else receiptList.add(new BillReceiptInfoImpl(receiptHeader, chartOfAccountsHibernateDAO, persistenceService, null)); } final ReportRequest reportInput = new ReportRequest(templateName, receiptList, reportParams); reportInput.setReportFormat(ReportFormat.PDF); reportInput.setPrintDialogOnOpenReport(false); return reportInput; } /** * @param receipts - list of receipts which have to be processed as successful payments. For payments created as a response * from bill desk, size of the array will be 1. */ @Transactional public ReceiptHeader createOnlineSuccessPayment(final ReceiptHeader receiptHeader, final Date transactionDate, final String transactionId, final BigDecimal transactionAmt, final String authStatusCode, final String remarks, final BillingIntegrationService billingService) { receiptHeader.setStatus( collectionsUtil.getReceiptStatusForCode(CollectionConstants.RECEIPT_STATUS_CODE_APPROVED)); receiptHeader.setReceiptInstrument(createOnlineInstrument(transactionDate, transactionId, transactionAmt)); receiptHeader.setIsReconciled(Boolean.FALSE); receiptHeader.getOnlinePayment().setAuthorisationStatusCode(authStatusCode); receiptHeader.getOnlinePayment().setTransactionNumber(transactionId); receiptHeader.getOnlinePayment().setTransactionAmount(transactionAmt); receiptHeader.getOnlinePayment().setTransactionDate(transactionDate); receiptHeader.getOnlinePayment().setRemarks(remarks); // set online payment status as SUCCESS receiptHeader.getOnlinePayment() .setStatus(collectionsUtil.getStatusForModuleAndCode(CollectionConstants.MODULE_NAME_ONLINEPAYMENT, CollectionConstants.ONLINEPAYMENT_STATUS_CODE_SUCCESS)); persist(receiptHeader); LOGGER.debug("Persisted receipt after receiving success message from the payment gateway"); return updateFinancialAndBillingSystem(receiptHeader, billingService); } @Transactional public ReceiptHeader updateFinancialAndBillingSystem(final ReceiptHeader receiptHeader, final BillingIntegrationService billingService) { try { final Boolean createVoucherForBillingService = collectionsUtil.checkVoucherCreation(receiptHeader); if (createVoucherForBillingService) { createVoucherForReceipt(receiptHeader); LOGGER.debug("Updated financial systems and created voucher."); } } catch (final ApplicationRuntimeException ex) { LOGGER.error("Receipt Service Exception while updateFinancialAndBillingSystem", ex); throw new ApplicationRuntimeException("Failed to create voucher in Financials"); } updateBillingSystemWithReceiptInfo(receiptHeader, billingService, null); return receiptHeader; } @Transactional public void persistFieldReceipt(final ReceiptHeader receiptHeader, final List<InstrumentHeader> instrumentHeaderList) { final Set<InstrumentHeader> instHeaderSet = new HashSet<>(createInstrument(instrumentHeaderList)); receiptHeader.setReceiptInstrument(instHeaderSet); persist(receiptHeader); LOGGER.info("Receipt Created with receipt number: " + receiptHeader.getReceiptnumber()); updateFinancialAndBillingSystem(receiptHeader, null); LOGGER.info("Billing system updated with receipt info"); } @Transactional public void updateDishonoredInstrumentStatus(final ReceiptHeader receiptHeader, final InstrumentHeader bounceInstrumentInfo, final EgwStatus receiptStatus, final boolean isReconciled) { financialsUtil.updateInstrumentHeader(bounceInstrumentInfo); // update receipts - set status to INSTR_BOUNCED and recon flag to false updateReceiptHeaderStatus(receiptHeader, receiptStatus, false); LOGGER.debug("Updated receipt status to " + receiptStatus.getCode() + " set reconcilation to false"); updateBillingSystemWithReceiptInfo(receiptHeader, null, bounceInstrumentInfo); } /** * This method updates the status and reconciliation flag for the given receipt * * @param receiptHeader <code>ReceiptHeader</code> objects whose status and reconciliation flag have to be modified * @param status a <code>EgwStatus</code> instance representing the state to which the receipt has to be updated with * @param isReconciled a <code>Boolean</code> flag indicating the value for the reconciliation status */ @Transactional public void updateReceiptHeaderStatus(final ReceiptHeader receiptHeader, final EgwStatus status, final boolean isReconciled) { if (status != null) receiptHeader.setStatus(status); receiptHeader.setIsReconciled(isReconciled); update(receiptHeader); } @Transactional public ReceiptHeader reconcileOnlineSuccessPayment(final ReceiptHeader onlinePaymentReceiptHeader, final Date txnDate, final String txnRefNo, final BigDecimal txnAmount, final String txnAuthStatus, final List<ReceiptDetail> reconstructedList, final ReceiptDetail debitAccountDetail) { final BillingIntegrationService billingService = (BillingIntegrationService) collectionsUtil .getBean(onlinePaymentReceiptHeader.getService().getCode() + CollectionConstants.COLLECTIONS_INTERFACE_SUFFIX); if (reconstructedList != null) { onlinePaymentReceiptHeader.getReceiptDetails().clear(); persistReceiptObject(onlinePaymentReceiptHeader); LOGGER.debug("Reconstructed receiptDetailList : " + reconstructedList.toString()); for (final ReceiptDetail receiptDetail : reconstructedList) { receiptDetail.setReceiptHeader(onlinePaymentReceiptHeader); onlinePaymentReceiptHeader.addReceiptDetail(receiptDetail); } onlinePaymentReceiptHeader.addReceiptDetail(debitAccountDetail); } return createOnlineSuccessPayment(onlinePaymentReceiptHeader, txnDate, txnRefNo, txnAmount, txnAuthStatus, null, billingService); } public void setCollectionsUtil(final CollectionsUtil collectionsUtil) { this.collectionsUtil = collectionsUtil; } public void setFinancialsUtil(final FinancialsUtil financialsUtil) { this.financialsUtil = financialsUtil; } public void setPersistenceService(final PersistenceService persistenceService) { this.persistenceService = persistenceService; } public void setChallanService(final ChallanService challanService) { this.challanService = challanService; } /** * No work flow before cut off Date OR logged in user is Bank Collection Operator else Start work flow for newly created * receipt. */ public Boolean isReceiptCreateApprovedStatus(ReceiptHeader receiptHeader) { final Date cutOffDate = getDataEntryCutOffDate(); if ((cutOffDate != null && receiptHeader.getReceiptdate().before(cutOffDate)) || collectionsUtil.isRoleToCreateReceiptApprovedStatus(collectionsUtil.getLoggedInUser())) return true; else return false; } /** * Create receipt in approved status * @param receiptHeader */ public void setReceiptApprovedStatus(ReceiptHeader receiptHeader) { receiptHeader.setStatus(collectionsUtil.getStatusForModuleAndCode( CollectionConstants.MODULE_NAME_RECEIPTHEADER, CollectionConstants.RECEIPT_STATUS_CODE_APPROVED)); } public void validateReceiptCancellation(String receiptNumber, String serviceCode, String consumerCode) { if (!serviceCode.equals(CollectionConstants.SERVICECODE_LAMS)) { BillingIntegrationService billingService = getBillingServiceBean(serviceCode); ReceiptCancellationInfo receiptCancellationInfo = billingService.validateCancelReceipt(receiptNumber, consumerCode); if (!receiptCancellationInfo.getCancellationAllowed()) { String validationMsg = receiptCancellationInfo.getValidationMessage(); throw new ValidationException(new ValidationError("validationMsg", validationMsg)); } } } }