Dépôt officiel du code source de l'ERP OpenConcerto
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);
}
}
}