/*
* Offene-Pflege.de (OPDE)
* Copyright (C) 2006-2012 Torsten Löhr
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License V2 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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
* www.offene-pflege.de
* ------------------------
* Auf deutsch (freie Übersetzung. Rechtlich gilt die englische Version)
* Dieses Programm ist freie Software. Sie können es unter den Bedingungen der GNU General Public License,
* wie von der Free Software Foundation veröffentlicht, weitergeben und/oder modifizieren, gemäß Version 2 der Lizenz.
*
* Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es Ihnen von Nutzen sein wird, aber
* OHNE IRGENDEINE GARANTIE, sogar ohne die implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN
* BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.
*
* Sie sollten ein Exemplar der GNU General Public License zusammen mit diesem Programm erhalten haben. Falls nicht,
* schreiben Sie an die Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.
*
*/
package op.allowance;
import com.jidesoft.pane.CollapsiblePane;
import com.jidesoft.pane.CollapsiblePanes;
import com.jidesoft.pane.event.CollapsiblePaneAdapter;
import com.jidesoft.pane.event.CollapsiblePaneEvent;
import com.jidesoft.popup.JidePopup;
import com.jidesoft.swing.JideBoxLayout;
import com.jidesoft.swing.JideButton;
import entity.Allowance;
import entity.AllowanceTools;
import entity.files.SYSFilesTools;
import entity.info.Resident;
import entity.info.ResidentTools;
import gui.GUITools;
import gui.interfaces.CleanablePanel;
import gui.interfaces.DefaultCPTitle;
import op.OPDE;
import op.system.InternalClassACL;
import op.threads.DisplayManager;
import op.threads.DisplayMessage;
import op.tools.*;
import org.jdesktop.swingx.JXSearchField;
import org.jdesktop.swingx.VerticalLayout;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import org.joda.time.LocalDate;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
import javax.persistence.OptimisticLockException;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyVetoException;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
/**
* @author tloehr
*/
public class PnlAllowance extends CleanablePanel {
// NumberFormat cf = NumberFormat.getCurrencyInstance();
Format monthFormatter = new SimpleDateFormat("MMMM yyyy");
private JScrollPane jspSearch;
private CollapsiblePanes searchPanes;
private JXSearchField txtSearch;
private JComboBox cmbResident;
private ArrayList<Resident> lstResidents;
private HashMap<String, ArrayList<Allowance>> cashmap;
private HashMap<String, CollapsiblePane> cpMap;
private HashMap<String, JPanel> contentmap;
private HashMap<Allowance, JPanel> linemap;
private HashMap<String, BigDecimal> carrySums;
private HashMap<Resident, Pair<LocalDate, LocalDate>> minmax;
private JPanel pnlCash;
private JScrollPane jspCash;
private CollapsiblePanes cpsCash;
public PnlAllowance(JScrollPane jspSearch) {
super("admin.residents.cash");
this.jspSearch = jspSearch;
initComponents();
prepareSearchArea();
initPanel();
reloadDisplay();
}
@Override
public String getInternalClassID() {
return internalClassID;
}
private void initPanel() {
OPDE.getMainframe().collapseNursingRecords();
lstResidents = new ArrayList<Resident>();
cpMap = new HashMap<String, CollapsiblePane>();
cashmap = new HashMap<String, ArrayList<Allowance>>();
contentmap = new HashMap<String, JPanel>();
linemap = new HashMap<Allowance, JPanel>();
carrySums = new HashMap<>();
minmax = new HashMap<>();
lstResidents = ResidentTools.getAllActive();
}
@Override
public void reload() {
lstResidents.clear();
lstResidents = ResidentTools.getAllActive();
reloadDisplay();
}
@Override
public void cleanup() {
super.cleanup();
lstResidents.clear();
cpsCash.removeAll();
searchPanes.removeAll();
cashmap.clear();
cpMap.clear();
contentmap.clear();
carrySums.clear();
minmax.clear();
}
private void initComponents() {
pnlCash = new JPanel();
jspCash = new JScrollPane();
cpsCash = new CollapsiblePanes();
//======== this ========
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
//======== pnlCash ========
{
pnlCash.setLayout(new BoxLayout(pnlCash, BoxLayout.X_AXIS));
//======== jspCash ========
{
//======== cpsCash ========
{
cpsCash.setLayout(new BoxLayout(cpsCash, BoxLayout.X_AXIS));
}
jspCash.setViewportView(cpsCash);
}
pnlCash.add(jspCash);
}
add(pnlCash);
}
private void reloadDisplay() {
/***
* _ _ ____ _ _
* _ __ ___| | ___ __ _ __| | _ \(_)___ _ __ | | __ _ _ _
* | '__/ _ \ |/ _ \ / _` |/ _` | | | | / __| '_ \| |/ _` | | | |
* | | | __/ | (_) | (_| | (_| | |_| | \__ \ |_) | | (_| | |_| |
* |_| \___|_|\___/ \__,_|\__,_|____/|_|___/ .__/|_|\__,_|\__, |
* |_| |___/
*/
final boolean withworker = false;
cpsCash.removeAll();
cashmap.clear();
cpMap.clear();
contentmap.clear();
carrySums.clear();
minmax.clear();
if (withworker) {
OPDE.getMainframe().setBlocked(true);
OPDE.getDisplayManager().setProgressBarMessage(new DisplayMessage(SYSTools.xx("misc.msg.wait"), -1, 100));
SwingWorker worker = new SwingWorker() {
@Override
protected Object doInBackground() throws Exception {
int progress = 0;
OPDE.getDisplayManager().setProgressBarMessage(new DisplayMessage(SYSTools.xx("misc.msg.wait"), progress, lstResidents.size()));
for (Resident resident : lstResidents) {
progress++;
createCP4(resident);
OPDE.getDisplayManager().setProgressBarMessage(new DisplayMessage(SYSTools.xx("misc.msg.wait"), progress, lstResidents.size()));
}
return null;
}
@Override
protected void done() {
OPDE.getDisplayManager().setMainMessage(SYSTools.xx(internalClassID));
buildPanel();
OPDE.getDisplayManager().setProgressBarMessage(null);
OPDE.getMainframe().setBlocked(false);
}
};
worker.execute();
} else {
for (Resident resident : lstResidents) {
createCP4(resident);
}
OPDE.getDisplayManager().setMainMessage(SYSTools.xx(internalClassID));
// if (currentResident != null) {
// OPDE.getDisplayManager().setMainMessage(ResidentTools.getLabelText(currentResident));
// } else {
// OPDE.getDisplayManager().setMainMessage(SYSTools.xx(internalClassID));
// }
buildPanel();
}
}
private CollapsiblePane createCP4(final Resident resident) {
/***
* _ ____ ____ _ _ ______ _ _ _ __
* ___ _ __ ___ __ _| |_ ___ / ___| _ \| || | / / _ \ ___ ___(_) __| | ___ _ __ | |\ \
* / __| '__/ _ \/ _` | __/ _ \ | | |_) | || |_| || |_) / _ \/ __| |/ _` |/ _ \ '_ \| __| |
* | (__| | | __/ (_| | || __/ |___| __/|__ _| || _ < __/\__ \ | (_| | __/ | | | |_| |
* \___|_| \___|\__,_|\__\___|\____|_| |_| | ||_| \_\___||___/_|\__,_|\___|_| |_|\__| |
* \_\ /_/
*/
final String key = resident.getRID();
if (!cpMap.containsKey(key)) {
cpMap.put(key, new CollapsiblePane());
try {
cpMap.get(key).setCollapsed(true);
} catch (PropertyVetoException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
final CollapsiblePane cpResident = cpMap.get(key);
if (!carrySums.containsKey(getKey(resident, SYSCalendar.eoy(new LocalDate())))) {
carrySums.put(getKey(resident, SYSCalendar.eoy(new LocalDate())), AllowanceTools.getSUM(resident, SYSCalendar.eoy(new LocalDate())));
}
BigDecimal sumOverall = carrySums.get(getKey(resident, SYSCalendar.eoy(new LocalDate())));
String title = "<html><table border=\"0\">" +
"<tr>" +
"<td width=\"520\" align=\"left\"><font size=+1>" + resident.toString() + "</font></td>" +
"<td width=\"200\" align=\"right\"><font size=+1" +
(sumOverall.compareTo(BigDecimal.ZERO) < 0 ? " color=\"red\" " : "") +
">" + SYSTools.formatCurrency(sumOverall) + "</font></td>" +
"</tr>" +
"</table>" +
"</html>";
DefaultCPTitle cptitle = new DefaultCPTitle(title, e -> {
try {
cpResident.setCollapsed(!cpResident.isCollapsed());
} catch (PropertyVetoException pve) {
// BAH!
}
});
if (OPDE.getAppInfo().isAllowedTo(InternalClassACL.ARCHIVE, internalClassID) && OPDE.getAppInfo().isAllowedTo(InternalClassACL.PRINT, internalClassID)) {
/***
* ____ _ _ ____ _ _ _
* | _ \ _ __(_)_ __ | |_| _ \ ___ ___(_) __| | ___ _ __ | |_
* | |_) | '__| | '_ \| __| |_) / _ \/ __| |/ _` |/ _ \ '_ \| __|
* | __/| | | | | | | |_| _ < __/\__ \ | (_| | __/ | | | |_
* |_| |_| |_|_| |_|\__|_| \_\___||___/_|\__,_|\___|_| |_|\__|
*
*/
final JButton btnPrintResident = new JButton(SYSConst.icon22print2);
btnPrintResident.setPressedIcon(SYSConst.icon22print2Pressed);
btnPrintResident.setAlignmentX(Component.RIGHT_ALIGNMENT);
btnPrintResident.setContentAreaFilled(false);
btnPrintResident.setBorder(null);
btnPrintResident.setToolTipText(SYSTools.xx("admin.residents.cash.btnprintresident.tooltip"));
btnPrintResident.addActionListener(actionEvent -> SYSFilesTools.print(AllowanceTools.getAsHTML(AllowanceTools.getAll(resident), BigDecimal.ZERO, resident), true));
cptitle.getRight().add(btnPrintResident);
}
cpResident.setTitleLabelComponent(cptitle.getMain());
cpResident.setSlidingDirection(SwingConstants.SOUTH);
/***
* _ _ _ _ _ _ _
* ___| (_) ___| | _____ __| | ___ _ __ _ __ ___ ___(_) __| | ___ _ __ | |_
* / __| | |/ __| |/ / _ \/ _` | / _ \| '_ \ | '__/ _ \/ __| |/ _` |/ _ \ '_ \| __|
* | (__| | | (__| < __/ (_| | | (_) | | | | | | | __/\__ \ | (_| | __/ | | | |_
* \___|_|_|\___|_|\_\___|\__,_| \___/|_| |_| |_| \___||___/_|\__,_|\___|_| |_|\__|
*
*/
cpResident.addCollapsiblePaneListener(new CollapsiblePaneAdapter() {
@Override
public void paneExpanded(CollapsiblePaneEvent collapsiblePaneEvent) {
// somebody clicks on the name of the resident. the cash informations
// are loaded from the database, if necessary.
cpResident.setContentPane(createContentPanel4(resident));
}
});
cpResident.setBackground(getBG(resident, 7));
if (!cpResident.isCollapsed()) {
cpResident.setContentPane(createContentPanel4(resident));
}
cpResident.setHorizontalAlignment(SwingConstants.LEADING);
cpResident.setOpaque(false);
return cpResident;
}
private JPanel createContentPanel4(final Resident resident) {
JPanel pnlContent = new JPanel(new VerticalLayout());
final JidePopup popupTX = new JidePopup();
popupTX.setMovable(false);
PnlTX pnlTX = getPnlTX(resident, null);
popupTX.setContentPane(pnlTX);
popupTX.removeExcludedComponent(pnlTX);
popupTX.setDefaultFocusComponent(pnlTX);
final JideButton btnNewTX = GUITools.createHyperlinkButton(SYSTools.xx("admin.residents.cash.enterTXs"), SYSConst.icon22add, null);
btnNewTX.addActionListener(actionEvent -> {
popupTX.setOwner(btnNewTX);
GUITools.showPopup(popupTX, SwingConstants.NORTH);
});
btnNewTX.setBackground(getBG(resident, 9));
btnNewTX.setOpaque(true);
pnlContent.add(btnNewTX);
if (!minmax.containsKey(resident)) {
minmax.put(resident, AllowanceTools.getMinMax(resident));
}
if (minmax.get(resident) != null) {
LocalDate start = SYSCalendar.bom(minmax.get(resident).getFirst());
LocalDate end = resident.isActive() ? new LocalDate() : SYSCalendar.eom(minmax.get(resident).getSecond());
CollapsiblePane cpArchive = new CollapsiblePane(SYSTools.xx("admin.residents.cash.archive"));
try {
cpArchive.setCollapsed(true);
} catch (PropertyVetoException e) {
//bah!
}
cpArchive.setBackground(getBG(resident, 7));
JPanel pnlArchive = new JPanel(new VerticalLayout());
cpArchive.setContentPane(pnlArchive);
for (int year = end.getYear(); year >= start.getYear(); year--) {
if (year >= new LocalDate().getYear() - 1) {
pnlContent.add(createCP4(resident, year));
} else if (OPDE.getAppInfo().isAllowedTo(InternalClassACL.ARCHIVE, internalClassID)) {
pnlArchive.add(createCP4(resident, year));
}
}
if (pnlArchive.getComponentCount() > 0) {
pnlContent.add(cpArchive);
}
}
return pnlContent;
}
private CollapsiblePane createCP4(final Resident resident, final int year) {
LocalDate min = SYSCalendar.bom(minmax.get(resident).getFirst());
LocalDate max = resident.isActive() ? new LocalDate() : SYSCalendar.eom(minmax.get(resident).getSecond());
final LocalDate start = new LocalDate(year, 1, 1).isBefore(min.dayOfMonth().withMinimumValue()) ? min.dayOfMonth().withMinimumValue() : new LocalDate(year, 1, 1);
final LocalDate end = new LocalDate(year, 12, 31).isAfter(max.dayOfMonth().withMaximumValue()) ? max.dayOfMonth().withMaximumValue() : new LocalDate(year, 12, 31);
final String key = resident.getRID() + "-" + year;
if (!cpMap.containsKey(key)) {
cpMap.put(key, new CollapsiblePane());
try {
cpMap.get(key).setCollapsed(true);
} catch (PropertyVetoException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
final CollapsiblePane cpYear = cpMap.get(key);
if (!carrySums.containsKey(key + "-12")) {
carrySums.put(key + "-12", AllowanceTools.getSUM(resident, SYSCalendar.eoy(start)));
}
String title = "<html><table border=\"0\">" +
"<tr>" +
"<td width=\"520\" align=\"left\"><font size=+1>" + Integer.toString(year) + "</font></td>" +
"<td width=\"200\" align=\"right\">" +
(carrySums.get(key + "-12").compareTo(BigDecimal.ZERO) < 0 ? "<font color=\"red\">" : "") +
SYSTools.formatCurrency(carrySums.get(key + "-12")) +
(carrySums.get(key + "-12").compareTo(BigDecimal.ZERO) < 0 ? "</font>" : "") +
"</td>" +
"</tr>" +
"</table>" +
"</font></html>";
DefaultCPTitle cptitle = new DefaultCPTitle(title, e -> {
try {
cpYear.setCollapsed(!cpYear.isCollapsed());
} catch (PropertyVetoException pve) {
// BAH!
}
});
GUITools.addExpandCollapseButtons(cpYear, cptitle.getRight());
/***
* ____ _ _ __ __
* | _ \ _ __(_)_ __ | |\ \ / /__ __ _ _ __
* | |_) | '__| | '_ \| __\ V / _ \/ _` | '__|
* | __/| | | | | | | |_ | | __/ (_| | |
* |_| |_| |_|_| |_|\__||_|\___|\__,_|_|
*
*/
final JButton btnPrintYear = new JButton(SYSConst.icon22print2);
btnPrintYear.setPressedIcon(SYSConst.icon22print2Pressed);
btnPrintYear.setAlignmentX(Component.RIGHT_ALIGNMENT);
btnPrintYear.setContentAreaFilled(false);
btnPrintYear.setBorder(null);
btnPrintYear.setToolTipText(SYSTools.xx("misc.tooltips.btnprintyear"));
btnPrintYear.addActionListener(actionEvent -> {
String carry4printKey = resident.getRID() + "-" + (year - 1) + "-12";
if (!carrySums.containsKey(carry4printKey)) {
carrySums.put(carry4printKey, AllowanceTools.getSUM(resident, SYSCalendar.eoy(start.minusYears(1))));
}
SYSFilesTools.print(AllowanceTools.getAsHTML(AllowanceTools.getYear(resident, start.toDate()), carrySums.get(carry4printKey), resident), true);
});
cptitle.getRight().add(btnPrintYear);
cpYear.setTitleLabelComponent(cptitle.getMain());
cpYear.setSlidingDirection(SwingConstants.SOUTH);
cpYear.setBackground(SYSConst.orange1[SYSConst.medium3]);
cpYear.setOpaque(true);
/***
* _ _ _ _
* ___| (_) ___| | _____ __| | ___ _ __ _ _ ___ __ _ _ __
* / __| | |/ __| |/ / _ \/ _` | / _ \| '_ \ | | | |/ _ \/ _` | '__|
* | (__| | | (__| < __/ (_| | | (_) | | | | | |_| | __/ (_| | |
* \___|_|_|\___|_|\_\___|\__,_| \___/|_| |_| \__, |\___|\__,_|_|
* |___/
*/
cpYear.addCollapsiblePaneListener(new CollapsiblePaneAdapter() {
@Override
public void paneExpanded(CollapsiblePaneEvent collapsiblePaneEvent) {
JPanel pnlContent = new JPanel(new VerticalLayout());
// somebody clicked on the year
// monthly informations will be generated. even if there
// are no allowances for that month
for (LocalDate month = end; month.compareTo(start) >= 0; month = month.minusMonths(1)) {
pnlContent.add(createCP4(resident, month));
}
cpYear.setContentPane(pnlContent);
cpYear.setOpaque(false);
}
});
cpYear.setBackground(getBG(resident, 9));
if (!cpYear.isCollapsed()) {
JPanel pnlContent = new JPanel(new VerticalLayout());
for (LocalDate month = end; month.compareTo(start) > 0; month = month.minusMonths(1)) {
pnlContent.add(createCP4(resident, month));
}
cpYear.setContentPane(pnlContent);
}
cpYear.setHorizontalAlignment(SwingConstants.LEADING);
cpYear.setOpaque(false);
return cpYear;
}
private CollapsiblePane createCP4(final Resident resident, final LocalDate month) {
final String key = getKey(resident, month);
if (!cpMap.containsKey(key)) {
cpMap.put(key, new CollapsiblePane());
try {
cpMap.get(key).setCollapsed(true);
} catch (PropertyVetoException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
final CollapsiblePane cpMonth = cpMap.get(key);
if (!carrySums.containsKey(key)) {
carrySums.put(key, AllowanceTools.getSUM(resident, SYSCalendar.eom(month)));
}
String title = "<html><table border=\"0\">" +
"<tr>" +
"<td width=\"520\" align=\"left\">" + monthFormatter.format(month.toDate()) + "</td>" +
"<td width=\"200\" align=\"right\">" +
(carrySums.get(key).compareTo(BigDecimal.ZERO) < 0 ? "<font color=\"red\">" : "") +
SYSTools.formatCurrency(carrySums.get(key)) +
(carrySums.get(key).compareTo(BigDecimal.ZERO) < 0 ? "</font>" : "") +
"</td>" +
"</tr>" +
"</table>" +
"</font></html>";
DefaultCPTitle cptitle = new DefaultCPTitle(title, e -> {
try {
cpMonth.setCollapsed(!cpMonth.isCollapsed());
} catch (PropertyVetoException pve) {
// BAH!
}
});
/***
* ____ _ _ __ __ _ _
* | _ \ _ __(_)_ __ | |_| \/ | ___ _ __ | |_| |__
* | |_) | '__| | '_ \| __| |\/| |/ _ \| '_ \| __| '_ \
* | __/| | | | | | | |_| | | | (_) | | | | |_| | | |
* |_| |_| |_|_| |_|\__|_| |_|\___/|_| |_|\__|_| |_|
*
*/
final JButton btnPrintMonth = new JButton(SYSConst.icon22print2);
btnPrintMonth.setPressedIcon(SYSConst.icon22print2Pressed);
btnPrintMonth.setAlignmentX(Component.RIGHT_ALIGNMENT);
btnPrintMonth.setContentAreaFilled(false);
btnPrintMonth.setBorder(null);
btnPrintMonth.setToolTipText(SYSTools.xx("misc.tooltips.btnprintmonth"));
btnPrintMonth.addActionListener(actionEvent -> {
if (!cashmap.containsKey(key)) {
cashmap.put(key, AllowanceTools.getMonth(resident, month.toDate()));
}
final BigDecimal carry4print = AllowanceTools.getSUM(resident, SYSCalendar.eom(month.minusMonths(1)));
SYSFilesTools.print(AllowanceTools.getAsHTML(cashmap.get(key), carry4print, resident), true);
});
cptitle.getRight().add(btnPrintMonth);
cpMonth.setTitleLabelComponent(cptitle.getMain());
cpMonth.setSlidingDirection(SwingConstants.SOUTH);
cpMonth.setBackground(getBG(resident, 10));
/***
* _ _ _ _ _ _
* ___| (_) ___| | _____ __| | ___ _ __ _ __ ___ ___ _ __ | |_| |__
* / __| | |/ __| |/ / _ \/ _` | / _ \| '_ \ | '_ ` _ \ / _ \| '_ \| __| '_ \
* | (__| | | (__| < __/ (_| | | (_) | | | | | | | | | | (_) | | | | |_| | | |
* \___|_|_|\___|_|\_\___|\__,_| \___/|_| |_| |_| |_| |_|\___/|_| |_|\__|_| |_|
*
*/
cpMonth.addCollapsiblePaneListener(new CollapsiblePaneAdapter() {
@Override
public void paneExpanded(CollapsiblePaneEvent collapsiblePaneEvent) {
cpMonth.setContentPane(createContentPanel4(resident, month));
cpMonth.setOpaque(false);
}
});
if (!cpMonth.isCollapsed()) {
cpMonth.setContentPane(createContentPanel4(resident, month));
}
cpMonth.setHorizontalAlignment(SwingConstants.LEADING);
cpMonth.setOpaque(false);
return cpMonth;
}
// End of variables declaration//GEN-END:variables
private void prepareSearchArea() {
searchPanes = new CollapsiblePanes();
searchPanes.setLayout(new JideBoxLayout(searchPanes, JideBoxLayout.Y_AXIS));
jspSearch.setViewportView(searchPanes);
JPanel mypanel = new JPanel();
mypanel.setLayout(new VerticalLayout(3));
mypanel.setBackground(Color.WHITE);
CollapsiblePane searchPane = new CollapsiblePane(SYSTools.xx(internalClassID));
searchPane.setStyle(CollapsiblePane.PLAIN_STYLE);
searchPane.setCollapsible(false);
try {
searchPane.setCollapsed(false);
} catch (PropertyVetoException e) {
OPDE.error(e);
}
GUITools.addAllComponents(mypanel, addCommands());
GUITools.addAllComponents(mypanel, addFilters());
searchPane.setContentPane(mypanel);
searchPanes.add(searchPane);
searchPanes.addExpansion();
}
private java.util.List<Component> addFilters() {
java.util.List<Component> list = new ArrayList<Component>();
txtSearch = new JXSearchField(SYSTools.xx("misc.msg.residentsearch"));
txtSearch.setFont(SYSConst.ARIAL14);
txtSearch.setInstantSearchDelay(100000);
txtSearch.addActionListener(e -> {
ArrayList<Resident> listSearchResidents = ResidentTools.getBy(txtSearch.getText().trim(), OPDE.getAppInfo().isAllowedTo(InternalClassACL.ARCHIVE, internalClassID));
if (listSearchResidents != null && !listSearchResidents.isEmpty()) {
cmbResident.setModel(SYSTools.list2cmb(listSearchResidents));
lstResidents = new ArrayList<Resident>();
lstResidents.add((Resident) cmbResident.getSelectedItem());
reloadDisplay();
} else {
OPDE.getDisplayManager().addSubMessage(new DisplayMessage("misc.msg.nodata"));
}
});
list.add(txtSearch);
cmbResident = new JComboBox();
cmbResident.setFont(SYSConst.ARIAL14);
cmbResident.addItemListener(e -> {
if (e.getStateChange() == ItemEvent.SELECTED) {
lstResidents = new ArrayList<Resident>();
lstResidents.add((Resident) e.getItem());
reloadDisplay();
}
});
list.add(cmbResident);
final JideButton btnAllActiveResidents = GUITools.createHyperlinkButton(SYSTools.xx("admin.residents.cash.showallactiveresidents"), SYSConst.icon22residentActive, null);
btnAllActiveResidents.addActionListener(actionEvent -> {
lstResidents = ResidentTools.getAllActive();
reloadDisplay();
});
list.add(btnAllActiveResidents);
if (OPDE.getAppInfo().isAllowedTo(InternalClassACL.ARCHIVE, internalClassID)) {
final JideButton btnAllInactiveResidents = GUITools.createHyperlinkButton(SYSTools.xx("admin.residents.cash.showallinactiveresidents"), SYSConst.icon22residentInactive, null);
btnAllInactiveResidents.addActionListener(actionEvent -> {
lstResidents = ResidentTools.getAllInactive();
reloadDisplay();
});
list.add(btnAllInactiveResidents);
final JideButton btnAllResidents = GUITools.createHyperlinkButton(SYSTools.xx("admin.residents.cash.showallresidents"), SYSConst.icon22residentBoth, null);
btnAllResidents.addActionListener(actionEvent -> {
lstResidents = ResidentTools.getAllInactive();
lstResidents.addAll(ResidentTools.getAllActive());
Collections.sort(lstResidents);
reloadDisplay();
});
list.add(btnAllResidents);
}
return list;
}
private java.util.List<Component> addCommands() {
java.util.List<Component> list = new ArrayList<Component>();
final JideButton btnNewTX = GUITools.createHyperlinkButton(SYSTools.xx("admin.residents.cash.enterTXs"), SYSConst.icon22add, null);
btnNewTX.addActionListener(actionEvent -> {
MyJDialog myJDialog = new MyJDialog(true);
myJDialog.setContentPane(getPnlTX(null, null));
myJDialog.pack();
myJDialog.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
currentEditor = null;
}
});
currentEditor = myJDialog;
myJDialog.setVisible(true);
});
list.add(btnNewTX);
if (OPDE.getAppInfo().isAllowedTo(InternalClassACL.MANAGER, internalClassID)) {
final JideButton btnPrintStat = GUITools.createHyperlinkButton(SYSTools.xx("admin.residents.cash.printstat"), SYSConst.icon22calc, null);
btnPrintStat.addActionListener(actionEvent -> SYSFilesTools.print(AllowanceTools.getOverallSumAsHTML(12), false));
list.add(btnPrintStat);
}
return list;
}
private Color getBG(Resident resident, int level) {
if (lstResidents.indexOf(resident) % 2 == 0) {
return SYSConst.purple1[level];
} else {
return SYSConst.greyscale[level];
}
}
private void buildPanel() {
cpsCash.removeAll();
cpsCash.setLayout(new JideBoxLayout(cpsCash, JideBoxLayout.Y_AXIS));
for (Resident resident : lstResidents) {
cpsCash.add(cpMap.get(resident.getRID()));
}
cpsCash.addExpansion();
}
private String getKey(Resident resident, LocalDate month) {
return resident.getRID() + "-" + month.getYear() + "-" + month.getMonthOfYear();
}
private JPanel createContentPanel4(final Resident resident, LocalDate month) {
final String key = getKey(resident, month);
if (!contentmap.containsKey(key)) {
JPanel pnlMonth = new JPanel(new VerticalLayout());
pnlMonth.setBackground(getBG(resident, 11));
pnlMonth.setOpaque(false);
// final String prevKey = resident.getRID() + "-" + SYSCalendar.eom(month.minusMonths(1)).getYear() + "-" + SYSCalendar.eom(month.minusMonths(1)).getMonthOfYear();
if (!carrySums.containsKey(key)) {
carrySums.put(key, AllowanceTools.getSUM(resident, SYSCalendar.eom(month.minusMonths(1))));
}
BigDecimal rowsum = carrySums.get(key);
if (!cashmap.containsKey(key)) {
cashmap.put(key, AllowanceTools.getMonth(resident, month.toDate()));
}
JLabel lblEOM = new JLabel("<html><table border=\"0\">" +
"<tr>" +
"<td width=\"130\" align=\"left\">" + DateFormat.getDateInstance().format(month.dayOfMonth().withMaximumValue().toDate()) + "</td>" +
"<td width=\"400\" align=\"left\">" + SYSTools.xx("admin.residents.cash.endofmonth") + "</td>" +
"<td width=\"100\" align=\"right\"></td>" +
"<td width=\"100\" align=\"right\">" +
(rowsum.compareTo(BigDecimal.ZERO) < 0 ? "<font color=\"red\">" : "") +
SYSTools.formatCurrency(rowsum) +
(rowsum.compareTo(BigDecimal.ZERO) < 0 ? "</font>" : "") +
"</td>" +
"</tr>" +
"</table>" +
"</font></html>");
pnlMonth.add(lblEOM);
for (final Allowance allowance : cashmap.get(key)) {
String title = "<html><table border=\"0\">" +
"<tr>" +
"<td width=\"130\" align=\"left\">" + DateFormat.getDateInstance().format(allowance.getPit()) + "</td>" +
"<td width=\"400\" align=\"left\">" + allowance.getText() + "</td>" +
"<td width=\"100\" align=\"right\">" +
(allowance.getAmount().compareTo(BigDecimal.ZERO) < 0 ? "<font color=\"red\">" : "") +
SYSTools.formatCurrency(allowance.getAmount()) +
(allowance.getAmount().compareTo(BigDecimal.ZERO) < 0 ? "</font>" : "") +
"</td>" +
"<td width=\"100\" align=\"right\">" +
(rowsum.compareTo(BigDecimal.ZERO) < 0 ? "<font color=\"red\">" : "") +
SYSTools.formatCurrency(rowsum) +
(rowsum.compareTo(BigDecimal.ZERO) < 0 ? "</font>" : "") +
"</td>" +
"</tr>" +
"</table>" +
"</font></html>";
DefaultCPTitle cptitle = new DefaultCPTitle(title, e -> {
});
cptitle.getButton().setIcon(allowance.isReplaced() || allowance.isReplacement() ? SYSConst.icon22eraser : null);
if (OPDE.getAppInfo().isAllowedTo(InternalClassACL.UPDATE, internalClassID)) {
/***
* _____ _ _ _
* | ____|__| (_) |_
* | _| / _` | | __|
* | |__| (_| | | |_
* |_____\__,_|_|\__|
*
*/
final JButton btnEdit = new JButton(SYSConst.icon22edit3);
btnEdit.setPressedIcon(SYSConst.icon22edit3Pressed);
btnEdit.setAlignmentX(Component.RIGHT_ALIGNMENT);
btnEdit.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
btnEdit.setContentAreaFilled(false);
btnEdit.setBorder(null);
btnEdit.setToolTipText(SYSTools.xx("admin.residents.cash.btnedit.tooltip"));
btnEdit.addActionListener(actionEvent -> {
final JidePopup popupTX = new JidePopup();
popupTX.setMovable(false);
PnlTX pnlTX = getPnlTX(resident, allowance);
popupTX.setContentPane(pnlTX);
popupTX.removeExcludedComponent(pnlTX);
popupTX.setDefaultFocusComponent(pnlTX);
popupTX.setOwner(btnEdit);
GUITools.showPopup(popupTX, SwingConstants.WEST);
});
cptitle.getRight().add(btnEdit);
// you can edit your own entries or you are a manager. once they are replaced or a replacement record, its over.
btnEdit.setEnabled((OPDE.getAppInfo().isAllowedTo(InternalClassACL.MANAGER, internalClassID) || allowance.getUser().equals(OPDE.getLogin().getUser())) && !allowance.isReplaced() && !allowance.isReplacement());
/***
* _ _ _ _______ __
* | | | |_ __ __| | ___ |_ _\ \/ /
* | | | | '_ \ / _` |/ _ \ | | \ /
* | |_| | | | | (_| | (_) | | | / \
* \___/|_| |_|\__,_|\___/ |_| /_/\_\
*
*/
final JButton btnUndoTX = new JButton(SYSConst.icon22undo);
btnUndoTX.setPressedIcon(SYSConst.icon22Pressed);
btnUndoTX.setAlignmentX(Component.RIGHT_ALIGNMENT);
btnUndoTX.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
btnUndoTX.setContentAreaFilled(false);
btnUndoTX.setBorder(null);
btnUndoTX.setToolTipText(SYSTools.xx("admin.residents.cash.btnundotx.tooltip"));
btnUndoTX.addActionListener(actionEvent -> {
currentEditor = new DlgYesNo(SYSTools.xx("misc.questions.undo1") + "<br/><i>" + "<br/><i>" + allowance.getText() + " " + SYSTools.formatCurrency(allowance.getAmount()) + "</i><br/>" + SYSTools.xx("misc.questions.undo2"), SYSConst.icon48undo, answer -> {
if (answer.equals(JOptionPane.YES_OPTION)) {
EntityManager em = OPDE.createEM();
try {
em.getTransaction().begin();
Allowance myOldAllowance = em.merge(allowance);
Allowance myCancelAllowance = em.merge(new Allowance(myOldAllowance));
em.lock(em.merge(myOldAllowance.getResident()), LockModeType.OPTIMISTIC);
em.lock(myOldAllowance, LockModeType.OPTIMISTIC);
myOldAllowance.setReplacedBy(myCancelAllowance, em.merge(OPDE.getLogin().getUser()));
em.getTransaction().commit();
DateTime txDate = new DateTime(myCancelAllowance.getPit());
final String keyMonth = myCancelAllowance.getResident().getRID() + "-" + txDate.getYear() + "-" + txDate.getMonthOfYear();
contentmap.remove(keyMonth);
cpMap.remove(keyMonth);
cashmap.get(keyMonth).remove(allowance);
cashmap.get(keyMonth).add(myOldAllowance);
cashmap.get(keyMonth).add(myCancelAllowance);
Collections.sort(cashmap.get(keyMonth));
updateCarrySums(myCancelAllowance);
createCP4(myCancelAllowance.getResident());
try {
cpMap.get(keyMonth).setCollapsed(false);
} catch (PropertyVetoException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
buildPanel();
} catch (OptimisticLockException ole) {
OPDE.warn(ole);
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) {
OPDE.getMainframe().emptyFrame();
OPDE.getMainframe().afterLogin();
}
OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage());
} catch (Exception e) {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
OPDE.fatal(e);
} finally {
em.close();
currentEditor = null;
}
}
});
currentEditor.setVisible(true);
});
cptitle.getRight().add(btnUndoTX);
btnUndoTX.setEnabled(!allowance.isReplaced() && !allowance.isReplacement());
}
if (OPDE.getAppInfo().isAllowedTo(InternalClassACL.DELETE, internalClassID)) {
/***
* ____ _ _
* | _ \ ___| | ___| |_ ___
* | | | |/ _ \ |/ _ \ __/ _ \
* | |_| | __/ | __/ || __/
* |____/ \___|_|\___|\__\___|
*
*/
final JButton btnDelete = new JButton(SYSConst.icon22delete);
btnDelete.setPressedIcon(SYSConst.icon22deletePressed);
btnDelete.setAlignmentX(Component.RIGHT_ALIGNMENT);
btnDelete.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
btnDelete.setContentAreaFilled(false);
btnDelete.setBorder(null);
btnDelete.setToolTipText(SYSTools.xx("admin.residents.cash.btndelete.tooltip"));
btnDelete.addActionListener(actionEvent -> {
currentEditor = new DlgYesNo(SYSTools.xx("misc.questions.delete1") + "<br/><i>" + allowance.getText() + " " + SYSTools.formatCurrency(allowance.getAmount()) + "</i><br/>" + SYSTools.xx("misc.questions.delete2"), SYSConst.icon48delete, answer -> {
if (answer.equals(JOptionPane.YES_OPTION)) {
EntityManager em = OPDE.createEM();
try {
em.getTransaction().begin();
Allowance myAllowance = em.merge(allowance);
em.lock(em.merge(myAllowance.getResident()), LockModeType.OPTIMISTIC);
Allowance theOtherOne = null;
// Check for special cases
if (myAllowance.isReplacement()) {
theOtherOne = em.merge(myAllowance.getReplacementFor());
theOtherOne.setReplacedBy(null);
theOtherOne.setEditedBy(null);
myAllowance.setEditPit(null);
}
if (myAllowance.isReplaced()) {
theOtherOne = em.merge(myAllowance.getReplacedBy());
theOtherOne.setReplacementFor(null);
}
em.remove(myAllowance);
em.getTransaction().commit();
DateTime txDate = new DateTime(myAllowance.getPit());
final String keyMonth = myAllowance.getResident().getRID() + "-" + txDate.getYear() + "-" + txDate.getMonthOfYear();
cpMap.remove(keyMonth);
cashmap.get(keyMonth).remove(myAllowance);
if (theOtherOne != null) {
cashmap.get(keyMonth).remove(theOtherOne);
cashmap.get(keyMonth).add(theOtherOne);
Collections.sort(cashmap.get(keyMonth));
}
// only to update the carrysums. myAllowance will be discarded soon.
myAllowance.setAmount(myAllowance.getAmount().negate());
updateCarrySums(myAllowance);
createCP4(myAllowance.getResident());
try {
if (cpMap.containsKey(keyMonth)) {
cpMap.get(keyMonth).setCollapsed(false);
}
} catch (PropertyVetoException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
buildPanel();
} catch (OptimisticLockException ole) {
OPDE.warn(ole);
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) {
OPDE.getMainframe().emptyFrame();
OPDE.getMainframe().afterLogin();
}
OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage());
} catch (Exception e) {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
OPDE.fatal(e);
} finally {
em.close();
}
}
});
currentEditor.setVisible(true);
});
cptitle.getRight().add(btnDelete);
}
pnlMonth.add(cptitle.getMain());
linemap.put(allowance, cptitle.getMain());
rowsum = rowsum.subtract(allowance.getAmount());
}
JLabel lblBOM = new JLabel("<html><table border=\"0\">" +
"<tr>" +
"<td width=\"130\" align=\"left\">" + DateFormat.getDateInstance().format(month.dayOfMonth().withMinimumValue().toDate()) + "</td>" +
"<td width=\"400\" align=\"left\">" + SYSTools.xx("admin.residents.cash.startofmonth") + "</td>" +
"<td width=\"100\" align=\"right\"></td>" +
"<td width=\"100\" align=\"right\">" +
(rowsum.compareTo(BigDecimal.ZERO) < 0 ? "<font color=\"red\">" : "") +
SYSTools.formatCurrency(rowsum) +
(rowsum.compareTo(BigDecimal.ZERO) < 0 ? "</font>" : "") +
"</td>" +
"</tr>" +
"</table>" +
"</font></html>");
lblBOM.setBackground(getBG(resident, 11));
pnlMonth.add(lblBOM);
contentmap.put(key, pnlMonth);
}
return contentmap.get(key);
}
private PnlTX getPnlTX(Resident resident, final Allowance allowance) {
final BigDecimal editAmount = allowance != null ? allowance.getAmount() : null;
final Allowance allow = (allowance == null ? new Allowance(resident) : allowance);
return new PnlTX(allow, o -> {
if (o != null) {
EntityManager em = OPDE.createEM();
try {
em.getTransaction().begin();
final Allowance myAllowance = em.merge((Allowance) o);
em.lock(em.merge(myAllowance.getResident()), LockModeType.OPTIMISTIC);
em.getTransaction().commit();
if (!minmax.containsKey(myAllowance.getResident())) {
minmax.put(myAllowance.getResident(), AllowanceTools.getMinMax(myAllowance.getResident()));
}
DateTime txDate = new DateTime(myAllowance.getPit());
final String keyResident = myAllowance.getResident().getRID();
final String keyYear = myAllowance.getResident().getRID() + "-" + txDate.getYear();
final String keyMonth = myAllowance.getResident().getRID() + "-" + txDate.getYear() + "-" + txDate.getMonthOfYear();
if (!lstResidents.contains(myAllowance.getResident())) {
lstResidents.add(myAllowance.getResident());
Collections.sort(lstResidents);
}
if (!cashmap.containsKey(keyMonth)) {
cashmap.put(keyMonth, AllowanceTools.getMonth(myAllowance.getResident(), myAllowance.getPit()));
} else {
if (cashmap.get(keyMonth).contains(myAllowance)) {
cashmap.get(keyMonth).remove(myAllowance);
}
cashmap.get(keyMonth).add(myAllowance);
Collections.sort(cashmap.get(keyMonth));
}
// little trick to fix the carries
if (editAmount != null) {
updateCarrySums(myAllowance.getResident(), new LocalDate(myAllowance.getPit()), editAmount.negate());
}
// add the new / edited amount
updateCarrySums(myAllowance);
createCP4(myAllowance.getResident());
try {
if (cpMap.get(keyResident).isCollapsed())
cpMap.get(keyResident).setCollapsed(false);
if (cpMap.get(keyYear).isCollapsed())
cpMap.get(keyYear).setCollapsed(false);
if (cpMap.get(keyMonth).isCollapsed())
cpMap.get(keyMonth).setCollapsed(false);
} catch (PropertyVetoException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
buildPanel();
GUITools.scroll2show(jspCash, cpMap.get(keyMonth), cpsCash, o1 -> GUITools.flashBackground(linemap.get(myAllowance), Color.YELLOW, 2));
} catch (OptimisticLockException ole) {
OPDE.warn(ole);
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
if (ole.getMessage().indexOf("Class> entity.info.Resident") > -1) {
OPDE.getMainframe().emptyFrame();
OPDE.getMainframe().afterLogin();
}
OPDE.getDisplayManager().addSubMessage(DisplayManager.getLockMessage());
} catch (Exception e) {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
OPDE.fatal(e);
} finally {
em.close();
}
}
});
}
private void updateCarrySums(Allowance myAllowance) {
// String prevKey = getKey(myAllowance.getResident(), SYSCalendar.eom(new LocalDate(myAllowance.getPit()).minusMonths(1)));
// if (!carrySums.containsKey(prevKey)) {
// carrySums.put(prevKey, AllowanceTools.getSUM(myAllowance.getResident(), SYSCalendar.eom(new LocalDate(myAllowance.getPit()).minusMonths(1))));
// }
//
// // update carrysums
// for (LocalDate month = SYSCalendar.eom(new LocalDate(myAllowance.getPit())); month.compareTo(SYSCalendar.eoy(new LocalDate())) <= 0; month = SYSCalendar.eom(month.plusMonths(1))) {
// OPDE.debug(month.toString("yyyy-MM-dd"));
// final String key = getKey(myAllowance.getResident(), month);
//
// if (!carrySums.containsKey(key)) {
// prevKey = getKey(myAllowance.getResident(), SYSCalendar.eom(month.minusMonths(1)));
// carrySums.put(key, carrySums.get(prevKey).add(myAllowance.getAmount()));
// } else {
// carrySums.put(key, carrySums.get(key).add(myAllowance.getAmount()));
// }
//
// contentmap.remove(key);
// }
updateCarrySums(myAllowance.getResident(), new LocalDate(myAllowance.getPit()), myAllowance.getAmount());
}
private void updateCarrySums(Resident resident, LocalDate pit, BigDecimal amount) {
String prevKey = getKey(resident, SYSCalendar.eom(pit.minusMonths(1)));
if (!carrySums.containsKey(prevKey)) {
carrySums.put(prevKey, AllowanceTools.getSUM(resident, SYSCalendar.eom(pit).minusMonths(1)));
}
// update carrysums
for (LocalDate month = SYSCalendar.eom(pit); month.compareTo(SYSCalendar.eoy(new LocalDate())) <= 0; month = SYSCalendar.eom(month.plusMonths(1))) {
OPDE.debug(month.toString("yyyy-MM-dd"));
final String key = getKey(resident, month);
if (!carrySums.containsKey(key)) {
prevKey = getKey(resident, SYSCalendar.eom(month.minusMonths(1)));
carrySums.put(key, carrySums.get(prevKey).add(amount));
} else {
carrySums.put(key, carrySums.get(key).add(amount));
}
contentmap.remove(key);
}
// fix minmax interval
Interval myMinMax = new Interval(minmax.get(resident).getFirst().toDateTimeAtStartOfDay(), SYSCalendar.eod(minmax.get(resident).getSecond()));
if (myMinMax.isBefore(pit.toDateTimeAtCurrentTime())) {
minmax.put(resident, new Pair(minmax.get(resident).getFirst(), SYSCalendar.eom(pit)));
} else if (myMinMax.isAfter(pit.toDateTimeAtCurrentTime())) {
minmax.put(resident, new Pair(SYSCalendar.bom(pit), minmax.get(resident).getSecond()));
}
}
}