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

Java tutorial

Introduction

Here is the source code for com.sfs.whichdoctor.dao.CreditDAOImpl.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.PrivilegesBean;
import com.sfs.beans.UserBean;
import com.sfs.whichdoctor.beans.CreditBean;
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.PersonBean;
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.TreeMap;

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 CreditDAOImpl.
 */
public class CreditDAOImpl extends WhichDoctorFinancialObjectDAOImpl implements CreditDAO {

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

    /**
     * Used to load a CreditBean with a specific creditId.
     *
     * @param creditId the credit id
     *
     * @return the credit bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final CreditBean load(final int creditId) throws WhichDoctorDaoException {
        return load(creditId, new BuilderBean(), false);
    }

    /**
     * Used to load a CreditBean with a specific creditId and supplied load
     * options.
     *
     * @param creditId the credit id
     * @param loadDetails the load details
     *
     * @return the credit bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final CreditBean load(final int creditId, final BuilderBean loadDetails) throws WhichDoctorDaoException {
        return load(creditId, loadDetails, false);
    }

    /**
     * Used to load a CreditBean with a specific name and supplied load options.
     * A boolean parameter identifies whether to use the default reader
     * connection or optional writer connection datasource.
     *
     * @param creditId the credit id
     * @param loadDetails the load details
     * @param useWriter the use writer
     *
     * @return the credit bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    private CreditBean load(final int creditId, final BuilderBean loadDetails, final boolean useWriter)
            throws WhichDoctorDaoException {

        CreditBean credit = null;

        dataLogger.info("Credit Id: " + creditId + " requested");

        final String loadSQL = getSQL().getValue("credit/load") + " AND credit.CreditId = ?";

        JdbcTemplate jdbcTemplate = this.getJdbcTemplateReader();
        if (useWriter) {
            jdbcTemplate = this.getJdbcTemplateWriter();
        }

        try {
            credit = (CreditBean) jdbcTemplate.queryForObject(loadSQL, new Object[] { creditId }, new RowMapper() {
                public Object mapRow(final ResultSet rs, final int rowNum) throws SQLException {
                    return loadCredit(rs, loadDetails);
                }
            });

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

    /**
     * Used to load a CreditBean with a specific name.
     *
     * @param strCredit the str credit
     *
     * @return the credit bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final CreditBean load(final String strCredit) throws WhichDoctorDaoException {
        return load(strCredit, new BuilderBean());
    }

    /**
     * Used to load a CreditBean with a specific name and supplied load options.
     *
     * @param strCredit the str credit
     * @param loadDetails the load details
     *
     * @return the credit bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final CreditBean load(final String strCredit, final BuilderBean loadDetails)
            throws WhichDoctorDaoException {

        dataLogger.info("Credit Name: " + strCredit + " requested");

        int creditGUID = 0;

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

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

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

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

    /**
     * Used to load a CreditBean with a specific GUID.
     *
     * @param guid the guid
     *
     * @return the credit bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final CreditBean loadGUID(final int guid) throws WhichDoctorDaoException {
        return loadGUID(guid, new BuilderBean());
    }

    /**
     * Used to load a CreditBean with a specific GUID and supplied load options.
     *
     * @param guid the guid
     * @param loadDetails the load details
     *
     * @return the credit bean
     *
     * @throws WhichDoctorDaoException the which doctor dao exception
     */
    public final CreditBean loadGUID(final int guid, final BuilderBean loadDetails) throws WhichDoctorDaoException {

        dataLogger.info("Credit GUID: " + guid + " requested");

        CreditBean credit = null;

        final String loadSQL = getSQL().getValue("credit/load") + " AND credit.GUID = ? AND credit.Active = true";

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

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

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

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

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

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

    /**
     * Deletes the CreditBean.
     *
     * @param credit the credit
     * @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 CreditBean credit, final UserBean checkUser, final PrivilegesBean privileges)
            throws WhichDoctorDaoException {

        boolean success = false;

        if (privileges.getPrivilege(checkUser, "credits", "delete")) {
            // Before deleting the credit remove its child objects
            final BuilderBean loadDetails = new BuilderBean();
            loadDetails.setParameter("LOAD_ALL", true);
            try {
                final CreditBean deleteObj = this.loadGUID(credit.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());
            }
        }

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

    /**
     * Save the updated credit bean.
     *
     * @param credit the credit
     * @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 CreditBean credit, final UserBean checkUser, final PrivilegesBean privileges,
            final String action) throws WhichDoctorDaoException {

        // Create credit requires all the essential information to be supplied
        if (credit.getDescription() == null) {
            throw new WhichDoctorDaoException("Credit description field " + "cannot be null");
        }
        if (StringUtils.isBlank(credit.getDescription())) {
            throw new WhichDoctorDaoException("Credit description field cannot " + "be an empty string");
        }
        if (credit.getTypeName() == null) {
            throw new WhichDoctorDaoException("Credit requires a credit type");
        }
        if (StringUtils.isBlank(credit.getTypeName())) {
            throw new WhichDoctorDaoException("Credit requires a credit type");
        }
        if (StringUtils.equals(credit.getTypeName(), "Null")) {
            throw new WhichDoctorDaoException("Credit requires a credit type");
        }
        if (credit.getValue() == 0) {
            throw new WhichDoctorDaoException("The credit requires a value");
        }
        if (credit.getPersonId() == 0 && credit.getOrganisationId() == 0) {
            throw new WhichDoctorDaoException("Credit must be attributed to " + "a person or organisation");
        }
        if (!privileges.getPrivilege(checkUser, "credits", action)) {
            throw new WhichDoctorDaoException("Insufficient user credentials to " + action + " credit");
        }

        int typeId = 0;
        try {
            FinancialTypeBean financialObject = financialTypeDAO.load("Credit", credit.getTypeName(),
                    credit.getClassName());
            typeId = financialObject.getFinancialTypeId();
        } catch (Exception e) {
            dataLogger.error("Error loading financial type for credit: " + e.getMessage());
            throw new WhichDoctorDaoException("Credit requires a valid type");
        }

        int existingDebitGUID = 0;
        // Load the existing credit (if GUID > 0) to check if the
        // associated debit has changed.
        if (credit.getGUID() > 0) {
            try {
                final BuilderBean existingDetails = new BuilderBean();
                existingDetails.setParameter("DEBITS_FULL", true);
                final CreditBean existingCredit = this.loadGUID(credit.getGUID(), existingDetails);
                if (existingCredit.getDebit() != null) {
                    existingDebitGUID = existingCredit.getDebit().getGUID();
                }
            } catch (WhichDoctorDaoException wde) {
                dataLogger.error("Error loading existing credit: " + wde.getMessage());
            }
        }

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

        int creditId = 0;

        /* Does a credit number need to be generated */
        Date issued = new Date(Calendar.getInstance().getTimeInMillis());
        if (credit.getIssued() != null) {
            issued = new Date(credit.getIssued().getTime());
        }

        DebitBean debit = credit.getDebit();
        if (debit == null) {
            debit = new DebitBean();
        }
        Timestamp sqlTimeStamp = new Timestamp(Calendar.getInstance().getTimeInMillis());

        ArrayList<Object> parameters = new ArrayList<Object>();
        parameters.add(credit.getDescription());
        parameters.add(credit.getNumber());
        parameters.add(credit.getCancelled());
        parameters.add(credit.getGSTRate());
        parameters.add(credit.getValue());
        parameters.add(credit.getNetValue());
        parameters.add(credit.getPersonId());
        parameters.add(credit.getOrganisationId());
        parameters.add(issued);
        parameters.add(typeId);
        parameters.add(debit.getGUID());
        parameters.add(credit.getActive());
        parameters.add(sqlTimeStamp);
        parameters.add(checkUser.getDN());
        parameters.add(credit.getLogMessage(action));

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

        if (creditId > 0) {
            dataLogger.info(checkUser.getDN() + " created creditId: " + String.valueOf(creditId));

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

            // Update the related debit's calculated values
            if (existingDebitGUID > 0) {
                // Update the previous debit GUID
                this.getDebitDAO().refreshDebitValues(existingDebitGUID);
            }
            if (debit.getGUID() > 0 && debit.getGUID() != existingDebitGUID) {
                this.getDebitDAO().refreshDebitValues(debit.getGUID());
            }

            // Update the search index
            if (credit.getOrganisationId() > 0) {
                this.getSearchIndexDAO().updateCurrentBalanceIndex(credit.getOrganisationId(), "organisation");
            } else {
                this.getSearchIndexDAO().updateCurrentBalanceIndex(credit.getPersonId(), "person");
            }
        }
        return creditId;
    }

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

        try {
            if (StringUtils.equals(action, "delete")) {
                this.getJdbcTemplateWriter().update(this.getSQL().getValue("credit/deleteSummary"),
                        new Object[] { credit.getGUID() });
            } else {
                /* Create or modify the financial summarty */
                this.getJdbcTemplateWriter().update(this.getSQL().getValue("credit/editSummary"),
                        new Object[] { credit.getGUID(), typeId, credit.getNumber(), credit.getDescription(),
                                credit.getValue(), credit.getNetValue(), credit.getCancelled(), issued,
                                credit.getPersonId(), credit.getOrganisationId(),

                                typeId, credit.getNumber(), credit.getDescription(), credit.getValue(),
                                credit.getNetValue(), credit.getCancelled(), issued, credit.getPersonId(),
                                credit.getOrganisationId() });
            }
        } 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 CreditBean.
     *
     * @param deleteObjects the delete objects
     * @param checkUser the check user
     * @param privileges the privileges
     */
    private void deleteAssociatedObjects(final CreditBean deleteObjects, final UserBean checkUser,
            final PrivilegesBean privileges) {

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

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

        CreditBean credit = new CreditBean();

        // Create resource bean and fill with dataset info.
        credit.setId(rs.getInt("CreditId"));
        credit.setGUID(rs.getInt("GUID"));

        credit.setAbbreviation(rs.getString("Abbreviation"));
        credit.setTypeName(rs.getString("Type"));
        credit.setClassName(rs.getString("CreditType"));

        credit.setNumber(rs.getString("CreditNo"));

        credit.setDescription(rs.getString("Description"));

        credit.setPersonId(rs.getInt("PersonId"));
        if (credit.getPersonId() > 0) {
            credit.setPerson(loadPerson(rs, credit.getPersonId(), loadDetails));
        }

        credit.setOrganisationId(rs.getInt("OrganisationId"));
        if (credit.getOrganisationId() > 0) {
            credit.setOrganisation(loadOrganisation(rs, credit.getOrganisationId(), loadDetails));
        }

        credit.setValue(rs.getDouble("Value"));
        credit.setNetValue(rs.getDouble("NetValue"));
        try {
            credit.setIssued(rs.getDate("Issued"));
        } catch (SQLException e) {
            credit.setIssued(null);
        }
        credit.setCancelled(rs.getBoolean("Cancelled"));
        credit.setGSTRate(rs.getDouble("GSTRate"));

        if (loadDetails.getBoolean("DEBITS_FULL")) {
            int debitGUID = rs.getInt("InvoiceId");
            if (debitGUID > 0) {
                DebitBean debit = new DebitBean();
                try {
                    debit = this.getDebitDAO().loadGUID(debitGUID);
                } catch (Exception e) {
                    dataLogger.error("Error loading debit for credit: " + e.getMessage());
                }
                if (debit.getId() > 0) {
                    credit.setDebit(debit);
                }
            }
        }
        credit.setSecurity(rs.getString("Security"));

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

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

        if (loadDetails.getBoolean("MEMO")) {
            try {
                credit.setMemo(this.getMemoDAO().load(credit.getGUID(), loadDetails.getBoolean("MEMO_FULL")));
            } catch (Exception e) {
                dataLogger.error("Error loading memos for credit: " + e.getMessage());
            }
        }

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

        if (loadDetails.getBoolean("CREATED")) {
            UserBean user = new UserBean();
            user.setDN(rs.getString("CreatedBy"));
            user.setPreferredName(rs.getString("CreatedFirstName"));
            user.setLastName(rs.getString("CreatedLastName"));
            credit.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"));
            credit.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"));
            credit.setExportedUser(user);
        }
        return credit;
    }

    /**
     * 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 credit: " + 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"));

        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 credit: " + 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 Credit and default values
        SearchResultsBean results = new SearchResultsBean();
        SearchBean groupSearch = this.getSearchDAO().initiate("group", null);
        groupSearch.setLimit(0);

        GroupBean searchCriteria = (GroupBean) groupSearch.getSearchCriteria();
        searchCriteria.setObjectType("Credits");
        ItemBean item = new ItemBean();
        item.setObject2GUID(guid);
        TreeMap<String, ItemBean> items = new TreeMap<String, ItemBean>();
        items.put("Credit", 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 credit: " + e.getMessage());
        }

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

        return groups;
    }
}