OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 151 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
 * 
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each file.
 */
 
 package org.openconcerto.erp.core.common.ui;

import org.openconcerto.erp.core.finance.accounting.model.Currency;
import org.openconcerto.erp.core.finance.accounting.model.CurrencyConverter;
import org.openconcerto.sql.model.SQLField;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.view.list.IListe;
import org.openconcerto.sql.view.list.ITableModel;
import org.openconcerto.sql.view.list.ListSQLLine;
import org.openconcerto.sql.view.list.SQLTableModelColumn;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.JLabelBold;
import org.openconcerto.utils.TableSorter;
import org.openconcerto.utils.Tuple2;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.beans.PropertyChangeListener;
import java.math.BigDecimal;
import java.math.MathContext;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.event.EventListenerList;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;

public class IListTotalPanel extends JPanel {
    CurrencyConverter cc = new CurrencyConverter();

    public enum Type {
        // Pourcentage moyen d'une colonne
        MOYENNE_POURCENT,
        // Moyenne d'une colonne
        MOYENNE_DEVISE,
        // Somme total d'une colonne
        SOMME,
        // Somme total d'une colonne
        SOMME_QTE,
        // Marge en pourcentage requiert dans la liste la colonne achat en premier et vente en
        // deuxieme
        MOYENNE_MARGE,
        // Requiert le field TTC
        AVANCEMENT_TTC,
        // TOTAL DES LIGNES
        COUNT;
    };

    DecimalFormat decimalFormat = new DecimalFormat("##,##0.00");

    EventListenerList loadingListener = new EventListenerList();
    private final IListe list;
    private final Map<SQLTableModelColumn, JLabel> map = new HashMap<SQLTableModelColumn, JLabel>();

    public IListTotalPanel(IListe l, final List<SQLField> listField) {
        this(l, initListe(l, listField), null, null);
    }

    public IListTotalPanel(IListe l, final List<SQLField> listField, String title) {
        this(l, initListe(l, listField), null, title);
    }

    public static List<Tuple2<? extends SQLTableModelColumn, Type>> initListe(IListe iL, List<SQLField> l) {
        List<Tuple2<? extends SQLTableModelColumn, Type>> lFinal = new ArrayList<Tuple2<? extends SQLTableModelColumn, Type>>();

        for (SQLField field : l) {
            final SQLTableModelColumn col = iL.getSource().getColumn(field);
            if (col == null)
                throw new IllegalArgumentException("No column with just " + field + " : " + iL.getSource().getColumns());
            lFinal.add(Tuple2.create(col, Type.SOMME));
        }
        return lFinal;
    }

    public IListTotalPanel(IListe l, final List<Tuple2<? extends SQLTableModelColumn, Type>> listField, final List<Tuple2<SQLField, ?>> filters, String title) {
        this(l, listField, filters, null, title);
    }

    /**
     * 
     * @param l
     * @param listField Liste des fields à totaliser
     * @param filters filtre ex : Tuple((SQLField)NATEXIER,(Boolean)FALSE)
     */
    public IListTotalPanel(IListe l, final List<Tuple2<? extends SQLTableModelColumn, Type>> listField, final List<Tuple2<SQLField, ?>> filters, final List<Tuple2<SQLField, ?>> filtersNot,
            String title) {
        super(new GridBagLayout());
        this.list = l;
        this.setOpaque(false);

        GridBagConstraints c = new DefaultGridBagConstraints();
        c.gridx = GridBagConstraints.RELATIVE;
        c.weightx = 0;
        if (title != null && title.trim().length() > 0) {
            JLabel sep = new JLabel(title);
            c.weightx = 1;
            c.gridwidth = GridBagConstraints.REMAINDER;
            this.add(sep, c);
            c.gridy++;
            c.gridwidth = 1;
        }
        // Filtre
        for (Tuple2<? extends SQLTableModelColumn, Type> field2 : listField) {
            c.weightx = 0;
            final SQLTableModelColumn col = field2.get0();
            if (col == null) {
                throw new IllegalStateException("null SQLTableModelColumn in " + listField);
            }
            final JLabelBold comp = new JLabelBold(col.getName());
            comp.setHorizontalAlignment(SwingConstants.RIGHT);
            this.add(comp, c);
            JLabelBold textField = new JLabelBold("0");
            textField.setHorizontalAlignment(SwingConstants.RIGHT);
            this.map.put(field2.get0(), textField);
            c.weightx = 1;
            this.add(textField, c);
            c.weightx = 0;
            if (field2.get1() == Type.SOMME || field2.get1() == Type.MOYENNE_DEVISE || field2.get1() == Type.AVANCEMENT_TTC) {
                this.add(new JLabelBold(Currency.getSymbol(cc.getCompanyCurrencyCode())), c);
            } else if (field2.get1() == Type.MOYENNE_POURCENT || field2.get1() == Type.MOYENNE_MARGE) {
                this.add(new JLabelBold("%"), c);
            }
            c.gridy++;
        }

        this.list.addListener(new TableModelListener() {

            private Object getValueAt(final ListSQLLine line, final SQLTableModelColumn col, final List<SQLTableModelColumn> columns) {
                final int indexOf = columns.indexOf(col);
                final Object res = line.getValueAt(indexOf);
                if (res == null)
                    throw new IllegalStateException("Null value for " + col + " in " + line);
                return res;
            }

            @Override
            public void tableChanged(TableModelEvent e) {
                final TableModel model = (TableModel) e.getSource();
                final ITableModel sqlModel;
                if (model instanceof ITableModel)
                    sqlModel = (ITableModel) model;
                else
                    sqlModel = (ITableModel) ((TableSorter) model).getTableModel();

                Map<SQLTableModelColumn, BigDecimal> mapTotal = new HashMap<SQLTableModelColumn, BigDecimal>();
                Map<SQLTableModelColumn, Double> mapPourcent = new HashMap<SQLTableModelColumn, Double>();
                Map<SQLTableModelColumn, Integer> mapPourcentSize = new HashMap<SQLTableModelColumn, Integer>();
                for (Tuple2<? extends SQLTableModelColumn, Type> field : listField) {
                    if (field.get1() == Type.COUNT) {
                        map.get(field.get0()).setText(String.valueOf(model.getRowCount()));
                    }
                }

                for (int i = 0; i < model.getRowCount(); i++) {
                    final ListSQLLine line = sqlModel.getRow(i);
                    final SQLRowValues rowAt = line.getRow();
                    final List<SQLTableModelColumn> columns = line.getColumns().getColumns();

                    for (final Tuple2<? extends SQLTableModelColumn, Type> field : listField) {
                        final Type type = field.get1();

                        if (type == Type.MOYENNE_POURCENT) {
                            final Double n2 = (Double) getValueAt(line, field.get0(), columns);

                            boolean in = true;

                            if (filters != null) {
                                for (Tuple2<SQLField, ?> tuple2 : filters) {
                                    in = in && rowAt.getObject(tuple2.get0().getName()).equals(tuple2.get1());
                                }
                            }

                            if (filtersNot != null) {
                                for (Tuple2<SQLField, ?> tuple2 : filtersNot) {
                                    in = in && !rowAt.getObject(tuple2.get0().getName()).equals(tuple2.get1());
                                }
                            }

                            if (in) {

                                if (mapPourcent.get(field.get0()) == null) {
                                    mapPourcent.put(field.get0(), n2);
                                } else {
                                    mapPourcent.put(field.get0(), n2 + mapPourcent.get(field.get0()));
                                }

                                if (mapPourcentSize.get(field.get0()) == null) {
                                    mapPourcentSize.put(field.get0(), 1);
                                } else {
                                    mapPourcentSize.put(field.get0(), mapPourcentSize.get(field.get0()).intValue() + 1);
                                }

                            }
                        } else if (type == Type.AVANCEMENT_TTC) {

                            BigDecimal n = mapTotal.get(field.get0());
                            BigDecimal ttc = BigDecimal.valueOf(line.getRow().getObjectAs("T_TTC", Number.class).doubleValue());

                            BigDecimal av = BigDecimal.valueOf(((Number) getValueAt(line, field.get0(), columns)).doubleValue());

                            boolean in = true;

                            if (filters != null) {
                                for (Tuple2<SQLField, ?> tuple2 : filters) {
                                    in = in && rowAt.getObject(tuple2.get0().getName()).equals(tuple2.get1());
                                }
                            }
                            if (filtersNot != null) {
                                for (Tuple2<SQLField, ?> tuple2 : filtersNot) {
                                    in = in && !rowAt.getObject(tuple2.get0().getName()).equals(tuple2.get1());
                                }
                            }

                            if (in) {
                                if (n == null) {
                                    mapTotal.put(field.get0(), ttc.multiply(av).movePointLeft(2));
                                } else {
                                    mapTotal.put(field.get0(), n.add(ttc.multiply(av).movePointLeft(2)));
                                }
                            }
                        } else if (type != Type.MOYENNE_MARGE && type != Type.COUNT) {
                            BigDecimal n = mapTotal.get(field.get0());

                            final Object value = getValueAt(line, field.get0(), columns);
                            final BigDecimal n2 = BigDecimal.valueOf(((Number) value).doubleValue());

                            boolean in = true;

                            if (filters != null) {
                                for (Tuple2<SQLField, ?> tuple2 : filters) {
                                    in = in && rowAt.getObject(tuple2.get0().getName()).equals(tuple2.get1());
                                }
                            }
                            if (filtersNot != null) {
                                for (Tuple2<SQLField, ?> tuple2 : filtersNot) {
                                    in = in && !rowAt.getObject(tuple2.get0().getName()).equals(tuple2.get1());
                                }
                            }

                            if (in) {
                                if (n == null) {
                                    mapTotal.put(field.get0(), n2);
                                } else {
                                    mapTotal.put(field.get0(), n.add(n2));
                                }
                            }
                        }
                    }
                }

                for (Tuple2<? extends SQLTableModelColumn, Type> field : listField) {
                    if (field.get1() == Type.MOYENNE_MARGE) {

                        BigDecimal totalVT = mapTotal.get(listField.get(0).get0());
                        BigDecimal totalHA = mapTotal.get(listField.get(1).get0());
                        if (totalHA != null && totalVT != null && totalVT.longValue() != 0) {
                            map.get(field.get0()).setText(decimalFormat.format(totalVT.subtract(totalHA).divide(totalVT, MathContext.DECIMAL32).doubleValue() * 100.0D));
                        } else {
                            map.get(field.get0()).setText(decimalFormat.format(0));
                        }
                    } else if (field.get1() == Type.MOYENNE_POURCENT) {
                        Double l = mapPourcent.get(field.get0());
                        Integer d = mapPourcentSize.get(field.get0());
                        if (l != null && d != null && d != 0) {
                            map.get(field.get0()).setText(decimalFormat.format(l / (double) d));
                        } else {
                            map.get(field.get0()).setText(decimalFormat.format(0));
                        }
                    } else if (field.get1() != Type.COUNT) {
                        BigDecimal l = mapTotal.get(field.get0());
                        if (l != null) {
                            map.get(field.get0()).setText(decimalFormat.format(l.doubleValue()));
                        } else {
                            map.get(field.get0()).setText(decimalFormat.format(0));
                        }
                    }
                }
                fireUpdated();
            }
        });
    }

    public void fireUpdated() {
        for (PropertyChangeListener l : this.loadingListener.getListeners(PropertyChangeListener.class)) {
            l.propertyChange(null);
        }
    }

    public void addListener(PropertyChangeListener l) {
        this.loadingListener.add(PropertyChangeListener.class, l);
    }

}