/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
package lu.tudor.santec.gecamed.billing.ejb.session.beans;

import java.util.Collection;

import javax.annotation.security.RolesAllowed;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.persistence.NoResultException;

import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Account;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Invoice;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Ledger;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Settlement;
import lu.tudor.santec.gecamed.billing.ejb.session.interfaces.SettlementInterface;
import lu.tudor.santec.gecamed.core.ejb.session.beans.GECAMedSessionBean;
import lu.tudor.santec.gecamed.office.ejb.entity.beans.Physician;

//***************************************************************************
//* Interface Definition and Members                                        *
//***************************************************************************

/**
 * The SettlementBean manages access to settlement methods.
 * @author nico.mack@tudor.lu
 */

@Stateless
@Remote (SettlementInterface.class)
public class SettlementBean extends GECAMedSessionBean implements SettlementInterface
	{
	private static final long serialVersionUID = 1L;
	
//***************************************************************************
//* Class Primitives                                                        *
//***************************************************************************

//***************************************************************************
//* Class Body                                                              *
//***************************************************************************
//---------------------------------------------------------------------------
/**
 * Returns a very specific account identified by the specified Id.
 * @param p_ID specifies the Id of the account to get from
 * database.
 * @return The account with the specified Id, <code>null</code> if
 * no such account exists.
 */
//---------------------------------------------------------------------------

public Account getAccountByID (Integer p_ID) throws Exception 
	{
	Account l_Account;
	
	try	{
		l_Account = m_EntityManager.find (Account.class, p_ID);
		}
	catch (NoResultException p_Exception)
		{
		l_Account = null;
		}

	return l_Account;
	}

//---------------------------------------------------------------------------
/**
 * Returns a very specific settlement method identified by the specified Id.
 * @param p_ID specifies the Id of the settlement method to get from
 * database.
 * @return The settlement method with the specified Id, <code>null</code> if
 * no such settlement method exists.
 */
//---------------------------------------------------------------------------

public Settlement getSettlementByID (Integer p_ID) throws Exception 
	{
	Settlement l_Settlement;
	
	try	{
		l_Settlement = m_EntityManager.find(Settlement.class, p_ID);
		}
	catch (NoResultException p_Exception)
		{
		l_Settlement = null;
		}

	return l_Settlement;
	}

//---------------------------------------------------------------------------
/**
 * Fetches all settlement methods defined in the database.
 * @return a collection holding all settlement methods defined in the database,
 * <code>null</code> if none are available.
 */
//---------------------------------------------------------------------------

@RolesAllowed("gecam")
@SuppressWarnings("unchecked")
public Collection <Settlement> getAllSettlements() throws Exception 
	{
	Collection 	l_Settlements;

	try	{
		l_Settlements = m_EntityManager.createNamedQuery (Settlement.c_AllSettlements).getResultList();
		}
	catch (NoResultException p_Exception)
		{
		l_Settlements = null;
		}
		
	return l_Settlements;
	}

//---------------------------------------------------------------------------
/**
 * Fetches all transfer settlement defined in the database. Transfer settlements
 * are settlements that define a bank account to transfer money to. 
 * @return a collection holding all transfer settlements defined in the database,
 * <code>null</code> if none are available.
 */
//---------------------------------------------------------------------------

@RolesAllowed("gecam")
@SuppressWarnings("unchecked")
public Collection <Settlement> getTransferSettlements() throws Exception 
	{
	Collection 	l_Settlements;

	try	{
		l_Settlements = m_EntityManager.createNamedQuery (Settlement.c_TransferSettlements).getResultList();
		}
	catch (NoResultException p_Exception)
		{
		l_Settlements = null;
		}

	return l_Settlements;
	}

//---------------------------------------------------------------------------
/**
 * Fetches all payment settlement defined in the database. Payment settlements
 * are settlements that define a payment method like cash, debit or credir card.
 * @return a collection holding all payment settlements defined in the database,
 * <code>null</code> if none are available.
 */
//---------------------------------------------------------------------------

@RolesAllowed("gecam")
@SuppressWarnings("unchecked")
public Collection <Settlement> getPaymentSettlements() throws Exception 
	{
	Collection 	l_Settlements;

	try	{
		l_Settlements = m_EntityManager.createNamedQuery (Settlement.c_PaymentSettlements).getResultList();
		}
	catch (NoResultException p_Exception)
		{
		l_Settlements = null;
		}

	return l_Settlements;
	}

//---------------------------------------------------------------------------
/**
 * Fetches all transfer settlement defined in the database for the specified 
 * holder. Transfer settlements are settlements that define a bank account to 
 * transfer money to. The holder is the physician this bank account belongs to.
 * @param p_Holder specifies the physician to get transfer settlements for.
 * @return a collection holding all transfer settlements defined in the database
 * for the specified holder, <code>null</code> if none are available.
 */
//---------------------------------------------------------------------------

@RolesAllowed("gecam")
@SuppressWarnings("unchecked")
public Collection<Settlement> getTransferSettlementsByHolder (Physician p_Holder) throws Exception 
	{
	Collection 	l_Settlements;

	try	{
		l_Settlements = m_EntityManager.createNamedQuery (Settlement.c_TransferSettlementsByHolder)
							.setParameter("holder", p_Holder)
							.getResultList();
		}
	catch (NoResultException p_Exception)
		{
		l_Settlements = null;
		}

	return l_Settlements;
	}

//---------------------------------------------------------------------------
/**
 * Fetches all transfer settlement defined in the database without a specific 
 * holder. Transfer settlements are settlements that define a bank account to 
 * transfer money to. A holder is a physician a bank account belongs to.
 * @return a collection holding all transfer settlements defined in the database
 * that do not specify a holder, <code>null</code> if none are available.
 */
//---------------------------------------------------------------------------

@RolesAllowed("gecam")
@SuppressWarnings("unchecked")
public Collection<Settlement> getTransferSettlementsWithoutHolder () throws Exception 
	{
	Collection 	l_Settlements;

	try	{
		l_Settlements = m_EntityManager.createNamedQuery (Settlement.c_TransferSettlementsWithoutHolder)
							.getResultList();
		}
	catch (NoResultException p_Exception)
		{
		l_Settlements = null;
		}

	return l_Settlements;
	}

//---------------------------------------------------------------------------
/**
 * saves the specifies settlement into the database.
 * @param p_Settlement specifies the settlement to save.
 * @return the persisted, i.e. saved settlement method.
 */
//---------------------------------------------------------------------------

public Settlement saveSettlement (Settlement p_Settlement) throws Exception 
	{
	Account l_Account = p_Settlement.getTransferAccount();
	if (l_Account != null) 
		{
		l_Account = m_EntityManager.merge (l_Account);
		p_Settlement.setTransferAccount (l_Account);
		}
	
	return m_EntityManager.merge(p_Settlement);
	}

//---------------------------------------------------------------------------
/**
 * Checks whether the specified settlement method is referenced either by
 * an invoice or by an entry in the ledger.
 * @param p_Settlement specifies the settlement method to check references for.
 * @return <code>true</code> if specified settlement method is referenced in
 * any way, <code>false</code> otherwise.
 */
//---------------------------------------------------------------------------

public Boolean checkTransferSettlementHasReferences (Settlement p_Settlement) throws Exception 
	{
	Long	l_Count;
	
	l_Count = (Long) m_EntityManager.createNamedQuery (Invoice.c_InvoiceCountBySettlement)
									.setParameter("settlement", p_Settlement)
									.getSingleResult();
	if (l_Count > 0 ) return true;
	
	l_Count = (Long) m_EntityManager.createNamedQuery (Ledger.c_LedgerCountBySettlement)
									.setParameter("settlement", p_Settlement)
									.getSingleResult();
	if (l_Count > 0 ) return true;
	
	return false;
	}

//---------------------------------------------------------------------------
/** 
 * Deletes the specified settlement method from the database.
 * @param p_Settlement specifies the settlement method to delete.
 */
//---------------------------------------------------------------------------

public void deleteSettlement (Settlement p_Settlement) throws Exception 
	{
	Settlement	l_Settlement;
	Account 	l_Account;
	
	l_Account = p_Settlement.getTransferAccount();
	
	l_Settlement = m_EntityManager.find(Settlement.class, p_Settlement.getId());
	if (l_Settlement != null)
		{
		m_EntityManager.remove(l_Settlement);
		}	
	
	if ((l_Account != null) && (l_Account.isPersistent()))
		{
		m_EntityManager.remove(m_EntityManager.find(Account.class, l_Account.getId()));
		}
	}

//***************************************************************************
//* End of Class															*
//***************************************************************************
	}
