OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 2011-2019 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.sales.product.ui;

import org.openconcerto.erp.config.Log;
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.sales.product.element.ReferenceArticleSQLElement;
import org.openconcerto.erp.panel.ITreeSelection;
import org.openconcerto.erp.preferences.GestionArticleGlobalPreferencePanel;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.element.SQLElementDirectory;
import org.openconcerto.sql.model.FieldPath;
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLRowValuesListFetcher;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.model.graph.Path;
import org.openconcerto.sql.preferences.SQLPreferences;
import org.openconcerto.sql.request.ListSQLRequest;
import org.openconcerto.sql.request.UpdateBuilder;
import org.openconcerto.sql.view.IListPanel;
import org.openconcerto.sql.view.ListeAddPanel;
import org.openconcerto.sql.view.list.BaseSQLTableModelColumn;
import org.openconcerto.sql.view.list.IListe;
import org.openconcerto.sql.view.list.SQLTableModelColumn;
import org.openconcerto.sql.view.list.SQLTableModelColumnPath;
import org.openconcerto.sql.view.list.SQLTableModelSource;
import org.openconcerto.sql.view.list.SQLTableModelSourceOnline;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.PanelFrame;
import org.openconcerto.utils.CollectionUtils;
import org.openconcerto.utils.DecimalUtils;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.logging.Level;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;

public class ListeDesArticlesFrame extends JFrame {
    private static final String TITLE = "Liste des articles";
    private final SQLTable sqlTableArticle;
    private final SQLTable sqlTableFamilleArticle;

    public ListeDesArticlesFrame(SQLElementDirectory dir) {
        final SQLElement elt = dir.getElement(ReferenceArticleSQLElement.class);
        final SQLElement articleFamilyElt = elt.getForeignElement("ID_FAMILLE_ARTICLE");
        final FamilleArticlePanel panelFam = new FamilleArticlePanel(articleFamilyElt);
        this.sqlTableArticle = elt.getTable();
        this.sqlTableFamilleArticle = articleFamilyElt.getTable();

        final SQLPreferences prefs = SQLPreferences.getMemCached(elt.getTable().getDBRoot());
        final boolean hasDeclinaison = prefs.getBoolean(GestionArticleGlobalPreferencePanel.ACTIVER_DECLINAISON, false);
        final File normalConfig = IListPanel.getConfigFile(elt, ListeAddPanel.class, "normal");
        final File virtualConfig = IListPanel.getConfigFile(elt, ListeAddPanel.class, "virtual");
        final SQLTableModelSourceOnline noDeclSrc = getTableSource(elt, null);
        final SQLTableModelSourceOnline withDeclSrc;
        final IListe liste;
        if (hasDeclinaison) {
            final List<String> fieldsDecl = new ArrayList<>();
            for (String fieldName : elt.getTable().getFieldsName()) {
                if (fieldName.startsWith("ID_ARTICLE_DECLINAISON_")) {
                    fieldsDecl.add(fieldName);
                }
            }
            withDeclSrc = getTableSource(elt, fieldsDecl);
            liste = new IListe(withDeclSrc, normalConfig);
        } else {
            withDeclSrc = null;
            liste = new IListe(noDeclSrc, virtualConfig);
        }

        final ListeAddPanel panel = new ListeAddPanel(elt, liste) {
            @Override
            protected void handleAction(final JButton source, final ActionEvent evt) {
                if (source == this.buttonEffacer && getListe().fetchSelectedRow() != null) {
                    JPanel panel = new JPanel();
                    GridBagConstraints c = new DefaultGridBagConstraints();
                    c.gridwidth = 2;
                    panel.add(new JLabel("Voulez vous supprimer ou rendre obsoléte?"), c);
                    JButton buttonObs = new JButton("Obsolète");
                    JButton buttonSuppr = new JButton("Supprimer");
                    c.gridy++;
                    panel.add(buttonObs, c);
                    c.gridx++;
                    panel.add(buttonSuppr, c);

                    final JFrame frame = new PanelFrame(panel, "Suppression d'article");
                    buttonObs.addActionListener(new ActionListener() {

                        @Override
                        public void actionPerformed(ActionEvent e) {
                            List<SQLRowAccessor> rowVals = liste.getSelectedRowAccessors();
                            UpdateBuilder build = new UpdateBuilder(ListeDesArticlesFrame.this.sqlTableArticle);
                            build.setObject("OBSOLETE", Boolean.TRUE);
                            List<Integer> ids = new ArrayList<Integer>();
                            for (SQLRowAccessor sqlRowValues : rowVals) {
                                ids.add(sqlRowValues.getID());
                            }
                            build.setWhere(Where.inValues(ListeDesArticlesFrame.this.sqlTableArticle.getKey(), ids));
                            ListeDesArticlesFrame.this.sqlTableArticle.getDBSystemRoot().getDataSource().execute(build.asString());
                            frame.dispose();
                        }
                    });
                    buttonSuppr.addActionListener(new ActionListener() {

                        @Override
                        public void actionPerformed(ActionEvent e) {
                            frame.dispose();
                            SuperHandleAction(source, evt);
                        }
                    });
                    frame.pack();
                    frame.setResizable(false);
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } else {
                    super.handleAction(source, evt);
                }
            }

            public void SuperHandleAction(final JButton source, final ActionEvent evt) {
                super.handleAction(source, evt);
            }
        };
        final JRadioButton radioNormal = new JRadioButton("Normal");
        final JRadioButton radioVirtuel = new JRadioButton("Virtuel");
        final Consumer<ListSQLRequest> updateWhere = (req) -> {
            req.putWhere(this.getClass(), getWhere(panelFam, radioVirtuel.isSelected()));
        };
        updateWhere.accept(panel.getListe().getRequest());

        GridBagConstraints c2 = new DefaultGridBagConstraints();
        c2.gridy = 4;
        c2.anchor = GridBagConstraints.EAST;
        c2.weightx = 0;
        c2.fill = GridBagConstraints.NONE;

        if (hasDeclinaison) {
            JPanel panelMode = new JPanel(new GridBagLayout());
            GridBagConstraints cMode = new DefaultGridBagConstraints();
            cMode.gridy = 4;
            cMode.anchor = GridBagConstraints.EAST;
            cMode.weightx = 0;
            cMode.fill = GridBagConstraints.NONE;
            ButtonGroup groupButton = new ButtonGroup();
            groupButton.add(radioNormal);
            groupButton.add(radioVirtuel);
            radioNormal.setSelected(true);
            panelMode.add(radioNormal, cMode);
            cMode.gridx++;
            panelMode.add(radioVirtuel, cMode);
            final ItemListener itemListener = new ItemListener() {
                @Override
                public void itemStateChanged(ItemEvent e) {
                    if (e.getStateChange() == ItemEvent.SELECTED) {
                        final boolean normal = radioNormal.isSelected();
                        final SQLTableModelSource src = normal ? withDeclSrc : noDeclSrc;
                        updateWhere.accept(src.getReq());
                        try {
                            panel.getListe().saveTableState();
                        } catch (IOException e1) {
                            // Table state isn't important
                            Log.get().log(Level.WARNING, "Couldn't save table state", e1);
                        }
                        panel.getListe().setConfigFile(null);
                        panel.getListe().setSource(src);
                        panel.getListe().setConfigFile(normal ? normalConfig : virtualConfig);
                    }
                }
            };
            radioNormal.addItemListener(itemListener);
            radioVirtuel.addItemListener(itemListener);
            c2.gridy++;
            panelMode.setBorder(BorderFactory.createTitledBorder("Vue"));
            panel.add(panelMode, c2);
        }
        JSplitPane pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JScrollPane(panelFam), panel);
        JPanel panelAll = new JPanel(new GridBagLayout());
        GridBagConstraints c = new DefaultGridBagConstraints();
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 1;
        c.weighty = 1;
        c.insets = new Insets(0, 0, 0, 0);
        panelAll.add(pane, c);

        final ITreeSelection tree = panelFam.getFamilleTree();
        tree.addValueListener(new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                updateWhere.accept(panel.getListe().getRequest());
            }
        });
        setTitle("Liste des articles");
        // rafraichir le titre à chaque changement de la liste
        panel.getListe().addListener(new TableModelListener() {
            public void tableChanged(TableModelEvent e) {
                setTitle(panel);
            }
        });
        panel.getListe().addListenerOnModel(new PropertyChangeListener() {
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if (evt.getPropertyName() == null || evt.getPropertyName().equals("loading") || evt.getPropertyName().equals("searching"))
                    setTitle(panel);
            }
        });

        panelFam.getCheckObsolete().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                final ListSQLRequest request = panel.getListe().getRequest();
                updateWhere.accept(request);
            }
        });

        this.setContentPane(panelAll);
    }

    protected void setTitle(ListeAddPanel panel) {
        String title = TITLE;
        if (panel.getListe().getModel().isLoading())
            title += ", chargement en cours";
        if (panel.getListe().getModel().isSearching())
            title += ", recherche en cours";

        setTitle(title);
    }

    private SQLTableModelSourceOnline getTableSource(SQLElement elt, List<String> fields) {
        final SQLTableModelSourceOnline createTableSource = elt.createTableSource();
        if (fields != null && !fields.isEmpty()) {
            for (String fieldName : fields) {
                final Path p = new Path(elt.getTable()).addForeignField(fieldName);
                final FieldPath fieldPath = new FieldPath(p, "NOM");
                createTableSource.getColumns().add(new SQLTableModelColumnPath(fieldPath, null, elt.getDirectory()));
            }
        }
        if (!elt.getTable().getDBRoot().contains("ARTICLE_PRIX_REVIENT")) {
            final SQLTableModelColumn colStock = new BaseSQLTableModelColumn("Valeur HT du stock", BigDecimal.class) {

                @Override
                protected Object show_(SQLRowAccessor r) {

                    SQLRowAccessor stock = r.getForeign("ID_STOCK");
                    if (stock == null || stock.isUndefined()) {
                        return BigDecimal.ZERO;
                    } else {
                        float qte = stock.getFloat("QTE_REEL");
                        BigDecimal ha = r.getBigDecimal("PA_HT");

                        BigDecimal total = ha.multiply(new BigDecimal(qte), DecimalUtils.HIGH_PRECISION);
                        if (total.signum() == 1) {
                            return total;
                        } else {
                            return BigDecimal.ZERO;
                        }
                    }
                }

                @Override
                public Set<FieldPath> getPaths() {
                    final SQLTable table = elt.getTable();
                    Path p = new Path(table);
                    Path p2 = new Path(table).addForeignField("ID_STOCK");
                    return CollectionUtils.createSet(new FieldPath(p, "PA_HT"), new FieldPath(p2, "QTE_REEL"));
                }
            };
            colStock.setRenderer(ComptaSQLConfElement.CURRENCY_RENDERER);
            createTableSource.getColumns().add(colStock);
        }

        return createTableSource;
    }

    /**
     * Filtre par rapport à la famille sélectionnée
     * 
     * @param panel
     * @return le where approprié
     */
    public Where getWhere(FamilleArticlePanel panel, boolean virtuals) {
        int id = panel.getFamilleTree().getSelectedID();

        Where w = null;

        if (panel.getCheckObsolete().isSelected()) {
            w = new Where(this.sqlTableArticle.getField("OBSOLETE"), "=", Boolean.FALSE);

            // FIXME Fonctionnement avec multidepot
            // w = w.or(new
            // Where(request.getAlias(this.sqlTableArticle.getForeignTable("ID_STOCK").getField("QTE_REEL")),
            // ">", 0));
        }

        w = new Where(this.sqlTableArticle.getField("VIRTUEL"), "=", virtuals).and(w);

        if (id > 1) {
            Set<Integer> idsMatch = new HashSet<>();
            idsMatch.add(id);

            fillChildren(idsMatch, CollectionUtils.createSet(id));

            Where w2 = new Where(this.sqlTableArticle.getField("ID_FAMILLE_ARTICLE"), "=", this.sqlTableFamilleArticle.getKey());
            w2 = w2.and(Where.inValues(this.sqlTableFamilleArticle.getKey(), idsMatch));
            w = w2.and(w);
        }
        return w;
    }

    private void fillChildren(Set<Integer> idsMatch, Set<Integer> father) {
        SQLRowValues rowVals = new SQLRowValues(this.sqlTableFamilleArticle);
        final String keyFieldName = rowVals.getTable().getKey().getName();
        rowVals.put(keyFieldName, null);
        SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowVals);
        List<SQLRowValues> children = fetcher.fetch(Where.inValues(this.sqlTableFamilleArticle.getField("ID_FAMILLE_ARTICLE_PERE"), father));
        Set<Integer> childToCheck = new HashSet<>();
        for (SQLRowValues child : children) {
            if (!idsMatch.contains(child.getID())) {
                childToCheck.add(child.getID());
                idsMatch.add(child.getID());
            }
        }
        if (!childToCheck.isEmpty()) {
            fillChildren(idsMatch, childToCheck);
        }

    }

}