/*******************************************************************************
 * 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.gui;

import java.awt.Color;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Set;

import javax.jms.DeliveryMode;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;
import javax.naming.InitialContext;
import javax.persistence.NoResultException;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.border.MatteBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import lu.tudor.santec.gecamed.addressbook.ejb.entity.beans.Contact;
import lu.tudor.santec.gecamed.addressbook.ejb.session.beans.AddressbookManager;
import lu.tudor.santec.gecamed.addressbook.ejb.session.interfaces.AddressbookInterface;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Act;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Invoice;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.InvoiceTemplate;
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.entity.beans.Statement;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.Suffix;
import lu.tudor.santec.gecamed.billing.ejb.entity.beans.TemplateRate;
import lu.tudor.santec.gecamed.billing.ejb.session.beans.AccountingBean;
import lu.tudor.santec.gecamed.billing.ejb.session.beans.HospitalizedBean;
import lu.tudor.santec.gecamed.billing.ejb.session.beans.InvoiceBean;
import lu.tudor.santec.gecamed.billing.ejb.session.beans.NomenclatureBean;
import lu.tudor.santec.gecamed.billing.ejb.session.beans.SettlementBean;
import lu.tudor.santec.gecamed.billing.ejb.session.interfaces.AccountingInterface;
import lu.tudor.santec.gecamed.billing.ejb.session.interfaces.HospitalizedInterface;
import lu.tudor.santec.gecamed.billing.ejb.session.interfaces.InvoiceInterface;
import lu.tudor.santec.gecamed.billing.ejb.session.interfaces.NomenclatureInterface;
import lu.tudor.santec.gecamed.billing.ejb.session.interfaces.SettlementInterface;
import lu.tudor.santec.gecamed.billing.gui.act.HospitalisationClassListener;
import lu.tudor.santec.gecamed.billing.gui.actions.ActivityListAction;
import lu.tudor.santec.gecamed.billing.gui.actions.CloseInvoiceAction;
import lu.tudor.santec.gecamed.billing.gui.actions.DeleteInvoiceAction;
import lu.tudor.santec.gecamed.billing.gui.actions.DisproveInvoiceAction;
import lu.tudor.santec.gecamed.billing.gui.actions.EditInvoiceAction;
import lu.tudor.santec.gecamed.billing.gui.actions.IssuedInvoiceListAction;
import lu.tudor.santec.gecamed.billing.gui.actions.NewInvoiceAction;
import lu.tudor.santec.gecamed.billing.gui.actions.NextInvoiceAction;
import lu.tudor.santec.gecamed.billing.gui.actions.OpenInvoiceAction;
import lu.tudor.santec.gecamed.billing.gui.actions.PreviousInvoiceAction;
import lu.tudor.santec.gecamed.billing.gui.actions.ReloadInvoicesAction;
import lu.tudor.santec.gecamed.billing.gui.actions.RevokeInvoiceAction;
import lu.tudor.santec.gecamed.billing.gui.actions.SettleInvoiceAction;
import lu.tudor.santec.gecamed.billing.gui.actions.ShowLedgerAction;
import lu.tudor.santec.gecamed.billing.gui.actions.TransactionListAction;
import lu.tudor.santec.gecamed.billing.gui.actions.VerifyInvoiceAction;
import lu.tudor.santec.gecamed.billing.gui.admin.NomenclaturePanel;
import lu.tudor.santec.gecamed.billing.gui.config.BillingAdminSettingsPlugin;
import lu.tudor.santec.gecamed.billing.gui.config.BillingUserSettingsPlugin;
import lu.tudor.santec.gecamed.billing.gui.event.invoice.InvoiceChangeEvent;
import lu.tudor.santec.gecamed.billing.gui.event.invoice.InvoiceEventDispatcher;
import lu.tudor.santec.gecamed.billing.gui.event.invoice.InvoiceEventSource;
import lu.tudor.santec.gecamed.billing.gui.event.invoice.InvoiceListener;
import lu.tudor.santec.gecamed.billing.gui.event.search.SearchModeEvent;
import lu.tudor.santec.gecamed.billing.gui.event.search.SearchModeListener;
import lu.tudor.santec.gecamed.billing.gui.event.usermode.UserModeListener;
import lu.tudor.santec.gecamed.billing.gui.hospitalisation.HospitalisationPanel;
import lu.tudor.santec.gecamed.billing.gui.invoice.InvoiceEditorPanel;
import lu.tudor.santec.gecamed.billing.gui.invoice.InvoiceListingPanel;
import lu.tudor.santec.gecamed.billing.gui.invoice.InvoicePropertiesPanel;
import lu.tudor.santec.gecamed.billing.gui.invoice.InvoiceStatusPanel;
import lu.tudor.santec.gecamed.billing.gui.ledger.LedgerDialog;
import lu.tudor.santec.gecamed.billing.gui.medpres.MedPres;
import lu.tudor.santec.gecamed.billing.gui.memo.MemoEditorPanel;
import lu.tudor.santec.gecamed.billing.gui.print.InvoicePrinter;
import lu.tudor.santec.gecamed.billing.gui.reminder.ReminderPanel;
import lu.tudor.santec.gecamed.billing.gui.search.SearchPanel;
import lu.tudor.santec.gecamed.billing.gui.settlement.RevokeDialog;
import lu.tudor.santec.gecamed.billing.gui.settlement.SettlementDialog;
import lu.tudor.santec.gecamed.billing.gui.statement.StatementInvoicesPanel;
import lu.tudor.santec.gecamed.billing.gui.statement.StatementPanel;
import lu.tudor.santec.gecamed.billing.gui.statistics.ActivityListDialog;
import lu.tudor.santec.gecamed.billing.gui.statistics.ActivityWorker;
import lu.tudor.santec.gecamed.billing.gui.statistics.InvoiceListDialog;
import lu.tudor.santec.gecamed.billing.gui.statistics.InvoiceWorker;
import lu.tudor.santec.gecamed.billing.gui.statistics.PatientActsDialog;
import lu.tudor.santec.gecamed.billing.gui.statistics.TransactionListDialog;
import lu.tudor.santec.gecamed.billing.gui.templates.InvoiceTemplateDialog;
import lu.tudor.santec.gecamed.billing.gui.trash.TrashPanel;
import lu.tudor.santec.gecamed.billing.utils.BillingAdminSettings;
import lu.tudor.santec.gecamed.billing.utils.BillingUserSettings;
import lu.tudor.santec.gecamed.billing.utils.InvoiceWorkflow;
import lu.tudor.santec.gecamed.billing.utils.StatementWorkflow;
import lu.tudor.santec.gecamed.core.ejb.entity.beans.NationalHoliday;
import lu.tudor.santec.gecamed.core.ejb.session.beans.NationalHolidayBean;
import lu.tudor.santec.gecamed.core.ejb.session.interfaces.NationalHolidayInterface;
import lu.tudor.santec.gecamed.core.gui.GECAMedAction;
import lu.tudor.santec.gecamed.core.gui.GECAMedColors;
import lu.tudor.santec.gecamed.core.gui.GECAMedLists;
import lu.tudor.santec.gecamed.core.gui.GECAMedLog;
import lu.tudor.santec.gecamed.core.gui.GECAMedMessage;
import lu.tudor.santec.gecamed.core.gui.GECAMedMessageListener;
import lu.tudor.santec.gecamed.core.gui.GECAMedModule;
import lu.tudor.santec.gecamed.core.gui.GECAMedTab;
import lu.tudor.santec.gecamed.core.gui.MainFrame;
import lu.tudor.santec.gecamed.core.gui.PatientListener;
import lu.tudor.santec.gecamed.core.gui.RegistrationDesk;
import lu.tudor.santec.gecamed.core.gui.utils.GradientFactory;
import lu.tudor.santec.gecamed.core.gui.widgets.AccidentPropertiesPanel;
import lu.tudor.santec.gecamed.core.gui.widgets.GECAMedBaseDialogImpl;
import lu.tudor.santec.gecamed.core.gui.widgets.PasswordAskDialog;
import lu.tudor.santec.gecamed.core.gui.widgets.animatedicon.AnimatedIcon;
import lu.tudor.santec.gecamed.core.gui.widgets.print.PrintParameterFetcher;
import lu.tudor.santec.gecamed.core.gui.widgets.progress.ProgressDialog;
import lu.tudor.santec.gecamed.core.gui.widgets.progress.ProgressExecutor;
import lu.tudor.santec.gecamed.core.gui.widgets.progress.ProgressWorker;
import lu.tudor.santec.gecamed.core.utils.ManagerFactory;
import lu.tudor.santec.gecamed.core.utils.querybuilder.HibernateCondition;
import lu.tudor.santec.gecamed.core.utils.querybuilder.HibernateList;
import lu.tudor.santec.gecamed.core.utils.querybuilder.HibernateOperator;
import lu.tudor.santec.gecamed.core.utils.querybuilder.WhereClause;
import lu.tudor.santec.gecamed.office.ejb.entity.beans.Physician;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.HospitalisationClass;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Insurance;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Passage;
import lu.tudor.santec.gecamed.patient.ejb.entity.beans.Patient;
import lu.tudor.santec.gecamed.patient.ejb.session.beans.HospitalisationClassBean;
import lu.tudor.santec.gecamed.patient.ejb.session.beans.InsuranceBean;
import lu.tudor.santec.gecamed.patient.ejb.session.beans.PatientAdminBean;
import lu.tudor.santec.gecamed.patient.ejb.session.interfaces.HospitalisationClassInterface;
import lu.tudor.santec.gecamed.patient.ejb.session.interfaces.InsuranceInterface;
import lu.tudor.santec.gecamed.patient.ejb.session.interfaces.PatientAdminInterface;
import lu.tudor.santec.gecamed.patient.gui.PatientManagerModule;
import lu.tudor.santec.gecamed.patient.gui.hospitalisation.PatientHospitalisationPanel;
import lu.tudor.santec.gecamed.patient.utils.SettingConstants;
import lu.tudor.santec.gecamed.usermanagement.ejb.entity.beans.GecamedUser;
import lu.tudor.santec.gecamed.usermanagement.ejb.session.beans.LoginBean;
import lu.tudor.santec.gecamed.usermanagement.ejb.session.interfaces.LoginInterface;
import lu.tudor.santec.gecamed.usermanagement.gui.settings.UserSettingsPlugin;
import lu.tudor.santec.i18n.Relocalizable;
import lu.tudor.santec.i18n.Translatrix;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import ucar.ma2.ArrayObject;
import bizcal.util.DateUtil;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

                 /*$$
                 $$$$
          $$$$$$$$$$$$$$$$$
        $$$$$$$$$$$$$$$$$$$$$$
     $$$$$$$     $$$$    $$$$$$$$
   $$$$$$        $$$$        $$$$$$$
  $$$$$$         $$$$          $$$$$$
  $$$$$$         $$$$
  $$$$$$         $$$$
   $$$$$$        $$$$
    $$$$$$$$     $$$$
      $$$$$$$$$$$$$$$
          $$$$$$$$$$$$$$$$$$
              $$$$$$$$$$$$$$$$
                 $$$$ $$$$$$$$$$
                 $$$$       $$$$$$$
                 $$$$          $$$$$$
                 $$$$           $$$$$$
$$$$$$$          $$$$          $$$$$$$
 $$$$$$          $$$$          $$$$$$$
  $$$$$$$        $$$$        $$$$$$$$
   $$$$$$$$      $$$$      $$$$$$$$
        $$$$$$$$$$$$$$$$$$$$$$$$
          $$$$$$$$$$$$$$$$$$$
               $$$$$$$$
                 $$$$
                 $$*/

//---------------------------------------------------------------------------
/** BillingPanel will be the main Panel of the Billing Module. All other
 *  billing related panels will be childs of BillingPanel.
 * @author lu.tudor.santec/Nico MACK
 * @version 1.0.0
 */
//---------------------------------------------------------------------------

//***************************************************************************
//* Class Definition and Members                                            *
//***************************************************************************

public class BillingModule extends GECAMedModule implements InvoiceEventSource,
															ActionListener,
															PropertyChangeListener,
														 	ChangeListener,
														 	KeyListener,
														 	PatientListener,
														 	InvoiceListener,
														 	SearchModeListener,
														 	GECAMedMessageListener,
														 	Relocalizable													 
	{
	private static final long serialVersionUID = 1L;

	private InvoiceStatusPanel			m_InvoiceStatusPanel			= null;
	private PatientSummaryPanel 		m_PatientSummaryPanel			= null;
	
	private JTabbedPane					m_MainPanel    					= null;
	private InvoiceEditorPanel			m_EditorPanel   				= null;
	private InvoiceListingPanel			m_InvoicePanel 					= null;
	private MemoEditorPanel				m_MemoPanel						= null;
	private ReminderPanel				m_ReminderPanel					= null;
	private StatementPanel				m_StatementPanel				= null;
	private SearchPanel					m_SearchPanel					= null;
	private TrashPanel					m_TrashPanel					= null;
	
	private JToggleButton				m_SuperUserSwitch				= null;
	
	private ImageIcon					m_DefaultBorderStamp			= null;
	private ImageIcon					m_SuperUserBorderStamp			= null;
	private ImageIcon					m_MemoStatic					= null;
	private AnimatedIcon				m_MemoBlinking					= null;
	
	private MatteBorder					m_DefaultBorder					= null;
	private MatteBorder					m_SuperUserBorder				= null;
	
	private SimpleDateFormat			m_DateFormat					= null;
	private SimpleDateFormat			m_TimeFormat					= null;

	private InvoiceInterface			m_InvoiceInterface				= null;
	private AccountingInterface			m_AccountingInterface			= null;
	private HospitalizedInterface		m_HospitalizedInterface			= null;
	private PatientAdminInterface		m_PatientInterface				= null;
	
	private Invoice						m_CurrentInvoice				= null;
	private Patient						m_CurrentPatient				= null;
	private InvoicePropertiesPanel		m_InvoiceProperties				= null;
	private AccidentPropertiesPanel		m_AccidentProperties			= null;
	private HospitalisationPanel		m_HospitalisationProperties		= null;
//	private MedTransPanel 				m_MedTransProperties			= null;
	
	private Collection <GECAMedAction>  m_InvoiceActions;
	private Collection <GECAMedAction>  m_StatementActions;
	private Collection <GECAMedAction>  m_AccountingActions;
//	private Collection <GECAMedAction>  m_AdminActions;
	
	private InvoiceEventDispatcher 		m_InvoiceListeners;

	private NomenclaturePanel			m_NomenclaturePanel;
	
	private PatientActsDialog 			patientActsDialog;
	
	//========================================================================
	//= Static members
	//========================================================================
	
	private static BillingModule			  	m_Instance		= null;

	private static boolean						m_SuperUserMode	= false;
	private static boolean						m_WasModified   = false;
	
//	private static Boolean 						m_UseLeadingZeros = null;
	
	private static BillingAdminSettingsPlugin 	m_AdminSettings	= new BillingAdminSettingsPlugin();
	private static BillingUserSettingsPlugin 	m_UserSettings	= new BillingUserSettingsPlugin ();
	
	private static Collection <UserModeListener> m_UserModeListeners;

	private static Logger m_Logger = Logger.getLogger (BillingModule.class.getName());
	
	private static Collection <HospitalisationClass> m_HospitalisationClasses;
//	private static Collection <Physician>			 m_Physicians;
	private static Collection <GecamedUser>		 	 m_Users;
	private static Collection <Insurance>			 m_HealthInsurances;
	private static Collection <Settlement>			 m_SettlementMethods;
	private static Collection <Suffix>				 m_Suffixes;
	private static Collection <NationalHoliday>		 m_NationalHolidays;
	private static Collection <Contact>		 	     m_MedPres;
	
	private TopicConnection						m_TopicConnection;
	private	TopicSession						m_TopicSession;
	private Topic								m_Topic;

	private NomenclatureInterface m_NomenclatureInterface;

	private GECAMedBaseDialogImpl m_TrashDialog;

	
//***************************************************************************
//* Class Constants                                                         *
//***************************************************************************

	private static final Collection <Integer> m_Dependencies = new ArrayList <Integer> ();
    
	static 	{
    		m_Dependencies.add(InvoiceInterface.c_PatientDependency);
    		m_Dependencies.add(InvoiceInterface.c_ModifierDependency);
	    	}
	
	public static final Color m_ModulePlainModeColor = new Color ( 55,200,155);
	public static final Color m_ModuleSuperModeColor = new Color (237,127,127);
		
	private final static String c_Columns	= 	"pref,3dlu,pref,3dlu,pref,fill:pref:grow";
			
	private final static String c_Rows		=   "pref,3dlu," +
										 		"fill:pref,3dlu," +
										 		"fill:200px:grow,3dlu,pref";
	
	public final static int c_InvoiceTab		= 0;
	public final static int c_EditorTab			= 1;
	public final static int c_MemoTab			= 2;
	public final static int c_SearchTab			= 3;
	public final static int c_ReminderTab		= 4;
	public final static int c_StatementTab		= 5;
	public final static int c_TrashTab			= 6;
	
	private final static char	c_NextInvoiceHotKey 		= KeyEvent.VK_F2;
	private final static char	c_PreviousInvoiceHotKey 	= KeyEvent.VK_F1;
	private final static char	c_SettleInvoiceHotKey 		= KeyEvent.VK_F4;
	private final static char	c_RevokeInvoiceHotKey 		= KeyEvent.VK_F5;
	
    /**
     * The name of the module
     */
    public static final String MODULE_NAME = "Billing";
	
    public static final String	c_BillingUpdateTopic 		= "topic/GECAMed/billingUpdateTopic";
    public static final String  c_ClientIdProperty			= "clientId";
    
    /**
     * Permissions
     */

    public static final String c_BillingModule				= "BillingModule";
    
    public static final String c_Invoices					= "Invoices";
    public static final String c_HospitalizedInvoices		= "HospitalizedInvoices";
       
    public static final String c_viewStem	 				= "view";
    public static final String c_createStem 				= "create";
    public static final String c_verifyStem	 				= "verify";
    public static final String c_disproveStem	 			= "disprove";
    public static final String c_closeStem	 				= "close";
    public static final String c_openStem					= "open";
    public static final String c_openAllStem	 			= "openAll";
    public static final String c_printStem	 				= "print";
    public static final String c_printOpenStem	 			= "printOpen";
    public static final String c_remindStem		 			= "remind";
    public static final String c_settleStem		 			= "settle";
    public static final String c_revokeStem		 			= "revoke";
    public static final String c_cancelStem		 			= "cancel";
    public static final String c_editStem	 				= "edit";
    public static final String c_deleteStem		 			= "delete";
    public static final String c_undeleteStem				= "undelete";
    
    public static final String c_viewInvoices 				= c_viewStem + c_Invoices;
    public static final String c_createInvoices 			= c_createStem + c_Invoices;
    public static final String c_verifyInvoices 			= c_verifyStem + c_Invoices;
    public static final String c_disproveInvoices 			= c_disproveStem + c_Invoices;
    public static final String c_closeInvoices 				= c_closeStem + c_Invoices;
    public static final String c_openInvoices				= c_openStem + c_Invoices;
    public static final String c_openAllInvoices 			= c_openAllStem + c_Invoices;
    public static final String c_printInvoices 				= c_printStem + c_Invoices;
    public static final String c_printOpenInvoices 			= c_printOpenStem + c_Invoices;
    public static final String c_remindInvoices 			= c_remindStem + c_Invoices;
    public static final String c_settleInvoices 			= c_settleStem + c_Invoices;
    public static final String c_revokeInvoices 			= c_revokeStem + c_Invoices;
    public static final String c_cancelInvoices 			= c_cancelStem + c_Invoices;
    public static final String c_editInvoices 				= c_editStem + c_Invoices;
    public static final String c_deleteInvoices 			= c_deleteStem + c_Invoices;
    public static final String c_undeleteInvoices			= c_undeleteStem + c_Invoices;

    public static final String c_editAllMemos 				= "editAllMemos";

    public static final String c_viewStatements 			= "viewStatements";
    public static final String c_createStatements 			= "createStatements";
    public static final String c_editStatements 			= "editStatements";
    public static final String c_closeStatements 			= "closeStatements";
    public static final String c_openStatements 			= "openStatements";
    public static final String c_printStatements 			= "printStatements";
    public static final String c_settleStatements 			= "settleStatements";
    public static final String c_deleteStatements 			= "deleteStatements";

    public static final String c_viewReminders 				= "viewReminders";
    public static final String c_printReminderLists 		= "printReminderLists";
    public static final String c_printReminders 			= "printReminders";
    public static final String c_revokeReminders 			= "revokeReminders";

    public static final String c_printTransactionList 		= "printTransactionList";
    public static final String c_printInvoiceList 			= "printInvoiceList";
    public static final String c_printActivityList 			= "printActivityList";
    public static final String c_ViewLedgers 				= "viewLedgers";
//    public static final String c_changeKeyValue 			= "changeKeyValue";
//    public static final String c_importUCMRates 			= "importUCMRates";

    public static final String c_viewTrash 					= "viewTrash";
    
    public static final String c_superUser 					= "superUser";    
    
    public static final Double  c_Zero	   = 0d;
    
//***************************************************************************
//* Constructors                                       						*
//***************************************************************************

public BillingModule () 
    {	
	super(MainFrame.getInstance(), MODULE_NAME, "billing.png",m_ModulePlainModeColor);
	
    JPanel				l_BillingPanel;
	JMenu				l_BillingMenu;
    CellConstraints		l_Constraints;
    FormLayout			l_Layout;
    MouseAdapter		l_MouseAdapter;
    GECAMedMessage		l_Message; 
 //   Boolean				l_MaidenNameIsMarriedName;
    
    Translatrix.addBundle("lu.tudor.santec.gecamed.billing.gui.resources.WidgetResources");

    m_Instance = this;
    
    //========================================================================
    //* Step 1. Prefetch commonly used data from database
    //========================================================================
   
    m_HospitalisationClasses = this.prefetchHospitalisationClasses();
//    m_Physicians 			 = this.prefetchPhysicians();
    m_Users					 = this.prefetchUsers();
    m_HealthInsurances 		 = this.prefetchHealthInsurances();
    m_SettlementMethods		 = this.prefetchSettlementMethods();
    m_Suffixes				 = this.prefetchSuffixes();
    m_NationalHolidays		 = this.prefetchNationalHolidays();
    m_MedPres		 		 = this.prefetchMedPres();
    
 	Act.setAllSuffixes	(m_Suffixes);
	Act.setHolidays	(m_NationalHolidays);
   
	m_AdminSettings.relocalize();
	m_UserSettings.relocalize();
	
	this.addAdminSettingsPlugin (m_AdminSettings);
	this.addSettingsPlugin		(m_UserSettings);
	
	m_NomenclaturePanel = new NomenclaturePanel ();
	MainFrame.addAdminTab(m_NomenclaturePanel);
		
	l_Message = new GECAMedMessage(BillingModule.getInstance(), InvoiceTemplateDialog.c_TemplateOrderChanged, null, null);		
	MainFrame.fireGECAMedMessage (l_Message);
	
	Invoice.setInsurances (this.getHealthInsurances());
	Invoice.setExpiryPeriod 	((Integer)BillingModule.getSetting(BillingAdminSettings.c_DuePeriodSetting));
 	
	if (PatientManagerModule.getInstance().administrativeElementsPlugin.getValue(SettingConstants.MAIDEN_CONFIG) != null)
		{
//		l_MaidenNameIsMarriedName = (Boolean) PatientManagerModule.getInstance().administrativeElementsPlugin.getValue(AdministrativeElementsPlugin.MAIDEN_CONFIG);
//		Activity.setMaidenNameIsMarriedName(l_MaidenNameIsMarriedName);
//		InvoiceStub.setMaidenNameIsMarriedName (l_MaidenNameIsMarriedName);		
//		TrashedInvoiceStub.setMaidenNameIsMarriedName(l_MaidenNameIsMarriedName);
//		Transaction.setMaidenNameIsMarriedName(l_MaidenNameIsMarriedName);
		}

    m_UserModeListeners = new ArrayList <UserModeListener> ();
    m_InvoiceListeners = new InvoiceEventDispatcher ();
    
    m_InvoiceProperties			= new InvoicePropertiesPanel ();
	m_AccidentProperties		= new AccidentPropertiesPanel ();
	m_HospitalisationProperties	= new HospitalisationPanel ();
//	m_MedTransProperties		= new MedTransPanel ();

	
//	m_InvoiceProperties.populatePhysicians (GECAMedLists.getListReference(Physician.class));
    m_InvoiceProperties.populateInsurances (m_HealthInsurances);
	m_InvoiceProperties.addPropertyChangeListener(this);
    
    m_HospitalisationProperties.populateHospitalisationClasses(m_HospitalisationClasses);
//    m_MedTransProperties.populateMedTrans();
      
	m_PatientSummaryPanel 		= new PatientSummaryPanel();
   	m_PatientSummaryPanel.addPropertyChangeListener(this);
	
	m_InvoiceStatusPanel 		= new InvoiceStatusPanel ();
      
    m_DefaultBorderStamp   = BillingModule.getIconResource ("border_none.png");
    m_SuperUserBorderStamp = BillingModule.getIconResource ("border_danger.png");
     
	m_MemoStatic 	  	= BillingModule.getIconResource ("memo.png");
	m_MemoBlinking 	  	= new AnimatedIcon (BillingModule.getIconResource ("memo_flashing_white.gif"));
  
    m_DefaultBorder   = new MatteBorder(-1,-1,-1,-1,m_DefaultBorderStamp);
    m_SuperUserBorder = new MatteBorder(-1,-1,-1,-1,m_SuperUserBorderStamp);   
    
    this.setOpaque(false);
    this.setBorder(m_DefaultBorder);
    this.setCanDisplayPatient(true);
    
    l_BillingPanel = new JPanel();
    l_BillingPanel.setOpaque(false);
        
    l_Constraints  = new CellConstraints();
     
    l_Layout = new FormLayout(c_Columns, c_Rows);
    l_BillingPanel.setLayout(l_Layout);
  
	m_MainPanel = new JTabbedPane();
    m_MainPanel.addChangeListener(this);
    m_MainPanel.setOpaque(false);	
    
     //=======================================================================
    // Step 1. Setup Invoice Listing Panel
    //=======================================================================

   	m_InvoicePanel = new InvoiceListingPanel ();
   	m_InvoicePanel.setTitle(Translatrix.getTranslationString("BillingModule.InvoiceTab"));
	
   	if ((Boolean)BillingModule.getUserSetting("General.ShowTabIcons"))
   		m_InvoicePanel.setIcon(BillingModule.getIconResource ("patient_invoices_tab.png"));
   	
   	//-----------------------------------------------------------------------
   	// Setup a MouseAdapter to intercept double-clicks on invoice. Double-click
   	// on invoice ought to open invoice in Editor Panel. Right-click on invoice
   	// ought to settle currently selected invoice.
    //-----------------------------------------------------------------------
  	
	l_MouseAdapter = new MouseAdapter()
	{
		public void mouseClicked (MouseEvent e)
		{
			if (e.getClickCount() == 2)
				editSelectedInvoice();
		}
		
		
		public void mousePressed (MouseEvent e)
		{
			if (e.isPopupTrigger())
				settleSelectedInvoice(e);
		}
		
		
		public void mouseReleased (MouseEvent e)
		{
			if (e.isPopupTrigger())
				settleSelectedInvoice(e);
		}
	};
  
    m_InvoicePanel.addKeyListener   (this); 
    m_InvoicePanel.addMouseListener (l_MouseAdapter); 
    m_InvoicePanel.addInvoiceListener (this);
    m_InvoicePanel.addSearchModeListener(this);
   	m_InvoicePanel.addToTabbedPane(m_MainPanel);
   	
   	//=======================================================================
   	// Step 2. Setup Invoice Editor Panel
   	//=======================================================================
	
	m_EditorPanel = new InvoiceEditorPanel (m_Suffixes, GECAMedLists.getListReference(Physician.class));
	m_EditorPanel.setTitle(Translatrix.getTranslationString("BillingModule.EntryTab"));
	
	if ((Boolean)BillingModule.getUserSetting("General.ShowTabIcons"))
		m_EditorPanel.setIcon(BillingModule.getIconResource ("edit_tab.png"));
	
	m_EditorPanel.addPropertyChangeListener(this);
   	m_EditorPanel.addToTabbedPane(m_MainPanel);
  	  
   	//=======================================================================
   	// Step 3. Setup Invoice Memo Panel
   	//=======================================================================
 	
   	m_MemoPanel = new MemoEditorPanel ();
   	m_MemoPanel.setTitle(Translatrix.getTranslationString("BillingModule.MemoTab"));
   	
	if ((Boolean)BillingModule.getUserSetting("General.ShowTabIcons"))	
		m_MemoPanel.setIcon(BillingModule.getIconResource ("memos_tab.png"));

	m_MemoPanel.addPropertyChangeListener(this);
  	m_MemoPanel.addToTabbedPane(m_MainPanel);
	   	
  	//=======================================================================
   	// Step 2. Setup Invoice Editor Panel
   	//=======================================================================
	
	m_SearchPanel = new SearchPanel ();
	m_SearchPanel.setTitle(Translatrix.getTranslationString("BillingModule.SearchTab"));
	
	if ((Boolean)BillingModule.getUserSetting("General.ShowTabIcons"))
		m_SearchPanel.setIcon(BillingModule.getIconResource ("invoices_search_tab.png"));
	
	m_SearchPanel.addInvoiceListener(this);
	m_SearchPanel.addPropertyChangeListener(this);
   	m_SearchPanel.addToTabbedPane(m_MainPanel);
 
   	//=======================================================================
   	// Step 4. Setup Invoice Reminder Panel
   	//=======================================================================
 	
    if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_viewReminders))
    	{
    	m_ReminderPanel = new ReminderPanel ();
    	m_ReminderPanel.setTitle(Translatrix.getTranslationString("BillingModule.ReminderTab"));
   	
    	if ((Boolean)BillingModule.getUserSetting("General.ShowTabIcons"))
    		m_ReminderPanel.setIcon(BillingModule.getIconResource ("reminders_tab.png"));

    	m_ReminderPanel.addInvoiceListener(this);
    	m_ReminderPanel.addPropertyChangeListener(this);
    	m_ReminderPanel.addToTabbedPane(m_MainPanel);
    	}
    	
  	//=======================================================================
   	// Step 5. Setup Statement Panel
   	//=======================================================================
  	
	if (	((Boolean)BillingModule.getSetting(BillingAdminSettings.c_ThirdPartyStatementsSetting))
		&&  (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_viewStatements))	)
		{
		m_StatementPanel = new StatementPanel ();
		m_StatementPanel.setTitle(Translatrix.getTranslationString("BillingModule.StatementTab"));
		
		if ((Boolean)BillingModule.getUserSetting("General.ShowTabIcons"))
			m_StatementPanel.setIcon(BillingModule.getIconResource ("statements_tab.png"));

	  	m_StatementPanel.addInvoiceListener(this);
		m_StatementPanel.addPropertyChangeListener(this);
		m_StatementPanel.addToTabbedPane(m_MainPanel);
		}
		
  	//=======================================================================
   	// Step 5. Setup Statement Panel
   	//=======================================================================
  	
	if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_viewTrash))
		{
		m_TrashPanel = new TrashPanel (m_Users);
		m_TrashPanel.setTitle(Translatrix.getTranslationString("BillingModule.TrashTab"));
		
		if ((Boolean)BillingModule.getUserSetting("General.ShowTabIcons"))
			m_TrashPanel.setIcon(BillingModule.getIconResource ("trash_tab.png"));

		m_TrashPanel.addInvoiceListener(this);
//		m_TrashPanel.addToTabbedPane(m_MainPanel);
		
		m_TrashDialog = new GECAMedBaseDialogImpl(mainFrame, Translatrix.getTranslationString("BillingModule.TrashTab"), GECAMedBaseDialogImpl.CLOSE_BUTTON_MODE, m_TrashPanel);
		m_TrashDialog.setSize(1000, 700);
		
		}
	
	//=======================================================================
   	// Step 5
   	//=======================================================================
    
   	m_MainPanel.setSelectedIndex(c_InvoiceTab);
    m_MainPanel.setEnabledAt(c_InvoiceTab,true);

    l_BillingPanel.add(m_PatientSummaryPanel, 		l_Constraints.xywh(1, 1, 6, 1));
    l_BillingPanel.add(m_InvoiceProperties, 		l_Constraints.xywh(1, 3, 1, 1));
    
	if ((Boolean)BillingModule.getSetting(BillingAdminSettings.c_HospitalisationSetting))
		{
		l_BillingPanel.add(m_HospitalisationProperties, l_Constraints.xywh(3, 3, 1, 1));
		l_BillingPanel.add(m_AccidentProperties, 		l_Constraints.xywh(5, 3, 1, 1));
		
		// MED TRANS Panel Disabled for now.....
//		if ((Boolean)BillingModule.getSetting(BillingAdminSettings.c_ShowMedTransPanelSetting)) {
//			l_BillingPanel.add(m_MedTransProperties, 		l_Constraints.xywh(6, 3, 1, 1));			
//		}
		}
	else {
		l_BillingPanel.add(m_AccidentProperties, 		l_Constraints.xywh(3, 3, 1, 1));
		
		// MED TRANS Panel Disabled for now.....
//		if ((Boolean)BillingModule.getSetting(BillingAdminSettings.c_ShowMedTransPanelSetting)) {
//			l_BillingPanel.add(m_MedTransProperties, 		l_Constraints.xywh(5, 3, 1, 1));	
//		}
	}
	
    l_BillingPanel.add(m_MainPanel, 				l_Constraints.xywh(1, 5, 6, 1));
    l_BillingPanel.add(m_InvoiceStatusPanel, 		l_Constraints.xywh(1, 7, 6, 1));
  
//    this.setContentPanel (l_BillingPanel);
  this.setContentPanel (GradientFactory.makeGradient(l_BillingPanel,new Color (92,163,229),GECAMedColors.c_GECAMedBackground));

    l_BillingMenu = new JMenu (Translatrix.getTranslationString("Billing"));
    this.setModuleMenu(l_BillingMenu);
    	
  	//=======================================================================
   	// Step 6 Create Module Actions
   	//=======================================================================

    m_InvoiceActions    = new ArrayList <GECAMedAction> ();
    m_StatementActions  = new ArrayList <GECAMedAction> ();
    m_AccountingActions = new ArrayList <GECAMedAction> ();
//    m_AdminActions      = new ArrayList <GECAMedAction> ();
          
    this.createInvoiceActions();
    
	if (m_InvoiceActions.size() > 0) this.addTopButtonSeparator();
	
    this.createAccountingActions();
    
	if (m_AccountingActions.size() > 0) this.addTopButtonSeparator();
   	
//	if ((Boolean)BillingModule.getSetting(BillingAdminSettings.c_ThirdPartyStatementsSetting))
//		{
//		this.createStatementActions();  	    	
//		
//		if (m_StatementActions.size() > 0) this.addTopButtonSeparator();
//		}
	
//	this.createAdminActions();
	
	if (m_TrashPanel != null) {
		this.addTopButtonSeparator();
		GECAMedAction		l_Action;     	 
	    l_Action = new GECAMedAction (this, "BillingModule.TrashTab", getIconResource ("trash_tab.png"), null, true, true, false) {
			private static final long serialVersionUID = 1L;
	    	public void actionPerformed(ActionEvent p_Event) {
	    		m_TrashPanel.updateListing();
	    		m_TrashDialog.showCenteredDialog();
	    	}
	    };
	    l_Action.add();
	}
	
		
    if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_superUser))
		{ 	     	 
    	this.addTopButtonSeparator();

    	m_SuperUserSwitch = new JToggleButton ();
    	m_SuperUserSwitch.setIcon(getIconResource("plainuser.png"));
    	m_SuperUserSwitch.setSelectedIcon(getIconResource("superuser.png"));
    	m_SuperUserSwitch.addActionListener(this);
    	
    	this.addTopButton(m_SuperUserSwitch);    	
		}
 
   GECAMedModule.addPatientListener (this);
   RegistrationDesk.addGECAMedMessageListener (this); 
    
   if (m_InvoicePanel != null)  RegistrationDesk.addPhysicianListener (m_InvoicePanel);
   if (m_ReminderPanel != null) RegistrationDesk.addPhysicianListener (m_ReminderPanel);
   
   this.connectToBillingUpdateTopic();
   this.subscribeToBillingUpdateTopic();
   
   this.patientActsDialog = new PatientActsDialog();
   
   this.relocalize();
   }


//---------------------------------------------------------------------------

private NomenclatureInterface getNomenclatureInterface ()
	{
	if (m_NomenclatureInterface != null) return m_NomenclatureInterface;
	
	try {
		m_NomenclatureInterface = (NomenclatureInterface) ManagerFactory.getRemote(NomenclatureBean.class);
		} 
	catch (Exception p_Exception) 
		{
		m_NomenclatureInterface = null;
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}
	
	return m_NomenclatureInterface;
	}


//---------------------------------------------------------------------------
/**
 * Creates all invoice related actions
 */
//---------------------------------------------------------------------------

private void createInvoiceActions ()
	{
	GECAMedAction		l_Action;
	
	if (userHasPermission (BillingModule.c_BillingModule,BillingModule.c_createInvoices))
		{ 	
	   	l_Action = new NewInvoiceAction (this,
		    								 "BillingModule.NewInvoice",
		    								 getIconResource("new_invoice.png"),
		    								 KeyEvent.VK_N,
		    								 true, true, false);
	   	l_Action.add();
	   	m_InvoiceActions.add(l_Action);
		}
   	
   if (userHasPermission (BillingModule.c_BillingModule,BillingModule.c_editInvoices))
		{ 	
		l_Action = new EditInvoiceAction (this,
			   	  						  "BillingModule.EditInvoice",
			   	  						  getIconResource("edit_invoice.png"),
			   	  						  KeyEvent.VK_E,
			   	  						  true, false, false);
		l_Action.add();
		m_InvoiceActions.add(l_Action);
		}
	
   if (userHasPermission (BillingModule.c_BillingModule,BillingModule.c_verifyInvoices))
		{ 	
		l_Action = new VerifyInvoiceAction (this,
			   	  						  "BillingModule.VerifyInvoice",
			   	  						  getIconResource("invoice_verify_action.png"),
			   	  						  KeyEvent.VK_V,
			   	  						  true, true, false);
		l_Action.add();
		m_InvoiceActions.add(l_Action);
		}

   if (userHasPermission (BillingModule.c_BillingModule,BillingModule.c_disproveInvoices))
		{ 	
		l_Action = new DisproveInvoiceAction (this,
			   	  						      "BillingModule.DisproveInvoice",
			   	  						      getIconResource("invoice_disprove_action.png"),
			   	  						      KeyEvent.VK_D,
			   	  						      true, true, false);
		l_Action.add();
		m_InvoiceActions.add(l_Action);
		}

   if (userHasPermission (BillingModule.c_BillingModule,BillingModule.c_closeInvoices))
		{ 	
	   	l_Action = new CloseInvoiceAction (this,
				   	  							"BillingModule.CloseInvoice",
				   	  							getIconResource("invoice_close_action.png"),
				   	  							KeyEvent.VK_C,
				   	  							true, true, false);
	   	l_Action.add();
	   	m_InvoiceActions.add(l_Action);
		}
	
   if (userHasPermission (BillingModule.c_BillingModule,BillingModule.c_openInvoices))
		{ 	
		l_Action = new OpenInvoiceAction (this,
			   	  						  "BillingModule.OpenInvoice",
			   	  						  getIconResource("invoice_open_action.png"),
			   	  						  KeyEvent.VK_O,
			   	  						  true, true, false);
		l_Action.add();
		m_InvoiceActions.add(l_Action);
		}

	if (userHasPermission (BillingModule.c_BillingModule,BillingModule.c_settleInvoices))
		{ 	
		l_Action = new SettleInvoiceAction (this,
				    					    "BillingModule.SettleInvoice",
				    					    getIconResource("pay_invoice.png"),
				    						KeyEvent.VK_S,
				    						true, true, false);
		
		l_Action.setHotKey(c_SettleInvoiceHotKey);
		l_Action.add();
		m_InvoiceActions.add(l_Action);
		}

	if (userHasPermission (BillingModule.c_BillingModule,BillingModule.c_revokeInvoices))
		{ 	
		l_Action = new RevokeInvoiceAction (this,
											"BillingModule.RevokeInvoice",
											getIconResource("revoke_invoice.png"),
											KeyEvent.VK_R,
											true, true, false);
		
		l_Action.setHotKey(c_RevokeInvoiceHotKey);
		l_Action.add();
		m_InvoiceActions.add(l_Action);
		}

	if (userHasPermission (BillingModule.c_BillingModule,BillingModule.c_deleteInvoices))
		{ 	
		l_Action = new DeleteInvoiceAction (this,
					    					"BillingModule.DeleteInvoice",
					    					getIconResource("delete_invoice.png"),
					    					KeyEvent.VK_T,
					    					true, true, false);
		l_Action.add();
		m_InvoiceActions.add(l_Action);
		}

	l_Action = new ReloadInvoicesAction (this,
										"BillingModule.ReloadInvoices",
										getIconResource("reload_invoices.png"),
										KeyEvent.VK_F8,
										true,true,false);
	
	l_Action.add();
	m_InvoiceActions.add(l_Action);
										
	l_Action = new NextInvoiceAction (this,
			  						  "BillingModule.NextInvoice",
				  					  getIconResource("next_invoice.png"),
				  					  KeyEvent.VK_F2,
				  					  false, false, false);
	
	l_Action.setHotKey(c_NextInvoiceHotKey);
	l_Action.add();
	m_InvoiceActions.add(l_Action);

  	l_Action = new PreviousInvoiceAction (this,
										  "BillingModule.PreviousInvoice",
										  getIconResource("previous_invoice.png"),
										  KeyEvent.VK_F1,
										  false, false, false);
  	
  	l_Action.setHotKey(c_PreviousInvoiceHotKey);
  	l_Action.add();
  	m_InvoiceActions.add(l_Action);
	}

//---------------------------------------------------------------------------
/**
 * Creates all accounting related actions
 */
//---------------------------------------------------------------------------

private void createAccountingActions ()
	{
	GECAMedAction		l_Action;
	
	if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_printTransactionList))
		{ 	     	 
      	l_Action = new TransactionListAction (this,
      								  "BillingModule.DayBook",
      								  getIconResource("transaction_list.png"),
      								  KeyEvent.VK_F,
      								  true, true, false);
      	l_Action.add();
      	m_AccountingActions.add(l_Action);
		}
	
	if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_printInvoiceList))
		{ 	     	 
		l_Action = new IssuedInvoiceListAction (this,
  								  		 "BillingModule.InvoiceList",
  								  		 getIconResource("invoice_list.png"),
  								  		 KeyEvent.VK_I,
  								  		 true, true, false);
		l_Action.add();
		m_AccountingActions.add(l_Action);
		}

	if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_printActivityList))
		{ 	     	 
      	l_Action = new ActivityListAction (this,
      								  "BillingModule.ActivityList",
      								  getIconResource("activity_list.png"),
      								  KeyEvent.VK_A,
      								  true, true, false);
      	l_Action.add();
      	m_AccountingActions.add(l_Action);
		}

	if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_ViewLedgers))
		{ 	     	 
      	l_Action = new ShowLedgerAction (this,
      								  "BillingModule.ShowLedger",
      								  getIconResource("show_ledger.png"),
      								  KeyEvent.VK_F12,
      								  true, true, false);
      	l_Action.add();
      	m_AccountingActions.add(l_Action);
		}
	
//	if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_ViewLedgers))
//	{ 	     	 
  	l_Action = new GECAMedAction (this,
  								  "BillingModule.ShowPatientActs",
  								  getIconResource("patient_act_list.png"),
  								  null,
  								  true, true, false) {

									private static final long serialVersionUID = 1L;
									@Override
									public void actionPerformed(ActionEvent p_Event) {
										new Thread() {
											public void run() {
												Patient p = m_CurrentPatient;
												patientActsDialog.showPatientActs(p);												
											}
										}.start();
									}

  	};
  	l_Action.add();
  	m_AccountingActions.add(l_Action);
//	}
	
	}

//---------------------------------------------------------------------------
/**
 * Creates all statement related actions
 */
//---------------------------------------------------------------------------

//private void createStatementActions ()
//	{
//	GECAMedAction		l_Action;
//	   
//	if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_createStatements))
//		{    	
//		l_Action = new NewStatementAction (this,
//	   										"BillingModule.NewStatement",
//	   										getIconResource("stmnt_create_action.png"),
//	   										KeyEvent.VK_T,
//	   										true, true, false);
//		l_Action.add();
//		m_StatementActions.add(l_Action);
//		}
//   	
//	if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_deleteStatements))
//		{    	
//	 	l_Action = new DeleteStatementAction (this,
//											"BillingModule.DeleteStatement",
//											getIconResource("stmnt_delete_action.png"),
//											KeyEvent.VK_R,
//											true, true, false);
//	 	l_Action.add();
//	 	m_StatementActions.add(l_Action);
//		}
//		
//	if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_closeStatements))
//		{    	
//		l_Action = new CloseStatementAction (this,
//											"BillingModule.CloseStatement",
//											getIconResource("stmnt_close_action.png"),
//											KeyEvent.VK_C,
//											true, true, false);
//		l_Action.add();
//		m_StatementActions.add(l_Action);
//		}
//	    	
//	if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_openStatements))
//		{    	
//		l_Action = new OpenStatementAction (this,
//											"BillingModule.OpenStatement",
//											getIconResource("stmnt_open_action.png"),
//											KeyEvent.VK_C,
//											true, true, false);
//		l_Action.add();
//		m_StatementActions.add(l_Action);
//		}
//	    	
//	if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_printStatements))
//		{    	
//		l_Action = new PrintStatementAction (this,
//											"BillingModule.PrintStatement",
//											getIconResource("stmnt_print_action.png"),
//											KeyEvent.VK_P,
//											true, true, false);
//		l_Action.add();
//		m_StatementActions.add(l_Action);
//		}
//	}

//---------------------------------------------------------------------------
/**
 * Creates all billing module administration related actions
 */
//---------------------------------------------------------------------------

//private void createAdminActions ()
//	{
//	GECAMedAction		l_Action;
//
//	l_Action = new HL7ImportAction (this,
//									"BillingModule.HL7Import",
//									getIconResource("hl7.png"),
//									KeyEvent.VK_I,
//									true, true, false);
//	l_Action.add();
//	m_AdminActions.add(l_Action);
//	}

//---------------------------------------------------------------------------

public static Date stripTime (Date p_OriginalDate)
	{
	GregorianCalendar	l_StrippedDate;

	if (p_OriginalDate == null) return null;

	l_StrippedDate = new GregorianCalendar ();
	l_StrippedDate.setTime (p_OriginalDate);
	l_StrippedDate.set (Calendar.HOUR_OF_DAY,0);
	l_StrippedDate.set (Calendar.MINUTE,0);
	l_StrippedDate.set (Calendar.SECOND,0);
	l_StrippedDate.set (Calendar.MILLISECOND,0);
	return l_StrippedDate.getTime();
	}

//---------------------------------------------------------------------------

public static Date earliestOfDay (Date p_OriginalDate)
	{
	GregorianCalendar	l_StrippedDate;

	if (p_OriginalDate == null) return null;

	l_StrippedDate = new GregorianCalendar ();
	l_StrippedDate.setTime (p_OriginalDate);
	l_StrippedDate.set (Calendar.HOUR_OF_DAY,0);
	l_StrippedDate.set (Calendar.MINUTE,0);
	l_StrippedDate.set (Calendar.SECOND,0);
	l_StrippedDate.set (Calendar.MILLISECOND,0);
	return l_StrippedDate.getTime();
	}

//---------------------------------------------------------------------------

public static Date latestOfDay (Date p_OriginalDate)
	{
	GregorianCalendar	l_StrippedDate;

	if (p_OriginalDate == null) return null;

	l_StrippedDate = new GregorianCalendar ();
	l_StrippedDate.setTime (p_OriginalDate);
	l_StrippedDate.set (Calendar.HOUR_OF_DAY,23);
	l_StrippedDate.set (Calendar.MINUTE,59);
	l_StrippedDate.set (Calendar.SECOND,59);
	l_StrippedDate.set (Calendar.MILLISECOND,999);
	return l_StrippedDate.getTime();
	}

//---------------------------------------------------------------------------

public static Date firstOfMonth (Date p_OriginalDate)
	{
	GregorianCalendar	l_FirstOfMonth;
	
	l_FirstOfMonth = new GregorianCalendar();
	l_FirstOfMonth.setTime (p_OriginalDate);
	l_FirstOfMonth.set (Calendar.DAY_OF_MONTH, 1);

	return l_FirstOfMonth.getTime();
	}

//---------------------------------------------------------------------------

public static boolean isFirstOfMonth (Date p_Date)
	{
	GregorianCalendar	l_FirstOfMonth;
	
	l_FirstOfMonth = new GregorianCalendar();
	l_FirstOfMonth.setTime (p_Date);	
	return (l_FirstOfMonth.get (Calendar.DAY_OF_MONTH) == 1);
	}

//---------------------------------------------------------------------------

public static Date lastOfMonth (Date p_OriginalDate)
	{
	GregorianCalendar	l_LastOfMonth;
	int					l_LastDay;
	
	l_LastOfMonth = new GregorianCalendar();
	l_LastOfMonth.setTime (p_OriginalDate);
	l_LastDay = l_LastOfMonth.getActualMaximum (Calendar.DAY_OF_MONTH);	
	l_LastOfMonth.set (Calendar.DAY_OF_MONTH, l_LastDay);

	return l_LastOfMonth.getTime();
	}

//---------------------------------------------------------------------------

public static Date getEarliestDate (Date p_FirstDate, Date p_SecondDate)
	{
	Date l_EarliestDate = null;
	
	if ((p_FirstDate != null) && (p_SecondDate != null))
		{
		switch (p_FirstDate.compareTo(p_SecondDate))
			{
			case -1: l_EarliestDate = p_FirstDate;
					 break;
			case  0: l_EarliestDate = p_FirstDate;
				     break;
			case  1: l_EarliestDate = p_SecondDate;
					 break;
			}
		}
	else if ((p_FirstDate == null) && (p_SecondDate != null)) l_EarliestDate = p_SecondDate;
		else if ((p_FirstDate != null) && (p_SecondDate == null)) l_EarliestDate = p_FirstDate;
	
	return l_EarliestDate;
	}
	
//---------------------------------------------------------------------------

public static Date getLatestDate (Date p_FirstDate, Date p_SecondDate)
	{
	Date l_LatestDate = null;
	
	if ((p_FirstDate != null) && (p_SecondDate != null))
		{
		switch (p_FirstDate.compareTo(p_SecondDate))
			{
			case -1: l_LatestDate = p_SecondDate;
					 break;
			case  0: l_LatestDate = p_SecondDate;
				     break;
			case  1: l_LatestDate = p_FirstDate;
					 break;
			}
		}
	else if ((p_FirstDate == null) && (p_SecondDate != null)) l_LatestDate = p_SecondDate;
		else if ((p_FirstDate != null) && (p_SecondDate == null)) l_LatestDate = p_FirstDate;
	
	return l_LatestDate;
	}
	
//---------------------------------------------------------------------------
/**
 * Returns the value of the admin billing setting specified by p_Setting.
 * Admin settings are those settings that are common to all users.
 * @param p_Setting specifies the name of the admin setting to get the
 * value of.
 * @return the value (Object) of the admin setting specified by p_Setting.
 */
//---------------------------------------------------------------------------

public static Object getSetting (String p_Setting)
	{
	return m_AdminSettings.getValue(p_Setting);
	}


//---------------------------------------------------------------------------

public static Object getUserSetting (String p_Setting)
	{
	if ("General.ShowTabIcons".equals(p_Setting)) return Boolean.TRUE;
	else return m_UserSettings.getValue(p_Setting);
	}

//---------------------------------------------------------------------------

public static Collection<Contact> getMedPres ()
	{
	return m_MedPres;
	}

//---------------------------------------------------------------------------
/**
 * The static getInstance method returns a reference to the current
 * instance of the BillingModule
 * @return current instance (this) of BillingModule 
 */
//---------------------------------------------------------------------------

public static BillingModule getInstance()
	{
	return m_Instance;
	}

//---------------------------------------------------------------------------

public static boolean userHasPermissionForInvoice (Invoice p_Invoice, String p_PermissionStem, boolean p_WithNotification)
	{
	String	l_Permission = "";
	boolean	l_HasPermission;
	
	if ((p_Invoice == null) || (p_PermissionStem == null)) return false;
	
	if (p_Invoice.isAmbulatory() && !p_Invoice.isPaidByThirdParty())
		 l_Permission = p_PermissionStem + c_Invoices;
	else l_Permission = p_PermissionStem + c_HospitalizedInvoices;	
	
	l_HasPermission =  userHasPermission(BillingModule.c_BillingModule, l_Permission);
	
	if ((p_WithNotification == true) && (l_HasPermission == false))
		notifyUser ("BillingModule.InsufficientPrivilegesTitle",
					"BillingModule.InsufficientPrivilegesMessage",
					null);
	
	return l_HasPermission;
	}

//---------------------------------------------------------------------------
/**
 * Notifies the user about a problem by showing a Dialog. The dialog will
 * only have an okay button.
 * @param p_TitleKey specifies the translatrix key for title of the dialog 
 * to show.
 * @param p_MessageKey specifies the translatrix key of actual message to show 
 * in the dialog.
 * @param p_Filler specifies the data for the placeholders in actual message.
 */
//---------------------------------------------------------------------------

public static void notifyUser (String p_TitleKey, String p_MessageKey, String[] p_Filler)
	{
	String 		l_Message;
//	int			l_UserChoice;
	Color		l_DefaultColor;
	
	Object[] l_Options = {Translatrix.getTranslationString ("core.ok") };
	
	if (p_Filler != null)
		 l_Message = Translatrix.getTranslationString(p_MessageKey,p_Filler);		
	else l_Message = Translatrix.getTranslationString(p_MessageKey);		
	
    l_DefaultColor = (Color) UIManager.getDefaults().get("OptionPane.background");   
    UIManager.getDefaults().put("OptionPane.background", GECAMedColors.c_GECAMedBackground );
    UIManager.getDefaults().put("Panel.background", GECAMedColors.c_GECAMedBackground );
    UIManager.getDefaults().put("Button.background", GECAMedColors.c_GECAMedBackground );

    // TODO: DOES THIS MAKE SENSE, IF THE OPTION IS NEVER READ ??? !!!
//    l_UserChoice = JOptionPane.showOptionDialog (
    JOptionPane.showOptionDialog (MainFrame.getInstance(),
									l_Message,
									Translatrix.getTranslationString (p_TitleKey),
									JOptionPane.OK_OPTION,    
									JOptionPane.INFORMATION_MESSAGE,
									null,
									l_Options,
									l_Options[0]);	

    UIManager.getDefaults().put("OptionPane.background", 	l_DefaultColor );
    UIManager.getDefaults().put("Panel.background", 		l_DefaultColor );
    UIManager.getDefaults().put("Button.background", 		l_DefaultColor );
	}

//---------------------------------------------------------------------------
/**
 * Asks the user to confirm an action by showing a dialog with a yes and no
 * option.
 * @param p_TitleKey specifies the translatrix key for title of the dialog 
 * to show.
 * @param p_MessageKey specifies the translatrix key of actual message to show 
 * in the dialog.
 * @param p_Filler specifies the data for the placeholders in actual message.
 * @return Either JOptionPane.YES_OPTION or JOptionPane.NO_OPTION
 */
//---------------------------------------------------------------------------

public static int getUserConfirmation (String p_TitleKey, String p_MessageKey, String[] p_Filler)
	{
	String 		l_Message;
	int			l_UserChoice;
	Color		l_DefaultColor;
	JLabel		l_MessageLabel;
	Object[] 	l_Options = {Translatrix.getTranslationString ("core.yes"),
					     	 Translatrix.getTranslationString ("core.no") };
	
	l_Message = Translatrix.getTranslationString(p_MessageKey,p_Filler);
	
    l_DefaultColor = (Color) UIManager.getDefaults().get("OptionPane.background");   
    UIManager.getDefaults().put("OptionPane.background", 	GECAMedColors.c_GECAMedBackground );
    UIManager.getDefaults().put("Panel.background", 		GECAMedColors.c_GECAMedBackground );
    UIManager.getDefaults().put("Button.background", 		GECAMedColors.c_GECAMedBackground );

    l_MessageLabel = new JLabel(l_Message);
    l_MessageLabel.setOpaque(false);
    l_UserChoice = JOptionPane.showOptionDialog (	MainFrame.getInstance(),
												l_MessageLabel,
												Translatrix.getTranslationString (p_TitleKey),
												JOptionPane.YES_NO_OPTION, 
												JOptionPane.QUESTION_MESSAGE,
												null,
												l_Options,
												l_Options[1]); 
    
    UIManager.getDefaults().put("OptionPane.background", 	l_DefaultColor );
    UIManager.getDefaults().put("Panel.background", 		l_DefaultColor );
    UIManager.getDefaults().put("Button.background", 		l_DefaultColor );
	
	return l_UserChoice;
	}

//---------------------------------------------------------------------------
/** returns the ImageIcon Resource specified by p_IconName.
 * @param p_IconName specifies the name of the icon to get from application resources.
 * @return the ImageIcon specified by p_IconName, or <CODE>null</CODE> if specified does not exist.
 */
//---------------------------------------------------------------------------

public static ImageIcon getIconResource (String p_IconName) 
	{
	String 		l_IconPath;
	URL 			l_Location;

	l_IconPath = new String("resources/" + p_IconName);
	l_Location = BillingModule.class.getResource(l_IconPath);

	if (l_Location != null)
		 return new ImageIcon(l_Location);
	else return new ImageIcon(l_IconPath);
	}

//---------------------------------------------------------------------------

public static ImageIcon getScaledIcon (String p_IconName, int size) 
	{
	ImageIcon l_Icon = null;
	
	l_Icon = getIconResource(p_IconName);
	if (l_Icon != null)
		l_Icon = new ImageIcon (l_Icon.getImage().getScaledInstance(size, size, Image.SCALE_SMOOTH));
	
	return l_Icon;
	}

//***************************************************************************
//* Interface Getters                                                       *
//***************************************************************************
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
/**
 * The private getInvoiceInterface returns an instance of the InvoiceBean
 * session bean. On the first call, the InvoiceBean will actualy be looked up
 * via JNDI. Once it has been found, the reference to the bean will be stored
 * in a private data member. Doing so avoids JNDI lookups on later calls.
 * @return an instance of the InvoiceBean session bean.
 */
//---------------------------------------------------------------------------

public InvoiceInterface getInvoiceInterface ()
	{
	if (m_InvoiceInterface != null) return m_InvoiceInterface;

	try {
		m_InvoiceInterface = (InvoiceInterface) ManagerFactory.getRemote(InvoiceBean.class);

//		InitialContext l_Context = new InitialContext();
//		m_InvoiceInterface = (InvoiceInterface) l_Context.lookup("InvoiceBean/remote");
//		l_Context.close();
		} 
	catch (Exception p_Exception) 
		{
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}

	return m_InvoiceInterface;
	}

//---------------------------------------------------------------------------
/**
 * The private getAccountingInterface returns an instance of the AccountingBean
 * session bean. On the first call, the AccountingBean will actualy be looked up
 * via JNDI. Once it has been found, the reference to the bean will be stored
 * in a private data member. Doing so avoids JNDI lookups on later calls.
 * @return an instance of the AccountingBean session bean.
 */
//---------------------------------------------------------------------------

public AccountingInterface getAccountingInterface ()
	{
	if (m_AccountingInterface != null) return m_AccountingInterface;

	try {
		m_AccountingInterface = (AccountingInterface) ManagerFactory.getRemote(AccountingBean.class);
//		InitialContext l_Context = new InitialContext();
//		m_AccountingInterface = (AccountingInterface) l_Context.lookup("AccountingBean/remote");
//		l_Context.close();
		} 
	catch (Exception p_Exception) 
		{
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}

	return m_AccountingInterface;
	}

//---------------------------------------------------------------------------
/**
 * The private getInvoiceInterface returns an instance of the StatisticsBean
 * session bean. On the first call, the StatisticsBean will actualy be looked up
 * via JNDI. Once it has been found, the reference to the bean will be stored
 * in a private data member. Doing so avoids JNDI lookups on later calls.
 * @return an instance of the StatisticsBean session bean.
 */
//---------------------------------------------------------------------------

//private StatisticsInterface getStatisticsInterface ()
//	{
//	if (m_StatisticsInterface != null) return m_StatisticsInterface;
//
//	try {
//		m_StatisticsInterface = (StatisticsInterface) ManagerFactory.getRemote(StatisticsBean.class);
////		InitialContext l_Context = new InitialContext();
////		m_StatisticsInterface = (StatisticsInterface) l_Context.lookup("StatisticsBean/remote");
////		l_Context.close();
//		} 
//	catch (Exception p_Exception) 
//		{
//		m_Logger.warn(p_Exception.getLocalizedMessage());
//		}
//
//	return m_StatisticsInterface;
//	}

//---------------------------------------------------------------------------
/**
 * The private getHospitalizedInterface returns an instance of the HospitalizedBean
 * session bean. On the first call, the HospitalizedBean will actualy be looked up
 * via JNDI. Once it has been found, the reference to the bean will be stored
 * in a private data member. Doing so avoids JNDI lookups on later calls.
 * @return an instance of the HospitalizedBean session bean.
 */
//---------------------------------------------------------------------------

private HospitalizedInterface getHospitalizedInterface ()
	{
	if (m_HospitalizedInterface != null) return m_HospitalizedInterface;

	try {
		m_HospitalizedInterface = (HospitalizedInterface) ManagerFactory.getRemote(HospitalizedBean.class);
//		InitialContext l_Context = new InitialContext();
//		m_HospitalizedInterface = (HospitalizedInterface) l_Context.lookup("HospitalizedBean/remote");
//		l_Context.close();
		} 
	catch (Exception p_Exception) 
		{
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}

	return m_HospitalizedInterface;
	}

//---------------------------------------------------------------------------
/**
 * The private getPatientInterface returns an instance of the PatientAdminBean
 * session bean. On the first call, the PatientAdminBean will actualy be looked up
 * via JNDI. Once it has been found, the reference to the bean will be stored
 * in a private data member. Doing so avoids JNDI lookups on later calls.
 * @return an instance of the PatientAdminBean session bean.
 */
//---------------------------------------------------------------------------

private PatientAdminInterface getPatientInterface ()
	{
	if (m_PatientInterface != null) return m_PatientInterface;

	try {
		m_PatientInterface = (PatientAdminInterface) ManagerFactory.getRemote(PatientAdminBean.class);
//		InitialContext l_Context = new InitialContext();
//		m_PatientInterface = (PatientAdminInterface) l_Context.lookup("PatientAdminBean/remote");
//		l_Context.close();
		} 
	catch (Exception p_Exception) 
		{
		m_Logger.warn(p_Exception.getLocalizedMessage());
		}

	return m_PatientInterface;
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* Class Primitives                                                        *
//***************************************************************************
//---------------------------------------------------------------------------

private Invoice getNewInvoiceFromPropertyChangeEvent (PropertyChangeEvent p_ChangeEvent)
	{
	Invoice l_Invoice = null;
	
	if (p_ChangeEvent == null) return l_Invoice;
	
	if (p_ChangeEvent.getNewValue() instanceof Invoice) 
		{
		l_Invoice    = (Invoice) p_ChangeEvent.getNewValue();
		l_Invoice	 = this.fetchLazyDependencies (l_Invoice);
		}

	return l_Invoice;
	}

//---------------------------------------------------------------------------

private Invoice getOldInvoiceFromPropertyChangeEvent (PropertyChangeEvent p_ChangeEvent)
	{
	Invoice l_Invoice = null;
	
	if (p_ChangeEvent == null) return l_Invoice;
	
	if (p_ChangeEvent.getOldValue() instanceof Invoice) 
		{
		l_Invoice    = (Invoice) p_ChangeEvent.getOldValue();
		l_Invoice	 = this.fetchLazyDependencies (l_Invoice);
		}

	return l_Invoice;
	}

//---------------------------------------------------------------------------
/**
 * Switches the BillingModule into Super User mode. All User mode listeners
 * will be notified about this change. 
 */
//---------------------------------------------------------------------------

private void switchToSuperUser ()
	{
	PasswordAskDialog	l_PasswordDialog;
	
	l_PasswordDialog = new PasswordAskDialog ();
	if (l_PasswordDialog.showCentered() == true)
		{
		this.setBorder(m_SuperUserBorder);
		this.titlePanel.setColor(m_ModuleSuperModeColor);
		m_SuperUserMode = true;
		InvoiceWorkflow.setExtendedMode(true);
		StatementWorkflow.setExtendedMode(true);
		this.notifyUserModeListeners ();	
		
		GECAMedLog.user(BillingModule.MODULE_NAME, "SUPERUSER MODE ON", "Switched to superuser mode");
		
		}
	else m_SuperUserSwitch.setSelected(false);
	}

//---------------------------------------------------------------------------
/**
 * Switches the BillingModule back into Plain User mode. All User mode 
 * listeners will be notified about this change. 
 */
//---------------------------------------------------------------------------

private void switchToPlainUser ()
	{
	Color	l_TitleColor;

	this.setBorder(m_DefaultBorder);
	l_TitleColor = (m_WasModified)?GECAMedColors.c_ModifiedTitleBackground:m_ModulePlainModeColor;
	this.titlePanel.setColor(l_TitleColor);	

	m_SuperUserMode = false;
	InvoiceWorkflow.setExtendedMode(false);
	StatementWorkflow.setExtendedMode(false);
	
	GECAMedLog.user(BillingModule.MODULE_NAME, "SUPERUSER MODE OFF", "Switched back to normal user mode");
	
	this.notifyUserModeListeners ();
	}

//===========================================================================
//= User Mode Listener Primitives
//===========================================================================
//---------------------------------------------------------------------------
/**
 * adds the specified UserModeListeners to the list of Listeners. Doing
 * so ensures that specified listener will be notified about changes of
 * user mode.
 * @param p_Listener specifies the UserModeListener to be added.
 */
//---------------------------------------------------------------------------

public void addUserModeListener (UserModeListener p_Listener)
	{
	m_UserModeListeners.add(p_Listener);
	}

//---------------------------------------------------------------------------
/**
 * adds the specified UserModeListeners to the list of Listeners. Doing
 * so ensures that specified listener will be notified about changes of
 * user mode.
 * @param p_Listener specifies the UserModeListener to be added.
 */
//---------------------------------------------------------------------------

public void removeUserModeListener (UserModeListener p_Listener)
	{
	if (m_UserModeListeners.contains(p_Listener)) m_UserModeListeners.remove(p_Listener);
	}

//---------------------------------------------------------------------------
/**
 * The notifyUserModeListeners notifies all registered UserModeListeners about
 * changes in the user mode. Notification is done by calling each listeners
 * userModeChanged method.
 */
//---------------------------------------------------------------------------

private void notifyUserModeListeners ()
	{
	Iterator <UserModeListener>	l_ListenerIterator;
	UserModeListener			l_Listener;
	
	l_ListenerIterator = m_UserModeListeners.iterator();
	while (l_ListenerIterator.hasNext())
		{
		l_Listener = l_ListenerIterator.next();
		l_Listener.userModeChanged(m_SuperUserMode);
		}
	}

//===========================================================================
//= Invoice Listener Primitives
//===========================================================================
//---------------------------------------------------------------------------

public void addInvoiceListener (InvoiceListener p_Listener)
	{
	if ((m_InvoiceListeners == null) || (p_Listener == null)) return;
	
	m_InvoiceListeners.addInvoiceListener (p_Listener);
	}

//---------------------------------------------------------------------------

public void removeInvoiceListener (InvoiceListener p_Listener)
	{
	if ((m_InvoiceListeners == null) || (p_Listener == null)) return;

	m_InvoiceListeners.removeInvoiceListener (p_Listener);
	}

//---------------------------------------------------------------------------

private void notifyInvoiceListeners (InvoiceChangeEvent p_Event)
	{
	if (m_InvoiceListeners == null) return;
	
	m_InvoiceListeners.notifyInvoiceListeners (p_Event);
	}

//---------------------------------------------------------------------------
//===========================================================================
//= Billing Update Topic Subscription
//===========================================================================
//---------------------------------------------------------------------------
/**
 * connects to the Billing Update Topic to publish invoice changes to
 * GECAMed clients online.
 */
//---------------------------------------------------------------------------

private void connectToBillingUpdateTopic ()
	{
	InitialContext			l_Context;
	TopicConnectionFactory	l_Factory;
  
	try {
		l_Context = new InitialContext();
		l_Factory = (TopicConnectionFactory) l_Context.lookup("ConnectionFactory");
		m_TopicConnection = l_Factory.createTopicConnection();
		m_Topic = (Topic) l_Context.lookup(c_BillingUpdateTopic);
		m_TopicSession = m_TopicConnection.createTopicSession(false,TopicSession.AUTO_ACKNOWLEDGE);
		m_TopicConnection.start();
		
		m_TopicConnection.setExceptionListener(new ExceptionListener() {
			public void onException(JMSException e) {
				try {
					m_Logger.warn("JMS Topic Connection lost, closing Connection.", e);
					disconnectFromBillingUpdateTopic();
				} catch (Throwable ee) {
					m_Logger.error("Error Closing JMS Topic Connection", ee);
				}
				
			}
		});

		l_Context.close();

		MainFrame.addShutdownHook("Closing JMS connection to " + c_BillingUpdateTopic, new Thread() 
      		{
			public void run() 
      			{
				disconnectFromBillingUpdateTopic ();
      			}
      		});
  		} 
	catch (Exception p_Exception) 
		{
		m_Logger.log(Level.WARN, "Establishing connection to " + c_BillingUpdateTopic + " failed!", p_Exception);
		}
	}

//---------------------------------------------------------------------------
/**
 * disconnects from the Billing Update Topic
 */
//---------------------------------------------------------------------------

private void disconnectFromBillingUpdateTopic ()
	{
	if (m_TopicSession == null) return;
	
	try {
		m_Logger.info("Closing JMS connection to " + c_BillingUpdateTopic);
		m_TopicSession.close();
		m_TopicConnection.close();
		m_TopicSession    = null;
		m_TopicConnection = null;
		} 
	catch (JMSException p_Exception) 
		{
		m_Logger.log(Level.WARN, "Closing connection to " + c_BillingUpdateTopic + " failed!", p_Exception);
		}
	catch (Throwable p_Exception)
		{
		m_Logger.log(Level.WARN, "Closing connection to " + c_BillingUpdateTopic + " failed!", p_Exception);
		}
	}

//---------------------------------------------------------------------------

public class BillingUpdateMessageListener implements MessageListener
	{
    public BillingUpdateMessageListener()
    	{
    	}

    public void onMessage (Message p_Message)
    	{
    	ObjectMessage			l_Message;
    	InvoiceChangeEvent		l_Event = null;
    	String					l_ClientId;
    	Invoice					l_Invoice;
    	Collection <Integer>	l_InvoiceIDs;
    	
    	// Consider only Messages of the right kind.
    	
    	if (p_Message instanceof ObjectMessage)
    		{
    		l_Message = (ObjectMessage) p_Message;
     		try	{
     			// Make sure we ignore messages that we published ourselves
     			
//     			System.out.println("received Billing Update Message");
     			
     			l_ClientId = l_Message.getStringProperty(c_ClientIdProperty);
     			if (!MainFrame.getClientId().equals(l_ClientId))
     				{
     				l_Event = (InvoiceChangeEvent) l_Message.getObject();
     				l_Event.setOriginator(InvoiceChangeEvent.ORIGIN_REMOTE);
//     				System.out.println("sending to listener Billing Update Message");
     				}
     			} 
    		catch (JMSException p_Exception)
    			{
    			m_Logger.log(Level.ERROR, "Failed to retrieve InvoiceChangeEvent from JMS Message!",p_Exception);
    			}
     		
    		// If we were able to extract the Invoice Change Event from the
    		// message, then we're going to process it.
    		
    		if (l_Event != null)
    			{
    			// First step consists in notifying registered Invoice Change
    			// Listeners about the incoming Event. To make sure that
    			// Listeners will be able to identify the source of the event,
    			// we're going to set the received ObjectMessage as the
    			// Event's source.
    			
    			try {
    				l_Event.setSource (l_Message);
        			notifyInvoiceListeners (l_Event);
        			
        			if (!l_Event.isMultiple())
        				{
       				
        				// Single Invoice Update Event. If changed Invoice matches
        				// current Invoice, then we're going to update current
        				// Invoice right away.
        				
        				l_Invoice = l_Event.getInvoice();	
        				if ((l_Invoice != null) && (l_Invoice.equals(m_CurrentInvoice)))
        					{
        					l_Invoice = fetchLazyDependencies (l_Invoice);
        					setInvoice (l_Invoice);
        					}
        				}
        			else
        				{
        				// Multiple Invoice Update Event. If changed Invoices
        				// include current Invoice, then we're going to update
        				// current Invoice as well.
        				
        				l_InvoiceIDs = l_Event.getInvoiceIDs();
        				if ((l_InvoiceIDs != null) && 
        				    (m_CurrentInvoice != null) && 
        				    (l_InvoiceIDs.contains(m_CurrentInvoice.getId())))
        					{
        					l_Invoice = getInvoiceById (m_CurrentInvoice.getId());
        					l_Invoice = fetchLazyDependencies (l_Invoice);
        					setInvoice (l_Invoice);
        					}
        				}
				} catch (ArrayIndexOutOfBoundsException aob) {
				} catch (Exception e) {
					m_Logger.warn("Error processing Billing Update Message: " + e.getMessage());
				}   			
    			}	
    		}
    	}
	}

//---------------------------------------------------------------------------

public void subscribeToBillingUpdateTopic ()
	{
    TopicSubscriber			l_Receiver;
    
	if (m_TopicSession == null) return;
    
    try {
        l_Receiver = m_TopicSession.createSubscriber (m_Topic);
        l_Receiver.setMessageListener (new BillingUpdateMessageListener());
    	} 
	catch (Exception p_Exception) 
		{
		m_Logger.log(Level.WARN, "Subscribing to " + c_BillingUpdateTopic + " failed!", p_Exception);
		}
	}

//---------------------------------------------------------------------------

public void publishToBillingUpdateTopic (InvoiceChangeEvent p_Event)
	{
	TopicPublisher 		l_Publisher;
	ObjectMessage		l_Message;
	InvoiceChangeEvent	l_Event;
	
	if (m_TopicSession == null) return;
	
	// Strip Event Source from Event to avoid serialization problems.
	
	if (p_Event.isMultiple())
		 l_Event = new InvoiceChangeEvent (null,p_Event.getType(), p_Event.getInvoiceIDs());
	else l_Event = new InvoiceChangeEvent (null,p_Event.getType(), p_Event.getInvoice());
	
	try {
		l_Publisher = m_TopicSession.createPublisher (m_Topic);
        l_Message   = m_TopicSession.createObjectMessage (l_Event);
		l_Message.setStringProperty(c_ClientIdProperty, MainFrame.getClientId());
        l_Publisher.publish (l_Message);
		l_Publisher.close();
		} 
	catch (JMSException p_Exception)       
        {
		m_Logger.log(Level.WARN, "Publishing to " + c_BillingUpdateTopic + " failed!", p_Exception);
        }
	}

//---------------------------------------------------------------------------

public void fireInvoiceChange (int p_Type, Invoice p_Invoice)
	{
	InvoiceChangeEvent 	l_Event;
	
	l_Event = new InvoiceChangeEvent (this,p_Type,p_Invoice);
	l_Event.setOriginator(getCurrentUser().getLogin());
	
	this.notifyInvoiceListeners (l_Event);
	this.publishToBillingUpdateTopic(l_Event);
	}

//---------------------------------------------------------------------------

public void fireMultipleInvoiceChange (int p_Type, Collection <Integer> p_InvoiceIds)
	{
	InvoiceChangeEvent 	l_Event;
	
	l_Event = new InvoiceChangeEvent (this,p_Type,p_InvoiceIds);
	l_Event.setOriginator(getCurrentUser().getLogin());	
	
	this.notifyInvoiceListeners (l_Event);
	this.publishToBillingUpdateTopic (l_Event);
	}

//===========================================================================
//= GUI Primitives
//===========================================================================

//---------------------------------------------------------------------------

public static ImageIcon getButtonIcon (String p_IconName)
	{
	ImageIcon l_Icon; 
	
	if ((Boolean)MainFrame.getInstance().userSettings.getValue(UserSettingsPlugin.SMALL_ICONS))
		{
		l_Icon = new ImageIcon (BillingModule.getIconResource(p_IconName).getImage().getScaledInstance(16,16,Image.SCALE_SMOOTH));
		}
	else l_Icon = BillingModule.getIconResource(p_IconName);

	return l_Icon;
	}

//---------------------------------------------------------------------------
/**
 * Enables or disables a group of GECAMed actions.
 * @param p_Actions specifies the group of actions to be enabled or disabled.
 * @param p_EnableThem specifies whether to enable or disable the specified
 * group of actions.
 */
//---------------------------------------------------------------------------

//private void setActionEnabled (Collection <GECAMedAction> p_Actions, boolean p_EnableThem)
//	{
//	Iterator <GECAMedAction> l_ActionIterator;
//	
//	if (p_Actions == null) return;
//	
//	l_ActionIterator = p_Actions.iterator();
//	while (l_ActionIterator.hasNext()) l_ActionIterator.next().setEnabled(p_EnableThem);
//	}

//---------------------------------------------------------------------------
/**
 * Fetches all available hospitalisation classes from database.
 * @return a collection containing all hospitalisation classes defined
 * in the database.
 */
//---------------------------------------------------------------------------

private Collection <HospitalisationClass> prefetchHospitalisationClasses ()
	{
	HospitalisationClassInterface 		l_HospitalisationInterface;
	Collection <HospitalisationClass>	l_HospitalisationClasses;
	
	l_HospitalisationInterface = null;
	l_HospitalisationClasses   = null;
	
	try {
		l_HospitalisationInterface = (HospitalisationClassInterface) ManagerFactory.getRemote(HospitalisationClassBean.class);
		l_HospitalisationClasses = l_HospitalisationInterface.getAllHospitalisationClasses ();
		} 
	catch (Exception p_Exception) 
		{
		m_Logger.log(Level.ERROR,"Failed to prefetch Hospitalisation classes!",p_Exception);
		}
	
	return l_HospitalisationClasses;
	}

//---------------------------------------------------------------------------
/**
 * Fetches all available physicians from database.
 * @return a collection containing all physicians defined
 * in the database.
 */
//---------------------------------------------------------------------------

private Collection <Insurance> prefetchHealthInsurances ()
	{
	InsuranceInterface 		l_InsuranceInterface;
	Collection <Insurance>	l_Insurances;
	
	l_InsuranceInterface = null;
	l_Insurances		 = null;
	
	try {
		l_InsuranceInterface = (InsuranceInterface) ManagerFactory.getRemote(InsuranceBean.class);
		l_Insurances = l_InsuranceInterface.getAllInsurances();
		} 
	catch (Exception p_Exception) 
		{
		m_Logger.log(Level.ERROR,"Failed to prefetch Health Insurances!",p_Exception);
		}
	
	return l_Insurances;
	}

//---------------------------------------------------------------------------
/**
 * Fetches all available physicians from database.
 * @return a collection containing all physicians defined
 * in the database.
 */
//---------------------------------------------------------------------------

//private Collection <Physician> prefetchPhysicians ()
//	{
//	OfficeManagerInterface 	l_OfficInterface;
//	Collection <Physician>	l_Physicians;
//	
//	l_OfficInterface = null;
//	l_Physicians   = null;
//	
//	try {
//		l_OfficInterface = (OfficeManagerInterface) ManagerFactory.getRemote(OfficeManagerBean.class);
//		l_Physicians = l_OfficInterface.getAllPhysicians();
//		} 
//	catch (Exception p_Exception) 
//		{
//		m_Logger.log(Level.ERROR,"Failed to prefetch Physicians!",p_Exception);
//		}
//	
//	return l_Physicians;
//	}

//---------------------------------------------------------------------------
/**
 * Fetches all available users from database.
 * @return a collection containing all users defined
 * in the database.
 */
//---------------------------------------------------------------------------

private Collection <GecamedUser> prefetchUsers ()
	{
	LoginInterface 				l_LoginInterface;
	Collection <GecamedUser>	l_Users;
	
	l_LoginInterface = null;
	l_Users   		 = null;
	
	try {
		l_LoginInterface = (LoginInterface) ManagerFactory.getRemote(LoginBean.class);
		l_Users = l_LoginInterface.getAllUsers();
		} 
	catch (Exception p_Exception) 
		{
		m_Logger.log(Level.ERROR,"Failed to prefetch Users!",p_Exception);
		}
	
	return l_Users;
	}

//---------------------------------------------------------------------------
/**
* Fetches all available Contacts with medPres Acronym for the Med Pres from database.
* @return a collection containing all users defined
* in the database.
*/
//---------------------------------------------------------------------------

public Collection <Contact> prefetchMedPres ()
	{
	AddressbookInterface		l_AddressInterface;
	Collection <Contact>		l_MedPres;
	
	l_AddressInterface = null;
	l_MedPres   		 = null;
	
	try {
		l_AddressInterface = (AddressbookInterface) ManagerFactory.getRemote(AddressbookManager.class);
		l_MedPres = l_AddressInterface.getMedPres();
		} 
	catch (Exception p_Exception) 
		{
		m_Logger.log(Level.ERROR,"Failed to prefetch MedPres Contacts!",p_Exception);
		}
	
//	if (this.m_MedTransProperties != null) {
//		this.m_MedTransProperties.populateMedTrans();		
//	}
	
	return l_MedPres;
	}



//---------------------------------------------------------------------------
/**
 * Fetches all available settlement (payment) methods from database.
 * @return a collection containing all settlement (payment) methods defined
 * in the database.
 */
//---------------------------------------------------------------------------

private Collection <Settlement> prefetchSettlementMethods ()
	{
	SettlementInterface 	l_SettlementInterface;
	Collection <Settlement>	l_SettlementMethods = null;

	try {
		l_SettlementInterface = (SettlementInterface) ManagerFactory.getRemote(SettlementBean.class);
		l_SettlementMethods = l_SettlementInterface.getAllSettlements();
		} 
	catch (Exception p_Exception) 
		{
		m_Logger.log(Level.ERROR,"Failed to prefetch Settlement Methods!",p_Exception);
		}
		
	return l_SettlementMethods;
	}

//---------------------------------------------------------------------------

private Collection <Suffix> prefetchSuffixes ()
	{
	NomenclatureInterface	l_NomenclatureInterface;
	Collection <Suffix>		l_Suffixes = null;

	try {
		l_NomenclatureInterface = getNomenclatureInterface();
		l_Suffixes = l_NomenclatureInterface.getAllSuffixes ();
		}
	catch (Exception p_Exception) 
		{
		m_Logger.log(Level.ERROR,"Failed to prefetch Suffixes!",p_Exception);
		}
	
	return l_Suffixes;
	}

//---------------------------------------------------------------------------

private Collection <NationalHoliday> prefetchNationalHolidays ()
	{
	NationalHolidayInterface	 l_HolidayInterface;
	Collection <NationalHoliday> l_Holidays = null;

	try {
		l_HolidayInterface = (NationalHolidayInterface) ManagerFactory.getRemote(NationalHolidayBean.class);
		l_Holidays = l_HolidayInterface.getAllNationalHolidays ();
		}
	catch (Exception p_Exception) 
		{
		m_Logger.log(Level.ERROR,"Failed to prefetch National Holidays!",p_Exception);
		}
	
	return l_Holidays;
	}

//---------------------------------------------------------------------------
/**
 * Fetches the closer if available for the specified invoice and initializes
 * the specified invoices' closer property with fetched closer. The closer
 * of an invoice is the gecamed user who put the invoice into closed state.
 * Invoice closer is one of the invoice properties that are not fetched eagerly
 * together with invoice, that's why it has to be fetched explicitely.
 * @param specifies the invoice to fetch the closer of.
 * @return the specified invoice with initialized closer property.
 */
//---------------------------------------------------------------------------

private Invoice fetchCloserForInvoice (Invoice p_Invoice)
	{
	InvoiceInterface l_InvoiceInterface;
	
	if (p_Invoice == null) return p_Invoice;
	
	l_InvoiceInterface 		= getInvoiceInterface();
	
	if (l_InvoiceInterface != null)
		{
		try {
			p_Invoice = l_InvoiceInterface.fetchCloserForInvoice(p_Invoice);
			}
		catch (Exception p_Exception) 
			{
			m_Logger.log(Level.ERROR,"Failed to fetch Closer for Invoice" ,p_Exception);
			}
		}	
	
	return p_Invoice; 
	}

//---------------------------------------------------------------------------

public Invoice getInvoiceById (Integer p_InvoiceId)
	{
	InvoiceInterface 	l_InvoiceInterface;
	Invoice				l_Invoice = null;
	
	l_InvoiceInterface 	= getInvoiceInterface();
	
	if ((l_InvoiceInterface != null) && (p_InvoiceId != null))
		{
		try {
			l_Invoice = l_InvoiceInterface.getInvoiceByID(p_InvoiceId);
			}
		catch (Exception p_Exception) 
			{
			m_Logger.log(Level.ERROR,"Failed to get Invoice with ID " +  p_InvoiceId + "!",p_Exception);
			}
		}	
	
	return l_Invoice; 
	}

//---------------------------------------------------------------------------

public Collection <Invoice> getInvoicesByIds (Collection <Integer> p_InvoiceIds)
	{
	InvoiceInterface 		l_InvoiceInterface;
	HibernateCondition		l_Condition;
	WhereClause				l_Clause;
	Collection <Invoice>	l_Invoices;
	
	l_Invoices = new LinkedHashSet <Invoice> ();
	
	if ((p_InvoiceIds == null) || (p_InvoiceIds.isEmpty())) return l_Invoices;
	
	l_InvoiceInterface 	= getInvoiceInterface();
	
	if (l_InvoiceInterface != null)
		{
		try	{
			l_Condition   = new HibernateCondition ("id",
					    							HibernateOperator.c_InOperator,
					    							new HibernateList (p_InvoiceIds));
			
			l_Clause = new WhereClause ();
			l_Clause.addCondition (l_Condition);
			l_Invoices = l_InvoiceInterface.getInvoicesByWhereClause(l_Clause);
			}
		catch (Exception p_Exception) 
			{
			m_Logger.log(Level.ERROR,"Failed to get Invoices for specified IDs!",p_Exception);
			}
		}
	
	return l_Invoices;
	}

//---------------------------------------------------------------------------

private Invoice getInvoiceByAccessionNumber (String p_AccessionNumber)
	{
	InvoiceInterface 	l_InvoiceInterface;
	Invoice				l_Invoice = null;
	
	l_InvoiceInterface 	= getInvoiceInterface();
	
	if (l_InvoiceInterface != null)
		{
		try {
			l_Invoice = l_InvoiceInterface.getInvoiceByAccessionNumber(p_AccessionNumber);
			}
		catch (Exception p_Exception) 
			{
			m_Logger.log(Level.ERROR,"Failed to get Invoice by Accession Number!" ,p_Exception);
			}
		}	
	
	return l_Invoice; 
	}

//---------------------------------------------------------------------------

public Invoice fetchLazyDependencies (Invoice p_Invoice)
	{
	InvoiceInterface		l_InvoiceInterface = null;
	Invoice					l_Invoice		   = null;
	
	l_InvoiceInterface = getInvoiceInterface ();
	
	if ((p_Invoice == null) || (l_InvoiceInterface == null)) return null;

	if (p_Invoice.isPersistent() == false) return p_Invoice;
	
	try {
		l_Invoice = l_InvoiceInterface.fetchLazyDependencies (p_Invoice, m_Dependencies);
		}
	catch (Exception p_Exception) 
		{
		m_Logger.log(Level.ERROR,"Failed to fetch lazy Dependencies for invoice with ID " + p_Invoice.getId() ,p_Exception);
		}
	
	return l_Invoice;
	}

//---------------------------------------------------------------------------

private  Invoice verifyInvoicedActs (Invoice p_Invoice)
	{
	InvoiceInterface 	l_InvoiceInterface = null;
	Set <Act>			l_InvoiceActs	   = null;
	
	if ((p_Invoice == null) || (!p_Invoice.isPersistent())) return p_Invoice;
	
	l_InvoiceInterface = this.getInvoiceInterface();
	if (l_InvoiceInterface == null) return p_Invoice;
	
	try	{
		l_InvoiceActs = p_Invoice.getActs();
		l_InvoiceActs = l_InvoiceInterface.verifyActs (l_InvoiceActs);
		p_Invoice.setActs (l_InvoiceActs);
		}
	catch (Exception p_Exception) 
		{
		m_Logger.log(Level.ERROR,"Failed to verify acts of invoice with ID " + p_Invoice.getId() + "!",p_Exception);
		}
	
	return p_Invoice;
	}

//---------------------------------------------------------------------------

public Collection <Ledger> getLedgersForInvoice (Invoice p_Invoice)
	{
	AccountingInterface		l_AccountingInterface = null;
	Collection <Ledger>		l_Ledgers			= null;
	
	l_AccountingInterface = getAccountingInterface ();
	
	if ((p_Invoice == null) || (l_AccountingInterface == null)) return null;

	if (p_Invoice.isPersistent() == false) return null;
	
	try {
		l_Ledgers = l_AccountingInterface.getLedgersByInvoice(p_Invoice);
		}
	catch (Exception p_Exception) 
		{
		m_Logger.log(Level.ERROR,"Failed to Legers for Invoice with ID " + p_Invoice.getId() ,p_Exception);
		}
	
	return l_Ledgers;
	}

//---------------------------------------------------------------------------

private Passage getPassageByID (Integer p_PassageId)
	{
	HospitalizedInterface l_HospitalizedInterface;
	Passage				  l_Passage = null;
	
	l_HospitalizedInterface = this.getHospitalizedInterface();
	if (l_HospitalizedInterface != null)
		{
		try	{
			l_Passage = l_HospitalizedInterface.getPassageById(p_PassageId);
			}
		catch (NoResultException p_Exception)
			{
			l_Passage = null;
			}
		catch (Exception p_Exception)
			{
			l_Passage = null;
			m_Logger.log(Level.ERROR,"Failed to get Passage" ,p_Exception);		
			}
		}
		
	return l_Passage;
	}

//---------------------------------------------------------------------------

private void processPassageVerified (Integer p_PassageId)
	{
	Passage		l_Passage = null;
	Invoice		l_Invoice;
		
	if (!(Boolean)getUserSetting (BillingUserSettings.c_AutoVerificationSetting)) return;
	
	l_Passage = this.getPassageByID (p_PassageId);
	if (l_Passage != null)
		{
		l_Invoice = this.getInvoiceByAccessionNumber (l_Passage.getAccessionNumber());
		l_Invoice = this.fetchLazyDependencies (l_Invoice);	
		l_Invoice = this.verifyInvoicedActs	   (l_Invoice);
		
		if (l_Invoice.allActsVerified()) 
			 this.verifyInvoice (l_Invoice);
		else this.disproveInvoice(l_Invoice);
		}
	}

//---------------------------------------------------------------------------

//private void processPassageChange (Integer p_PassageId)
//	{
//	Passage				  l_Passage = null;
//	
//	l_Passage = this.getPassageByID(p_PassageId);
//		
//	if (l_Passage != null)
//		{
//		if (l_Passage.getRX() == false) this.withdrawPassage (l_Passage);
//								   else this.restorePassage  (l_Passage);
//		}
//	}

//---------------------------------------------------------------------------

private void processPassageOpen (Integer p_PassageId)
	{
	Passage		l_Passage = null;
	Invoice		l_Invoice;
	
	l_Passage = this.getPassageByID(p_PassageId);
		
	if (l_Passage != null)
		{
		l_Invoice = this.getInvoiceByAccessionNumber(l_Passage.getAccessionNumber());
		if (l_Invoice != null)
			{
			l_Invoice = this.fetchLazyDependencies(l_Invoice);
			this.reset();
			this.editInvoice(l_Invoice);
			if (!MainFrame.getInstance().currentModule.equals(this))
				MainFrame.getInstance().selectModule(BillingModule.MODULE_NAME);
			}
		}
	}

//---------------------------------------------------------------------------

//private void withdrawPassage (Passage p_Passage)
//	{
//	HospitalizedInterface l_HospitalizedInterface;
//	Invoice				  l_Invoice;
//	Act					  l_Act;
//	InvoiceChangeEvent	  l_Event;
//	
//	String []			  l_Filler;
//	
//	if (p_Passage == null) return;
//	
//	l_HospitalizedInterface = this.getHospitalizedInterface();
//	if (l_HospitalizedInterface != null)
//		{
//		try	{			
//			l_Invoice = l_HospitalizedInterface.getInvoiceToWithdrawActFrom(p_Passage);
//			if (l_Invoice == null) return;
//			
//			if (!userHasPermissionForInvoice (l_Invoice, BillingModule.c_editStem,true)) return;
//			
//			if (l_Invoice.isLocked())
//				{
//				l_Filler = new String [1];
//				l_Filler [0] = l_Invoice.formatInvoiceNumber(Invoice.c_LongFormat);
//				
//				notifyUser ("BillingModule.CanNotWithdrawFromLockedInvoiceTitle",
//					    	"BillingModule.CanNotWithdrawFromLockedInvoiceMessage",
//					    	l_Filler);
//				return;
//				}
//		
//			l_Act = l_HospitalizedInterface.getActToWithdraw (p_Passage);
//			l_Invoice = l_HospitalizedInterface.withdrawAct(l_Act, l_Invoice);
//			
//			l_Event = new InvoiceChangeEvent (this,InvoiceChangeEvent.c_InvoiceUpdated,l_Invoice);
//			this.notifyInvoiceListeners(l_Event);
//			}
//		catch (NoResultException p_Exception)
//			{
//			
//			}
//		catch (Exception p_Exception)
//			{
//			m_Logger.log(Level.ERROR,"Failed to withdraw Passage" ,p_Exception());		
//			}
//		}
//	}

//---------------------------------------------------------------------------

//private void restorePassage (Passage p_Passage)
//	{
//	HospitalizedInterface l_HospitalizedInterface;
//	Invoice				  l_Invoice;
//	Act					  l_Act;
//	InvoiceChangeEvent	  l_Event;
//	
//	String []			  l_Filler;
//	
//	if (p_Passage == null) return;
//	
//	l_HospitalizedInterface = this.getHospitalizedInterface();
//	if (l_HospitalizedInterface != null)
//		{
//		try	{			
//			l_Invoice = l_HospitalizedInterface.getInvoiceToRestoreActTo(p_Passage);
//			if (l_Invoice == null) 
//				{
//				notifyUser ("BillingModule.RestoreToNewInvoiceTitle",
//					    	"BillingModule.RestoreToNewInvoiceMessage",
//					    	null);
//
//				l_Invoice = l_HospitalizedInterface.newInvoiceForPassage(p_Passage);
//				}
//			
//			if (!userHasPermissionForInvoice (l_Invoice, BillingModule.c_editStem,true)) return;
//
//			if (l_Invoice.isLocked())
//				{
//				l_Filler = new String [1];
//				l_Filler [0] = l_Invoice.formatInvoiceNumber(Invoice.c_LongFormat);
//				
//				notifyUser ("BillingModule.CanNotRestoreToLockedInvoiceTitle",
//						    "BillingModule.CanNotRestoreToLockedInvoiceMessage",
//						    l_Filler);
//				
//				l_Invoice = l_HospitalizedInterface.newInvoiceForPassage(p_Passage);
//				return;
//				}
//		
//			l_Act = l_HospitalizedInterface.getActToRestore (p_Passage);
//			l_Invoice = l_HospitalizedInterface.restoreAct(l_Act, l_Invoice);
//			
//			l_Event = new InvoiceChangeEvent (this,InvoiceChangeEvent.c_InvoiceUpdated,l_Invoice);
//			this.notifyInvoiceListeners(l_Event);
//			}
//		catch (NoResultException p_Exception)
//			{
//			
//			}
//		catch (Exception p_Exception)
//			{
//			m_Logger.log(Level.ERROR,"Failed to restore Passage" ,p_Exception());		
//			}
//		}
//	}

//---------------------------------------------------------------------------

private Patient getPatientBySocalSecurityNumber (String p_SocalSecurityNumber)
	{
	PatientAdminInterface l_PatientInterface;
	Patient				  l_Patient = null;

	if (p_SocalSecurityNumber == null) return null;
	
	l_PatientInterface = this.getPatientInterface();
	if (l_PatientInterface != null)
		{
		try	{
			l_Patient = l_PatientInterface.getPatientBySocialSecurityNumber(p_SocalSecurityNumber);
			}
		catch (NoResultException p_Exception)
			{
			}
		catch (Exception p_Exception)
			{
			m_Logger.log(Level.ERROR,"Failed to get Patient by SSN" ,p_Exception);		
			}
		}
	
	return l_Patient;
	}

//---------------------------------------------------------------------------

private Patient getPatientByRecordNumber (Integer p_RecordNumber)
	{
	PatientAdminInterface l_PatientInterface;
	Patient				  l_Patient = null;

	if (p_RecordNumber == null) return null;
	
	l_PatientInterface = this.getPatientInterface();
	if (l_PatientInterface != null)
		{
		try	{			
			l_Patient = l_PatientInterface.getPatient(p_RecordNumber);
			}
		catch (NoResultException p_Exception)
			{			
			}
		catch (Exception p_Exception)
			{
			m_Logger.log(Level.ERROR,"Failed to get Patient by Record Number" ,p_Exception);		
			}
		}
	
	return l_Patient;
	}

//---------------------------------------------------------------------------

private Invoice getInvoiceByInvoiceNumber (Integer p_InvoiceNumber)
	{
	InvoiceInterface	l_InvoiceInterface;
	Invoice				l_Invoice = null;
	
	if (p_InvoiceNumber == null) return null;
	
	l_InvoiceInterface = this.getInvoiceInterface();
	if (l_InvoiceInterface != null)
		{
		try	{			
			l_Invoice = l_InvoiceInterface.getInvoiceByID(p_InvoiceNumber);
			
			l_Invoice = l_InvoiceInterface.fetchLazyDependencies (l_Invoice, m_Dependencies);
			}
		catch (NoResultException p_Exception)
			{			
			}
		catch (Exception p_Exception)
			{
			m_Logger.log(Level.ERROR,"Failed to get Invoice by Invoice Number!" ,p_Exception);		
			}
		}
	
	return l_Invoice;
	}

//---------------------------------------------------------------------------
/**
 * sets the specified invoice as the current invoice of the BillingModule.
 * Setting the current invoice entails the following cours of actions:
 * 1.) If specified invoice was null, the method disables the Invoice Editor
 * and Memo Tab and returns right away. In case the invoice was not null,
 * both Tabs will be enabled.
 * 2.) Depending on whether the specified invoice is persistent or not,
 * the module header will either display the full Invoice number or a message
 * saying that specified invoice is new.
 * 3.) If specified invoice has its patient property set (which should be 
 * the case), the Patient Summary Panel will be initialized and the modules
 * current patient member will be set.
 * 4.) Next step consists in passing the specified invoice to the Invoice
 * Properties, Accident Properties, Hospitalisation Properties and invoice
 * status panels.
 * 5.) Last but not least, if either the Invoice Editor or the Memo Tab
 * are currently showing, the currently showing tab will also receive the
 * specified invoice.
 * @param p_Invoice specifies the invoice to be set as current module invoice. 
 */
//---------------------------------------------------------------------------

public void setInvoice (Invoice p_Invoice)
	{	
	String[] l_Filler;
	
//	System.out.println("setInvoice: " + p_Invoice);
	
	if (p_Invoice == null && m_WasModified)
		return;
	
	m_CurrentInvoice = p_Invoice;
	
//	System.out.println("Global:     " + m_CurrentInvoice);
	
	
	//======================================================================
	//= Case 1: There's no current invoice, i.e. specified invoice was null.
	//=         In that case, we will simply disable the Edit and Memo Tab.
	//======================================================================
	
	if (m_CurrentInvoice == null)
		{
		this.titlePanel.setTopic(Translatrix.getTranslationString("Billing"));
		
		m_MainPanel.setEnabledAt (c_EditorTab,false);
		m_MainPanel.setEnabledAt (c_MemoTab,false);

		m_InvoiceProperties.reset();
		m_AccidentProperties.reset();
		m_HospitalisationProperties.reset();
//		m_MedTransProperties.reset();
		m_InvoiceStatusPanel.reset();
		m_EditorPanel.reset();
		m_MemoPanel.reset();
		return;
		}
		
	//======================================================================
	//= Case 2: An invoice was specified.
	//======================================================================
		
	if (m_CurrentInvoice.isPersistent())
		{
		l_Filler = new String [1];
		l_Filler[0] = m_CurrentInvoice.formatInvoiceNumber(false, true);
		
		this.titlePanel.setTopic(Translatrix.getTranslationString("BillingModule.Invoice",l_Filler));
		}
	else
		{
		this.titlePanel.setTopic(Translatrix.getTranslationString("Billing") + ": " +
							     Translatrix.getTranslationString("BillingModule.NewInvoice"));
		}
	this.titlePanel.repaint();
		
	m_MainPanel.setEnabledAt(c_EditorTab,true);
	m_MainPanel.setEnabledAt(c_MemoTab,true);
			
	if (m_CurrentInvoice.getPatient() != null)
		{
		m_PatientSummaryPanel.setPatient 	(m_CurrentInvoice.getPatient());
		m_CurrentPatient = m_CurrentInvoice.getPatient();
		}
	
	this.reflectInvoiceStatus (m_CurrentInvoice);
	
	m_EditorPanel.setInvoice	(m_CurrentInvoice);
	if (m_MemoPanel.isShowing()) 	m_MemoPanel.setInvoice	(m_CurrentInvoice);
	if (!m_InvoicePanel.isShowing())m_InvoicePanel.setInvoice(m_CurrentInvoice);
} 

//---------------------------------------------------------------------------

private void reflectInvoiceStatus (Invoice p_Invoice)
	{
	m_InvoiceProperties.setInvoice  	     (p_Invoice);
	m_AccidentProperties.setInvoice  		 (p_Invoice);
	m_HospitalisationProperties.setInvoice   (p_Invoice);
//	m_MedTransProperties.setInvoice   		 (p_Invoice);
	m_InvoiceStatusPanel.setInvoice 		 (p_Invoice);		
		
	if ((p_Invoice.getNumberOfMemos() != null) && (p_Invoice.getNumberOfMemos() > 0))
		 m_MainPanel.setIconAt(c_MemoTab, m_MemoBlinking);
	else m_MainPanel.setIconAt(c_MemoTab, m_MemoStatic);
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* Class Body                                                              *
//***************************************************************************
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------

public void setAccident (String p_AccidentNumber, Date p_AccidentDate)
	{
	m_AccidentProperties.setAccident(true);
	m_AccidentProperties.setAccidentNumber (p_AccidentNumber);
	m_AccidentProperties.setAccidentDate (p_AccidentDate);
	m_AccidentProperties.revalidate();
	}

//---------------------------------------------------------------------------

public void showTab (int p_Tab)
{
//	GECAMedTab l_CurrentTab;
	
	m_MainPanel.setSelectedIndex(p_Tab);
//	l_CurrentTab = (GECAMedTab) m_MainPanel.getSelectedComponent();
//	l_CurrentTab.preparetoShowup();
}

//---------------------------------------------------------------------------
/**
 * The preparetoShowup method (inherited from GECAMedModule) will be called
 * before the BillingModule will show. Depending on the current state of the
 * BillingModule, the following course of actions entails:
 * 1.) The module queries the application for the currently open patient.
 * If none is open, then nothing will be done.
 * 2.) If a patient is currently open, the module opens the invoice listing
 * tab by default.
 * 3.) Next, Invoice, Accident and Hospitalisation Properties Panels are
 * disabled. Disabling them is done because they're only supposed to show
 * data while invoice listing tab is open. 
 * 4.) If Invoice Listing isn't currently in search mode, then current patient
 * will be passed to invoice listing panel. Doing so will update the listing
 * by showing all the invoices related to the patient. Furthermore, we'll
 * select the first invoice by default. If Invoice Listing is currently in search 
 * mode, then we'll do nothing.
 */
//---------------------------------------------------------------------------

public void preparetoShowup()
	{
	Patient l_Patient;
	
	l_Patient = getCurrentPatient();
	
	if (	(l_Patient != null)
		 && l_Patient.equals (m_CurrentPatient)) return;
		
	m_CurrentPatient = l_Patient;
	if (m_CurrentPatient != null)
		{
		m_PatientSummaryPanel.setPatient (m_CurrentPatient);

		m_MainPanel.setSelectedIndex (c_InvoiceTab);
		
		m_InvoiceProperties.setEnabled(false);
		m_AccidentProperties.setEnabled(false);
		m_HospitalisationProperties.setEnabled(false);
//		m_MedTransProperties.setEnabled(false);
		
//		this.setInvoice (null);

//		m_InvoiceStatusPanel.reset();
//		m_EditorPanel.reset();
//		m_MemoPanel.reset();
		
		if (m_InvoicePanel.isInSearchMode()==false)
			{
			m_InvoicePanel.setPatient(m_CurrentPatient);
			m_InvoicePanel.selectFirstInvoice();
			}
			
		this.setInvoice (m_InvoicePanel.getSelectedInvoice());
		}
	}

//---------------------------------------------------------------------------

@Override
public void afterShowup() 
	{
	}

//---------------------------------------------------------------------------
/**
 * The preparetoShowup method (inherited from GECAMedModule) will be called
 * just before the BillingModule will be hidden and another module will be
 * shown. If current patient of billing module differs from current patient
 * of application, then we'll set modules' patient as current patient of
 * application.
 */
//---------------------------------------------------------------------------

public void preparetoHide ()
	{
//	GECAMedTab	l_CurrentTab;
	Patient 	l_Patient;
	
//	l_Patient = getCurrentPatient ();
//	
//	if ((m_CurrentPatient != null) && (!m_CurrentPatient.equals(l_Patient)))
//		{
//		setCurrentPatient (m_CurrentPatient);
//		}

	l_Patient = m_PatientSummaryPanel.getPatient();

	if (l_Patient != null)
		{
		m_CurrentPatient = l_Patient;
		setCurrentPatient (m_CurrentPatient);
		}
	
//	l_CurrentTab = (GECAMedTab) m_MainPanel.getSelectedComponent();
//	l_CurrentTab.preparetoHide();
	}

//---------------------------------------------------------------------------
/**
 * Returns the billing modules' current invoice. Billing modules' current
 * invoice is the invoice that was last set via the setInvoice method.
 * @return billing modules' current invoice if set, null otherwise
 * @see setInvoice
 */
//---------------------------------------------------------------------------

public Invoice getCurrentInvoice ()
	{
	return m_CurrentInvoice;
	}

//---------------------------------------------------------------------------

public MemoEditorPanel getMemoPanel ()
{
	return m_MemoPanel;
}

//---------------------------------------------------------------------------

public InvoicePropertiesPanel getInvoiceProperties()
	{
	return m_InvoiceProperties;
	}

//---------------------------------------------------------------------------

public AccidentPropertiesPanel getAccidentProperties()
	{
	return m_AccidentProperties;
	}

//---------------------------------------------------------------------------

public HospitalisationPanel getHospitalisationProperties()
	{
	return m_HospitalisationProperties;
	}

//---------------------------------------------------------------------------

//public MedTransPanel getMedTransProperties()
//{
//return m_MedTransProperties;
//}

//---------------------------------------------------------------------------

public PatientSummaryPanel getPatientSummaryPanel()
	{
	return m_PatientSummaryPanel;
	}

//---------------------------------------------------------------------------

public Collection <HospitalisationClass> getHospitalisationClasses ()
	{
		return m_HospitalisationClasses;
	}

//---------------------------------------------------------------------------

//public Collection <Physician> getPhysicians ()
//	{
//	return m_Physicians;
//	}

//---------------------------------------------------------------------------

public Collection <Insurance> getHealthInsurances ()
	{
	return m_HealthInsurances;
	}


//---------------------------------------------------------------------------

//public Collection <Insurance> getPrimaryHealthInsurances ()
//	{
//	Collection <Insurance>	l_PrimaryInsurances;
//	Iterator <Insurance> 	l_InsuranceIterator;
//	Insurance			 	l_Insurance;
//	
//	if (m_HealthInsurances == null) return null;
//	
//	l_PrimaryInsurances = new LinkedHashSet <Insurance> ();
//	
//	l_InsuranceIterator = m_HealthInsurances.iterator();
//	while (l_InsuranceIterator.hasNext())
//		{
//		l_Insurance = l_InsuranceIterator.next();
//		
//		if (l_Insurance.getPrimary()) l_PrimaryInsurances.add (l_Insurance);
//		}
//	
//	return l_PrimaryInsurances;
//	}

//---------------------------------------------------------------------------

public Collection <Insurance> getThirdPartyPayers ()
	{
	Collection <Insurance>	l_ThirdPartyPayers;
	Iterator <Insurance> 	l_InsuranceIterator;
	Insurance			 	l_Insurance;
	
	if (m_HealthInsurances == null) return null;
	
	l_ThirdPartyPayers = new LinkedHashSet <Insurance> ();
	
	l_InsuranceIterator = m_HealthInsurances.iterator();
	while (l_InsuranceIterator.hasNext())
		{
		l_Insurance = l_InsuranceIterator.next();
		
		if (l_Insurance.getThirdParty()) l_ThirdPartyPayers.add (l_Insurance);
		}
	
	return l_ThirdPartyPayers;
	}

//---------------------------------------------------------------------------

public Collection <Settlement> getSettlementMethods ()
	{
	return m_SettlementMethods;
	}

//---------------------------------------------------------------------------

public Collection <Suffix> getSuffixes ()
	{
	return m_Suffixes;
	}

//---------------------------------------------------------------------------

public Collection <NationalHoliday> getNationalHolidays ()
	{
	return m_NationalHolidays;
	}

//---------------------------------------------------------------------------

public Collection <GecamedUser> getUsers ()
	{
	return m_Users;
	}

//---------------------------------------------------------------------------

public void reloadInvoices ()
	{
	Patient l_Patient;
	
	if (m_CurrentPatient != null)
		{
		if (m_InvoicePanel.isInSearchMode()) m_InvoicePanel.resetSearch();
		l_Patient = m_CurrentPatient;
		m_CurrentPatient = null;
		this.patientChanged(l_Patient);
		}
	}

//---------------------------------------------------------------------------

	public void editInvoice(Invoice p_Invoice) {
		GECAMedTab l_CurrentTab;

		if (p_Invoice == null)
			return;

		this.setInvoice(p_Invoice);
		m_MainPanel.setSelectedIndex(c_EditorTab);
		l_CurrentTab = (GECAMedTab) m_MainPanel.getSelectedComponent();
		l_CurrentTab.preparetoShowup();
	}

//---------------------------------------------------------------------------

public Invoice setModifier (Invoice p_Invoice)
	{
	if (p_Invoice == null) return null;
	
	p_Invoice.setModifier(BillingModule.getCurrentUser());
	p_Invoice.setModificationDate(new Date ());
	
	return p_Invoice;
	}

//---------------------------------------------------------------------------

public void setModified (boolean p_WasModified)
	{
	Color	l_TitleColor;
		
	m_WasModified = p_WasModified;
	
	if (m_SuperUserMode) return;
		
	l_TitleColor = (m_WasModified)?GECAMedColors.c_ModifiedTitleBackground:m_ModulePlainModeColor;
	this.titlePanel.setColor(l_TitleColor);	
	
	Invoice inv = getInvoiceEditorPanel().getEditedInvoice();
	if (inv != null) {
		inv.monetize();
		m_InvoiceStatusPanel.setInvoice (inv);		
	}
	
	}

//---------------------------------------------------------------------------
public boolean isModified()
{
	return m_WasModified;
}

//---------------------------------------------------------------------------

//public Invoice registerTransaction (Invoice 		p_Invoice,
//							  		Settlement 		p_Method,
//							  		Date	  		p_Date,
//							  		Double	  		p_Credit,
//							  		Double	  		p_Debit)
//	{
//	InvoiceInterface	l_InvoiceInterface;
//	AccountingInterface	l_AccountingInterface;
//	Ledger				l_Transaction;
//	double				l_Credit;
//	double				l_Debit;
//	
//	if (p_Invoice == null) return p_Invoice; 
//	
//	l_Credit = (p_Credit != null)?p_Credit.doubleValue():0d;
//	l_Debit  = (p_Debit  != null)?p_Debit.doubleValue():0d;
//
//	if ((l_Credit == 0) && (l_Debit == 0))
//		{
//		m_Logger.warn("Attempt to register transaction with both debit and credit set to 0 for invoice with ID " + p_Invoice.getId());
//		}
//	
//	l_AccountingInterface 	= getAccountingInterface();
//	
//	if ( (l_AccountingInterface != null))
//		{
//		try {
//			p_Invoice.monetize();
//			
//			p_Invoice = saveInvoice (p_Invoice);
//			
//			l_Transaction = new Ledger ();
//			l_Transaction.setInvoice(p_Invoice);
//			l_Transaction.setSettlement(p_Method);
//			l_Transaction.setSettlementDate(p_Date);
//			l_Transaction.setCashier(BillingModule.getCurrentUser());
//			l_Transaction.setCredit(p_Credit);
//			l_Transaction.setDebit (p_Debit);
//			
//			l_Transaction = l_AccountingInterface.saveLedger(l_Transaction);
//			}
//		catch (Exception p_Exception) 
//			{
//			m_Logger.log(Level.ERROR, "Error setteling invoice " + p_Invoice.getId(),p_Exception);
//			}
//		}
//	
//	return p_Invoice;
//	}

//---------------------------------------------------------------------------

public static boolean copyRequired (Invoice p_Invoice)
	{
	int		l_Action;

	if (p_Invoice == null) return false;
	
	l_Action = InvoiceWorkflow.previewStateChange (p_Invoice, InvoiceWorkflow.c_PrintAction);
	return copyRequired (p_Invoice,l_Action);
	}

//---------------------------------------------------------------------------

public static boolean copyRequired (Invoice p_Invoice, int p_Action)
	{
	boolean	l_CopyRequired;
	
	if (p_Invoice == null) return false;

	l_CopyRequired = p_Invoice.alreadyPrinted() 
	//		&& (p_Action != InvoiceWorkflow.c_DoPrintOriginal)
	;
	
	return l_CopyRequired;
	}

//---------------------------------------------------------------------------

public Invoice printInvoice (Invoice p_Invoice, boolean p_PrintCopy)
	{
	InvoicePrinter l_InvoicePrinter;
	HashMap<String, Object> l_Parameter;
	
	l_InvoicePrinter = new InvoicePrinter();
	p_Invoice.monetize();
	
	l_Parameter = PrintParameterFetcher.createDefaultPrintParameter(p_Invoice);
	
	if (l_InvoicePrinter.printInvoice (p_Invoice, p_PrintCopy, true, l_Parameter))
		{
//		if (!p_Invoice.alreadyPrinted()) p_Invoice.setPrintDate (new Date ());
		p_Invoice = this.saveInvoice (p_Invoice);
		}
		
	l_InvoicePrinter.close ();
	return p_Invoice;
	}

//---------------------------------------------------------------------------


public Invoice settleInvoice (Invoice p_Invoice, Date p_SettlementDate, boolean p_PrintSettledInvoice)
	{
	SettlementDialog	l_SettlementDialog;
	int					l_Action;
	boolean				l_PrintCopy	   = false;
	
	if (p_Invoice == null) return null;
	
//	if (userHasPermission (BillingModule.c_BillingModule,BillingModule.c_settleInvoices))
	if (userHasPermissionForInvoice(p_Invoice, BillingModule.c_settleStem, true))		
		{		
		 m_SettlementMethods		 = this.prefetchSettlementMethods();
		if ((Boolean)BillingModule.getSetting(BillingAdminSettings.c_SplitBillingSetting))
			 l_SettlementDialog = new SettlementDialog(p_Invoice.getPhysician(),this.getSettlementMethods());
		else l_SettlementDialog = new SettlementDialog(null,this.getSettlementMethods());
		
		l_SettlementDialog.pack();
		l_SettlementDialog.setInvoice(p_Invoice);
		l_SettlementDialog.setSettlementDate(p_SettlementDate);
		l_SettlementDialog.setPrintSettledInvoice(p_PrintSettledInvoice);
		MainFrame.showDialogCentered (l_SettlementDialog);
		
		//====================================================================
		//= Wait for user to finish dialog
		//====================================================================
		
		if (!l_SettlementDialog.invoiceSettled()) return null;
		
		p_Invoice = l_SettlementDialog.getInvoice();
		p_SettlementDate = p_Invoice.getSettlementDate();
		
		//====================================================================
		//= Before actually settling the invoice, we check whether the user
		//= decided to print a copy of the settled invoice. When printing the
		//= invoice though, it is important to check whether it has already
		//= been printed before or not. If the invoice at hand has already
		//= been printed, we have explicitely mark the new copy as such.
		//====================================================================

		if (l_SettlementDialog.getPrintSettledInvoice() == true)
			{
			l_PrintCopy = copyRequired (p_Invoice);
			}
			
		//====================================================================
		//= Start with the actual settlement process
		//====================================================================

		l_Action = InvoiceWorkflow.changeInvoiceState(p_Invoice,InvoiceWorkflow.c_PayAction);
		if (l_Action == InvoiceWorkflow.c_DoPay)
			{		
//			this.registerTransaction (p_Invoice, 
//									  p_Invoice.getSettlement(), 
//									  p_SettlementDate, 
//									  l_SettlementDialog.getPaidAmount(), 
//									  l_SettlementDialog.getReturnedAmount());
			
			// TODO LEDGER -> moved to Beanmethod
			try {
				p_Invoice = BillingModule.getInstance().getAccountingInterface().registerTransaction(
						p_Invoice, 
						l_SettlementDialog.getSettlement(), 
						l_SettlementDialog.getSettlementDate(), 
						l_SettlementDialog.getPaidAmount(), 
						l_SettlementDialog.getReturnedAmount(),
						l_SettlementDialog.getDeduction(),
						false);
							
				GECAMedLog.user ("Billing","SETTLE Invoice", "Settled Invoice No: "+ p_Invoice + " via " + l_SettlementDialog.getSettlement() + " Invoice Balance:" + p_Invoice.getBalance() + " Payed:"+l_SettlementDialog.getPaidAmount()+ " Returned:"+l_SettlementDialog.getReturnedAmount()+ " Deduction:"+l_SettlementDialog.getDeduction());
				
			} catch (Exception e) {
				m_Logger.error("Error settling Invoice: " + p_Invoice , e);
			}
			
			fireInvoiceChange (InvoiceChangeEvent.c_InvoiceStatusChanged, p_Invoice);
			
			
			
			if (l_SettlementDialog.getPrintSettledInvoice() == true)
				{
				this.printInvoice (p_Invoice, l_PrintCopy);
				}			
			}
		}
	
	return p_Invoice;
	}

//---------------------------------------------------------------------------

public Invoice revokeInvoice (Invoice p_Invoice, Date p_RevokeDate, boolean p_PrintRevokedInvoice) {
	RevokeDialog		l_RevokeDialog;
	int					l_Action;
	boolean				l_PrintCopy	   = false;
	
	if (p_Invoice == null) return null;

	if (userHasPermissionForInvoice(p_Invoice, BillingModule.c_revokeStem,true)) {		
		l_RevokeDialog = new RevokeDialog();
		l_RevokeDialog.pack();
		l_RevokeDialog.setInvoice(p_Invoice);
		l_RevokeDialog.setPrintRevokedInvoice(p_PrintRevokedInvoice);
		MainFrame.showDialogCentered (l_RevokeDialog);
		
		//====================================================================
		//= Wait for user to finish dialog
		//====================================================================
	
		if (!l_RevokeDialog.invoiceRevoked()) return p_Invoice;
		p_Invoice = l_RevokeDialog.getInvoice();
			
		l_Action = InvoiceWorkflow.changeInvoiceState(p_Invoice,InvoiceWorkflow.c_RevokeAction);
		
		if (l_Action == InvoiceWorkflow.c_DoRevoke) {		

			try {
				p_Invoice = BillingModule.getInstance().getAccountingInterface().registerTransaction(
						p_Invoice, 
						l_RevokeDialog.getRevokedSettlement(), 
						p_RevokeDate, 
						c_Zero, 
						l_RevokeDialog.getRevokedAmount(),
						c_Zero,
						true);
				GECAMedLog.user ("Billing","REVOKE Invoice","Revoked " + l_RevokeDialog.getRevokedAmount() + "€ from Invoice: " + p_Invoice.getId());

			} catch (Exception e) {
				m_Logger.error("Error revoking Invoice: " + p_Invoice , e);
			}
			
			fireInvoiceChange (InvoiceChangeEvent.c_InvoiceStatusChanged, p_Invoice);
			
			
			if (l_RevokeDialog.getPrintRevokedInvoice() == true) {
				l_PrintCopy = copyRequired (p_Invoice);
				l_Action = InvoiceWorkflow.changeInvoiceState (p_Invoice, InvoiceWorkflow.c_PrintAction);
								
				if (l_Action == InvoiceWorkflow.c_DoPrint) {
					this.printInvoice(p_Invoice,l_PrintCopy);
				}
			}			
		}
	}

	return p_Invoice;
}

//---------------------------------------------------------------------------

public Invoice verifyInvoice (Invoice p_Invoice)
	{
	InvoiceInterface	l_InvoiceInterface;
	int					l_Action;

	if (p_Invoice == null) return null;

//	if (userHasPermission (BillingModule.c_BillingModule,BillingModule.c_verifyInvoices))
	if (userHasPermissionForInvoice (p_Invoice, BillingModule.c_verifyStem, true))		
		{
		l_Action = InvoiceWorkflow.changeInvoiceState (p_Invoice,InvoiceWorkflow.c_VerifyAction);
		if (l_Action == InvoiceWorkflow.c_DoVerify)
			{
			l_InvoiceInterface 		= getInvoiceInterface();
			
			if (l_InvoiceInterface != null)
				{
				try {
					p_Invoice = this.saveInvoice (p_Invoice);
					p_Invoice = l_InvoiceInterface.fetchPatientForInvoice (p_Invoice);
					
					fireInvoiceChange (InvoiceChangeEvent.c_InvoiceStatusChanged, p_Invoice);
					
					GECAMedLog.user ("Billing","VERIFY Invoice","Verified Invoice with ID " + p_Invoice.getId());
					}
				catch (Exception p_Exception) 
					{
					m_Logger.log(Level.ERROR,p_Exception.getLocalizedMessage(),p_Exception);
					}
				}
			}
		}
	return p_Invoice;
	}

//---------------------------------------------------------------------------

public Invoice disproveInvoice (Invoice p_Invoice)
	{
	InvoiceInterface	l_InvoiceInterface;
	int					l_Action;

	if (p_Invoice == null) return null;

	if (userHasPermissionForInvoice (p_Invoice, BillingModule.c_disproveStem, true))		
		{
		l_Action = InvoiceWorkflow.changeInvoiceState (p_Invoice,InvoiceWorkflow.c_DisproveAction);
		if (l_Action == InvoiceWorkflow.c_DoDisprove)
			{
			l_InvoiceInterface 		= getInvoiceInterface();
			
			if (l_InvoiceInterface != null)
				{
				try {
					p_Invoice = this.saveInvoice (p_Invoice);
					p_Invoice = l_InvoiceInterface.fetchPatientForInvoice (p_Invoice);
					
					fireInvoiceChange (InvoiceChangeEvent.c_InvoiceStatusChanged, p_Invoice);
					
					GECAMedLog.user ("Billing","DISPROVE Invoice","Disproved Invoice with ID " + p_Invoice.getId());
					}
				catch (Exception p_Exception) 
					{
					m_Logger.log(Level.ERROR,p_Exception.getLocalizedMessage(),p_Exception);
					}
				}
			}
		}
	return p_Invoice;
	}
//---------------------------------------------------------------------------

public Invoice closeInvoice (Invoice p_Invoice)
	{
	InvoiceInterface	l_InvoiceInterface;
	int					l_Action;

	if (p_Invoice == null) return null;

//	if (userHasPermission (BillingModule.c_BillingModule,BillingModule.c_closeInvoices))
	if (userHasPermissionForInvoice(p_Invoice, BillingModule.c_closeStem,true))
		{
		l_Action = InvoiceWorkflow.changeInvoiceState (p_Invoice,InvoiceWorkflow.c_CloseAction);
		if (l_Action == InvoiceWorkflow.c_DoClose)
			{
			l_InvoiceInterface 		= getInvoiceInterface();
			
			if (l_InvoiceInterface != null)
				{
				try {
					p_Invoice.setCloser(getCurrentUser());
					p_Invoice.setClosureDate(new Date());
					p_Invoice = this.saveInvoice (p_Invoice);
					p_Invoice = l_InvoiceInterface.fetchPatientForInvoice(p_Invoice);
					
					fireInvoiceChange (InvoiceChangeEvent.c_InvoiceStatusChanged, p_Invoice);
					
					GECAMedLog.user ("Billing","CLOSE Invoice","Closed Invoice with ID " + p_Invoice.getId());
					}
				catch (Exception p_Exception) 
					{
					m_Logger.log(Level.ERROR,p_Exception.getLocalizedMessage(),p_Exception);
					}
				}
			}
		}
	return p_Invoice;
	}

//---------------------------------------------------------------------------

public Invoice openInvoice (Invoice p_Invoice)
	{
	InvoiceInterface	l_InvoiceInterface;
	int					l_Action;
	String []			l_Filler;		
	
	if (p_Invoice == null) return null;

	if (!userHasPermissionForInvoice(p_Invoice, BillingModule.c_openStem,true)) return p_Invoice;
	
	if (	(BillingModule.getCurrentUser().equals (p_Invoice.getCloser()))
		 || (userHasPermissionForInvoice(p_Invoice, BillingModule.c_openAllStem,false)))
		{
		l_Action = InvoiceWorkflow.changeInvoiceState (p_Invoice,InvoiceWorkflow.c_OpenAction);
		if (l_Action == InvoiceWorkflow.c_DoOpen)
			{		
			l_InvoiceInterface 		= getInvoiceInterface();
			
			if (l_InvoiceInterface != null)
				{
				try {
					p_Invoice.setCloser(null);
					p_Invoice.setClosureDate(null);
					p_Invoice = this.saveInvoice (p_Invoice);
					p_Invoice = l_InvoiceInterface.fetchPatientForInvoice(p_Invoice);
						
					fireInvoiceChange (InvoiceChangeEvent.c_InvoiceStatusChanged, p_Invoice);
					
					GECAMedLog.user ("Billing","OPEN Invoice","Open Invoice with ID " + p_Invoice.getId());
					}
				catch (Exception p_Exception) 
					{
					m_Logger.log(Level.ERROR,p_Exception.getLocalizedMessage(),p_Exception);
					}
				}
			}
		}
	else
		{
		p_Invoice = fetchCloserForInvoice (p_Invoice);
				
		l_Filler = new String [4];
		l_Filler[0] = p_Invoice.formatInvoiceNumber(Invoice.c_LongFormat, true);
		l_Filler[1] = p_Invoice.getCloser().getName();
		l_Filler[2] = m_DateFormat.format (p_Invoice.getClosureDate());
		l_Filler[3] = m_TimeFormat.format (p_Invoice.getClosureDate());
				
		notifyUser ("BillingModule.ClosedByUserTitle",
				    "BillingModule.ClosedByUserMessage",
				    l_Filler);
		}
	
	return p_Invoice;
	}

//---------------------------------------------------------------------------

public void newInvoice (InvoiceTemplate p_Template)
	{
	Invoice 				l_NewInvoice;
	Patient					l_Patient;
	Physician				l_Physician;
	
	Iterator<TemplateRate> 	l_RateIterator;
	TemplateRate			l_TemplateRate;
	Calendar				l_Today;
	
	
	if (userHasPermission (BillingModule.c_BillingModule,BillingModule.c_createInvoices))
		{
		m_HospitalisationProperties.reset();
		m_AccidentProperties.reset();
//		m_MedTransProperties.reset();
		
		l_Patient = GECAMedModule.getCurrentPatient();
		l_Physician = GECAMedModule.getCurrentPhysician();
		
		if ((l_Patient != null) && l_Patient.isPersistent())
			{
			if (doesDuplicateInovicesAtDateExist (l_Patient, l_Physician, new Date(), false))
				return;
			
			l_NewInvoice = new Invoice ();
			l_NewInvoice.setState(Integer.valueOf (InvoiceWorkflow.c_NewState));
			l_NewInvoice.setPatient(l_Patient);
			l_NewInvoice.setHealthInsurance(l_Patient.getInsurance());
			try {
				l_NewInvoice.setMajoration(l_Patient.getInsurance().getMajoration());				
			} catch (Exception e) {
				m_Logger.warn("Error setting majoration");
			}
			l_NewInvoice.setPhysician (l_Physician);
			l_NewInvoice.setInvoiceDate(new Date());
			l_NewInvoice.setSiteId(MainFrame.getCurrentSiteId());
			l_NewInvoice.setHospitalisationClass(m_HospitalisationProperties.getHospitalisationClassForNewInvoice());
			
			if (p_Template != null)
				{
				l_Today = new GregorianCalendar();
				l_Today.set(Calendar.HOUR_OF_DAY, 	12);
				l_Today.set(Calendar.MINUTE, 		0);
				l_Today.set(Calendar.SECOND, 		0);
				l_Today.set(Calendar.MILLISECOND, 	0);
				
				l_RateIterator = p_Template.getTemplateRates().iterator();
				while (l_RateIterator.hasNext())
					{
					l_TemplateRate = l_RateIterator.next();
//					l_NewInvoice.addRate (l_TemplateRate.getRate(), l_Today.getTime(), l_TemplateRate.getSuffixes());
					Act l_Act = new Act();
					l_Act.setChanges(Act.CHANGED_USER);
					l_Act.setPerformedDate(l_Today.getTime());
					try {
						l_Act = getNomenclatureInterface().initializeAct(l_TemplateRate.getRate().getCode(), l_Act);						
					} catch (Exception e) {
						m_Logger.error("Error initializing Act",e);
					}
					l_NewInvoice.addAct(l_Act, l_Today.getTime(), l_TemplateRate.getSuffixes());
					}
				}
			
			this.setInvoice	(l_NewInvoice);
			
			m_MainPanel.setSelectedIndex (c_EditorTab);			
			m_MainPanel.validate();
			
			if (p_Template != null) {
				m_EditorPanel.setModified (true);				
			} else {
				m_EditorPanel.setModified (false);
			}
			
			if ((p_Template == null) && (Boolean)getUserSetting(BillingUserSettings.c_AutomaticallyAddActsSetting))
				{
				Act l_Act = new Act ();
				l_Act.setChanges(Act.CHANGED_USER);
				m_EditorPanel.requestFocus();
				m_EditorPanel.addAct (l_Act,true, false);
				}
			}
		else
			{
			MainFrame.getInstance().showMessage(Translatrix.getTranslationString("BillingModule.NoOpenPatient"));
			}
		}
	}

//---------------------------------------------------------------------------

/**
 * @author ferring
 * 
 * Checks, whether there is already an invoice for that patient and that physician at that date.
 * 
 * @param p_Patient the patient
 * @param p_Physician the physician
 * @param p_Date the date to set the new invoice
 * @param p_IsInvoiceOpen defines, if the invoice is already opened or just being created
 * @return <code>true</code> if the calling method should go on as usual
 * <code>false</code>: else
 */
public boolean doesDuplicateInovicesAtDateExist (Patient p_Patient, Physician p_Physician, Date p_Date, boolean p_IsInvoiceOpen) 
	{
	InvoiceInterface 	l_InvoiceManager;
	Invoice				l_InvoiceOfDate;
	Invoice				l_EditedInvoice;
	Set<Act>			l_Acts;
	BillingModule		l_Module;
	int 				l_Option;
	boolean 			l_ActsAdded		= false;
	
	
	if (p_IsInvoiceOpen
			&& m_MainPanel.getSelectedIndex() != c_EditorTab)
		// the date was changed, but the editor tab was not selected => don't care about it
		return false;
	
	l_EditedInvoice   = m_EditorPanel.getEditedInvoice();
	l_InvoiceManager  = (InvoiceInterface) ManagerFactory.getRemote(InvoiceBean.class);
	l_InvoiceOfDate	  = l_InvoiceManager.getInvoiceByPatientPhysicianAndDate(p_Patient, p_Physician, p_Date, 
						l_EditedInvoice != null ? l_EditedInvoice.getId() : null);
	
	/*  |- no invoice exists => do nothing
	 * -|
	 *  |				  		|- invoice is not yet opened => ask to create an invoice or load 
	 *  |						|								the existing (YES-NO-CANCEL-Option)
	 *  |- an invoice exists   -|
	 *  				  		|					|- ID is the same => do nothing
	 *  				  		|- invoice is open -|
	 *  											|					|- invoice is open => ask to open and ask to add the
	 *  											|					|		 			 current acts (2x YES-NO-Option)
	 *  											|- ID is different -|
	 *  																|- invoice is closed => just warn the user (OK-Option)
	 */
	if (l_InvoiceOfDate == null)
		// no invoice exists
		return false;
	
	if (p_IsInvoiceOpen)
		{
		// the invoice is opened (not in creation)
		if (l_InvoiceOfDate.getId().equals(l_EditedInvoice.getId()))
			// ID is the same
			return false;
		
		// ID is different
		if (l_InvoiceOfDate.getState() <= InvoiceWorkflow.c_OpenState)
			{
			// ask to open the other invoice
			l_Option = JOptionPane.showConfirmDialog(this, 
					Translatrix.getTranslationString("BillingModule.OpenExistingInvoiceWithThatDateMessage"), 
					Translatrix.getTranslationString("BillingModule.OpenExistingInvoiceWithThatDateTitle"), 
					JOptionPane.YES_NO_OPTION, 
					JOptionPane.QUESTION_MESSAGE);
			
			if (l_Option == JOptionPane.YES_OPTION)
				{
				// open the existing invoice
				l_Module = BillingModule.getInstance();
				l_InvoiceOfDate = this.fetchLazyDependencies(l_InvoiceOfDate);
				
				l_Acts = l_EditedInvoice.getActs();
				if (l_Acts != null
						&& !l_Acts.isEmpty())
					{
					// ask to add the current acts to the existing invoice
					l_Option = JOptionPane.showConfirmDialog(this, 
							Translatrix.getTranslationString("BillingModule.AddActsToExistingInvoiceMessage"), 
							Translatrix.getTranslationString("BillingModule.AddActsToExistingInvoiceTitle"), 
							JOptionPane.YES_NO_OPTION, 
							JOptionPane.QUESTION_MESSAGE);
					
					
					if (l_Option == JOptionPane.YES_OPTION)
						{
						l_InvoiceOfDate.getActs().addAll(l_Acts);
						l_ActsAdded = true;
						l_Module.saveInvoice(l_EditedInvoice);
						}
					}

				l_Module.setModified(false);
				editInvoice(l_InvoiceOfDate);
				l_Module.setModified(l_ActsAdded);
				
				return true;
				}
			else return false;
			}
		else
			{
			// just warn the user
			JOptionPane.showMessageDialog(this, 
					Translatrix.getTranslationString("BillingModule.InvoiceAlreadyExistsMessage"), 
					Translatrix.getTranslationString("BillingModule.InvoiceAlreadyExistsTitle"), 
					JOptionPane.WARNING_MESSAGE);
			return false;
			}
		}
	else 
		{
		// ask to create a new bill
		l_Option = JOptionPane.showConfirmDialog(this, 
				Translatrix.getTranslationString("BillingModule.CreateNewOrOpenLatestInvoiceMessage"), 
				Translatrix.getTranslationString("BillingModule.CreateNewOrOpenLatestInvoiceTitle"), 
				JOptionPane.YES_NO_CANCEL_OPTION, 
				JOptionPane.QUESTION_MESSAGE);
		
		switch (l_Option)
			{
			case JOptionPane.NO_OPTION:
				// open the existing invoice instead of creating a new one
				l_InvoiceOfDate = this.fetchLazyDependencies(l_InvoiceOfDate);
				editInvoice(l_InvoiceOfDate);
				
			case JOptionPane.CANCEL_OPTION:
				// do nothing ...
				return true;
				
			case JOptionPane.YES_OPTION:
			default:
				// create a new invoice ...
				return false;
			}
		}
	}

//---------------------------------------------------------------------------

private Invoice saveInvoice (Invoice p_Invoice)
	{
	InvoiceInterface	l_InvoiceInterface;
//	int					l_Action;

	if (p_Invoice == null) return null;

	l_InvoiceInterface 		= getInvoiceInterface();
			
	if (l_InvoiceInterface != null)
		{
		try {
			p_Invoice = l_InvoiceInterface.saveInvoice (p_Invoice);
			}
		catch (Exception p_Exception) 
			{
			m_Logger.log(Level.ERROR,"Failed to save Invoice!",p_Exception);
			}
		}
	return p_Invoice;
	}

//---------------------------------------------------------------------------

public void editSelectedInvoice ()
	{
	Invoice 	l_SelectedInvoice;
	
	l_SelectedInvoice = m_InvoicePanel.getSelectedInvoice();
		
	if (l_SelectedInvoice != null)
		{
//		if (userHasPermissionForInvoice (l_SelectedInvoice, BillingModule.c_editStem))
			{
			this.editInvoice (l_SelectedInvoice);
			}
		}
	}

//---------------------------------------------------------------------------

public void closeSelectedInvoice ()
	{
	Invoice 			l_SelectedInvoice;

	l_SelectedInvoice = m_InvoicePanel.getSelectedInvoice();
		
	if (l_SelectedInvoice != null)
		{
		if (userHasPermissionForInvoice (l_SelectedInvoice, BillingModule.c_closeStem,true))
			{
			l_SelectedInvoice = closeInvoice (l_SelectedInvoice);
			l_SelectedInvoice = this.fetchLazyDependencies(l_SelectedInvoice);
			
			m_InvoicePanel.setSelectedInvoice (l_SelectedInvoice);
			m_InvoicePanel.repaint();
			
			this.setInvoice (l_SelectedInvoice);
			//m_InvoicePanel.setSelectedInvoice (l_SelectedInvoice);
			}
		}
	}

//---------------------------------------------------------------------------

public void verifySelectedInvoice ()
	{
	Invoice 			l_SelectedInvoice;

	l_SelectedInvoice = m_InvoicePanel.getSelectedInvoice();
		
	if (l_SelectedInvoice != null)
		{
		if (userHasPermissionForInvoice (l_SelectedInvoice, BillingModule.c_verifyStem, true))
			{
			l_SelectedInvoice = verifyInvoice(l_SelectedInvoice);
			m_InvoicePanel.setSelectedInvoice (l_SelectedInvoice);
			m_InvoicePanel.repaint();
			
			this.setInvoice (m_InvoicePanel.getSelectedInvoice());
			//m_InvoicePanel.setSelectedInvoice (l_SelectedInvoice);
			}
		}
	}

//---------------------------------------------------------------------------

public void disproveSelectedInvoice ()
	{
	Invoice 			l_SelectedInvoice;

	l_SelectedInvoice = m_InvoicePanel.getSelectedInvoice();
		
	if (l_SelectedInvoice != null)
		{
		if (userHasPermissionForInvoice (l_SelectedInvoice, BillingModule.c_disproveStem, true))
			{
			l_SelectedInvoice = disproveInvoice (l_SelectedInvoice);
					
			m_InvoicePanel.setSelectedInvoice (l_SelectedInvoice);
			m_InvoicePanel.repaint();
			
			this.setInvoice (m_InvoicePanel.getSelectedInvoice());
			//m_InvoicePanel.setSelectedInvoice (l_SelectedInvoice);
			}
		}
	}

//---------------------------------------------------------------------------

public void openSelectedInvoice ()
	{
	Invoice 			l_SelectedInvoice;

	l_SelectedInvoice = m_InvoicePanel.getSelectedInvoice();
		
	if (l_SelectedInvoice != null)
		{
		if (userHasPermissionForInvoice (l_SelectedInvoice, BillingModule.c_openStem,true))
			{
			l_SelectedInvoice = openInvoice(l_SelectedInvoice);
			l_SelectedInvoice = this.fetchLazyDependencies(l_SelectedInvoice);
			
			m_InvoicePanel.setSelectedInvoice (l_SelectedInvoice);
			m_InvoicePanel.repaint();
			
			this.setInvoice (m_InvoicePanel.getSelectedInvoice());
			}
		}
	}

//---------------------------------------------------------------------------

private void settleSelectedInvoice (MouseEvent e)
{
	// select the clicked invoice
	JTable	table		= (JTable) e.getSource();
	int		clickedRow	= table.rowAtPoint(e.getPoint());
	table.setRowSelectionInterval(clickedRow, clickedRow);
	
	// settle the invoice
	settleSelectedInvoice();
}

//---------------------------------------------------------------------------

public void settleSelectedInvoice ()
	{
	Invoice 			l_SelectedInvoice;
	Statement			l_SelectedStatement;
	Date				l_SettlementDate;
	
	switch (m_MainPanel.getSelectedIndex())
		{
		case c_InvoiceTab :
			
			l_SelectedInvoice = m_InvoicePanel.getSelectedInvoice();
			if (l_SelectedInvoice != null)
			{
				if (userHasPermissionForInvoice (l_SelectedInvoice, BillingModule.c_settleStem,true))
				{	
					if (l_SelectedInvoice.isSettled())
					{
						MainFrame.getInstance().showMessage(Translatrix.getTranslationString("BillingModule.InvoiceFullySettled"));
						return;
					}
					
					if (splitInvoice(l_SelectedInvoice)) {
						BillingModule.getInstance().reloadInvoices();
						return;
					}
					
					l_SettlementDate = new Date ();
					l_SelectedInvoice = this.settleInvoice(l_SelectedInvoice, l_SettlementDate, false);
					m_InvoicePanel.setSelectedInvoice (l_SelectedInvoice);
					this.setInvoice (m_InvoicePanel.getSelectedInvoice());
					
					m_InvoicePanel.repaint();
				}
			}
			break;
				
		case c_EditorTab  :
		case c_MemoTab	  :
			
			l_SelectedInvoice = m_EditorPanel.getSelectedInvoice();
			if (l_SelectedInvoice != null)
				{
				if (userHasPermissionForInvoice (l_SelectedInvoice, BillingModule.c_settleStem,true))
					{	
					if (l_SelectedInvoice.isSettled())
						{
						MainFrame.getInstance().showMessage(Translatrix.getTranslationString("BillingModule.InvoiceFullySettled"));
						return;
						}

					if (splitInvoice(l_SelectedInvoice)) {
						BillingModule.getInstance().reloadInvoices();
						return;
					}
					
					l_SettlementDate = new Date ();
					l_SelectedInvoice = this.settleInvoice(l_SelectedInvoice, l_SettlementDate, false);
//					m_InvoicePanel.setSelectedInvoice (l_SelectedInvoice);
//					m_InvoicePanel.repaint();
//					
//					this.setInvoice (m_InvoicePanel.getSelectedInvoice());
					}
				}
			break;
				
		case c_StatementTab :
			
			if (m_StatementPanel.isEligibleForSettlement(StatementPanel.c_WithUserNotification) == false) return;
				
			l_SelectedInvoice = m_StatementPanel.getSelectedInvoice();
			if (l_SelectedInvoice != null)
				{
				if (userHasPermissionForInvoice (l_SelectedInvoice, BillingModule.c_settleStem,true))
					{
					if (l_SelectedInvoice.isSettled())
						{
						MainFrame.getInstance().showMessage(Translatrix.getTranslationString("BillingModule.InvoiceFullySettled"));
						return;
						}

					if (splitInvoice(l_SelectedInvoice)) {
						BillingModule.getInstance().reloadInvoices();
						return;
					}
					
					l_SelectedStatement = m_StatementPanel.getCurrentStatement();
					if (l_SelectedStatement != null)
						l_SettlementDate = l_SelectedStatement.getSettlementDate();
					else l_SettlementDate = new Date ();

					l_SelectedInvoice = this.settleInvoice (l_SelectedInvoice, l_SettlementDate, false);	
					m_StatementPanel.setSelectedInvoice(l_SelectedInvoice);
					m_StatementPanel.repaint();
					
					this.setInvoice(l_SelectedInvoice);
					}
				}
			break;					
		
		case c_SearchTab :
			
			l_SelectedInvoice = m_SearchPanel.getSelectedInvoice();
			if (l_SelectedInvoice != null)
				{
				if (userHasPermissionForInvoice (l_SelectedInvoice, BillingModule.c_settleStem,true))
					{
					if (l_SelectedInvoice.isSettled())
						{
						MainFrame.getInstance().showMessage(Translatrix.getTranslationString("BillingModule.InvoiceFullySettled"));
						return;
						}
					
					if (splitInvoice(l_SelectedInvoice)) {
						BillingModule.getInstance().reloadInvoices();
						return;
					}
					
					this.setInvoice (m_SearchPanel.getSelectedInvoice());
					l_SettlementDate = new Date ();
					l_SelectedInvoice =  this.settleInvoice(l_SelectedInvoice, l_SettlementDate, false);
					m_SearchPanel.reloadInvoices();
					
//					m_InvoicePanel.setSelectedInvoice (l_SelectedInvoice);
//					m_InvoicePanel.repaint();
					}
				}
			break;
		
		case c_ReminderTab :
				
			l_SelectedInvoice = m_ReminderPanel.getSelectedInvoice();
			if (l_SelectedInvoice != null)
				{
				if (userHasPermissionForInvoice (l_SelectedInvoice, BillingModule.c_settleStem,true))
					{				
					if (l_SelectedInvoice.isSettled())
						{
						MainFrame.getInstance().showMessage(Translatrix.getTranslationString("BillingModule.InvoiceFullySettled"));
						return;
						}
				
					l_SettlementDate = new Date ();
					this.settleInvoice (l_SelectedInvoice, l_SettlementDate, false);				
//					m_ReminderPanel.removeSelectedInvoice (l_SelectedInvoice);
//					m_ReminderPanel.repaint();
					
					m_ReminderPanel.reload();
					
					this.setInvoice(l_SelectedInvoice);
					}
				}	
			break;
		
		default:
			MainFrame.getInstance().showMessage(Translatrix.getTranslationString("BillingModule.cannotSettleFromHere"));
		}
	}


//---------------------------------------------------------------------------

public boolean splitInvoice(Invoice p_Invoice) {
	if (getInvoiceInterface() != null) {
		try {
			// Check for Splitting First Class CNS Invoice into CNS and
			// Private Invoice
			if (m_InvoiceInterface.isInvoiceSplittable(p_Invoice)) {

				String[] vars = new String[] { p_Invoice.getInvoiceNumber() };
				int n = JOptionPane.showConfirmDialog(this, Translatrix.getTranslationString("InvoiceEditorPanel.SplitFirstClassInvoiceText", vars), Translatrix.getTranslationString("InvoiceEditorPanel.SplitFirstClassInvoiceTitle"), JOptionPane.YES_NO_CANCEL_OPTION);

				if (n == JOptionPane.CANCEL_OPTION || n == JOptionPane.NO_OPTION) {
					return false;
				} else if (n == JOptionPane.YES_OPTION) {
					getInvoiceInterface().splitFirstClassHospitalizedInvoice(p_Invoice);
					GECAMedLog.user("Billing", "SPLITTING Invoice", "Splitted First Class Hospitalized Invoice with ID " + p_Invoice.getId() + " into 2 new Invoices ");
					return true;
				}
			}
		} catch (Exception p_Exception) {
			m_Logger.log(Level.ERROR, p_Exception.getLocalizedMessage(), p_Exception);
		}
	}
	return false;
}


public void revokeSelectedInvoice ()
	{
	Invoice 			l_SelectedInvoice;
	Statement			l_SelectedStatement;
	Date				l_RevokeDate;

	switch (m_MainPanel.getSelectedIndex())
		{
		case c_InvoiceTab :
		case c_EditorTab  :
		case c_MemoTab	  :
		
			l_SelectedInvoice = m_InvoicePanel.getSelectedInvoice();
			if (l_SelectedInvoice != null)
				{
				if (userHasPermissionForInvoice (l_SelectedInvoice, BillingModule.c_revokeStem,true))
					{
					if (!l_SelectedInvoice.receivedPayment())
						{
						MainFrame.getInstance().showMessage(Translatrix.getTranslationString("BillingModule.InvoiceNotPaid"));
						return;
						}

//					l_RevokeDate = new Date ();
					l_RevokeDate = (l_SelectedInvoice.getSettlementDate() != null)
									? l_SelectedInvoice.getSettlementDate() 
									: new Date ();
					
					l_SelectedInvoice = this.revokeInvoice(l_SelectedInvoice,l_RevokeDate, false);
					m_InvoicePanel.setSelectedInvoice (l_SelectedInvoice);
					m_InvoicePanel.repaint();
					this.setInvoice (m_InvoicePanel.getSelectedInvoice());
					}
				}
			break;

		case c_StatementTab :	
				
			if (m_StatementPanel.isEligibleForSettlement(StatementPanel.c_WithUserNotification) == false) return;

			l_SelectedInvoice = m_StatementPanel.getSelectedInvoice();
			if (l_SelectedInvoice != null)
				{
				if (userHasPermissionForInvoice (l_SelectedInvoice, BillingModule.c_revokeStem,true))
					{
					if (!l_SelectedInvoice.receivedPayment())
						{
						MainFrame.getInstance().showMessage(Translatrix.getTranslationString("BillingModule.InvoiceNotPaid"));
						return;
						}

					l_SelectedStatement = m_StatementPanel.getCurrentStatement();
					if (l_SelectedStatement != null)
						 l_RevokeDate = l_SelectedStatement.getSettlementDate();
					else l_RevokeDate = new Date ();
					
					l_SelectedInvoice = this.revokeInvoice (l_SelectedInvoice, l_RevokeDate, false);				
					m_StatementPanel.setSelectedInvoice(l_SelectedInvoice);
					m_StatementPanel.repaint();
					
					this.setInvoice(l_SelectedInvoice);
					}
				}
			break;					
		}				
	}

//---------------------------------------------------------------------------

public void deleteSelectedInvoices ()
	{
	if (m_MainPanel.getSelectedIndex() == c_InvoiceTab)
		m_InvoicePanel.deleteSelectedInvoices();
	}

//---------------------------------------------------------------------------

public void showLedger ()
	{
	Invoice 		l_SelectedInvoice;
	LedgerDialog	l_Dialog;
		
	if (m_CurrentInvoice != null && m_CurrentInvoice.isPersistent())
		{
		l_Dialog = new LedgerDialog (m_CurrentInvoice.formatInvoiceNumber(true, false));
		l_Dialog.setLedgers(this.getLedgersForInvoice(m_CurrentInvoice));
		l_Dialog.pack();
		MainFrame.showDialogCentered (l_Dialog);		
		}
	}

//---------------------------------------------------------------------------

public void nextInvoice ()
	{
	Invoice l_Invoice;
	
	if (m_InvoicePanel.selectNextInvoice())
		{
		l_Invoice = m_InvoicePanel.getSelectedInvoice();
		m_EditorPanel.setInvoice(l_Invoice);
		m_MemoPanel.setInvoice(l_Invoice);
		}
	}

//---------------------------------------------------------------------------

public void previousInvoice ()
	{
	Invoice l_Invoice;
	
	if (m_InvoicePanel.selectPreviousInvoice())
		{
		l_Invoice = m_InvoicePanel.getSelectedInvoice();
		m_EditorPanel.setInvoice(l_Invoice);
		m_MemoPanel.setInvoice(l_Invoice);
		}
	}


//---------------------------------------------------------------------------

public void addStatement ()
	{
	if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_createStatements))
		{
		m_MainPanel.setSelectedIndex(c_StatementTab);
		m_StatementPanel.newStatement ();
		}
	}

//---------------------------------------------------------------------------

public void deleteSelectedStatements ()
	{
	if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_deleteStatements))
		{
		m_MainPanel.setSelectedIndex(c_StatementTab);
		m_StatementPanel.deleteSelectedStatements();
		}
	}

//---------------------------------------------------------------------------

public void closeSelectedStatement ()
{
if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_closeStatements))
	{
	m_MainPanel.setSelectedIndex(c_StatementTab);
	m_StatementPanel.closeSelectedStatement();
	}
}

//---------------------------------------------------------------------------

public void openSelectedStatement ()
{
if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_openStatements))
	{
	m_MainPanel.setSelectedIndex(c_StatementTab);
	m_StatementPanel.openSelectedStatement();
	}
}

//---------------------------------------------------------------------------

public void printSelectedStatement ()
{
if (userHasPermission(BillingModule.c_BillingModule,BillingModule.c_printStatements))
	{
	m_MainPanel.setSelectedIndex(c_StatementTab);
	m_StatementPanel.printSelectedStatement();
	}
}

//---------------------------------------------------------------------------

public void triggerHL7Import ()
	{
	Queue 					l_Queue		= null;
	QueueConnectionFactory 	l_Factory	= null;
	QueueConnection			l_Connection = null;
	QueueSession			l_Session	= null;
	QueueSender				l_Sender		= null;
		
	try {
		InitialContext l_Context = new InitialContext();
		l_Queue = (Queue) l_Context.lookup("queue/gecamed");
		l_Factory = (QueueConnectionFactory) l_Context.lookup("ConnectionFactory");
		l_Connection = l_Factory.createQueueConnection();
		l_Session = l_Connection.createQueueSession(false,QueueSession.AUTO_ACKNOWLEDGE);
		} 
	catch (Exception e) 
		{
		e.printStackTrace ();
		}

	if (l_Session == null) return;
	
	try	{
		TextMessage msg = l_Session.createTextMessage("HL7import");
		l_Sender = l_Session.createSender(l_Queue);
		l_Sender.send(msg,DeliveryMode.NON_PERSISTENT,0,1000000);
		l_Sender.close();
		l_Session.close();
		l_Connection.close();
		}
	catch (JMSException p_Exception)
		{
		p_Exception.printStackTrace();
		}		
	}

//---------------------------------------------------------------------------

public void printActivityList ()
	{
	ActivityListDialog	l_Dialog;
	ActivityWorker	l_Renderer;
	
	l_Dialog = new ActivityListDialog();
	l_Dialog.pack();
	MainFrame.showDialogCentered (l_Dialog);
	
	if (l_Dialog.wasValidated()) 
		{
		l_Renderer = new ActivityWorker ();
		l_Renderer.setFromDate(l_Dialog.getPerformedFromDate());
		l_Renderer.setUntilDate(l_Dialog.getPerformedUntilDate());
		l_Renderer.setWhereClause(l_Dialog.getWhereClause());
		l_Renderer.printActivities();
		}
	}

//---------------------------------------------------------------------------

public void printIssuedInvoiceList ()
	{
	InvoiceListDialog	l_Dialog;
	InvoiceWorker		l_Renderer;
	
	l_Dialog = new InvoiceListDialog ();
	l_Dialog.pack();
	MainFrame.showDialogCentered (l_Dialog);

	if (l_Dialog.wasValidated()) 
		{
		l_Renderer = new InvoiceWorker ();
		l_Renderer.setFromDate(l_Dialog.getFromDate());
		l_Renderer.setUntilDate(l_Dialog.getUntilDate());
		l_Renderer.setOnlyTotals(l_Dialog.onlyTotals());
		l_Renderer.setWhereClause(l_Dialog.getWhereClause());
		l_Renderer.printIssuedInvoices();
		}
	}

//---------------------------------------------------------------------------

public void printTransactionList ()
	{
	TransactionListDialog l_TransactionListDialog;
	ProgressDialog		  l_ProgressDialog;
	ProgressWorker		  l_PrintWorker;
	
	Date				l_Today = new Date ();
	Date				l_FromDate;
	Date				l_UntilDate;
	Physician 			l_Physician = null;
	GecamedUser 		l_Cashier = null;

	l_TransactionListDialog = new TransactionListDialog ();
	l_TransactionListDialog.setFromDate (l_Today);
//	l_TransactionListDialog.setUntilDate (l_Today);
	l_TransactionListDialog.setSingleCashier (false);
	l_TransactionListDialog.setCashier (GECAMedModule.getCurrentUser());
	l_TransactionListDialog.setEffectiveTransactions ((Boolean)getUserSetting (BillingUserSettings.c_EffectiveTransactionsSetting));
	MainFrame.showDialogCentered(l_TransactionListDialog);
	
	if (l_TransactionListDialog.wasValidated())
		{
		l_FromDate = l_TransactionListDialog.getFromDate();
			
		l_UntilDate = (l_TransactionListDialog.getUntilDate() != null)
					  ?l_TransactionListDialog.getUntilDate()
					  :l_FromDate;
		
		if (l_TransactionListDialog.isSingleCashier()) l_Cashier = l_TransactionListDialog.getCashier();
		if ((Boolean)getSetting (BillingAdminSettings.c_SplitBillingSetting)) l_Physician = GECAMedModule.getCurrentPhysician();

		l_ProgressDialog = new ProgressDialog ();
		l_ProgressDialog.setCancelable(true);
		l_ProgressDialog.setProgressBarMode (ProgressDialog.c_Indetermined);

		l_ProgressDialog.setTitle("BillingModule.PrintTransactionListTitle");
		l_ProgressDialog.setMessage("BillingModule.PrintTransactionListMessage",null);
		l_ProgressDialog.pack();
		
		final Date l_WorkerFromDate        = l_FromDate;
		final Date l_WorkerUntilDate       = l_UntilDate;
		final Physician l_WorkerPhysician  = l_Physician;
		final GecamedUser l_WorkerCashier  = l_Cashier;
		final boolean l_WorkerTransactions = l_TransactionListDialog.onlyEffectiveTransactions();
		final boolean l_WorkerTransfers    = l_TransactionListDialog.includeTransfers();
		final boolean l_WorkerTotals       = l_TransactionListDialog.onlyTotals();
		final ProgressDialog l_WorkerDialog = l_ProgressDialog;
		
		l_PrintWorker = new ProgressWorker () 
			{
			private InvoicePrinter m_InvoicePrinter;
			
			public void start ()
				{
				MainFrame.showDialogCentered (l_WorkerDialog);
				}
			
			public Object work ()
				{
				m_InvoicePrinter = new InvoicePrinter();
				m_InvoicePrinter.printTransactionList (l_WorkerFromDate,
													   l_WorkerUntilDate,
													   l_WorkerPhysician,
													   l_WorkerCashier,
													   l_WorkerTransactions,
													   l_WorkerTransfers,
													   l_WorkerTotals);
				return "";
				}
		
			public void abort ()
				{
				m_InvoicePrinter.close();
				l_WorkerDialog.setVisible(false);
				}	
			
			public void done ()
				{
				m_InvoicePrinter.close();
				l_WorkerDialog.setVisible(false);
				}	
			};
				
		ProgressExecutor l_Executor = new ProgressExecutor ();
		l_ProgressDialog.setProgressExecutor(l_Executor);

		l_Executor.setWorker(l_PrintWorker);
		l_Executor.startExecution();
		}
	}

//---------------------------------------------------------------------------

public void propertyChange(PropertyChangeEvent p_ChangeEvent) 
	{
    String  			l_Property;
    String				l_SSN;
	Integer				l_InvoiceNumber;
    Invoice				l_Invoice;
	Invoice				l_OldInvoice;
    Patient				l_Patient;
    Integer				l_RecordNumber;
    String				l_Filler [];
	
    l_Property = p_ChangeEvent.getPropertyName();
    
    //========================================================================
    //= Events from PatientSummaryPanel
    //========================================================================
   
    if (p_ChangeEvent.getSource ().equals(m_PatientSummaryPanel))
		{
		l_Patient = null;
		if (PatientSummaryPanel.c_SSNChanged.equals(l_Property))
			{
			l_SSN = (String) p_ChangeEvent.getNewValue();
			l_Patient = this.getPatientBySocalSecurityNumber(l_SSN);
			if (l_Patient != null) 
				{
				MainFrame.getInstance().showMessage(Translatrix.getTranslationString("BillingModule.MatchingPatientFound"));								
				BillingModule.setCurrentPatient(l_Patient,true);
				//this.patientChanged (l_Patient);
				}
			else 
				{
				MainFrame.getInstance().showMessage(Translatrix.getTranslationString("BillingModule.NoMatchingPatientFound"));
				this.reset ();
				}			
			}
		else if (PatientSummaryPanel.c_RecordNumberChanged.equals(l_Property))
			{
			try 
				{
				l_RecordNumber = Integer.parseInt((String)p_ChangeEvent.getNewValue());
				l_Patient = this.getPatientByRecordNumber(l_RecordNumber);
				}
			catch (NumberFormatException p_Exception)
				{
				}
			
			if (l_Patient != null) 
				{
				MainFrame.getInstance().showMessage(Translatrix.getTranslationString("BillingModule.MatchingPatientFound"));								
				BillingModule.setCurrentPatient(l_Patient,true);
//				this.patientChanged (l_Patient);
				}
			else 
				{
				MainFrame.getInstance().showMessage(Translatrix.getTranslationString("BillingModule.NoMatchingPatientFound"));
				this.reset ();
				}			
			}
		}
	
    //========================================================================
    //= Events from InvoicePropertiesPanel
    //========================================================================

    else if (p_ChangeEvent.getSource ().equals(m_InvoiceProperties))
    	{
//		System.out.println(p_ChangeEvent);
		
    	if (InvoicePropertiesPanel.c_InvoiceNumber.equals(l_Property))	
    		{
    		l_InvoiceNumber = (Integer) p_ChangeEvent.getNewValue();
    		l_Invoice = this.getInvoiceByInvoiceNumber(l_InvoiceNumber);
    		
    		if (l_Invoice != null)
    			{
    			l_Filler = new String [1];
				l_Filler[0] = l_Invoice.formatInvoiceNumber(Invoice.c_LongFormat, true);	
				   				
    			MainFrame.getInstance().showMessage(Translatrix.getTranslationString("BillingModule.MatchingInvoiceFound",l_Filler));								
				BillingModule.setCurrentPatient (l_Invoice.getPatient(),true);
    			m_InvoicePanel.selectInvoice(l_Invoice.formatInvoiceNumber(Invoice.c_LongFormat, true));
    			}
    		else
    			{
 				MainFrame.getInstance().showMessage(Translatrix.getTranslationString("BillingModule.NoMatchingInvoiceFound"));
    			}
    		}
    	else //if (InvoicePropertiesPanel.c_HealthInsurance.equals(l_Property))
    		{
    		m_EditorPanel.propertyChange(p_ChangeEvent);
    		}
    	}
      
    //========================================================================
    //= Events from InvoiceEditorPanel
    //========================================================================

    else if (p_ChangeEvent.getSource ().equals(m_EditorPanel))
        {
     	l_OldInvoice = this.getOldInvoiceFromPropertyChangeEvent(p_ChangeEvent);
    	l_Invoice    = this.getNewInvoiceFromPropertyChangeEvent(p_ChangeEvent);
    	
    	if (l_Invoice != null) {
    		m_CurrentInvoice = l_Invoice;  
//    		System.out.println("propertyChanged from InvoiceEditorPanel: " + m_CurrentInvoice);
    	} else {
    		l_Invoice = m_CurrentInvoice;    		
    	}
		
		if (	(l_OldInvoice != null) && (!l_OldInvoice.isPersistent())
			&&  (l_Invoice    != null) && (l_Invoice.isPersistent()) )
			{
			m_InvoicePanel.addInvoice (l_Invoice);
			m_InvoicePanel.selectInvoice(l_Invoice.formatInvoiceNumber(Invoice.c_LongFormat, true));
			}
    	
    	if (InvoiceEditorPanel.c_InvoiceSaved.equals(l_Property))
			{    		
    		m_InvoiceProperties.setInvoice  (l_Invoice);
			m_AccidentProperties.setInvoice	(l_Invoice);
			m_InvoiceStatusPanel.setInvoice (l_Invoice);
			m_InvoicePanel.setInvoice (l_Invoice);
			
			fireInvoiceChange (InvoiceChangeEvent.c_InvoiceUpdated,l_Invoice);
			}
		else if (InvoiceEditorPanel.c_InvoicePrinted.equals(l_Property))
			{
			m_InvoicePanel.revalidate();
			m_InvoiceStatusPanel.setInvoice (l_Invoice);
			m_InvoicePanel.setInvoice (l_Invoice);
			
			fireInvoiceChange (InvoiceChangeEvent.c_InvoiceStatusChanged,l_Invoice);
			}
		else if (InvoiceEditorPanel.c_InvoiceModified.equals(l_Property))
			{
//			m_InvoiceStatusPanel.setInvoice 	(l_Invoice);	
			
			m_InvoicePanel.setInvoice 	(l_Invoice);
			
//			l_Event = new InvoiceChangeEvent (null,InvoiceChangeEvent.c_SingleInvoiceUpdated,l_Invoice);
//			this.publishToBillingUpdateTopic(l_Event);
			}
		else if (InvoiceEditorPanel.c_InvoicePaid.equals(l_Property))
			{
			m_InvoiceStatusPanel.setInvoice 	(l_Invoice);
			m_InvoicePanel.setInvoice 	(l_Invoice);
			
			fireInvoiceChange (InvoiceChangeEvent.c_InvoiceStatusChanged,l_Invoice);
			}
        }
    
    //========================================================================
    //= Events from MemoPanel
    //========================================================================

    else if (p_ChangeEvent.getSource ().equals(m_MemoPanel))
	    {
    	l_Invoice    = this.getNewInvoiceFromPropertyChangeEvent(p_ChangeEvent);
    	
    	if (l_Invoice != null) {
    		m_CurrentInvoice = l_Invoice;
//    		System.out.println("propertyChanged from  MemoPanel: " + m_CurrentInvoice);
    	} else {
    		l_Invoice = m_CurrentInvoice;
    	}

		if (MemoEditorPanel.c_InvoiceUpdated.equals(l_Property))
			{
			m_InvoiceStatusPanel.setInvoice (l_Invoice);	
			m_InvoicePanel.setInvoice(l_Invoice);
			
			fireInvoiceChange (InvoiceChangeEvent.c_InvoiceStatusChanged,l_Invoice);
			}
	    }
   
    //========================================================================
    //= Events from StatementPanel
    //========================================================================

    else if (p_ChangeEvent.getSource ().equals(m_StatementPanel))
    	{
    	l_Invoice    = this.getNewInvoiceFromPropertyChangeEvent(p_ChangeEvent);
    	
    	if (l_Invoice != null) {
    		m_CurrentInvoice = l_Invoice;
//    		System.out.println("propertyChanged from StatementPanel: " + m_CurrentInvoice);
    	} else {
    		l_Invoice = m_CurrentInvoice;
    	}
   		
    	if (StatementInvoicesPanel.c_InvoiceSettled.equals(l_Property))
    		{
    		m_InvoiceStatusPanel.setInvoice (l_Invoice);
    		m_InvoicePanel.setInvoice(l_Invoice);
    		m_InvoicePanel.validate();
    		}
    	else if (StatementInvoicesPanel.c_InvoiceRevoked.equals(l_Property))
			{
			m_InvoiceStatusPanel.setInvoice (l_Invoice);
			m_InvoicePanel.setInvoice(l_Invoice);
			m_InvoicePanel.validate();
			}
    	} 
    }
 
//---------------------------------------------------------------------------

public void stateChanged(ChangeEvent p_Event) 
	{
	}

//---------------------------------------------------------------------------

public void invoiceChanged (InvoiceChangeEvent p_Event) 
	{
	Invoice l_Invoice;
	Patient	l_Patient;
	
	switch (p_Event.getType())
		{			
		case InvoiceChangeEvent.c_InvoiceSelectionChanged:
		
			l_Invoice = p_Event.getInvoice();
			this.setInvoice(l_Invoice);
			break;
		
		case InvoiceChangeEvent.c_InvoiceUpdated:
		
			l_Invoice = p_Event.getInvoice();
			if (l_Invoice != null)
				{
				l_Patient = l_Invoice.getPatient();
				if ((l_Patient != null) && l_Patient.equals(m_CurrentPatient))
					{
					this.reloadInvoices();
					}
				this.fireInvoiceChange(InvoiceChangeEvent.c_InvoiceUpdated, l_Invoice);
				}
			break;
		
		}
	}

//---------------------------------------------------------------------------

public void patientChanged (Patient p_Patient) 
	{	
	//=======================================================================
	//= Check first of all whether patient is not null and whether
	//= it is already stored in the database.
	//=======================================================================

	if ((p_Patient != null) && (p_Patient.isPersistent()))
		{
		//====================================================================
		//= If specified patient is the same as current patient, then we
		//= won't do anything
		//====================================================================
		
		if (p_Patient.equals(m_CurrentPatient)) 
			{
			m_CurrentPatient = p_Patient;
			m_PatientSummaryPanel.setPatient (p_Patient);
			return;
			}
			
		//====================================================================
		//= Next, if Billing module is currently showing, then we have to do
		//= a couple of things. First of all we have to switch to Invoice Tab,
		//= showing the list of invoices for specified patient. Next, we have
		//= to reset this module's current invoice as its none of this patients.
		//= In case Invoice Panel (in Invoice Tab) was in search mode, i.e. a
		//= search criterion was specified in table header, then we have to
		//= reset that search. After all has been reset, we're going to initialize
		//= Invoice Panel by setting its patient to specified one, pre-selecting
		//= the first invoice in list by default.
		//====================================================================
		
		if (this.isShowing())
			{
			m_MainPanel.setSelectedIndex(c_InvoiceTab);
			this.setInvoice(null);
			m_InvoiceStatusPanel.reset();
			m_EditorPanel.reset();
			m_MemoPanel.reset();
			
			m_CurrentPatient = p_Patient;
			
			if (m_InvoicePanel.isInSearchMode()) m_InvoicePanel.resetSearch();
			m_InvoicePanel.setPatient(p_Patient);
			m_InvoicePanel.selectFirstInvoice();
			this.setInvoice (m_InvoicePanel.getSelectedInvoice());
			
			m_PatientSummaryPanel.setPatient (p_Patient);
			}
		else
			{
			m_EditorPanel.setInvoice(null);
			this.reset ();
			if (m_InvoicePanel.isInSearchMode()) {
					m_InvoicePanel.resetSearch();				
				}
			}
		}
	else
		{
		//=======================================================================
		//= In case no valid patient was specified we're going to reset
		//= everything
		//=======================================================================
		m_EditorPanel.setInvoice(null);		
		this.reset ();
		}
	}

//---------------------------------------------------------------------------

/**
 * @author ferring
 * This method is needed to pass the filter option to the InvoiceListingPanel.
 * 
 * @param p_FilterByPhysician
 */
public void setInvoicePanelFilter (boolean p_FilterByPhysician)
	{
	this.m_InvoicePanel.setFilterByPhysician(p_FilterByPhysician);
	}

//---------------------------------------------------------------------------

public Date getDateOfInvoicePropertiesPanel ()
	{
	return m_InvoiceProperties.getInvoiceDate();
	}

//---------------------------------------------------------------------------

public void searchModeChanged (SearchModeEvent p_Event) 
	{
	if (p_Event.getSource() == m_InvoicePanel)
		{
		if (p_Event.isSearching() == false)
			{
			if (m_CurrentPatient != null)
				{
				setCurrentPatient (m_CurrentPatient);
				m_InvoicePanel.setPatient(m_CurrentPatient);
				m_InvoicePanel.selectFirstInvoice();
				this.setInvoice (m_InvoicePanel.getSelectedInvoice());
				}
				
			if ((Boolean)BillingModule.getUserSetting("General.ShowTabIcons"))
				m_InvoicePanel.setIcon(BillingModule.getIconResource("patient_invoices_tab.png"));
			}	
		else
			{
			if ((Boolean)BillingModule.getUserSetting("General.ShowTabIcons"))
				m_InvoicePanel.setIcon(BillingModule.getIconResource("invoices_search_tab.png"));
			}
		}
	}

//---------------------------------------------------------------------------

public void reset ()
	{
	m_InvoicePanel.reset();
	m_PatientSummaryPanel.reset();
	m_InvoiceStatusPanel.reset();
	m_EditorPanel.reset();
	m_MemoPanel.reset();
	
	m_CurrentPatient = null;	
	}

//---------------------------------------------------------------------------

public void handleGECAMedMessage (GECAMedMessage p_Message) 
	{
	Integer	l_PassageID;
	Patient	l_Patient;
	
	if (p_Message.getModul() instanceof PatientManagerModule)
		{
		if (p_Message.getMessage().equals(PatientHospitalisationPanel.PASSAGE_VERIFIED_CHANGED))
			{
			l_PassageID = (Integer) p_Message.getNewValue();
			this.processPassageVerified (l_PassageID);
			}	
//		else if (p_Message.getMessage().equals(PatientHospitalisationPanel.PASSAGE_RX_CHANGED))
//			{
//			l_PassageID = (Integer) p_Message.getNewValue();
//			this.processPassageChange (l_PassageID);
//			}	
		else if (p_Message.getMessage().equals(PatientHospitalisationPanel.PASSAGE_OPEN))
			{
			l_PassageID = (Integer) p_Message.getNewValue();
			this.processPassageOpen (l_PassageID);
			}
		else if (p_Message.getMessage().equals(PatientManagerModule.PATIENT_UPDATED))
			{
			l_Patient = (Patient) p_Message.getNewValue();
			if ((l_Patient != null) && (l_Patient.equals(m_CurrentPatient)))
				this.reloadInvoices();
			}
		} 
	else if (MedPres.MEDPRES_CHANGED.equals(p_Message.getMessage())) 
		{
		m_MedPres = this.prefetchMedPres();
		}
	}

//---------------------------------------------------------------------------

public void keyTyped(KeyEvent p_Event) 
	{
	}

//---------------------------------------------------------------------------

public void keyPressed(KeyEvent p_Event) 
	{
	if(!p_Event.isConsumed())
		{
		switch (p_Event.getKeyChar())    
			{
			case KeyEvent.VK_BACK_SPACE :
			case KeyEvent.VK_DELETE     : deleteSelectedInvoices();
										  break;
			case KeyEvent.VK_ENTER	    : editSelectedInvoice ();
										  break;
			}
		}   
	}

//---------------------------------------------------------------------------

public void keyReleased(KeyEvent p_Event) 
	{
	}

//---------------------------------------------------------------------------

public void actionPerformed (ActionEvent p_Event) 
	{
	if (p_Event.getSource().equals(m_SuperUserSwitch))
		{
		if (m_SuperUserSwitch.isSelected()) 
			 this.switchToSuperUser(); 
		else this.switchToPlainUser();
		}
	}

//---------------------------------------------------------------------------

public void relocalize ()
	{
	Iterator <GECAMedAction>	l_ActionIterator;
	Locale  l_Locale;
	
	super.relocalize();
	  	
	l_Locale = Translatrix.getLocale ();
	    	  	
	if (l_Locale != null)
		{
	    m_DateFormat = new SimpleDateFormat ("d MMMM yyyy",l_Locale);
	    m_TimeFormat = new SimpleDateFormat ("HH:mm",l_Locale);	
		}
	else
		{
	    m_DateFormat = new SimpleDateFormat ("d MMMM yyyy");
	    m_TimeFormat = new SimpleDateFormat ("HH:mm");	
		}

	if (m_InvoiceProperties != null)			m_InvoiceProperties.relocalize();
	if (m_AccidentProperties != null)			m_AccidentProperties.relocalize();
	if (m_HospitalisationProperties != null)	m_HospitalisationProperties.relocalize();
//	if (m_MedTransProperties != null)			m_MedTransProperties.relocalize();
	
	m_AdminSettings.relocalize();
	m_UserSettings.relocalize();

	if (m_NomenclaturePanel != null) m_NomenclaturePanel.relocalize ();	
	
	if (m_CurrentInvoice != null)
		 this.setInvoice (m_CurrentInvoice);
	else 
		this.titlePanel.setTopic(Translatrix.getTranslationString("Billing"));

	if (m_InvoicePanel != null) 
		{
		m_InvoicePanel.setTitle (Translatrix.getTranslationString("BillingModule.InvoiceTab"));
		m_InvoicePanel.relocalize();
		}
		
	if (m_EditorPanel != null)  
		{
		m_EditorPanel.setTitle (Translatrix.getTranslationString("BillingModule.EntryTab"));
		m_EditorPanel.relocalize();
		}
		
	if (m_MemoPanel != null)    
		{
		m_MemoPanel.setTitle (Translatrix.getTranslationString("BillingModule.MemoTab"));
		m_MemoPanel.relocalize();
		}
	
	if (m_StatementPanel != null)    
		{
		m_StatementPanel.setTitle (Translatrix.getTranslationString("BillingModule.StatementTab"));
		m_StatementPanel.relocalize();
		}
	
	if (m_ReminderPanel != null)
		{
		m_ReminderPanel.setTitle (Translatrix.getTranslationString("BillingModule.ReminderTab"));
		m_ReminderPanel.relocalize();
		
		}
		
	if (m_InvoiceActions != null)
		{
		l_ActionIterator = m_InvoiceActions.iterator();
		while (l_ActionIterator.hasNext())
			{
			l_ActionIterator.next().relocalize();
			}
		}

	if (m_StatementActions != null)
		{
		l_ActionIterator = m_StatementActions.iterator();
		while (l_ActionIterator.hasNext())
			{
			l_ActionIterator.next().relocalize();
			}
		}
	
	if (m_AccountingActions != null)
		{
		l_ActionIterator = m_AccountingActions.iterator();
		while (l_ActionIterator.hasNext())
			{
			l_ActionIterator.next().relocalize();
			}
		}
	}

//---------------------------------------------------------------------------

public void addHospitalisationClassListener (HospitalisationClassListener l)
	{
	m_HospitalisationProperties.addHospitalisationClassListener(l);
	}

//---------------------------------------------------------------------------

public void removeHospitalisationClassListener (HospitalisationClassListener l)
	{
	m_HospitalisationProperties.removeHospitalisationClassListener(l);
	}

public InvoiceEditorPanel getInvoiceEditorPanel ()
{
	return m_EditorPanel;
}


public boolean checkActDate(Date checkDate) {
	String check = "";
	boolean bDateChecked = false;
	
	
	if (checkDate == null) return true;
	
	try {
		
		Date today = DateUtil.round2Day(new Date());
		Date bDate = getCurrentPatient().getBirthDate();
		
		if ((Boolean)BillingModule.getSetting(BillingAdminSettings.c_CheckActFuture)) {
			if (!DateUtil.isSameDay(today, checkDate) && checkDate.after(today)) {
				check += Translatrix.getTranslationString("BillingAdminSettingsPlugin.ActFutureLabel") + "\n"; 
			}
		}
		
		if ((Boolean)BillingModule.getSetting(BillingAdminSettings.c_CheckActBeforeBirthDate)) {
			if (bDate == null) {
				bDateChecked = true;
				check += Translatrix.getTranslationString("BillingAdminSettingsPlugin.ActNoBirthdate") + "\n"; 
			}else if (checkDate.before(bDate)) {
				check += Translatrix.getTranslationString("BillingAdminSettingsPlugin.ActBeforeBirthLabel") + "\n"; 
			}
		}
		
		if ((Boolean)BillingModule.getSetting(BillingAdminSettings.c_CheckBirthDate)) {
			if (bDate == null) {
				if (! bDateChecked)
					check += Translatrix.getTranslationString("BillingAdminSettingsPlugin.ActNoBirthdate") + "\n"; 
			} else {
				Integer maxAge = (Integer) BillingModule.getSetting(BillingAdminSettings.c_CheckBirthDateMax);
				int diffDays = DateUtil.getDateDiff(today, bDate);
				if (diffDays > (maxAge * 365)) {
					check += Translatrix.getTranslationString("BillingAdminSettingsPlugin.ActBirthdateCheckLabel") + " " + maxAge + "\n"; 
				}					
			}
		}
		
		if (check.length() > 0) {
			Object[] options = {
					Translatrix.getTranslationString("BillingAdminSettingsPlugin.Actkeep"),
					Translatrix.getTranslationString("BillingAdminSettingsPlugin.Actcancel")};
			int n = JOptionPane.showOptionDialog(this,
					check,
					Translatrix.getTranslationString("BillingAdminSettingsPlugin.ActCheckTitle"),
					JOptionPane.YES_NO_OPTION,
					JOptionPane.QUESTION_MESSAGE,
					null,     //do not use a custom Icon
					options,  //the titles of buttons
					options[0]); //default button title
			if (n == JOptionPane.NO_OPTION) 
				return false;
		}
	} catch (Exception e) {
		m_Logger.error("Error checking Act date!", e);
	}
	
	return true;
}



//---------------------------------------------------------------------------

//public static boolean useLeadingZeros ()
//	{
//	if (m_UseLeadingZeros == null)
//		{
//		m_UseLeadingZeros = (Boolean) BillingModule.getSetting(
//							BillingAdminSettings.c_UseLeadingZerosSetting);
//	
//		if (m_UseLeadingZeros == null)
//			m_UseLeadingZeros = Boolean.TRUE;
//		}
//	
//	return m_UseLeadingZeros.booleanValue();
//	}


//***************************************************************************
//* End Of Class                                                            *
//***************************************************************************
	}

