com.sfs.whichdoctor.dao.ReceiptDAOImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.sfs.whichdoctor.dao.ReceiptDAOImpl.java

Source

/*******************************************************************************
 * Copyright (c) 2009 David Harrison.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl-3.0.html
 *
 * Contributors:
 *     David Harrison - initial API and implementation
 ******************************************************************************/
package com.sfs.whichdoctor.dao;

import com.sfs.beans.BuilderBean;
import com.sfs.beans.FinancialTypeBean;
import com.sfs.beans.ObjectTypeBean;
import com.sfs.beans.PrivilegesBean;
import com.sfs.beans.UserBean;
import com.sfs.whichdoctor.beans.DebitBean;
import com.sfs.whichdoctor.beans.GroupBean;
import com.sfs.whichdoctor.beans.ItemBean;
import com.sfs.whichdoctor.beans.OrganisationBean;
import com.sfs.whichdoctor.beans.PaymentBean;
import com.sfs.whichdoctor.beans.PersonBean;
import com.sfs.whichdoctor.beans.ReceiptBean;
import com.sfs.whichdoctor.beans.SearchBean;
import com.sfs.whichdoctor.beans.SearchResultsBean;

import java.sql.Date;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.TreeMap;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

/**
 * The Class ReceiptDAOImpl.
 */
public class ReceiptDAOImpl extends WhichDoctorFinancialObjectDAOImpl implements ReceiptDAO {

    /** The data logger. */
    private static Logger dataLogger = Logger.getLogger(ReceiptDAOImpl.class);

    /** The payment dao. */
    @Resource
    private PaymentDAO paymentDAO;

    /**
     * Used to get a ReceiptBean for a specified receiptId.
     *
     * @param receiptId the receipt id
     *
     * @return the receipt bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final ReceiptBean load(final int receiptId) throws WhichDoctorDaoException {
        return load(receiptId, new BuilderBean(), false);
    }

    /**
     * Used to get a ReceiptBean for a specified receiptId and supplied load
     * options.
     *
     * @param receiptId the receipt id
     * @param loadDetails the load details
     *
     * @return the receipt bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final ReceiptBean load(final int receiptId, final BuilderBean loadDetails)
            throws WhichDoctorDaoException {
        return load(receiptId, loadDetails, false);
    }

    /**
     * Used to get a ReceiptBean for a specified receiptId and supplied load
     * options. A boolean parameter identifies whether to use the default reader
     * connection or optional writer connection datasource.
     *
     * @param receiptId the receipt id
     * @param loadDetails the load details
     * @param useWriterConn the use writer conn
     *
     * @return the receipt bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    private ReceiptBean load(final int receiptId, final BuilderBean loadDetails, final boolean useWriterConn)
            throws WhichDoctorDaoException {

        ReceiptBean receipt = null;

        final String loadSQL = getSQL().getValue("receipt/load")
                + " AND receipt.ReceiptId = ? GROUP BY receipt.ReceiptId";

        JdbcTemplate jdbcTemplate = this.getJdbcTemplateReader();

        if (useWriterConn) {
            jdbcTemplate = this.getJdbcTemplateWriter();
        }

        try {
            receipt = (ReceiptBean) jdbcTemplate.queryForObject(loadSQL, new Object[] { receiptId },
                    new RowMapper() {

                        public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException {
                            return loadReceipt(rs, loadDetails);
                        }
                    });

        } catch (IncorrectResultSizeDataAccessException ie) {
            dataLogger.debug("No results found for this search:" + ie.getMessage());
        }
        return receipt;
    }

    /**
     * Used to get a ReceiptBean for a specified name.
     *
     * @param strReceipt the str receipt
     *
     * @return the receipt bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final ReceiptBean load(final String strReceipt) throws WhichDoctorDaoException {
        return load(strReceipt, new BuilderBean());
    }

    /**
     * Used to get a ReceiptBean for a specified name and supplied load details.
     *
     * @param strReceipt the str receipt
     * @param loadDetails the load details
     *
     * @return the receipt bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final ReceiptBean load(final String strReceipt, final BuilderBean loadDetails)
            throws WhichDoctorDaoException {

        dataLogger.info("Receipt Name: " + strReceipt + " requested");

        int receiptGUID = 0;

        final String loadSQL = getSQL().getValue("receipt/loadName");

        try {
            receiptGUID = this.getJdbcTemplateReader().queryForInt(loadSQL, new Object[] { strReceipt });

        } catch (IncorrectResultSizeDataAccessException ie) {
            dataLogger.debug("No results found for this search:" + ie.getMessage());
        }

        if (receiptGUID > 0) {
            return loadGUID(receiptGUID, loadDetails);
        } else {
            throw new WhichDoctorDaoException("Sorry no receipt matching " + "those details could be identified");
        }
    }

    /**
     * Used to get a ReceiptBean for a specified guid.
     *
     * @param guid the guid
     *
     * @return the receipt bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final ReceiptBean loadGUID(final int guid) throws WhichDoctorDaoException {
        return loadGUID(guid, new BuilderBean());
    }

    /**
     * Used to get a ReceiptBean for a specified guid and supplied load details.
     *
     * @param guid the guid
     * @param loadDetails the load details
     *
     * @return the receipt bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final ReceiptBean loadGUID(final int guid, final BuilderBean loadDetails)
            throws WhichDoctorDaoException {

        ReceiptBean receipt = null;

        final String loadSQL = getSQL().getValue("receipt/load")
                + " AND receipt.Active = true AND receipt.GUID = ? " + "GROUP BY receipt.ReceiptId";

        try {
            receipt = (ReceiptBean) this.getJdbcTemplateReader().queryForObject(loadSQL, new Object[] { guid },
                    new RowMapper() {
                        public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException {
                            return loadReceipt(rs, loadDetails);
                        }
                    });

        } catch (IncorrectResultSizeDataAccessException ie) {
            dataLogger.debug("No results found for this search:" + ie.getMessage());
        }
        return receipt;
    }

    /**
     * Creates the ReceiptBean.
     *
     * @param receipt the receipt
     * @param checkUser the check user
     * @param privileges the privileges
     *
     * @return the receipt bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final ReceiptBean create(final ReceiptBean receipt, final UserBean checkUser,
            final PrivilegesBean privileges) throws WhichDoctorDaoException {
        receipt.setActive(true);
        int receiptId = save(receipt, checkUser, privileges, "create");

        return load(receiptId, new BuilderBean(), true);
    }

    /**
     * Modify the ReceiptBean.
     *
     * @param receipt the receipt
     * @param checkUser the check user
     * @param privileges the privileges
     *
     * @return the receipt bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final ReceiptBean modify(final ReceiptBean receipt, final UserBean checkUser,
            final PrivilegesBean privileges) throws WhichDoctorDaoException {
        receipt.setActive(true);
        int receiptId = save(receipt, checkUser, privileges, "modify");

        return load(receiptId, new BuilderBean(), true);
    }

    /**
     * Delete the ReceiptBean.
     *
     * @param receipt the receipt
     * @param checkUser the check user
     * @param privileges the privileges
     *
     * @return true, if successful
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final boolean delete(final ReceiptBean receipt, final UserBean checkUser,
            final PrivilegesBean privileges) throws WhichDoctorDaoException {

        boolean success = false;

        if (privileges.getPrivilege(checkUser, "receipts", "delete")) {
            // Before deleting the receipt remove its child objects
            final BuilderBean loadDetails = new BuilderBean();
            loadDetails.setParameter("LOAD_ALL", true);
            try {
                final ReceiptBean deleteObj = this.loadGUID(receipt.getGUID(), loadDetails);
                deleteAssociatedObjects(deleteObj, checkUser, privileges);

            } catch (WhichDoctorDaoException wde) {
                dataLogger.error("Error deleting children: " + wde.getMessage(), wde);
                throw new WhichDoctorDaoException("Error deleting children objects: " + wde.getMessage());
            }
        }

        receipt.setActive(false);
        int receiptId = save(receipt, checkUser, privileges, "delete");
        if (receiptId > 0) {
            success = true;
        }
        return success;
    }

    /**
     * Save.
     *
     * @param receipt the receipt
     * @param checkUser the check user
     * @param privileges the privileges
     * @param action the action
     *
     * @return the int
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    private int save(final ReceiptBean receipt, final UserBean checkUser, final PrivilegesBean privileges,
            final String action) throws WhichDoctorDaoException {

        // Create receipt requires all the essential receipt information
        if (receipt.getDescription() == null) {
            throw new WhichDoctorDaoException("Receipt description field " + "cannot be null");
        }
        if (receipt.getDescription().compareTo("") == 0) {
            throw new WhichDoctorDaoException("Receipt description field " + "cannot be an empty string");
        }
        if (receipt.getPersonId() == 0 && receipt.getOrganisationId() == 0) {
            throw new WhichDoctorDaoException("Receipt must be attributed to a person or organisation");
        }
        if (!privileges.getPrivilege(checkUser, "receipts", action)) {
            throw new WhichDoctorDaoException("Insufficient user credentials " + "to " + action + " receipt");
        }

        /* Get the typeId */
        int typeId = 0;
        try {
            FinancialTypeBean financialObject = this.financialTypeDAO.load("Receipt", receipt.getTypeName(),
                    receipt.getClassName());
            typeId = financialObject.getFinancialTypeId();
        } catch (Exception e) {
            dataLogger.error("Error loading financial type for receipt: " + e.getMessage());
            throw new WhichDoctorDaoException("Receipt requires a valid type");
        }
        /* Get the ProcessTypeId */
        int processTypeId = 0;
        try {
            ObjectTypeBean object = this.getObjectTypeDAO().load("Process Type", "", receipt.getProcessType());
            processTypeId = object.getObjectTypeId();
        } catch (Exception e) {
            dataLogger.error("Error loading objecttype for process type: " + e.getMessage());
            throw new WhichDoctorDaoException("Receipt requires a valid " + "process type");
        }

        /* Check if the receipt number exists, if not create one */
        receipt.setNumber(this.checkNumber("receipt", receipt.getNumber(), receipt.getIssued()));

        int receiptId = 0;

        Date issued = new Date(Calendar.getInstance().getTimeInMillis());
        if (receipt.getIssued() != null) {
            issued = new Date(receipt.getIssued().getTime());
        }
        Timestamp sqlTimeStamp = new Timestamp(Calendar.getInstance().getTimeInMillis());

        ArrayList<Object> parameters = new ArrayList<Object>();
        parameters.add(receipt.getDescription());
        parameters.add(receipt.getNumber());
        parameters.add(processTypeId);
        parameters.add(Integer.parseInt(receipt.getBatchReference()));
        parameters.add(receipt.getBank());
        parameters.add(receipt.getBranch());
        parameters.add(receipt.getCancelled());
        parameters.add(typeId);
        parameters.add(receipt.getPersonId());
        parameters.add(receipt.getOrganisationId());
        parameters.add(issued);
        parameters.add(receipt.getActive());
        parameters.add(sqlTimeStamp);
        parameters.add(checkUser.getDN());
        parameters.add(receipt.getLogMessage(action));

        try {
            Integer[] result = this.performUpdate("receipt", receipt.getGUID(), parameters, "Receipt", checkUser,
                    action);
            /* Set the returned guid and id values */
            receipt.setGUID(result[0]);
            receiptId = result[1];
        } catch (Exception e) {
            dataLogger.error("Error processing receipt record: " + e.getMessage());
            throw new WhichDoctorDaoException("Error processing receipt: " + e.getMessage());
        }

        if (receiptId > 0) {

            dataLogger.info(checkUser.getDN() + " created receiptId: " + String.valueOf(receiptId));

            // Update the financial summary
            updateFinancialSummary(action, receipt, typeId, issued);

            postProcessReceiptChange(receipt);
        }

        return receiptId;
    }

    /**
     * Update the financial summary.
     *
     * @param action the action
     * @param receipt the receipt
     * @param typeId the type id
     * @param issued the issued
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    private void updateFinancialSummary(final String action, final ReceiptBean receipt, final int typeId,
            final Date issued) throws WhichDoctorDaoException {

        if (!StringUtils.equals(action, "delete")) {
            /* Modify the financial summary for this entry */
            try {
                this.getJdbcTemplateWriter().update(this.getSQL().getValue("receipt/editSummary"), new Object[] {
                        typeId, receipt.getDescription(), receipt.getCancelled(), issued, receipt.getGUID() });
            } catch (DataAccessException dae) {
                dataLogger.error("Failed to modify the financial summary: " + dae.getMessage());
                throw new WhichDoctorDaoException("Failed to modify the financial summary: " + dae.getMessage());
            }
        }
    }

    /**
     * Delete the objects associated with the supplied ReceiptBean.
     *
     * @param deleteObjects the delete objects
     * @param checkUser the check user
     * @param privileges the privileges
     */
    private void deleteAssociatedObjects(final ReceiptBean deleteObjects, final UserBean checkUser,
            final PrivilegesBean privileges) {

        if (deleteObjects.getPayments() != null) {
            for (PaymentBean payment : deleteObjects.getPayments()) {
                try {
                    payment.setLogMessage(payment.getLogMessage("delete"));
                    this.paymentDAO.delete(payment, deleteObjects, checkUser, privileges);
                } catch (WhichDoctorDaoException wde) {
                    dataLogger.error("Error deleting payment: " + wde.getMessage());
                }
            }
        }

        deleteMemos(deleteObjects, checkUser, privileges);
        deleteGroups(deleteObjects, checkUser, privileges);
    }

    /**
     * Perform post update receipt changes.
     *
     * @param receipt the receipt
     */
    private void postProcessReceiptChange(final ReceiptBean receipt) {

        Collection<PaymentBean> payments = new ArrayList<PaymentBean>();
        try {
            payments = this.paymentDAO.load(receipt.getGUID(), true);
        } catch (WhichDoctorDaoException wde) {
            dataLogger.error("Error loading payments for receipt: " + wde.getMessage());
        }

        // Update the calculated debit totals for the associated debit
        if (payments != null) {
            for (PaymentBean payment : payments) {
                final DebitBean debit = payment.getDebit();
                if (debit != null && debit.getGUID() > 0) {
                    this.getDebitDAO().refreshDebitValues(debit.getGUID());
                }
            }
        }

        // Update the search index
        try {
            if (receipt.getOrganisationId() > 0) {
                this.getSearchIndexDAO().updateCurrentBalanceIndex(receipt.getOrganisationId(), "organisation");
            } else {
                this.getSearchIndexDAO().updateCurrentBalanceIndex(receipt.getPersonId(), "person");
            }
        } catch (WhichDoctorDaoException wde) {
            dataLogger.error("Error updating receipt search index: " + wde.getMessage());
        }
    }

    /**
     * Load receipt.
     *
     * @param rs the rs
     * @param loadDetails the load details
     *
     * @return the receipt bean
     *
     * @throws SQLException the SQL exception
     */
    private ReceiptBean loadReceipt(final ResultSet rs, final BuilderBean loadDetails) throws SQLException {

        ReceiptBean receipt = new ReceiptBean();

        receipt.setId(rs.getInt("ReceiptId"));
        receipt.setGUID(rs.getInt("GUID"));

        receipt.setAbbreviation(rs.getString("Abbreviation"));
        receipt.setNumber(rs.getString("ReceiptNo"));
        receipt.setDescription(rs.getString("Description"));
        receipt.setProcessType(rs.getString("ProcessType"));
        receipt.setProcessAbbreviation(rs.getString("ProcessAbbreviation"));
        receipt.setBatchReference(rs.getInt("BatchReference"));
        receipt.setBank(rs.getString("Bank"));
        receipt.setBranch(rs.getString("Branch"));
        try {
            receipt.setIssued(rs.getDate("Issued"));
        } catch (SQLException e) {
            receipt.setIssued(null);
        }
        receipt.setCancelled(rs.getBoolean("Cancelled"));

        int organisationGUID = rs.getInt("OrganisationId");
        int personGUID = rs.getInt("PersonId");

        if (personGUID > 0) {
            receipt.setPerson(loadPerson(rs, personGUID, loadDetails));
        }
        if (organisationGUID > 0) {
            receipt.setOrganisation(loadOrganisation(rs, organisationGUID, loadDetails));
        }

        receipt.setTypeName(rs.getString("Type"));
        receipt.setClassName(rs.getString("ReceiptType"));
        receipt.setTotalValue(rs.getDouble("TotalValue"));
        receipt.setSecurity(rs.getString("Security"));

        receipt.setActive(rs.getBoolean("Active"));
        if (loadDetails.getBoolean("HISTORY")) {
            try {
                receipt.setCreatedDate(rs.getTimestamp("CreatedDate"));
            } catch (SQLException sqe) {
                dataLogger.debug("Error reading CreatedDate: " + sqe.getMessage());
            }
            receipt.setCreatedBy(rs.getString("CreatedBy"));
            try {
                receipt.setModifiedDate(rs.getTimestamp("ModifiedDate"));
            } catch (SQLException sqe) {
                dataLogger.debug("Error reading ModifiedDate: " + sqe.getMessage());
            }
            receipt.setModifiedBy(rs.getString("ModifiedBy"));
            try {
                receipt.setExportedDate(rs.getTimestamp("ExportedDate"));
            } catch (SQLException sqe) {
                dataLogger.debug("Error reading ExportedDate: " + sqe.getMessage());
            }
            receipt.setExportedBy(rs.getString("ExportedBy"));
        }

        if (loadDetails.getBoolean("TAGS")) {
            try {
                receipt.setTags(this.getTagDAO().load(receipt.getGUID(), loadDetails.getString("USERDN"), true));
            } catch (Exception e) {
                dataLogger.error("Error loading tags for receipt: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("MEMO")) {
            try {
                receipt.setMemo(this.getMemoDAO().load(receipt.getGUID(), loadDetails.getBoolean("MEMO_FULL")));
            } catch (Exception e) {
                dataLogger.error("Error loading memos: " + e.getMessage());
            }
        }
        if (loadDetails.getBoolean("PAYMENT")) {
            try {
                receipt.setPayments(
                        this.paymentDAO.load(receipt.getGUID(), loadDetails.getBoolean("PAYMENT_FULL")));
            } catch (Exception e) {
                dataLogger.error("Error loading payment details: " + e.getMessage());
            }
        }

        if (loadDetails.getBoolean("GROUPS")) {
            receipt.setGroups(loadGroups(receipt.getGUID()));
        }

        if (loadDetails.getBoolean("CREATED")) {
            UserBean user = new UserBean();
            user.setDN(rs.getString("CreatedBy"));
            user.setPreferredName(rs.getString("CreatedFirstName"));
            user.setLastName(rs.getString("CreatedLastName"));
            receipt.setCreatedUser(user);
        }
        if (loadDetails.getBoolean("MODIFIED")) {
            UserBean user = new UserBean();
            user.setDN(rs.getString("ModifiedBy"));
            user.setPreferredName(rs.getString("ModifiedFirstName"));
            user.setLastName(rs.getString("ModifiedLastName"));
            receipt.setModifiedUser(user);
        }
        if (loadDetails.getBoolean("EXPORTED")) {
            UserBean user = new UserBean();
            user.setDN(rs.getString("ExportedBy"));
            user.setPreferredName(rs.getString("ExportedFirstName"));
            user.setLastName(rs.getString("ExportedLastName"));
            receipt.setExportedUser(user);
        }
        return receipt;
    }

    /**
     * Load person.
     *
     * @param rs the rs
     * @param personId the person id
     * @param loadDetails the load details
     *
     * @return the person bean
     *
     * @throws SQLException the SQL exception
     */
    private PersonBean loadPerson(final ResultSet rs, final int personId, final BuilderBean loadDetails)
            throws SQLException {

        PersonBean person = new PersonBean();
        person.setGUID(personId);
        person.setPersonIdentifier(rs.getInt("PersonIdentifier"));
        person.setPreferredName(rs.getString("PreferredName"));
        person.setFirstName(rs.getString("FirstName"));
        person.setLastName(rs.getString("LastName"));
        person.setTitle(rs.getString("Title"));
        person.setGender(rs.getString("Gender"));

        // Load address.
        if (loadDetails.getBoolean("ADDRESS")) {
            try {
                person.setAddress(this.getAddressDAO().load(person.getGUID(), false,
                        loadDetails.getString("ADDRESS_CLASS"), loadDetails.getString("ADDRESS_TYPE")));
            } catch (Exception e) {
                dataLogger.error("Error loading address for receipt: " + e.getMessage());
            }
        }

        return person;
    }

    /**
     * Load organisation.
     *
     * @param rs the rs
     * @param organisationId the organisation id
     * @param loadDetails the load details
     *
     * @return the organisation bean
     *
     * @throws SQLException the SQL exception
     */
    private OrganisationBean loadOrganisation(final ResultSet rs, final int organisationId,
            final BuilderBean loadDetails) throws SQLException {

        OrganisationBean organisation = new OrganisationBean();
        organisation.setGUID(organisationId);
        organisation.setName(rs.getString("OrganisationName"));
        // Load address...
        if (loadDetails.getBoolean("ADDRESS")) {
            try {
                organisation.setAddress(this.getAddressDAO().load(organisation.getGUID(), false,
                        loadDetails.getString("ADDRESS_CLASS"), loadDetails.getString("ADDRESS_TYPE")));
            } catch (Exception e) {
                dataLogger.error("Error loading address for receipt: " + e.getMessage());
            }
        }

        return organisation;
    }

    /**
     * Load groups.
     *
     * @param guid the guid
     *
     * @return the array list< group bean>
     */
    private ArrayList<GroupBean> loadGroups(final int guid) {

        // Create new SearchBean of type Receipt and default values
        SearchResultsBean results = new SearchResultsBean();
        SearchBean groupSearch = this.getSearchDAO().initiate("group", null);
        groupSearch.setLimit(0);

        GroupBean searchCriteria = (GroupBean) groupSearch.getSearchCriteria();
        searchCriteria.setObjectType("Receipts");
        ItemBean item = new ItemBean();
        item.setObject2GUID(guid);
        TreeMap<String, ItemBean> items = new TreeMap<String, ItemBean>();
        items.put("Receipt", item);
        searchCriteria.setItems(items);

        groupSearch.setSearchCriteria(searchCriteria);
        try {
            BuilderBean loadGroup = new BuilderBean();
            loadGroup.setParameter("ITEMS", true);
            loadGroup.setParameter("REFERENCEID", String.valueOf(guid));
            results = this.getSearchDAO().search(groupSearch, loadGroup);
        } catch (Exception e) {
            dataLogger.error("Error loading groups for receipt: " + e.getMessage());
        }

        ArrayList<GroupBean> groups = new ArrayList<GroupBean>();
        for (Object group : results.getSearchResults()) {
            groups.add((GroupBean) group);
        }

        return groups;
    }

}