OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 182 | 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.component;

import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement;
import org.openconcerto.erp.core.common.ui.CodeFournisseurItemTable;
import org.openconcerto.erp.core.common.ui.TotalPanel;
import org.openconcerto.erp.core.finance.accounting.model.CurrencyConverter;
import org.openconcerto.erp.core.finance.tax.model.TaxeCache;
import org.openconcerto.erp.core.sales.product.element.ArticleCodeClientTable;
import org.openconcerto.erp.core.sales.product.element.ReferenceArticleSQLElement;
import org.openconcerto.erp.core.sales.product.element.SupplierPriceListTable;
import org.openconcerto.erp.core.sales.product.element.UniteVenteArticleSQLElement;
import org.openconcerto.erp.core.sales.product.model.ProductHelper;
import org.openconcerto.erp.core.sales.product.ui.ArticleCategorieComptableTable;
import org.openconcerto.erp.core.sales.product.ui.ArticleDesignationTable;
import org.openconcerto.erp.core.sales.product.ui.ArticlePromotionTable;
import org.openconcerto.erp.core.sales.product.ui.ArticleTarifTable;
import org.openconcerto.erp.core.sales.product.ui.ProductItemListTable;
import org.openconcerto.erp.core.sales.product.ui.ProductQtyPriceListTable;
import org.openconcerto.erp.core.sales.product.ui.RowValuesTableEditionPanel;
import org.openconcerto.erp.core.supplychain.stock.element.DepotStockSQLElement;
import org.openconcerto.erp.model.ISQLCompteSelector;
import org.openconcerto.erp.preferences.DefaultNXProps;
import org.openconcerto.erp.preferences.GestionArticleGlobalPreferencePanel;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.element.BaseSQLComponent;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLRowListRSH;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLSelect;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.preferences.SQLPreferences;
import org.openconcerto.sql.request.ComboSQLRequest;
import org.openconcerto.sql.sqlobject.ElementComboBox;
import org.openconcerto.sql.sqlobject.SQLTextCombo;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.FormLayouter;
import org.openconcerto.ui.JDate;
import org.openconcerto.ui.TitledSeparator;
import org.openconcerto.ui.component.ITextArea;
import org.openconcerto.ui.component.InteractionMode;
import org.openconcerto.ui.preferences.DefaultProps;
import org.openconcerto.utils.DecimalUtils;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.StringUtils;
import org.openconcerto.utils.Tuple2;
import org.openconcerto.utils.text.SimpleDocumentListener;

import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;

public class ReferenceArticleSQLComponent extends BaseSQLComponent {

    protected JTextField textPVHT, textPVTTC, textPAHT;
    protected JTextField textMetrique1VT, textMetrique1HA;

    private final JCheckBox boxService = new JCheckBox(getLabelFor("SERVICE"));
    private final JCheckBox checkObs = new JCheckBox(getLabelFor("OBSOLETE"));
    private JTextField textNom;
    private JTextField textCode;
    private JTextField textPoids;
    private JTextField textValMetrique1, textValMetrique2, textValMetrique3;
    private DocumentListener htDocListener, ttcDocListener, detailsListener;
    private PropertyChangeListener propertyChangeListener;
    private PropertyChangeListener taxeListener;
    private final ElementComboBox comboSelTaxe = new ElementComboBox(false, 10);
    private final ElementComboBox comboSelModeVente = new ElementComboBox(false, 25);
    private JLabel labelMetriqueHA1 = new JLabel(getLabelFor("PRIX_METRIQUE_HA_1"), SwingConstants.RIGHT);
    private JLabel labelMetriqueVT1 = new JLabel(getLabelFor("PRIX_METRIQUE_VT_1"), SwingConstants.RIGHT);

    protected ArticleDesignationTable tableDes = new ArticleDesignationTable();
    protected ArticleCodeClientTable tableCodeClient = new ArticleCodeClientTable();
    protected ArticleTarifTable tableTarifVente = new ArticleTarifTable(this);
    protected ArticlePromotionTable tableTarifPromotionVente = new ArticlePromotionTable(this);
    protected final ArticleCategorieComptableTable tableCatComptable = new ArticleCategorieComptableTable();;
    protected SupplierPriceListTable tableFourSec = new SupplierPriceListTable();

    protected ProductQtyPriceListTable tableTarifQteVente = new ProductQtyPriceListTable(this);
    protected ProductItemListTable tableBom;
    protected final JTextField textMarge = new JTextField(10);
    protected final JLabel labelMarge = new JLabel("%           ");
    protected ElementComboBox boxCR;
    protected JCheckBox boxMargeWithCR;

    protected List<ElementComboBox> boxesDeclinaison = new ArrayList<>();

    protected DocumentListener pieceHAArticle = new SimpleDocumentListener() {

        @Override
        public void update(DocumentEvent e) {

            if (!ReferenceArticleSQLComponent.this.textPAHT.getText().equalsIgnoreCase(ReferenceArticleSQLComponent.this.textMetrique1HA.getText())) {
                ReferenceArticleSQLComponent.this.textMetrique1HA.setText(ReferenceArticleSQLComponent.this.textPAHT.getText());
            }
        }

    };
    protected DocumentListener pieceVTArticle = new SimpleDocumentListener() {

        @Override
        public void update(DocumentEvent e) {
            if (!ReferenceArticleSQLComponent.this.textPVHT.getText().equalsIgnoreCase(ReferenceArticleSQLComponent.this.textMetrique1VT.getText())) {
                ReferenceArticleSQLComponent.this.textMetrique1VT.setText(ReferenceArticleSQLComponent.this.textPVHT.getText());
            }
        }

    };

    protected DocumentListener listenerMargeTextMarge = new SimpleDocumentListener() {
        @Override
        public void update(DocumentEvent e) {
            ReferenceArticleSQLComponent.this.textPVHT.getDocument().removeDocumentListener(ReferenceArticleSQLComponent.this.listenerMargeTextVT);
            updateVtFromMarge();
            ReferenceArticleSQLComponent.this.textPVHT.getDocument().addDocumentListener(ReferenceArticleSQLComponent.this.listenerMargeTextVT);
        }

    };

    protected DocumentListener listenerMargeTextVT = new SimpleDocumentListener() {
        @Override
        public void update(DocumentEvent e) {
            ReferenceArticleSQLComponent.this.textMarge.getDocument().removeDocumentListener(ReferenceArticleSQLComponent.this.listenerMargeTextMarge);
            if (ReferenceArticleSQLComponent.this.textPVHT.getText().trim().length() > 0 && ReferenceArticleSQLComponent.this.textPAHT.getText().trim().length() > 0) {
                final BigDecimal vt = StringUtils.getBigDecimalFromUserText(ReferenceArticleSQLComponent.this.textPVHT.getText());
                BigDecimal ha = StringUtils.getBigDecimalFromUserText(ReferenceArticleSQLComponent.this.textPAHT.getText());

                if (vt != null && ha != null) {
                    if (vt.signum() != 0 && ha.signum() != 0) {

                        if (boxMargeWithCR.isSelected() && boxCR != null) {
                            SQLRow rowCR = boxCR.getSelectedRow();
                            if (rowCR != null && !rowCR.isUndefined()) {
                                BigDecimal cr = rowCR.getBigDecimal("POURCENT");
                                ha = ha.multiply(cr.movePointLeft(2).add(BigDecimal.ONE), DecimalUtils.HIGH_PRECISION);
                            }
                        }

                        BigDecimal margeHT = vt.subtract(ha);

                        BigDecimal value;

                        if (DefaultNXProps.getInstance().getBooleanValue(TotalPanel.MARGE_MARQUE, false)) {
                            if (vt.compareTo(BigDecimal.ZERO) > 0) {
                                value = margeHT.divide(vt, DecimalUtils.HIGH_PRECISION).multiply(BigDecimal.valueOf(100), DecimalUtils.HIGH_PRECISION);
                            } else {
                                value = BigDecimal.ZERO;
                            }
                        } else {
                            value = margeHT.divide(ha, DecimalUtils.HIGH_PRECISION).multiply(BigDecimal.valueOf(100), DecimalUtils.HIGH_PRECISION);
                        }

                        if (value.compareTo(BigDecimal.ZERO) > 0) {
                            ReferenceArticleSQLComponent.this.textMarge.setText(value.setScale(6, RoundingMode.HALF_UP).toString());
                        } else {
                            ReferenceArticleSQLComponent.this.textMarge.setText("0");
                        }
                        labelMarge.setText("% (" + StringUtils.leftAlign(margeHT.setScale(2, RoundingMode.HALF_UP).toString(), 9) + ")");
                    }
                }
            }
            ReferenceArticleSQLComponent.this.textMarge.getDocument().addDocumentListener(ReferenceArticleSQLComponent.this.listenerMargeTextMarge);
        }
    };

    protected DocumentListener listenerMargeTextHA = new SimpleDocumentListener() {
        @Override
        public void update(DocumentEvent e) {
            ReferenceArticleSQLComponent.this.textPVHT.getDocument().removeDocumentListener(ReferenceArticleSQLComponent.this.listenerMargeTextVT);
            updateVtFromMarge();
            ReferenceArticleSQLComponent.this.textPVHT.getDocument().addDocumentListener(ReferenceArticleSQLComponent.this.listenerMargeTextVT);
        }
    };

    public void updateVtFromMarge() {
        if (this.textPAHT.getText().trim().length() > 0) {

            BigDecimal ha = StringUtils.getBigDecimalFromUserText(this.textPAHT.getText());
            if (ha != null && this.textMarge.getText().trim().length() > 0) {

                if (boxMargeWithCR.isSelected() && boxCR != null) {
                    SQLRow rowCR = this.boxCR.getSelectedRow();
                    if (rowCR != null && !rowCR.isUndefined()) {
                        BigDecimal cr = rowCR.getBigDecimal("POURCENT");
                        ha = ha.multiply(cr.movePointLeft(2).add(BigDecimal.ONE), DecimalUtils.HIGH_PRECISION);
                    }
                }

                BigDecimal d = StringUtils.getBigDecimalFromUserText(this.textMarge.getText());
                if (d == null) {
                    d = BigDecimal.ZERO;
                }
                final BigDecimal vt;
                if (DefaultNXProps.getInstance().getBooleanValue(TotalPanel.MARGE_MARQUE, false)) {
                    final BigDecimal e = BigDecimal.ONE.subtract(d.divide(BigDecimal.valueOf(100), DecimalUtils.HIGH_PRECISION));
                    if (e.signum() == 0) {
                        vt = BigDecimal.ZERO;
                    } else {
                        vt = ha.divide(e, DecimalUtils.HIGH_PRECISION).setScale(getTable().getField("PV_HT").getType().getDecimalDigits(), RoundingMode.HALF_UP);
                    }
                } else {
                    BigDecimal result = ha.multiply(d.divide(BigDecimal.valueOf(100), DecimalUtils.HIGH_PRECISION).add(BigDecimal.ONE));
                    vt = result.setScale(getTable().getField("PV_HT").getType().getDecimalDigits(), RoundingMode.HALF_UP);
                    this.textPVHT.setText(vt.toString());
                }
                this.textPVHT.setText(vt.toString());
                BigDecimal margeHT = vt.subtract(ha);
                labelMarge.setText("% (" + StringUtils.leftAlign(margeHT.setScale(2, RoundingMode.HALF_UP).toString(), 9) + ")");
            }
        }
    }

    public ReferenceArticleSQLComponent(SQLElement elt) {
        super(elt);
        if (elt.getTable().getDBRoot().contains("ARTICLE_ELEMENT")) {
            this.tableBom = new ProductItemListTable();
        }
    }

    @Override
    public void select(SQLRowAccessor r) {
        super.select(r);
        if (r != null && r.getID() > getTable().getUndefinedID()) {
            this.checkObs.setVisible(true);
            this.tableTarifVente.setArticleValues(r);
            selectModeVente(r.getForeignID("ID_MODE_VENTE_ARTICLE"));
        } else {
            if (r == null || !r.contains("CODE") || r.getString("CODE") == null || r.getString("CODE").trim().length() == 0) {
                this.textCode.setText(getElement().getDirectory().getElement(NumerotationAutoSQLElement.class).getNextNumero(getElement().getClass()));
            }
        }
        this.tableTarifVente.getRowValuesTable().insertFrom(r);
        this.tableTarifPromotionVente.getRowValuesTable().insertFrom(r);
        this.tableCatComptable.getRowValuesTable().insertFrom(r);
        this.tableFourSec.getRowValuesTable().insertFrom(r);
        this.tableTarifQteVente.getRowValuesTable().insertFrom(r);
        if (this.tableBom != null) {
            this.tableBom.getRowValuesTable().getRowValuesTableModel().insertFrom(r, getTable().getTable("ARTICLE_ELEMENT").getField("ID_ARTICLE_PARENT"));
        }
        this.tableDes.getRowValuesTable().insertFrom(r);
        this.tableCodeClient.getRowValuesTable().insertFrom(r);
        if (this.codeFournisseurTable != null) {
            this.codeFournisseurTable.getModel().insertFrom(r);
        }

        for (ElementComboBox elementComboBox : boxesDeclinaison) {
            elementComboBox.setEnabled(r != null && r.getNonEmptyForeign("ID_ARTICLE_VIRTUEL_PERE") != null ? InteractionMode.READ_WRITE : InteractionMode.DISABLED);
        }
    }

    public void addViews() {
        this.setLayout(new GridBagLayout());
        final GridBagConstraints c = new DefaultGridBagConstraints();

        this.textPVHT = new JTextField(15);
        this.textPVTTC = new JTextField(15);
        this.textPAHT = new JTextField(15);
        this.textPVHT.getDocument().addDocumentListener(this.listenerMargeTextVT);

        // Init metrique devise field
        this.textMetrique1HA = new JTextField(15);
        this.textMetrique1VT = new JTextField(15);

        // init metrique value field
        this.textValMetrique1 = new JTextField(15);
        this.textValMetrique2 = new JTextField(15);
        this.textValMetrique3 = new JTextField(15);

        this.textCode = new JTextField();
        this.textNom = new JTextField();
        this.textPoids = new JTextField(6);

        // Code
        JLabel codelabel = new JLabel(getLabelFor("CODE"));
        codelabel.setHorizontalAlignment(SwingConstants.RIGHT);
        DefaultGridBagConstraints.lockMinimumSize(codelabel);
        this.add(codelabel, c);
        c.gridx++;
        c.weightx = 1;
        DefaultGridBagConstraints.lockMinimumSize(textCode);
        this.add(this.textCode, c);

        // Famille
        c.gridx++;
        c.gridwidth = 1;
        c.weightx = 0;
        JLabel labelFamille = new JLabel(getLabelFor("ID_FAMILLE_ARTICLE"));
        labelFamille.setHorizontalAlignment(SwingConstants.RIGHT);
        DefaultGridBagConstraints.lockMinimumSize(labelFamille);
        this.add(labelFamille, c);
        c.gridx++;
        c.weightx = 1;
        c.gridwidth = 1;
        final ElementComboBox comboSelFamille = new ElementComboBox(false, 25);
        this.addSQLObject(comboSelFamille, "ID_FAMILLE_ARTICLE");
        DefaultGridBagConstraints.lockMinimumSize(comboSelFamille);
        this.add(comboSelFamille, c);

        // Nom
        c.gridy++;
        c.gridx = 0;
        c.weightx = 0;
        JLabel labelNom = new JLabel(getLabelFor("NOM"));
        labelNom.setHorizontalAlignment(SwingConstants.RIGHT);
        DefaultGridBagConstraints.lockMinimumSize(labelNom);
        this.add(labelNom, c);
        c.gridx++;
        c.weightx = 1;
        DefaultGridBagConstraints.lockMinimumSize(textNom);
        this.add(this.textNom, c);

        // Code barre
        c.gridx++;
        c.weightx = 0;
        JLabel labelCodeBarre = new JLabel(getLabelFor("CODE_BARRE"));
        labelCodeBarre.setHorizontalAlignment(SwingConstants.RIGHT);
        DefaultGridBagConstraints.lockMinimumSize(labelCodeBarre);
        this.add(labelCodeBarre, c);
        c.gridx++;
        c.weightx = 1;
        JTextField fieldCodeBarre = new JTextField();
        DefaultGridBagConstraints.lockMinimumSize(fieldCodeBarre);
        this.add(fieldCodeBarre, c);
        this.addView(fieldCodeBarre, "CODE_BARRE");

        SQLPreferences prefs = new SQLPreferences(getTable().getDBRoot());
        // Gestion des unités de vente
        final boolean gestionUV = prefs.getBoolean(GestionArticleGlobalPreferencePanel.UNITE_VENTE, true);
        c.gridy++;
        final ElementComboBox boxUnite = new ElementComboBox();
        if (gestionUV) {
            c.gridx = 0;
            c.weightx = 0;
            this.add(new JLabel(getLabelFor("ID_UNITE_VENTE"), SwingConstants.RIGHT), c);
            c.gridx++;
            c.weightx = 1;
            c.fill = GridBagConstraints.NONE;
            DefaultGridBagConstraints.lockMinimumSize(boxUnite);
            this.add(boxUnite, c);
            this.addView(boxUnite, "ID_UNITE_VENTE");
            c.fill = GridBagConstraints.HORIZONTAL;
        }
        c.gridx = 2;
        c.weightx = 0;
        this.add(new JLabel(getLabelFor("SKU"), SwingConstants.RIGHT), c);
        c.gridx++;
        c.weightx = 1;
        JTextField fieldSKU = new JTextField();
        DefaultGridBagConstraints.lockMinimumSize(fieldSKU);
        this.add(fieldSKU, c);
        this.addView(fieldSKU, "SKU");
        c.fill = GridBagConstraints.HORIZONTAL;

        c.gridy++;
        if (gestionUV) {
            c.gridx = 0;
            c.weightx = 0;
            this.add(new JLabel(getLabelFor("QTE_UNITAIRE"), SwingConstants.RIGHT), c);
            c.gridx++;
            c.weightx = 1;
            c.fill = GridBagConstraints.NONE;
            final JTextField qte = new JTextField(10);
            qte.setEditable(false);

            this.add(qte, c);
            this.addView(qte, "QTE_UNITAIRE", REQ);
            boxUnite.addModelListener("wantedID", new PropertyChangeListener() {

                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    if (!boxUnite.isEmpty() && boxUnite.getSelectedId() == UniteVenteArticleSQLElement.A_LA_PIECE) {
                        qte.setText("1");
                        qte.setEditable(false);
                    } else {
                        qte.setEditable(true);
                    }

                }
            });
            c.fill = GridBagConstraints.HORIZONTAL;
        }

        DefaultProps props = DefaultNXProps.getInstance();

        // Article détaillé
        String modeVente = props.getStringProperty("ArticleModeVenteAvance");
        Boolean bModeVente = Boolean.valueOf(modeVente);
        boolean modeVenteAvance = (bModeVente == null || bModeVente.booleanValue());

        if (modeVenteAvance) {
            addModeVenteAvance(c);
        }

        getMontantPanel(c, props);

        // Champ Module
        c.gridx = 0;
        c.gridy++;
        c.gridwidth = GridBagConstraints.REMAINDER;
        final JPanel addP = ComptaSQLConfElement.createAdditionalPanel();
        this.setAdditionalFieldsPanel(new FormLayouter(addP, 2));
        this.add(addP, c);

        JTabbedPane pane = new JTabbedPane();
        c.gridy++;
        c.weightx = 1;
        c.weighty = 1;

        pane.add("Tarifs de vente spéciaux", createTarifPanel());
        pane.add("Tarifs de vente par quantité", createTarifQtePanel());
        pane.add("Tarifs promotionnels", createTarifPromotionPanel());

        if (this.tableBom != null) {
            pane.add("Nomenclature", createBOMpanel());
        }
        pane.add("Exportation", createExportationPanel());
        pane.add("Achat", createAchatPanel());
        pane.add("Stock", createStockPanel());
        pane.add("Descriptif", createDescriptifPanel());
        pane.add("Désignations multilingues", createDesignationPanel());
        pane.add("Désignations clients", createCodeClientPanel());

        if (prefs.getBoolean(GestionArticleGlobalPreferencePanel.ACTIVER_DECLINAISON, false)) {

            pane.add("Déclinaison", createDeclinaisonPanel());
        }
        pane.add("Comptabilité", createComptaPanel());
        pane.add(getLabelFor("INFOS"), createInfosPanel());

        c.fill = GridBagConstraints.BOTH;
        this.add(pane, c);

        this.addSQLObject(this.textMetrique1HA, "PRIX_METRIQUE_HA_1");
        this.addSQLObject(this.textMetrique1VT, "PRIX_METRIQUE_VT_1");
        this.addSQLObject(this.textValMetrique1, "VALEUR_METRIQUE_1");
        this.addSQLObject(this.textValMetrique2, "VALEUR_METRIQUE_2");
        this.addSQLObject(this.textValMetrique3, "VALEUR_METRIQUE_3");
        this.addSQLObject(this.comboSelModeVente, "ID_MODE_VENTE_ARTICLE");
        this.addSQLObject(this.boxService, "SERVICE");

        this.addRequiredSQLObject(this.textNom, "NOM");
        this.addRequiredSQLObject(this.textCode, "CODE");

        this.addSQLObject(this.textPoids, "POIDS");

        this.comboSelTaxe.setButtonsVisible(false);
        this.propertyChangeListener = new PropertyChangeListener() {

            public void propertyChange(PropertyChangeEvent evt) {
                System.err.println(ReferenceArticleSQLComponent.this.comboSelModeVente.getSelectedId());
                selectModeVente(ReferenceArticleSQLComponent.this.comboSelModeVente.getSelectedId());

            }

        };
        setListenerModeVenteActive(true);
        this.comboSelModeVente.setValue(ReferenceArticleSQLElement.A_LA_PIECE);
    }

    protected Component createInfosPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setOpaque(false);
        GridBagConstraints c = new DefaultGridBagConstraints();
        c.weightx = 0;
        c.gridy++;
        c.gridx = 0;
        c.weightx = 0;
        JLabel labelifco = new JLabel(getLabelFor("IFCO"));

        panel.add(labelifco, c);
        c.weightx = 1;
        c.gridx++;
        JTextField textIfco = new JTextField(40);
        panel.add(textIfco, c);
        addView(textIfco, "IFCO");

        c.gridx++;
        c.weightx = 0;
        JLabel labelTare = new JLabel(getLabelFor("TARE"));
        panel.add(labelTare, c);
        c.weightx = 1;
        c.gridx++;
        JTextField textTare = new JTextField(40);
        panel.add(textTare, c);
        addView(textTare, "TARE");

        // c.gridy++;
        // c.gridx = 0;
        // c.weightx = 0;
        // JLabel labelDLC = new JLabel(getLabelFor("DLC"));
        // panel.add(labelDLC, c);
        // c.weightx = 1;
        // c.gridx++;
        // JDate dateDLC = new JDate();
        // panel.add(dateDLC, c);
        // addView(dateDLC, "DLC");

        c.weightx = 0;
        c.gridy++;
        c.gridx = 0;
        JLabel labelOption = new JLabel(getLabelFor("OPTION"));
        c.fill = GridBagConstraints.BOTH;
        panel.add(labelOption, c);
        c.weightx = 1;
        c.gridx++;
        JCheckBox boxOption = new JCheckBox();
        panel.add(boxOption, c);
        this.addSQLObject(boxOption, "OPTION");

        c.weightx = 0;
        c.gridy++;
        c.gridx = 0;
        if (getTable().contains("POIDS_COLIS_NET")) {
            JLabel labelPdsColis = new JLabel(getLabelFor("POIDS_COLIS_NET"));
            panel.add(labelPdsColis, c);
            c.weightx = 1;
            c.gridx++;
            JTextField textPdsColis = new JTextField(40);
            panel.add(textPdsColis, c);
            addView(textPdsColis, "POIDS_COLIS_NET");
            c.gridx++;
        }

        JLabel labelMasque = new JLabel(getLabelFor("MASQUE_CAISSE"));
        c.fill = GridBagConstraints.BOTH;
        panel.add(labelMasque, c);
        c.weightx = 1;
        c.gridx++;
        JCheckBox boxMasqueCaisse = new JCheckBox();
        panel.add(boxMasqueCaisse, c);
        this.addSQLObject(boxMasqueCaisse, "MASQUE_CAISSE");

        c.gridy++;
        c.gridx = 0;
        c.weightx = 0;
        JLabel labelEco = new JLabel(getLabelFor("ID_ECO_CONTRIBUTION"));
        c.fill = GridBagConstraints.BOTH;
        panel.add(labelEco, c);
        c.weightx = 1;
        c.gridx++;
        ElementComboBox box = new ElementComboBox();
        panel.add(box, c);

        c.weightx = 0;
        c.gridy++;
        c.gridx = 0;
        JLabel labelTaxeCompl = new JLabel(getLabelFor("ID_TAXE_COMPLEMENTAIRE"));
        c.fill = GridBagConstraints.BOTH;
        panel.add(labelTaxeCompl, c);
        c.weightx = 1;
        c.gridx++;
        ElementComboBox boxTaxeCompl = new ElementComboBox();
        panel.add(boxTaxeCompl, c);

        c.weightx = 0;
        c.gridy++;
        c.gridx = 0;
        JLabel labelMatiere = new JLabel(getLabelFor("MATIERE"));
        c.fill = GridBagConstraints.BOTH;
        panel.add(labelMatiere, c);
        c.weightx = 1;
        c.gridx++;
        SQLTextCombo comboMatiere = new SQLTextCombo();
        panel.add(comboMatiere, c);

        c.gridy++;
        c.gridx = 0;
        c.gridwidth = GridBagConstraints.REMAINDER;
        TitledSeparator sep = new TitledSeparator(getLabelFor("INFOS"));
        panel.add(sep, c);
        c.gridy++;
        c.weighty = 1;
        ITextArea infos = new ITextArea();
        c.fill = GridBagConstraints.BOTH;
        panel.add(infos, c);

        this.addSQLObject(infos, "INFOS");
        this.addSQLObject(comboMatiere, "MATIERE");
        this.addSQLObject(box, "ID_ECO_CONTRIBUTION");
        this.addSQLObject(boxTaxeCompl, "ID_TAXE_COMPLEMENTAIRE");
        return panel;
    }

    protected Component createDescriptifPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setOpaque(false);
        GridBagConstraints c = new DefaultGridBagConstraints();

        // Obsolete
        c.fill = GridBagConstraints.NONE;
        c.gridwidth = GridBagConstraints.REMAINDER;
        c.weightx = 1;
        this.checkObs.setOpaque(false);
        panel.add(this.checkObs, c);

        this.checkObs.setVisible(false);
        this.addView(this.checkObs, "OBSOLETE");

        if (getTable().getFieldsName().contains("COLORIS")) {
            JTextField fieldColoris = new JTextField();
            c.gridy++;
            c.fill = GridBagConstraints.HORIZONTAL;
            c.weightx = 0;
            c.gridwidth = 1;
            panel.add(new JLabel(getLabelFor("COLORIS")), c);

            c.weightx = 1;
            c.gridx++;
            panel.add(fieldColoris, c);
            this.addView(fieldColoris, "COLORIS");
        }
        JTextField fieldLongueur = new JTextField();
        c.gridy++;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0;
        c.gridwidth = 1;
        panel.add(new JLabel(getLabelFor("LONGUEUR")), c);

        c.weightx = 1;
        c.gridx++;
        panel.add(fieldLongueur, c);
        this.addView(fieldLongueur, "LONGUEUR");

        JTextField fieldLargeur = new JTextField();
        c.gridx++;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0;
        c.gridwidth = 1;
        panel.add(new JLabel(getLabelFor("LARGEUR")), c);
        c.weightx = 1;
        c.gridx++;
        panel.add(fieldLargeur, c);
        this.addView(fieldLargeur, "LARGEUR");

        JTextField fieldHauteur = new JTextField();
        c.gridy++;
        c.gridx = 0;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 0;
        c.gridwidth = 1;
        panel.add(new JLabel(getLabelFor("HAUTEUR")), c);

        c.weightx = 1;
        c.gridx++;
        panel.add(fieldHauteur, c);
        this.addView(fieldHauteur, "HAUTEUR");

        ITextArea area = new ITextArea();
        JLabel sep = new JLabel("Descriptif complet");
        c.gridy++;
        c.gridx = 0;
        c.gridwidth = GridBagConstraints.REMAINDER;
        c.fill = GridBagConstraints.HORIZONTAL;
        panel.add(sep, c);

        c.gridy++;
        c.weighty = 1;
        c.fill = GridBagConstraints.BOTH;
        panel.add(area, c);
        this.addView(area, "DESCRIPTIF");
        return panel;
    }

    protected Component createDesignationPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setOpaque(false);
        GridBagConstraints c = new DefaultGridBagConstraints();

        // Ajout des
        c.gridwidth = 1;
        c.weightx = 0;
        c.gridy++;
        c.gridx = 0;
        panel.add(new JLabel("Ajouter une désignation "), c);

        final ElementComboBox boxDes = new ElementComboBox();
        boxDes.init(Configuration.getInstance().getDirectory().getElement("LANGUE"));

        c.gridx++;
        panel.add(boxDes, c);

        c.fill = GridBagConstraints.NONE;
        c.gridx++;
        JButton buttonAjouterDes = new JButton("Ajouter");
        buttonAjouterDes.setOpaque(false);
        panel.add(buttonAjouterDes, c);
        c.gridx++;
        JButton buttonSupprimerDes = new JButton("Supprimer");
        buttonSupprimerDes.setOpaque(false);
        panel.add(buttonSupprimerDes, c);

        c.gridy++;
        c.gridx = 0;
        c.gridwidth = GridBagConstraints.REMAINDER;
        c.fill = GridBagConstraints.BOTH;
        c.weighty = 1;
        c.weightx = 1;
        this.tableDes.setOpaque(false);
        panel.add(this.tableDes, c);

        // Listerners
        buttonAjouterDes.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                int id = boxDes.getSelectedId();
                if (id <= 1) {
                    return;
                }
                int nbRows = tableDes.getModel().getRowCount();

                for (int i = 0; i < nbRows; i++) {
                    SQLRowValues rowVals = tableDes.getModel().getRowValuesAt(i);
                    int idLangue = Integer.parseInt(rowVals.getObject("ID_LANGUE").toString());
                    if (idLangue == id) {
                        JOptionPane.showMessageDialog(null, "Impossible d'ajouter.\nLa langue est déjà présente dans la liste!");
                        return;
                    }
                }

                SQLRowValues rowVals = new SQLRowValues(Configuration.getInstance().getBase().getTable("ARTICLE_DESIGNATION"));
                if (getSelectedID() > 1) {
                    rowVals.put("ID_ARTICLE", getSelectedID());
                }
                rowVals.put("ID_LANGUE", id);
                rowVals.put("NOM", "");
                tableDes.getModel().addRow(rowVals);
            }
        });
        buttonSupprimerDes.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                tableDes.removeSelectedRow();
            }
        });

        return panel;
    }

    protected Component createCodeClientPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setOpaque(false);
        GridBagConstraints c = new DefaultGridBagConstraints();

        c.gridx = 0;
        c.gridwidth = GridBagConstraints.REMAINDER;
        c.fill = GridBagConstraints.BOTH;
        c.weighty = 1;
        c.weightx = 1;
        this.tableCodeClient.setOpaque(false);
        panel.add(this.tableCodeClient, c);

        return panel;
    }

    protected Component createDeclinaisonPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setOpaque(false);
        GridBagConstraints c = new DefaultGridBagConstraints();

        c.weighty = 0;
        c.weightx = 0;

        panel.add(new JLabel(getLabelFor("ID_ARTICLE_VIRTUEL_PERE")), c);
        c.gridx++;
        c.weightx = 1;
        final ElementComboBox boxPere = new ElementComboBox();
        panel.add(boxPere, c);
        final ComboSQLRequest reqVir = getElement().createComboRequest();
        reqVir.setWhere(new Where(getElement().getTable().getField("VIRTUEL"), "=", Boolean.TRUE));
        boxPere.init(getElement(), reqVir);
        this.addView(boxPere, "ID_ARTICLE_VIRTUEL_PERE");
        c.gridx = 0;
        c.gridy++;

        List<String> declFiels = new ArrayList<String>();
        for (String string : getTable().getFieldsName()) {
            if (string.startsWith("ID_ARTICLE_DECLINAISON_")) {
                declFiels.add(string);
            }
        }

        this.boxesDeclinaison.clear();

        for (String field : declFiels) {
            c.weightx = 0;
            if (c.gridx == 4) {
                c.gridx = 0;
                c.gridy++;
            }
            panel.add(new JLabel(getLabelFor(field)), c);
            c.gridx++;
            c.weightx = 1;
            ElementComboBox box1 = new ElementComboBox();
            final SQLElement declElement = getElement().getForeignElement(field);
            box1.init(declElement, declElement.createComboRequest());
            box1.setEnabled(InteractionMode.DISABLED);
            panel.add(box1, c);
            this.addView(box1, field);

            this.boxesDeclinaison.add(box1);
            c.gridx++;
        }

        boxPere.addModelListener("wantedID", new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {

                for (ElementComboBox elementComboBox : boxesDeclinaison) {
                    elementComboBox.setEnabled(boxPere.getWantedID() != SQLRow.NONEXISTANT_ID ? InteractionMode.READ_WRITE : InteractionMode.DISABLED);
                }
            }
        });

        return panel;
    }

    protected Component createStockPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setOpaque(false);
        GridBagConstraints c = new DefaultGridBagConstraints();
        SQLPreferences prefs = new SQLPreferences(getTable().getDBRoot());
        boolean gestionStockMin = prefs.getBoolean(GestionArticleGlobalPreferencePanel.WARNING_STOCK_MIN, true);
        c.gridx = 0;
        c.gridy++;

        final JCheckBox boxStock = new JCheckBox(getLabelFor("GESTION_STOCK"));
        boxStock.setOpaque(false);
        panel.add(boxStock, c);
        this.addView(boxStock, "GESTION_STOCK");

        final JTextField fieldQteMin = new JTextField();
        final JTextField fieldQteAchat = new JTextField();
        boxStock.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                fieldQteMin.setEnabled(boxStock.isSelected());
                fieldQteAchat.setEnabled(boxStock.isSelected());
            }
        });

        boolean visibleDepot = (prefs.getBoolean(GestionArticleGlobalPreferencePanel.STOCK_MULTI_DEPOT, false));
        c.gridx = 0;
        c.gridy++;
        c.weightx = 0;
        final JLabel labelDepot = new JLabel(getLabelFor("ID_DEPOT_STOCK"));
        panel.add(labelDepot, c);
        labelDepot.setVisible(visibleDepot);
        c.gridx++;
        c.weightx = 1;
        ElementComboBox boxDepot = new ElementComboBox();
        panel.add(boxDepot, c);
        boxDepot.setVisible(visibleDepot);
        this.addView(boxDepot, "ID_DEPOT_STOCK", REQ);

        c.gridwidth = 1;
        if (gestionStockMin) {
            // c.gridx = 0;
            // c.gridy++;
            // c.weightx = 0;
            // panel.add(new JLabel(getLabelFor("QTE_MIN")), c);
            // c.gridx++;
            // c.weightx = 1;
            // panel.add(fieldQteMin, c);
            // this.addView(fieldQteMin, "QTE_MIN");

            c.gridx = 0;
            c.gridy++;
            c.weightx = 0;
            panel.add(new JLabel(getLabelFor("QTE_ACHAT")), c);
            c.gridx++;
            c.weightx = 1;
            panel.add(fieldQteAchat, c);
            this.addView(fieldQteAchat, "QTE_ACHAT");
        }

        //
        c.gridy++;
        c.gridx = 1;
        c.weightx = 1;
        JCheckBox DLCrequis = new JCheckBox("DLC requis");
        DLCrequis.setOpaque(false);
        panel.add(DLCrequis, c);
        addView(DLCrequis, "DLC_REQUIS");
        c.gridy++;
        JCheckBox DLUOrequis = new JCheckBox("DLUO requis");
        DLUOrequis.setOpaque(false);
        panel.add(DLUOrequis, c);
        addView(DLUOrequis, "DLUO_REQUIS");
        c.gridy++;
        JCheckBox numeroLotRequis = new JCheckBox("n° de lot requis");
        numeroLotRequis.setOpaque(false);
        panel.add(numeroLotRequis, c);
        addView(numeroLotRequis, "NUMERO_LOT_REQUIS");
        c.gridy++;
        JCheckBox numeroSerieRequis = new JCheckBox("n° de série requis");
        numeroSerieRequis.setOpaque(false);
        panel.add(numeroSerieRequis, c);
        addView(numeroSerieRequis, "NUMERO_SERIE_REQUIS");

        c.gridy++;
        c.weighty = 1;
        c.weightx = 1;
        c.fill = GridBagConstraints.BOTH;
        final JPanel spacer = new JPanel();
        spacer.setOpaque(false);
        panel.add(spacer, c);
        return panel;
    }

    protected Component createComptaPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setOpaque(false);
        GridBagConstraints c = new DefaultGridBagConstraints();
        c.gridwidth = 1;
        c.weighty = 0;
        c.weightx = 0;
        ISQLCompteSelector sel = new ISQLCompteSelector();
        c.fill = GridBagConstraints.BOTH;
        panel.add(new JLabel(getLabelFor("ID_COMPTE_PCE")), c);
        c.gridx++;
        c.weightx = 1;
        panel.add(sel, c);
        this.addView(sel, "ID_COMPTE_PCE");

        c.gridwidth = 1;
        c.gridy++;
        c.weighty = 0;
        c.gridx = 0;
        c.weightx = 0;
        ISQLCompteSelector selAchat = new ISQLCompteSelector();
        c.fill = GridBagConstraints.BOTH;
        panel.add(new JLabel(getLabelFor("ID_COMPTE_PCE_ACHAT")), c);
        c.gridx++;
        c.weightx = 1;
        panel.add(selAchat, c);
        this.addView(selAchat, "ID_COMPTE_PCE_ACHAT");

        c.gridy++;
        c.gridx = 0;
        c.weighty = 1;
        c.weightx = 1;
        c.fill = GridBagConstraints.BOTH;
        c.gridwidth = GridBagConstraints.REMAINDER;

        panel.add(createCategorieComptablePanel(), c);
        // final JPanel spacer = new JPanel();
        // spacer.setOpaque(false);
        // panel.add(spacer, c);
        return panel;
    }

    protected SQLRowValues rowValuesDefaultCodeFournisseur;
    protected CodeFournisseurItemTable codeFournisseurTable;

    protected Component createAchatPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setOpaque(false);
        GridBagConstraints c = new DefaultGridBagConstraints();
        // Fournisseur
        c.gridy++;
        c.gridx = 0;
        c.gridwidth = 1;
        c.weightx = 0;
        JLabel labelFournisseur = new JLabel(getLabelFor("ID_FOURNISSEUR"));
        labelFournisseur.setHorizontalAlignment(SwingConstants.RIGHT);
        panel.add(labelFournisseur, c);
        c.gridx++;
        c.weightx = 1;
        c.gridwidth = 2;
        final ElementComboBox comboSelFournisseur = new ElementComboBox(false, 25);
        panel.add(comboSelFournisseur, c);
        this.addView(comboSelFournisseur, "ID_FOURNISSEUR");

        SQLPreferences prefs = new SQLPreferences(ComptaPropsConfiguration.getInstanceCompta().getRootSociete());
        final boolean supplierCode = prefs.getBoolean(GestionArticleGlobalPreferencePanel.SUPPLIER_PRODUCT_CODE, false);

        // Tarif fournisseur
        c.gridy++;
        c.gridx = 0;
        c.gridwidth = GridBagConstraints.REMAINDER;
        TitledSeparator sep = new TitledSeparator("Tarifs fournisseurs");
        panel.add(sep, c);

        // Ajout fournisseur
        c.gridwidth = 1;
        c.weightx = 0;
        c.gridy++;
        c.gridx = 0;
        panel.add(new JLabel("Ajouter le fournisseur "), c);

        final ElementComboBox boxF = new ElementComboBox();
        boxF.init(Configuration.getInstance().getDirectory().getElement("FOURNISSEUR"));

        c.gridx++;
        panel.add(boxF, c);

        c.fill = GridBagConstraints.NONE;
        c.gridx++;
        JButton buttonAjouter = new JButton("Ajouter");
        buttonAjouter.setOpaque(false);
        panel.add(buttonAjouter, c);
        c.gridx++;
        JButton buttonSupprimer = new JButton("Supprimer");
        buttonSupprimer.setOpaque(false);
        panel.add(buttonSupprimer, c);

        c.gridwidth = GridBagConstraints.REMAINDER;
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 1;
        c.weighty = 1;
        c.gridy++;
        c.gridx = 0;
        c.fill = GridBagConstraints.BOTH;
        this.tableFourSec.setOpaque(false);
        panel.add(this.tableFourSec, c);

        // Listeners
        buttonAjouter.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                SQLRow rowCat = boxF.getSelectedRow();
                if (rowCat == null || rowCat.isUndefined()) {
                    return;
                }
                int nbRows = tableFourSec.getModel().getRowCount();

                // for (int i = 0; i < nbRows; i++) {
                // SQLRowValues rowVals = tableFourSec.getModel().getRowValuesAt(i);
                // int idTarif =
                // Integer.parseInt(rowVals.getObject("ID_FOURNISSEUR").toString());
                // if (idTarif == rowCat.getID()) {
                // JOptionPane.showMessageDialog(null, "Impossible d'ajouter.\nLe fournisseur
                // est déjà présent dans la liste!");
                // return;
                // }
                // }

                SQLRowValues rowVals = new SQLRowValues(Configuration.getInstance().getBase().getTable("ARTICLE_TARIF_FOURNISSEUR"));
                if (getSelectedID() > 1) {
                    rowVals.put("ID_ARTICLE", getSelectedID());
                }
                rowVals.put("ID_FOURNISSEUR", rowCat.getID());
                tableFourSec.getModel().addRow(rowVals);
            }
        });
        buttonSupprimer.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                tableFourSec.removeSelectedRow();
            }
        });
        if (getTable().getSchema().contains("CODE_FOURNISSEUR") && supplierCode) {
            c.gridy++;
            c.gridx = 0;
            c.gridwidth = GridBagConstraints.REMAINDER;
            TitledSeparator sepC = new TitledSeparator("Codes fournisseurs");
            panel.add(sepC, c);

            this.rowValuesDefaultCodeFournisseur = new SQLRowValues(getTable().getTable("CODE_FOURNISSEUR"));
            this.codeFournisseurTable = new CodeFournisseurItemTable(this.rowValuesDefaultCodeFournisseur);
            c.gridy++;
            c.gridx = 0;
            c.gridwidth = GridBagConstraints.REMAINDER;
            c.weighty = 1;
            c.weightx = 1;
            c.fill = GridBagConstraints.BOTH;
            panel.add(this.codeFournisseurTable, c);
            comboSelFournisseur.addValueListener(new PropertyChangeListener() {

                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    rowValuesDefaultCodeFournisseur.put("ID_FOURNISSEUR", comboSelFournisseur.getSelectedId());
                }
            });
        }
        return panel;

    }

    protected JPanel createExportationPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setOpaque(false);
        GridBagConstraints c = new DefaultGridBagConstraints();
        // Code douanier
        c.gridx = 0;
        c.weightx = 0;
        c.gridy++;
        c.gridwidth = 1;
        JLabel labelCodeD = new JLabel(getLabelFor("CODE_DOUANIER"));
        labelCodeD.setHorizontalAlignment(SwingConstants.RIGHT);
        panel.add(labelCodeD, c);

        c.gridx++;
        JTextField fieldCodeDouanier = new JTextField();
        c.weightx = 1;
        panel.add(fieldCodeDouanier, c);
        this.addView(fieldCodeDouanier, "CODE_DOUANIER");

        // Pays d'origine
        c.gridx++;
        c.weightx = 0;
        JLabel labelPays = new JLabel(getLabelFor("ID_PAYS"));
        labelPays.setHorizontalAlignment(SwingConstants.RIGHT);
        panel.add(labelPays, c);
        c.gridx++;
        c.weightx = 1;
        final ElementComboBox comboSelPays = new ElementComboBox(false);
        panel.add(comboSelPays, c);
        this.addView(comboSelPays, "ID_PAYS");
        c.gridy++;
        c.weighty = 1;
        c.weightx = 1;
        c.fill = GridBagConstraints.BOTH;
        final JPanel spacer = new JPanel();
        spacer.setOpaque(false);
        panel.add(spacer, c);
        return panel;
    }

    protected JPanel createTarifPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setOpaque(false);
        GridBagConstraints c = new DefaultGridBagConstraints();

        // Ajout tarif
        c.gridwidth = 1;
        c.weightx = 0;
        c.gridy++;
        c.gridx = 0;
        panel.add(new JLabel("Ajouter le tarif "), c);

        final ElementComboBox boxTarif = new ElementComboBox();
        boxTarif.init(Configuration.getInstance().getDirectory().getElement("TARIF"));

        c.gridx++;
        panel.add(boxTarif, c);

        c.fill = GridBagConstraints.NONE;
        c.gridx++;
        JButton buttonAjouter = new JButton("Ajouter");
        buttonAjouter.setOpaque(false);
        panel.add(buttonAjouter, c);
        c.gridx++;
        JButton buttonSupprimer = new JButton("Supprimer");
        buttonSupprimer.setOpaque(false);
        panel.add(buttonSupprimer, c);

        c.gridwidth = GridBagConstraints.REMAINDER;
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 1;
        c.weighty = 1;
        c.gridy++;
        c.gridx = 0;
        c.fill = GridBagConstraints.BOTH;
        this.tableTarifVente.setOpaque(false);
        panel.add(this.tableTarifVente, c);

        // Listeners
        buttonAjouter.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                SQLRow rowTarif = boxTarif.getSelectedRow();
                if (rowTarif == null || rowTarif.isUndefined()) {
                    return;
                }
                // int nbRows = tableTarifVente.getModel().getRowCount();

                // FIXME Check with qty
                // for (int i = 0; i < nbRows; i++) {
                // SQLRowValues rowVals = tableTarifVente.getModel().getRowValuesAt(i);
                // int idTarif = Integer.parseInt(rowVals.getObject("ID_TARIF").toString());
                // if (idTarif == rowTarif.getID()) {
                // JOptionPane.showMessageDialog(null,
                // "Impossible d'ajouter.\nLe tarif est déjà présent dans la liste!");
                // return;
                // }
                // }

                SQLRowValues rowVals = new SQLRowValues(Configuration.getInstance().getBase().getTable("ARTICLE_TARIF"));
                if (getSelectedID() > 1) {
                    rowVals.put("ID_ARTICLE", getSelectedID());
                }
                rowVals.put("ID_TARIF", rowTarif.getID());
                rowVals.put("ID_DEVISE", rowTarif.getInt("ID_DEVISE"));
                rowVals.put("ID_TAXE", rowTarif.getInt("ID_TAXE"));
                rowVals.put("PRIX_METRIQUE_VT_1", BigDecimal.ZERO);
                rowVals.put("PV_HT", BigDecimal.ZERO);
                rowVals.put("PV_TTC", BigDecimal.ZERO);
                tableTarifVente.getModel().addRow(rowVals);
            }
        });
        buttonSupprimer.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                tableTarifVente.removeSelectedRow();
            }
        });
        return panel;
    }

    protected JPanel createTarifPromotionPanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setOpaque(false);
        GridBagConstraints c = new DefaultGridBagConstraints();

        // Ajout tarif
        c.gridwidth = 1;
        c.weightx = 0;
        c.gridy++;
        c.gridx = 0;
        panel.add(new JLabel("Ajouter la promotion"), c);

        final ElementComboBox boxTarif = new ElementComboBox();
        boxTarif.init(Configuration.getInstance().getDirectory().getElement("TARIF_PROMOTION"));

        c.gridx++;
        panel.add(boxTarif, c);

        c.fill = GridBagConstraints.NONE;
        c.gridx++;
        JButton buttonAjouter = new JButton("Ajouter");
        buttonAjouter.setOpaque(false);
        panel.add(buttonAjouter, c);
        c.gridx++;
        JButton buttonSupprimer = new JButton("Supprimer");
        buttonSupprimer.setOpaque(false);
        panel.add(buttonSupprimer, c);

        c.gridwidth = GridBagConstraints.REMAINDER;
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 1;
        c.weighty = 1;
        c.gridy++;
        c.gridx = 0;
        c.fill = GridBagConstraints.BOTH;
        this.tableTarifPromotionVente.setOpaque(false);
        panel.add(this.tableTarifPromotionVente, c);

        // Listeners
        buttonAjouter.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                SQLRow rowTarif = boxTarif.getSelectedRow();
                if (rowTarif == null || rowTarif.isUndefined()) {
                    return;
                }

                SQLRowValues rowVals = new SQLRowValues(Configuration.getInstance().getBase().getTable("ARTICLE_TARIF_PROMOTION"));
                if (getSelectedID() > 1) {
                    rowVals.put("ID_ARTICLE", getSelectedID());
                }
                rowVals.put("ID_TARIF_PROMOTION", rowTarif.getID());
                rowVals.put("PRIX_METRIQUE_VT_1", BigDecimal.ZERO);
                rowVals.put("PV_HT", BigDecimal.ZERO);
                rowVals.put("PV_TTC", BigDecimal.ZERO);
                tableTarifPromotionVente.getModel().addRow(rowVals);
            }
        });
        buttonSupprimer.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                tableTarifPromotionVente.removeSelectedRow();
            }
        });
        return panel;
    }

    protected JPanel createCategorieComptablePanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setOpaque(false);
        GridBagConstraints c = new DefaultGridBagConstraints();

        // Ajout catégorie
        c.gridwidth = 1;
        c.weightx = 0;
        c.gridy++;
        c.gridx = 0;
        panel.add(new JLabel("Ajouter la catégorie "), c);

        final ElementComboBox boxCat = new ElementComboBox();
        boxCat.init(Configuration.getInstance().getDirectory().getElement("CATEGORIE_COMPTABLE"));

        c.gridx++;
        panel.add(boxCat, c);

        c.fill = GridBagConstraints.NONE;
        c.gridx++;
        JButton buttonAjouter = new JButton("Ajouter");
        buttonAjouter.setOpaque(false);
        panel.add(buttonAjouter, c);
        c.gridx++;
        JButton buttonSupprimer = new JButton("Supprimer");
        buttonSupprimer.setOpaque(false);
        panel.add(buttonSupprimer, c);

        c.gridwidth = GridBagConstraints.REMAINDER;
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 1;
        c.weighty = 1;
        c.gridy++;
        c.gridx = 0;
        c.fill = GridBagConstraints.BOTH;
        this.tableCatComptable.setOpaque(false);
        panel.add(this.tableCatComptable, c);

        // Listeners
        buttonAjouter.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                SQLRow rowCat = boxCat.getSelectedRow();
                if (rowCat == null || rowCat.isUndefined()) {
                    return;
                }
                int nbRows = tableCatComptable.getModel().getRowCount();

                for (int i = 0; i < nbRows; i++) {
                    SQLRowValues rowVals = tableCatComptable.getModel().getRowValuesAt(i);
                    int idTarif = Integer.parseInt(rowVals.getObject("ID_CATEGORIE_COMPTABLE").toString());
                    if (idTarif == rowCat.getID()) {
                        JOptionPane.showMessageDialog(null, "Impossible d'ajouter.\nLa catégorie est déjà présente dans la liste!");
                        return;
                    }
                }

                SQLRowValues rowVals = new SQLRowValues(Configuration.getInstance().getBase().getTable("ARTICLE_CATEGORIE_COMPTABLE"));
                if (getSelectedID() > 1) {
                    rowVals.put("ID_ARTICLE", getSelectedID());
                }
                rowVals.put("ID_CATEGORIE_COMPTABLE", rowCat.getID());
                tableCatComptable.getModel().addRow(rowVals);
            }
        });
        buttonSupprimer.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                tableCatComptable.removeSelectedRow();
            }
        });
        return panel;
    }

    protected JPanel createBOMpanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setOpaque(false);
        GridBagConstraints c = new DefaultGridBagConstraints();

        final JCheckBox checkAutoPrice = new JCheckBox(getLabelFor("AUTO_PRIX_MIN_VENTE_NOMENCLATURE"));
        panel.add(checkAutoPrice, c);
        this.addView(checkAutoPrice, "AUTO_PRIX_MIN_VENTE_NOMENCLATURE");
        c.gridx++;
        final JCheckBox checkAutoPriceHA = new JCheckBox(getLabelFor("AUTO_PRIX_ACHAT_NOMENCLATURE"));
        panel.add(checkAutoPriceHA, c);
        this.addView(checkAutoPriceHA, "AUTO_PRIX_ACHAT_NOMENCLATURE");

        checkAutoPrice.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                updatePricesNomenclature(checkAutoPrice, checkAutoPriceHA);
            }
        });
        checkAutoPriceHA.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                updatePricesNomenclature(checkAutoPrice, checkAutoPriceHA);
            }
        });

        c.gridwidth = GridBagConstraints.REMAINDER;
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 1;
        c.weighty = 1;
        c.gridx = 0;
        c.gridy++;
        c.fill = GridBagConstraints.BOTH;
        this.tableBom.setOpaque(false);
        panel.add(new RowValuesTableEditionPanel(this.tableBom), c);

        this.tableBom.getModel().addTableModelListener(new TableModelListener() {

            @Override
            public void tableChanged(TableModelEvent e) {
                updatePricesNomenclature(checkAutoPrice, checkAutoPriceHA);

            }

        });
        return panel;

    }

    protected void updatePricesNomenclature(final JCheckBox checkAutoPrice, final JCheckBox checkAutoPriceHA) {
        final Boolean vtAuto = checkAutoPrice.isSelected();
        final Boolean haAuto = checkAutoPriceHA.isSelected();
        if (vtAuto || haAuto) {
            ProductHelper helper = new ProductHelper(getTable().getDBRoot());

            Tuple2<BigDecimal, BigDecimal> p = helper.getStandardBomPrices(tableBom.getRowValuesTable().getRowValuesTableModel().getCopyOfValues());
            if (haAuto && p.get0() != null) {
                textPAHT.setText(p.get0().toString());
            }
            if (vtAuto && p.get1() != null) {
                textPVHT.setText(p.get1().toString());
            }
        }
    }

    protected JPanel createTarifQtePanel() {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setOpaque(false);
        GridBagConstraints c = new DefaultGridBagConstraints();

        c.gridwidth = GridBagConstraints.REMAINDER;
        c.fill = GridBagConstraints.BOTH;
        c.weightx = 1;
        c.weighty = 1;
        c.gridx = 0;
        c.fill = GridBagConstraints.BOTH;
        this.tableTarifQteVente.setOpaque(false);
        panel.add(new RowValuesTableEditionPanel(this.tableTarifQteVente), c);
        return panel;
    }

    protected void getMontantPanel(final GridBagConstraints c, DefaultProps props) {
        c.gridx = 0;
        c.gridy++;
        c.gridwidth = 1;
        // PA devise
        JPanel pDevise = new JPanel(new GridBagLayout());
        GridBagConstraints cDevise = new DefaultGridBagConstraints();
        cDevise.insets = new Insets(0, 0, 0, 4);
        c.weightx = 0;
        c.fill = GridBagConstraints.HORIZONTAL;
        this.add(new JLabel("Devise du fournisseur"), c);
        final ElementComboBox boxDevise = new ElementComboBox(true, 15);
        cDevise.gridx++;
        cDevise.weightx = 1;
        pDevise.add(boxDevise, cDevise);
        this.addView(boxDevise, "ID_DEVISE_HA");
        DefaultGridBagConstraints.lockMinimumSize(boxDevise);

        cDevise.weightx = 0;
        cDevise.gridx++;
        pDevise.add(new JLabel("Prix d'achat devise"), cDevise);
        final JTextField fieldHAD = new JTextField(15);
        cDevise.weightx = 1;
        cDevise.gridx++;
        pDevise.add(fieldHAD, cDevise);
        this.addView(fieldHAD, "PA_DEVISE");
        DefaultGridBagConstraints.lockMinimumSize(fieldHAD);

        c.gridx++;
        c.gridwidth = GridBagConstraints.REMAINDER;
        c.anchor = GridBagConstraints.WEST;
        c.weightx = 1;
        c.fill = GridBagConstraints.NONE;
        this.add(pDevise, c);
        fieldHAD.getDocument().addDocumentListener(new SimpleDocumentListener() {

            @Override
            public void update(DocumentEvent e) {

                if (!isFilling() && boxDevise != null && boxDevise.getSelectedRow() != null && !boxDevise.getSelectedRow().isUndefined()) {
                    BigDecimal ha = StringUtils.getBigDecimalFromUserText(fieldHAD.getText());
                    if (ha == null) {
                        ha = BigDecimal.ZERO;
                    }
                    CurrencyConverter c = new CurrencyConverter();
                    String devCode = boxDevise.getSelectedRow().getString("CODE");
                    textPAHT.setText(c.convert(ha, devCode, c.getCompanyCurrencyCode(), new Date(), true).setScale(getTable().getField("PA_DEVISE").getType().getDecimalDigits(), RoundingMode.HALF_UP)
                            .toString());

                }
            }
        });

        // PA
        JPanel p = new JPanel(new GridBagLayout());
        GridBagConstraints cAchat = new DefaultGridBagConstraints();
        cAchat.insets = new Insets(0, 0, 0, 4);
        c.gridx = 0;
        c.gridy++;
        c.weightx = 0;
        c.gridwidth = 1;
        c.fill = GridBagConstraints.HORIZONTAL;
        this.add(new JLabel(getLabelFor("PA_HT"), SwingConstants.RIGHT), c);
        cAchat.gridx++;
        cAchat.weightx = 1;
        p.add(this.textPAHT, cAchat);
        this.textPAHT.getDocument().addDocumentListener(this.listenerMargeTextHA);

        // Marge
        cAchat.gridx++;
        cAchat.weightx = 0;
        p.add(new JLabel("Marge"), cAchat);
        cAchat.weightx = 1;
        cAchat.gridx++;
        p.add(this.textMarge, cAchat);
        this.textMarge.getDocument().addDocumentListener(this.listenerMargeTextMarge);
        cAchat.gridx++;
        cAchat.weightx = 0;
        p.add(this.labelMarge, cAchat);

        // Poids
        JLabel labelPds = new JLabel(getLabelFor("POIDS"));
        cAchat.gridx++;
        cAchat.weightx = 0;
        p.add(labelPds, cAchat);
        labelPds.setHorizontalAlignment(SwingConstants.RIGHT);
        cAchat.weightx = 1;
        cAchat.gridx++;
        p.add(this.textPoids, cAchat);
        DefaultGridBagConstraints.lockMinimumSize(this.textPoids);

        // Service
        String sService = props.getStringProperty("ArticleService");
        Boolean bService = Boolean.valueOf(sService);
        if (bService != null && bService.booleanValue()) {
            cAchat.gridx++;
            cAchat.weightx = 0;
            p.add(this.boxService, cAchat);
        }

        c.gridx++;
        c.gridwidth = GridBagConstraints.REMAINDER;
        c.anchor = GridBagConstraints.WEST;
        c.weightx = 1;
        c.fill = GridBagConstraints.NONE;

        this.add(p, c);
        c.gridx = 0;
        c.gridy++;
        c.gridwidth = 1;

        if (getTable().contains("ID_COUT_REVIENT")) {
            // Cout de revient
            c.weightx = 0;
            c.fill = GridBagConstraints.HORIZONTAL;
            this.add(new JLabel(getLabelFor("ID_COUT_REVIENT"), SwingConstants.RIGHT), c);

            JPanel pCR = new JPanel(new GridBagLayout());
            GridBagConstraints cCR = new DefaultGridBagConstraints();
            cCR.insets = new Insets(0, 0, 0, 4);
            this.boxCR = new ElementComboBox(true, 15);

            pCR.add(boxCR, cCR);
            this.addView(boxCR, "ID_COUT_REVIENT");
            DefaultGridBagConstraints.lockMinimumSize(boxCR);
            boxCR.addModelListener("wantedID", new PropertyChangeListener() {

                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    if (!isFilling()) {
                        ReferenceArticleSQLComponent.this.textPVHT.getDocument().removeDocumentListener(ReferenceArticleSQLComponent.this.listenerMargeTextVT);
                        updateVtFromMarge();
                        ReferenceArticleSQLComponent.this.textPVHT.getDocument().addDocumentListener(ReferenceArticleSQLComponent.this.listenerMargeTextVT);
                    }
                }
            });
            cCR.gridx++;
            this.boxMargeWithCR = new JCheckBox(getLabelFor("MARGE_WITH_COUT_REVIENT"));
            pCR.add(boxMargeWithCR, cCR);
            addView(boxMargeWithCR, "MARGE_WITH_COUT_REVIENT");
            boxMargeWithCR.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent e) {
                    if (!isFilling()) {
                        ReferenceArticleSQLComponent.this.textPVHT.getDocument().removeDocumentListener(ReferenceArticleSQLComponent.this.listenerMargeTextVT);
                        updateVtFromMarge();
                        ReferenceArticleSQLComponent.this.textPVHT.getDocument().addDocumentListener(ReferenceArticleSQLComponent.this.listenerMargeTextVT);
                    }
                }
            });
            c.gridx++;
            c.gridwidth = GridBagConstraints.REMAINDER;
            c.anchor = GridBagConstraints.WEST;
            c.weightx = 1;
            c.fill = GridBagConstraints.NONE;
            this.add(pCR, c);
        }

        // PV HT
        c.gridx = 0;
        c.gridy++;

        JPanel p2 = new JPanel(new GridBagLayout());
        GridBagConstraints cVT = new DefaultGridBagConstraints();
        cVT.insets = new Insets(0, 0, 0, 4);

        c.weightx = 0;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.gridwidth = 1;
        this.add(new JLabel(getLabelFor("PV_HT"), SwingConstants.RIGHT), c);
        cVT.gridx++;
        cVT.weightx = 1;

        p2.add(this.textPVHT, cVT);

        // Taxe
        JLabel labelTaxe = new JLabel(getLabelFor("ID_TAXE"));
        cVT.gridx++;
        cVT.weightx = 0;
        p2.add(labelTaxe, cVT);
        labelTaxe.setHorizontalAlignment(SwingConstants.RIGHT);
        cVT.gridx++;
        // cVT.weightx = 1;

        p2.add(this.comboSelTaxe, cVT);

        // PV_TTC
        cVT.gridx++;
        cVT.weightx = 0;
        p2.add(new JLabel(getLabelFor("PV_TTC")), cVT);
        cVT.gridx++;
        cVT.weightx = 1;
        p2.add(this.textPVTTC, cVT);
        c.gridx = 1;

        c.gridwidth = GridBagConstraints.REMAINDER;
        c.anchor = GridBagConstraints.WEST;
        c.weightx = 1;
        c.fill = GridBagConstraints.NONE;
        this.add(p2, c);

        this.addRequiredSQLObject(this.textPAHT, "PA_HT");
        this.addRequiredSQLObject(this.textPVHT, "PV_HT");
        DefaultGridBagConstraints.lockMinimumSize(this.textPVHT);
        this.addRequiredSQLObject(this.comboSelTaxe, "ID_TAXE");
        DefaultGridBagConstraints.lockMinimumSize(this.comboSelTaxe);
        DefaultGridBagConstraints.lockMaximumSize(this.comboSelTaxe);
        this.addRequiredSQLObject(this.textPVTTC, "PV_TTC");
        DefaultGridBagConstraints.lockMinimumSize(this.textPVTTC);
        DefaultGridBagConstraints.lockMinimumSize(this.textPAHT);
        DefaultGridBagConstraints.lockMinimumSize(this.textMarge);
        this.ttcDocListener = new DocumentListener() {
            public void changedUpdate(DocumentEvent e) {
                setTextHT();
            }

            public void insertUpdate(DocumentEvent e) {
                setTextHT();
            }

            public void removeUpdate(DocumentEvent e) {
                setTextHT();
            }
        };

        this.htDocListener = new DocumentListener() {
            public void changedUpdate(DocumentEvent e) {
                setTextTTC();
            }

            public void insertUpdate(DocumentEvent e) {
                setTextTTC();
            }

            public void removeUpdate(DocumentEvent e) {
                setTextTTC();
            }

        };

        this.detailsListener = new SimpleDocumentListener() {

            @Override
            public void update(DocumentEvent e) {
                updatePiece();
            }

        };

        this.taxeListener = new PropertyChangeListener() {

            public void propertyChange(PropertyChangeEvent evt) {
                if (!isFilling()) {
                    if (ReferenceArticleSQLComponent.this.textPVHT.getText().trim().length() > 0) {
                        setTextTTC();
                    } else {
                        setTextHT();
                    }
                }
                tableTarifVente.fireModification();
            }
        };
        this.textPVHT.getDocument().addDocumentListener(this.htDocListener);
        this.textPVTTC.getDocument().addDocumentListener(this.ttcDocListener);
        this.comboSelTaxe.addValueListener(this.taxeListener);

        this.textMetrique1HA.getDocument().addDocumentListener(this.detailsListener);
        this.textMetrique1VT.getDocument().addDocumentListener(this.detailsListener);

        this.textValMetrique1.getDocument().addDocumentListener(this.detailsListener);
        this.textValMetrique2.getDocument().addDocumentListener(this.detailsListener);
        this.textValMetrique3.getDocument().addDocumentListener(this.detailsListener);

    }

    protected void setListenerModeVenteActive(boolean b) {
        if (b) {
            this.comboSelModeVente.addValueListener(this.propertyChangeListener);
        } else {
            this.comboSelModeVente.removePropertyChangeListener(this.propertyChangeListener);
        }
    }

    /**
     * @param c
     * @param props
     */
    protected void addModeVenteAvance(GridBagConstraints c) {
        DefaultProps props = DefaultNXProps.getInstance();
        JSeparator sep = new JSeparator();
        JLabel labelDetails = new JLabel("Article détaillé", SwingConstants.RIGHT);
        c.gridx = 0;
        c.gridy++;
        c.weightx = 0;
        this.add(labelDetails, c);
        c.gridx++;
        c.gridwidth = GridBagConstraints.REMAINDER;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 1;
        this.add(sep, c);

        // Mode de vente
        c.gridwidth = 1;
        c.weightx = 0;
        c.gridx = 0;
        c.gridy++;
        this.add(new JLabel(getLabelFor("ID_MODE_VENTE_ARTICLE"), SwingConstants.RIGHT), c);
        c.weightx = 1;
        c.gridx++;
        this.add(this.comboSelModeVente, c);

        // Prix metrique
        c.gridx = 0;
        c.weightx = 0;
        c.gridy++;
        this.add(this.labelMetriqueHA1, c);
        c.gridx++;
        c.weightx = 1;
        this.add(this.textMetrique1HA, c);

        c.gridx++;
        c.weightx = 0;
        this.add(this.labelMetriqueVT1, c);
        c.gridx++;
        c.weightx = 1;
        this.add(this.textMetrique1VT, c);

        // Metrique 1
        c.weightx = 0;
        JLabel labelMetrique1 = new JLabel(getLabelFor("VALEUR_METRIQUE_1"), SwingConstants.RIGHT);
        c.gridx = 0;
        c.gridy++;
        this.add(labelMetrique1, c);
        c.gridx++;
        c.weightx = 1;
        this.add(this.textValMetrique1, c);
        c.gridx++;
        c.weightx = 0;

        Boolean bMetrique1 = Boolean.valueOf(props.getStringProperty("ArticleLongueur"));
        labelMetrique1.setVisible(bMetrique1 == null || bMetrique1.booleanValue());
        this.textValMetrique1.setVisible(bMetrique1 == null || bMetrique1.booleanValue());

        // Metrique 2
        JLabel labelMetrique2 = new JLabel(getLabelFor("VALEUR_METRIQUE_2"), SwingConstants.RIGHT);
        c.gridx = 0;
        c.gridy++;
        c.weightx = 0;
        this.add(labelMetrique2, c);
        c.gridx++;
        c.weightx = 1;
        this.add(this.textValMetrique2, c);
        c.gridx++;
        c.weightx = 0;

        Boolean bMetrique2 = Boolean.valueOf(props.getStringProperty("ArticleLargeur"));
        labelMetrique2.setVisible(bMetrique2 == null || bMetrique2.booleanValue());
        this.textValMetrique2.setVisible(bMetrique2 == null || bMetrique2.booleanValue());

        // Metrique 3
        JLabel labelMetrique3 = new JLabel(getLabelFor("VALEUR_METRIQUE_3"), SwingConstants.RIGHT);
        c.gridx = 0;
        c.gridy++;
        c.weightx = 0;
        this.add(labelMetrique3, c);
        c.gridx++;
        c.weightx = 1;
        this.add(this.textValMetrique3, c);
        c.gridx++;

        Boolean bMetrique3 = Boolean.valueOf(props.getStringProperty("ArticlePoids"));
        labelMetrique3.setVisible(bMetrique3 == null || bMetrique3.booleanValue());
        this.textValMetrique3.setVisible(bMetrique3 == null || bMetrique3.booleanValue());

        // Article détaillé
        JSeparator sep2 = new JSeparator();
        JLabel labelPiece = new JLabel("Article pièce", SwingConstants.RIGHT);
        c.gridx = 0;
        c.gridy++;
        c.weightx = 0;
        this.add(labelPiece, c);
        c.gridx++;
        c.gridwidth = GridBagConstraints.REMAINDER;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.weightx = 1;
        this.add(sep2, c);

    }

    @Override
    public void update() {
        SQLRow row = this.getTable().getRow(this.getSelectedID());
        final int selectedID = getSelectedID();
            super.update();
        this.tableTarifVente.updateField("ID_ARTICLE", selectedID);
        this.tableCatComptable.updateField("ID_ARTICLE", selectedID);
        this.tableFourSec.updateField("ID_ARTICLE", selectedID);
        this.tableTarifQteVente.updateField("ID_ARTICLE", selectedID);
        this.tableTarifPromotionVente.updateField("ID_ARTICLE", selectedID);

        if (this.tableBom != null) {
            this.tableBom.updateField("ID_ARTICLE_PARENT", selectedID);
        }

        this.tableDes.updateField("ID_ARTICLE", selectedID);
        this.tableCodeClient.updateField("ID_ARTICLE", selectedID);
        if (this.codeFournisseurTable != null) {
            this.codeFournisseurTable.updateField("ID_ARTICLE", selectedID);
        }

        ((ReferenceArticleSQLElement) getElement()).initStock(selectedID);

        SQLSelect sel = new SQLSelect();
        SQLTable tableStock = getTable().getTable("STOCK");
        sel.addSelect(tableStock.getKey());
        Where w = new Where(tableStock.getField("ID_ARTICLE"), "=", selectedID).and(new Where(tableStock.getField("ID_DEPOT_STOCK"), "=", row.getForeignID("ID_DEPOT_STOCK")));
        sel.setWhere(w);

        List<SQLRow> stock = SQLRowListRSH.execute(sel);
        if (stock != null && stock.size() == 1) {
            try {
                row.createEmptyUpdateRow().put("ID_STOCK", stock.get(0).getID()).update();
            } catch (SQLException e) {
                ExceptionHandler.handle("Erreur lors de la mise à jour du stock principal", e);
            }
        }

        Runnable r = new Runnable() {
            @Override
            public void run() {
                SQLRow rowArticle = getTable().getRow(selectedID);
                List<SQLRow> itemsRows = rowArticle.getReferentRows(getTable().getTable("ARTICLE_ELEMENT").getField("ID_ARTICLE"));
                for (SQLRow rowArticleItem : itemsRows) {
                    SQLRow rowA = rowArticleItem.getForeign("ID_ARTICLE_PARENT");

                    if (rowA != null && !rowA.isUndefined()) {
                        final Boolean vtAuto = rowA.getBoolean("AUTO_PRIX_MIN_VENTE_NOMENCLATURE");
                        final Boolean haAuto = rowA.getBoolean("AUTO_PRIX_ACHAT_NOMENCLATURE");
                        if (vtAuto || haAuto) {
                            ProductHelper helper = new ProductHelper(rowA.getTable().getDBRoot());
                            Tuple2<BigDecimal, BigDecimal> p = helper.getStandardBomPrices(rowA.getReferentRows(rowA.getTable().getTable("ARTICLE_ELEMENT").getField("ID_ARTICLE_PARENT")));
                            SQLRowValues rowVals = rowA.createEmptyUpdateRow();
                            boolean up = false;
                            if (vtAuto && p.get1() != null) {
                                rowVals.put("PRIX_METRIQUE_VT_1", p.get1());
                                rowVals.put("PV_HT", p.get1());
                                float t = TaxeCache.getCache().getFirstTaxe().getFloat("TAUX");
                                if (!rowA.isForeignEmpty("ID_TAXE")) {
                                    t = TaxeCache.getCache().getTauxFromId(rowA.getForeignID("ID_TAXE"));
                                }

                                rowVals.put("PV_TTC", p.get1().multiply(new BigDecimal(t).movePointLeft(2).add(BigDecimal.ONE)).setScale(2, RoundingMode.HALF_UP));
                                up = true;
                            }
                            if (haAuto && p.get0() != null) {
                                rowVals.put("PRIX_METRIQUE_HA_1", p.get0());
                                rowVals.put("PA_HT", p.get0());
                                up = true;
                            }
                            if (up) {
                                try {
                                    rowVals.commit();
                                } catch (SQLException e) {
                                    ExceptionHandler.handle("Erreur lors de la mise à jour des tarifs des nomenclatures", e);
                                }
                            }
                        }
                    }
                }

            }
        };
        new Thread(r).run();
        ReferenceArticleSQLElement.updateDateAchat(getTable(), getTable().getRow(selectedID));

    }

    /**
     * Sélection d'un mode de vente pour l'article. Affiche les prix metriques requis et fixe les
     * valeurs.
     * 
     * @param id id du mode de vente
     */
    protected void selectModeVente(int id) {

        this.labelMetriqueHA1.setEnabled(true);
        this.labelMetriqueVT1.setEnabled(true);
        this.textMetrique1HA.setEnabled(true);
        this.textMetrique1VT.setEnabled(true);

        this.textPAHT.getDocument().removeDocumentListener(this.pieceHAArticle);
        this.textPVHT.getDocument().removeDocumentListener(this.pieceVTArticle);

        switch (id) {
        case ReferenceArticleSQLElement.AU_METRE_CARRE:
            this.labelMetriqueHA1.setText("Prix d'achat HT au mètre carré");
            this.labelMetriqueVT1.setText("Prix de vente HT au mètre carré");
            break;
        case ReferenceArticleSQLElement.AU_METRE_LARGEUR:
        case ReferenceArticleSQLElement.AU_METRE_LONGUEUR:
            this.labelMetriqueHA1.setText("Prix d'achat HT au mètre");
            this.labelMetriqueVT1.setText("Prix de vente HT au mètre");
            break;

        case ReferenceArticleSQLElement.AU_POID_METRECARRE:
            this.labelMetriqueHA1.setText("Prix d'achat HT au kilo");
            this.labelMetriqueVT1.setText("Prix de vente HT au kilo");
            break;
        case -1:
            // No break need to enable the listener
        default:
            this.labelMetriqueHA1.setEnabled(false);
            this.labelMetriqueVT1.setEnabled(false);
            this.textMetrique1HA.setEnabled(false);
            this.textMetrique1VT.setEnabled(false);

            this.textMetrique1HA.setText(this.textPAHT.getText().trim());
            this.textMetrique1VT.setText(this.textPVHT.getText().trim());
            this.textPAHT.getDocument().addDocumentListener(this.pieceHAArticle);
            this.textPVHT.getDocument().addDocumentListener(this.pieceVTArticle);
            break;
        }
        this.tableTarifVente.fireModification();
    }

    @Override
    public int insert(SQLRow order) {
        int id = super.insert(order);
        this.tableTarifVente.updateField("ID_ARTICLE", id);
        this.tableCatComptable.updateField("ID_ARTICLE", id);
        this.tableFourSec.updateField("ID_ARTICLE", id);
        this.tableTarifQteVente.updateField("ID_ARTICLE", id);
        this.tableTarifPromotionVente.updateField("ID_ARTICLE", id);
        if (this.tableBom != null) {
            this.tableBom.updateField("ID_ARTICLE_PARENT", id);
        }
        this.tableDes.updateField("ID_ARTICLE", id);
        this.tableCodeClient.updateField("ID_ARTICLE", id);
        if (this.codeFournisseurTable != null) {
            this.codeFournisseurTable.updateField("ID_ARTICLE", id);
        }
        ((ReferenceArticleSQLElement) getElement()).initStock(id);
        ReferenceArticleSQLElement.updateDateAchat(getTable(), getTable().getRow(id));

        // incrémentation du numéro auto
        if (NumerotationAutoSQLElement.getNextNumero(getElement().getClass(), new Date()).equalsIgnoreCase(this.textCode.getText().trim())) {
            final SQLTable tableNum = getElement().getDirectory().getElement(NumerotationAutoSQLElement.class).getTable();
            SQLRowValues rowVals = new SQLRowValues(tableNum);

            final SQLRow rowNumAuto = tableNum.getRow(2);
            if (rowNumAuto.getObject("ARTICLE_START") != null) {
                int val = rowNumAuto.getInt("ARTICLE_START");
                val++;
                rowVals.put("ARTICLE_START", new Integer(val));

                try {
                    rowVals.update(2);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

        return id;
    }

    @Override
    protected SQLRowValues createDefaults() {
        SQLRowValues rowVals = new SQLRowValues(getTable());

        rowVals.put("ID_TAXE", TaxeCache.getCache().getFirstTaxe().getID());
        rowVals.put("ID_DEPOT_STOCK", DepotStockSQLElement.DEFAULT_ID);
        rowVals.put("ID_UNITE_VENTE", UniteVenteArticleSQLElement.A_LA_PIECE);
        rowVals.put("QTE_UNITAIRE", BigDecimal.ONE);
        rowVals.put("ID_MODE_VENTE_ARTICLE", ReferenceArticleSQLElement.A_LA_PIECE);
        selectModeVente(ReferenceArticleSQLElement.A_LA_PIECE);
        rowVals.put("VALEUR_METRIQUE_1", Float.valueOf("1.0"));
        rowVals.put("PA_HT", BigDecimal.ZERO);
        rowVals.put("QTE_UNITAIRE", BigDecimal.ONE);
        rowVals.put("POIDS", Float.valueOf(0));
        rowVals.put("GESTION_STOCK", Boolean.TRUE);

        return rowVals;
    }

    protected void setTextHT() {
        if (!isFilling()) {
            this.textPVHT.getDocument().removeDocumentListener(this.htDocListener);
            final BigDecimal ttc = StringUtils.getBigDecimalFromUserText(this.textPVTTC.getText());
            if (ttc != null) {
                int id = this.comboSelTaxe.getSelectedId();
                if (id > 1) {
                    Float resultTaux = TaxeCache.getCache().getTauxFromId(id);
                    float taux = (resultTaux == null) ? 0.0F : resultTaux.floatValue() / 100.0F;
                    this.textPVHT.setText(ttc.divide(BigDecimal.valueOf(taux).add(BigDecimal.ONE), DecimalUtils.HIGH_PRECISION)
                            .setScale(getTable().getField("PV_HT").getType().getDecimalDigits(), RoundingMode.HALF_UP).toString());
                }
            }
            this.textPVHT.getDocument().addDocumentListener(this.htDocListener);
        }
    }

    protected void setTextTTC() {
        if (!isFilling()) {
            this.textPVTTC.getDocument().removeDocumentListener(this.ttcDocListener);
            final BigDecimal ht = StringUtils.getBigDecimalFromUserText(this.textPVHT.getText());
            if (ht != null) {
                int id = this.comboSelTaxe.getSelectedId();
                if (id > 1) {
                    final Float resultTaux = TaxeCache.getCache().getTauxFromId(id);
                    final float taux = (resultTaux == null) ? 0.0F : resultTaux.floatValue() / 100.0F;
                    this.textPVTTC.setText(ht.multiply(BigDecimal.valueOf(taux).add(BigDecimal.ONE), DecimalUtils.HIGH_PRECISION)
                            .setScale(getTable().getField("PV_TTC").getType().getDecimalDigits(), RoundingMode.HALF_UP).toString());
                }
            }
            this.textPVTTC.getDocument().addDocumentListener(this.ttcDocListener);
        }
    }

    /**
     * calcul du prix achat et vente ainsi que le poids total pour la piece
     */
    protected void updatePiece() {
        if (this.comboSelModeVente.getSelectedId() > 1 && this.comboSelModeVente.getSelectedId() != ReferenceArticleSQLElement.A_LA_PIECE) {
            SQLRowValues rowVals = getDetailsRowValues();
            float poidsTot = ReferenceArticleSQLElement.getPoidsFromDetails(rowVals);
            this.textPoids.setText(String.valueOf(poidsTot));
            this.textPAHT.setText(ReferenceArticleSQLElement.getPrixHAFromDetails(rowVals).setScale(getTable().getField("PA_HT").getType().getDecimalDigits(), RoundingMode.HALF_UP).toString());
            this.textPVHT.setText(ReferenceArticleSQLElement.getPrixVTFromDetails(rowVals).setScale(getTable().getField("PV_HT").getType().getDecimalDigits(), RoundingMode.HALF_UP).toString());
            this.tableTarifVente.fireModification();
        }
    }

    public int getSelectedTaxe() {
        return this.comboSelTaxe.getSelectedId();
    }

    public SQLRowValues getDetailsRowValues() {
        final SQLRowValues rowVals = new SQLRowValues(getTable());

        BigDecimal pAchat = StringUtils.getBigDecimalFromUserText(this.textMetrique1HA.getText());
        if (pAchat == null) {
            pAchat = BigDecimal.ZERO;
        }
        rowVals.put("PRIX_METRIQUE_HA_1", pAchat);

        BigDecimal pVente = StringUtils.getBigDecimalFromUserText(this.textMetrique1VT.getText());
        if (pVente == null) {
            pVente = BigDecimal.ZERO;
        }
        rowVals.put("PRIX_METRIQUE_VT_1", pVente);
        put(rowVals, this.textValMetrique1);
        put(rowVals, this.textValMetrique2);
        put(rowVals, this.textValMetrique3);
        rowVals.put("ID_MODE_VENTE_ARTICLE", this.comboSelModeVente.getSelectedId());

        return rowVals;
    }

    protected void put(SQLRowValues rowVals, JTextField comp) {
        Float f = (comp.getText() == null || comp.getText().trim().length() == 0) ? 0.0F : Float.valueOf(comp.getText());
        rowVals.put(this.getView(comp).getField().getName(), f);
    }

}