/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 Adempiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU General Public License for more details. *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
*****************************************************************************/
package org.compiere.pos;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputMethodEvent;
import java.awt.event.InputMethodListener;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.util.Locale;
import javax.swing.border.TitledBorder;
import org.compiere.apps.AEnv;
import org.compiere.grid.ed.VNumber;
import org.compiere.model.MCash;
import org.compiere.model.MCashBook;
import org.compiere.model.MCashLine;
import org.compiere.model.MInvoice;
import org.compiere.model.MQuery;
import org.compiere.swing.CButton;
import org.compiere.swing.CLabel;
import org.compiere.swing.CPanel;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.DisplayType;
import org.compiere.util.Env;
import org.compiere.util.Language;
import org.compiere.util.Msg;
import org.compiere.util.TimeUtil;
/**
* @author Comunidad de Desarrollo OpenXpertya
* *Basado en Codigo Original Modificado, Revisado y Optimizado de:
* *Jose A.Gonzalez, Conserti.
*
* @version $Id: CashSubFunctions.java,v 0.9 $
*
* @contributor $Id: Consultoria y Soporte en Redes y Tecnologias de la Informacion S.L.
*
* @contributor Emiliano Pereyra - http://www.ergio.com.ar
*
*/
public class CashSubFunctions extends PosQuery implements ActionListener, InputMethodListener
{
/**
*
*/
private static final long serialVersionUID = -7496311215470523905L;
/**
* Constructor
*/
public CashSubFunctions (PosBasePanel posPanel)
{
super(posPanel);
} // PosQueryProduct
private CButton f_initialChange = null;
private CButton f_inputsOutputs = null;
private CButton f_tickets = null;
private CButton f_closingCash = null;
private CButton f_cashScrutiny = null;
private CButton f_pos = null;
private CPanel buttonPanel;
// for initial change
private CPanel cInitial;
private CLabel l_PreviousChange = null;
private VNumber v_PreviousChange;
private CLabel l_change = null;
private VNumber v_change;
private CButton f_change = null;
// for cash scrutiny
private CPanel cScrutiny;
private CLabel l_previousBalance = null;
private VNumber v_previousBalance;
private CLabel l_ActualBalance = null;
private VNumber v_ActualBalance;
private CLabel l_difference = null;
private VNumber v_difference;
private CButton f_calculateDifference = null;
private CPanel panel;
// LAR improvements
private Locale locale = Language.getLoginLanguage().getLocale();
private NumberFormat nf = NumberFormat.getInstance(locale);
/** Logger */
private static CLogger log = CLogger.getCLogger(SubCheckout.class);
/**
* Set up Panel
*/
protected void init()
{
CPanel main = new CPanel();
main.setLayout(new BorderLayout(2,6));
main.setPreferredSize(new Dimension(400,600));
getContentPane().add(main);
// North
panel = new CPanel(new GridBagLayout());
main.add (panel, BorderLayout.CENTER);
panel.setBorder(new TitledBorder(Msg.getMsg(p_ctx, "Cash Functions")));
GridBagConstraints gbc = new GridBagConstraints();
//
gbc.gridx = 0;
gbc.gridy = 0;
gbc.anchor = GridBagConstraints.CENTER;
gbc.weightx = .3;
gbc.weighty = 0.05;
//******************** Main buttons **********************************
f_initialChange = createButtonAction("InitialChange", null);
f_initialChange.setMaximumSize(new Dimension(160,35));
f_initialChange.setMinimumSize(new Dimension(160,35));
f_initialChange.setPreferredSize(new Dimension(160,35));
panel.add (f_initialChange, gbc);
//
f_closingCash = createButtonAction("CashClosing", null);
f_closingCash.setPreferredSize(new Dimension(160,35));
f_closingCash.setMaximumSize(new Dimension(160,35));
f_closingCash.setMinimumSize(new Dimension(160,35));
gbc.gridy = 1;
panel.add (f_closingCash, gbc);
//
f_cashScrutiny = createButtonAction("CashScrutiny", null);
f_cashScrutiny.setPreferredSize(new Dimension(160,35));
f_cashScrutiny.setMaximumSize(new Dimension(160,35));
f_cashScrutiny.setMinimumSize(new Dimension(160,35));
gbc.gridy = 2;
panel.add (f_cashScrutiny, gbc);
//
f_inputsOutputs = createButtonAction("InputsOutputs", null);
f_inputsOutputs.setPreferredSize(new Dimension(160,35));
f_inputsOutputs.setMaximumSize(new Dimension(160,35));
f_inputsOutputs.setMinimumSize(new Dimension(160,35));
gbc.gridy = 3;
panel.add (f_inputsOutputs, gbc);
//
f_tickets = createButtonAction("Tickets", null);
f_tickets.setPreferredSize(new Dimension(160,35));
f_tickets.setMaximumSize(new Dimension(160,35));
f_tickets.setMinimumSize(new Dimension(160,35));
gbc.gridy = 4;
panel.add (f_tickets, gbc);
//
f_pos = createButtonAction("End", null);
f_pos.setPreferredSize(new Dimension(160,35));
f_pos.setMaximumSize(new Dimension(160,35));
f_pos.setMinimumSize(new Dimension(160,35));
gbc.gridy = 5;
panel.add (f_pos, gbc);
//*************************** Panel to put buttons *************************
gbc.gridx = 1;
gbc.anchor = GridBagConstraints.WEST;
gbc.gridy = 0;
gbc.gridheight = 5;
buttonPanel = new CPanel(new GridBagLayout());
buttonPanel.setBorder(new TitledBorder(""));
buttonPanel.setMaximumSize(new Dimension(300,400));
buttonPanel.setMinimumSize(new Dimension(300,400));
buttonPanel.setPreferredSize(new Dimension(300,400));
panel.add (buttonPanel, gbc);
//*************************** Panel for initial change *************************
gbc.gridx = 1;
gbc.anchor = GridBagConstraints.WEST;
gbc.gridy = 0;
gbc.gridheight = 5;
cInitial = new CPanel(new GridBagLayout());
cInitial.setBorder(new TitledBorder(Msg.getMsg(p_ctx, "InitialChange")));
cInitial.setVisible(false);
panel.add (cInitial, gbc);
GridBagConstraints gbc0 = new GridBagConstraints();
gbc0.anchor = GridBagConstraints.CENTER;
//
gbc0.gridx = 0;
gbc0.gridy = 0;
l_PreviousChange = new CLabel(Msg.getMsg(p_ctx, "PreviousChange"));
cInitial.add (l_PreviousChange, gbc0);
gbc0.gridx = 1;
v_PreviousChange = new VNumber("PreviousChange", false, true, false, DisplayType.Amount, "PreviousChange");
v_PreviousChange.setColumns(10, 25);
cInitial.add(v_PreviousChange, gbc0);
v_PreviousChange.setValue(Env.ZERO);
//
gbc0.gridx = 0;
gbc0.gridy = 1;
l_change = new CLabel(Msg.getMsg(p_ctx, "InitialChange"));
cInitial.add (l_change, gbc0);
gbc0.gridx = 1;
v_change = new VNumber("Change", false, false, true, DisplayType.Amount, "Change");
v_change.setColumns(10, 25);
cInitial.add(v_change, gbc0);
v_change.setValue(Env.ZERO);
gbc0.gridy = 2;
gbc0.gridx = 0;
gbc0.gridwidth = 2;
//gbc0.fill = GridBagConstraints.HORIZONTAL;
f_change = createButtonAction("SaveChange", null);
f_change.setText("Save Change");
f_change.setPreferredSize(new Dimension(160,35));
f_change.setMaximumSize(new Dimension(160,35));
f_change.setMinimumSize(new Dimension(160,35));
cInitial.add (f_change, gbc0);
cInitial.setMaximumSize(new Dimension(300,400));
cInitial.setMinimumSize(new Dimension(300,400));
cInitial.setPreferredSize(new Dimension(300,400));
//****************************** Panel for cash scrutiniy ************************
gbc.gridx = 1;
gbc.anchor = GridBagConstraints.WEST;
gbc.gridy = 0;
gbc.gridheight = 5;
// gbc.weightx = .7;
cScrutiny = new CPanel(new GridBagLayout());
cScrutiny.setBorder(new TitledBorder(Msg.getMsg(p_ctx, "CashScrutiny")));
cScrutiny.setVisible(false);
panel.add (cScrutiny, gbc);
GridBagConstraints gbc1 = new GridBagConstraints();
gbc1.anchor = GridBagConstraints.CENTER;
//
gbc1.gridx = 0;
gbc1.gridy = 0;
l_previousBalance = new CLabel(Msg.getMsg(p_ctx, "PreviousBalance"));
cScrutiny.add (l_previousBalance, gbc1);
gbc1.gridx = 1;
v_previousBalance = new VNumber("PreviousBalance", false, true, false, DisplayType.Amount, "PreviousBalance");
v_previousBalance.setColumns(10, 25);
cScrutiny.add(v_previousBalance, gbc1);
v_previousBalance.setValue(Env.ZERO);
//
gbc1.gridx = 0;
gbc1.gridy = 1;
l_ActualBalance = new CLabel("Actual Balance");
cScrutiny.add (l_ActualBalance, gbc1);
gbc1.gridx = 1;
v_ActualBalance = new VNumber("ActualBalance", false, false, true, DisplayType.Amount, "ActualBalance");
v_ActualBalance.setColumns(10, 25);
v_ActualBalance.addActionListener(this);
v_ActualBalance.addInputMethodListener(this);
cScrutiny.add(v_ActualBalance, gbc1);
v_ActualBalance.setValue(Env.ZERO);
//
gbc1.gridx = 0;
gbc1.gridy = 2;
l_difference = new CLabel(Msg.getMsg(p_ctx, "Difference"));
cScrutiny.add (l_difference, gbc1);
gbc1.gridx = 1;
v_difference = new VNumber("Difference", false, true, false, DisplayType.Amount, "Difference");
v_difference.setColumns(10, 25);
cScrutiny.add(v_difference, gbc1);
v_difference.setValue(Env.ZERO);
//
gbc1.gridx = 0;
gbc1.gridy = 4;
gbc1.gridwidth = 2;
gbc1.fill = GridBagConstraints.HORIZONTAL;
f_calculateDifference = createButtonAction("AnnotateDifference", null);
f_calculateDifference.setText("Annotate Difference");
f_calculateDifference.setPreferredSize(new Dimension(160,35));
f_calculateDifference.setMaximumSize(new Dimension(160,35));
f_calculateDifference.setMinimumSize(new Dimension(160,35));
cScrutiny.add (f_calculateDifference, gbc1);
cScrutiny.setMaximumSize(new Dimension(300,400));
cScrutiny.setMinimumSize(new Dimension(300,400));
cScrutiny.setPreferredSize(new Dimension(400,400));
} // init
/**
* Dispose
*/
public void dispose()
{
removeAll();
panel = null;
centerScroll = null;
confirm = null;
setVisible(false);
super.dispose();
} // dispose
/**
* Action Listener
* @param e event
*/
public void actionPerformed (ActionEvent e)
{
String action = e.getActionCommand();
if (action == null || action.length() == 0)
return;
log.info("actionPerformed: " + action);
// to display panel with initial change
if (action.equals("InitialChange"))
{
cmd_displayInitialChange();
}
// to display panel with cash closing
else if (action.equals("CashClosing"))
{
dispose();
Timestamp today = TimeUtil.getDay(System.currentTimeMillis());
MCash cash = MCash.get(p_ctx, p_pos.getC_CashBook_ID(), today, null);
MQuery query = new MQuery(MCash.Table_Name);
query.addRestriction("C_Cash_ID", MQuery.EQUAL, cash.getC_Cash_ID());
AEnv.zoom(query);
}
// to open window with inputs and outputs of cash
else if (action.equals("InputsOutputs"))
{
dispose();
Timestamp today = TimeUtil.getDay(System.currentTimeMillis());
MCash cash = MCash.get(p_ctx, p_pos.getC_CashBook_ID(), today, null);
AEnv.zoom(MCash.Table_ID, cash.getC_Cash_ID());
}
else if (action.equals("Tickets"))
{
cmd_displayTickets();
}
// Cash (Payment)
else if (action.equals("CashScrutiny"))
{
cmd_displayCashScrutiny();
}
else if (action.equals("End"))
{
dispose();
}
else if (action.equals("SaveChange"))
{
cmd_saveChange();
}
else if (action.equals("AnnotateDifference"))
{
cmd_calculateDifference();
cmd_annotateDifference();
}
else if (e.getSource() == v_ActualBalance)
cmd_calculateDifference();
} // actionPerformed
/**
* Desplegar panel de Cambio Inicial
*
* @author Comunidad de Desarrollo OpenXpertya
* *Basado en Codigo Original Modificado, Revisado y Optimizado de:
* *Copyright (c) ConSerTi
*/
private void cmd_displayInitialChange()
{
if (cScrutiny.isVisible())
cScrutiny.setVisible(false);
if (buttonPanel.isVisible())
buttonPanel.setVisible(false);
cInitial.setVisible(true);
Timestamp today = TimeUtil.getDay(System.currentTimeMillis());
MCash cash = MCash.get(p_ctx, p_pos.getC_CashBook_ID(), today, null);
if (cash != null)
{
v_PreviousChange.setValue(cash.getEndingBalance());
v_change.setValue(cash.getEndingBalance());
}
else
log.severe("No Cash");
}
/**
* Desplegar panel de Scrutiny de caja
*
* @author Comunidad de Desarrollo OpenXpertya
* *Basado en Codigo Original Modificado, Revisado y Optimizado de:
* *Copyright (c) ConSerTi
*/
private void cmd_displayCashScrutiny()
{
if (cInitial.isVisible())
cInitial.setVisible(false);
if (buttonPanel.isVisible())
buttonPanel.setVisible(false);
cScrutiny.setVisible(true);
// calculate total until the moment and shows it in scrutiny panel
Timestamp today = TimeUtil.getDay(System.currentTimeMillis());
MCash cash = MCash.get(p_ctx, p_pos.getC_CashBook_ID(), today, null);
v_previousBalance.setValue(cash.getEndingBalance());
}
private void cmd_displayTickets()
{
String sql = "SELECT C_DocTypeInvoice_ID FROM C_DocType WHERE C_DocType_ID=?";
int c_DocTypeInvoice_ID = DB.getSQLValue(null, sql, p_pos.getC_DocType_ID());
MQuery query = new MQuery(MInvoice.Table_Name);
query.addRestriction("C_DocType_ID", MQuery.EQUAL, c_DocTypeInvoice_ID);
AEnv.zoom(query);
dispose();
}
/**
* Save the initial change of the cash
*
* @author Comunidad de Desarrollo OpenXpertya
* *Basado en Codigo Original Modificado, Revisado y Optimizado de:
* *Copyright (c) ConSerTi
*/
private void cmd_saveChange()
{
Timestamp today = TimeUtil.getDay(System.currentTimeMillis());
MCash cash = MCash.get(p_ctx, p_pos.getC_CashBook_ID(), today, null);
BigDecimal initialChange = (BigDecimal)v_change.getValue();
if (cash != null && cash.get_ID() != 0 && initialChange.compareTo(cash.getEndingBalance()) != 0)
{
// Prepare localized message with arguments > "Initial Change Before: {0} Now {1}"
MessageFormat mf = new MessageFormat(Msg.getMsg(p_ctx, "InitialChangeBefore"), locale);
Object[] args = {nf.format(cash.getEndingBalance()), nf.format(initialChange) }; // {0}, {1}
String description = mf.format(args);
MCashLine cl = new MCashLine (cash);
cl.setCashType(MCashLine.CASHTYPE_Difference);
cl.setAmount(initialChange.subtract(cash.getEndingBalance()));
cl.setDescription(description);
cl.save();
}
v_PreviousChange.setValue(initialChange);
}
/**
* Calculate difference between previous balance and actual
* for cash scrutiny
*
* @author Comunidad de Desarrollo OpenXpertya
* *Basado en Codigo Original Modificado, Revisado y Optimizado de:
* *Copyright (c) ConSerTi
*/
private void cmd_calculateDifference()
{
// calculate difference between scrutiny of previous and actual balance
BigDecimal previousValue, actualValue;
Timestamp today = TimeUtil.getDay(System.currentTimeMillis());
MCash cash = MCash.get(p_ctx, p_pos.getC_CashBook_ID(), today, null);
v_previousBalance.setValue(cash.getEndingBalance());
previousValue = cash.getEndingBalance();
actualValue = (BigDecimal)v_ActualBalance.getValue();
v_difference.setValue(actualValue.subtract(previousValue));
}
/**
* Annotate the difference between previous balance and actual
* from cash scrutiny in the cash book
*
* @author Comunidad de Desarrollo OpenXpertya
* *Basado en Codigo Original Modificado, Revisado y Optimizado de:
* *Copyright (c) ConSerTi
*/
private void cmd_annotateDifference()
{
// calculate difference from scrutiny between previous and actual balance
BigDecimal previousValue, actualValue, difference;
previousValue = (BigDecimal)v_previousBalance.getValue();
actualValue = (BigDecimal)v_ActualBalance.getValue();
difference = actualValue.subtract(previousValue);
MCashBook cashBook = new MCashBook(p_ctx, p_pos.getC_CashBook_ID(), null);
Timestamp today = TimeUtil.getDay(System.currentTimeMillis());
MCash cash = MCash.get(p_ctx, cashBook.getC_CashBook_ID(), today, null);
if (cash != null && cash.get_ID() != 0 && difference.compareTo(cash.getStatementDifference()) != 0)
{
// Prepare localized message with arguments > "Cash Scrutiny -> Before: {0} Now {1}"
MessageFormat mf = new MessageFormat(Msg.getMsg(p_ctx, "CashScrutinyBefore"), locale);
Object[] args = {nf.format(previousValue), nf.format(actualValue) }; // {0}, {1}
String description = mf.format(args);
MCashLine cl = new MCashLine (cash);
cl.setCashType(MCashLine.CASHTYPE_Difference);
cl.setAmount(difference);
cl.setDescription(description);
cl.save();
}
cash = MCash.get(p_ctx, p_pos.getC_CashBook_ID(), today, null);
v_previousBalance.setValue(cash.getEndingBalance());
v_ActualBalance.setValue(Env.ZERO);
v_difference.setValue(Env.ZERO);
}
/**
* calculate difference in cash scrutiny every time the cursor moves
*/
public void caretPositionChanged(InputMethodEvent event)
{
cmd_calculateDifference();
}
/**
* calculate difference between cash scrutiniy each time the actual balance text changes
*/
public void inputMethodTextChanged(InputMethodEvent event)
{
cmd_calculateDifference();
}
@Override
protected void close() {
}
@Override
protected void enableButtons() {
}
@Override
public void reset() {
}
} // CashSubFunctions