OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 156 | 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 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.humanresources.payroll.element;

import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.common.ui.JNiceButton;
import org.openconcerto.erp.core.common.ui.PanelFrame;
import org.openconcerto.erp.core.humanresources.payroll.component.VariableRowTreeNode;
import org.openconcerto.erp.core.humanresources.payroll.report.FichePayeSheetXML;
import org.openconcerto.erp.core.humanresources.payroll.ui.FichePayeRenderer;
import org.openconcerto.erp.core.humanresources.payroll.ui.PanelCumulsPaye;
import org.openconcerto.erp.model.FichePayeModel;
import org.openconcerto.erp.model.MouseSheetXmlListeListener;
import org.openconcerto.erp.model.RubriquePayeTree;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.element.BaseSQLComponent;
import org.openconcerto.sql.element.SQLComponent;
import org.openconcerto.sql.element.SQLElementDirectory;
import org.openconcerto.sql.element.SQLElementLink.LinkType;
import org.openconcerto.sql.element.SQLElementLinksSetup;
import org.openconcerto.sql.element.TreesOfSQLRows;
import org.openconcerto.sql.model.SQLBase;
import org.openconcerto.sql.model.SQLField;
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.SQLSystem;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.sqlobject.ElementComboBox;
import org.openconcerto.sql.view.EditFrame;
import org.openconcerto.sql.view.IListFrame;
import org.openconcerto.sql.view.list.IListe;
import org.openconcerto.sql.view.list.IListeAction.IListeEvent;
import org.openconcerto.sql.view.list.RowAction.PredicateRowAction;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.JDate;
import org.openconcerto.ui.component.InteractionMode;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.ListMap;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.tree.TreePath;

public class FichePayeSQLElement extends ComptaSQLConfElement {

    public FichePayeSQLElement() {
        super("FICHE_PAYE", "une fiche de paye", "fiches de paye");

        MouseSheetXmlListeListener l = new MouseSheetXmlListeListener(FichePayeSheetXML.class);
        getRowActions().addAll(l.getRowActions());

        PredicateRowAction actionCumuls = new PredicateRowAction(new AbstractAction("Détails cumuls et variables") {

            @Override
            public void actionPerformed(ActionEvent e) {
                final PanelCumulsPaye pCumuls = new PanelCumulsPaye();
                final PanelFrame p = new PanelFrame(pCumuls, "Détails cumuls et variables");
                pCumuls.selectFiche(IListe.get(e).getSelectedRow().asRow());
                p.setVisible(true);
            }
        }, true);
        actionCumuls.setPredicate(IListeEvent.getSingleSelectionPredicate());
        getRowActions().add(actionCumuls);
        PredicateRowAction genererNonSimplifie = new PredicateRowAction(new AbstractAction("Créer le bulletin détaillé") {

            @Override
            public void actionPerformed(ActionEvent e) {

                SQLRow row = IListe.get(e).getSelectedRow().asRow();
                FichePayeSheetXML sheet = new FichePayeSheetXML(row, false);
                try {
                    sheet.createDocument();
                    sheet.showPrintAndExport(true, false, true);
                } catch (Exception e1) {
                    ExceptionHandler.handle("Erreur lors de la création du document.", e1);
                }
            }
        }, false);
        genererNonSimplifie.setPredicate(IListeEvent.getSingleSelectionPredicate());
        getRowActions().add(genererNonSimplifie);
    }

    @Override
    public ListMap<String, String> getShowAs() {
        final ListMap<String, String> map = new ListMap<>();
        map.put("ID_SALARIE", Arrays.asList("CODE", "NOM", "PRENOM", "ID_REGLEMENT_PAYE"));
        return map;
    }

    protected List<String> getListFields() {
        final List<String> l = new ArrayList<String>();
        l.add("ID_SALARIE");
        l.add("ID_MOIS");
        l.add("ANNEE");
        l.add("NET_A_PAYER");
        return l;
    }

    protected List<String> getComboFields() {
        final List<String> l = new ArrayList<String>();
        l.add("ID_SALARIE");
        l.add("ID_MOIS");
        l.add("ANNEE");
        return l;
    }

    @Override
    public boolean isPrivate() {
        return true;
    }

    @Override
    protected void setupLinks(SQLElementLinksSetup links) {
        super.setupLinks(links);
        if (getTable().contains("ID_INFOS_SALARIE_PAYE")) {
            links.get("ID_INFOS_SALARIE_PAYE").setType(LinkType.ASSOCIATION);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.openconcerto.devis.SQLElement#getComponent()
     */
    // FIXME Place des rubriques importantes --> [Brut -- cotisations -- cotisations with CSG --
    // Net]
    // FIXME Date periode must be correct
    public SQLComponent createComponent() {
        return new BaseSQLComponent(this) {

            private FichePayeModel model;
            private ElementComboBox comboSelProfil, selSalCombo;
            private EditFrame edit = null;
            private ElementComboBox selMois;
            private int dernMois, dernAnnee;
            private JTextField textAnnee;
            JDate dateDu, dateAu;
            private JScrollPane paneTreeLeft;
            private JPanel pDate;

            public void addViews() {

                this.dernMois = 0;
                this.dernAnnee = 0;

                this.setLayout(new GridBagLayout());

                final RubriquePayeTree tree = new RubriquePayeTree();
                tree.expandRow(0);
                JPanel panelLeft = new JPanel(new GridBagLayout());
                GridBagConstraints cLeft = new DefaultGridBagConstraints();
                cLeft.fill = GridBagConstraints.BOTH;
                cLeft.weightx = 1;
                cLeft.weighty = 1;
                cLeft.gridheight = GridBagConstraints.REMAINDER;
                panelLeft.add(tree, cLeft);
                this.paneTreeLeft = new JScrollPane(tree);
                // this.add(this.paneTreeLeft, c);

                // Panel Fiche paye on the right
                // Salarie
                JPanel panelRight = new JPanel(new GridBagLayout());
                final GridBagConstraints c = new DefaultGridBagConstraints();
                // Tree elt Fiche de Paye On the left
                c.fill = GridBagConstraints.HORIZONTAL;
                c.weightx = 1;
                c.weighty = 0;
                c.gridheight = 1;
                c.gridwidth = 2;
                this.selSalCombo = new ElementComboBox();

                panelRight.add(this.selSalCombo, c);

                // Mois

                JLabel labelMois = new JLabel("Fiche de paye du mois de");
                this.selMois = new ElementComboBox(true, 20);
                JLabel labelDu = new JLabel("Du");
                JLabel labelAu = new JLabel("Au");
                this.dateDu = new JDate();
                this.dateAu = new JDate();

                JLabel labelAnnee = new JLabel("Année");
                this.textAnnee = new JTextField();
                {
                    this.pDate = new JPanel(new GridBagLayout());
                    GridBagConstraints cDate = new DefaultGridBagConstraints();
                    cDate.weightx = 0;
                    cDate.gridx = GridBagConstraints.RELATIVE;
                    this.pDate.setOpaque(false);
                    this.pDate.add(labelMois, cDate);
                    cDate.weightx = 1;
                    this.pDate.add(this.selMois, cDate);
                    cDate.weightx = 0;
                    this.pDate.add(labelAnnee, cDate);
                    cDate.weightx = 1;
                    this.pDate.add(this.textAnnee, cDate);
                    cDate.weightx = 0;
                    this.pDate.add(labelDu, cDate);
                    cDate.weightx = 0;
                    this.pDate.add(this.dateDu, cDate);
                    cDate.weightx = 0;
                    this.pDate.add(labelAu, cDate);
                    cDate.weightx = 0;
                    this.pDate.add(this.dateAu, cDate);

                    c.gridy++;
                    c.fill = GridBagConstraints.HORIZONTAL;
                    c.weightx = 1;
                    c.weighty = 0;
                    c.gridheight = 1;
                    c.gridwidth = 2;
                    panelRight.add(this.pDate, c);
                }

                // Action Button

                JPanel pButtons = new JPanel(new GridBagLayout());
                pButtons.setOpaque(false);
                JButton buttonUp = new JNiceButton(IListFrame.class.getResource("fleche_haut.png"));
                JButton buttonDown = new JNiceButton(IListFrame.class.getResource("fleche_bas.png"));
                JButton buttonRemove = new JNiceButton(SQLComponent.class.getResource("delete.png"));
                {
                    GridBagConstraints cButtons = new DefaultGridBagConstraints();
                    cButtons.weightx = 0;
                    cButtons.fill = GridBagConstraints.NONE;
                    cButtons.gridx = GridBagConstraints.RELATIVE;
                    pButtons.add(buttonUp, cButtons);
                    pButtons.add(buttonDown, cButtons);
                    pButtons.add(buttonRemove, cButtons);
                }
                c.gridx += 2;
                c.fill = GridBagConstraints.NONE;
                c.weightx = 0;
                c.weighty = 0;
                c.gridwidth = 1;
                panelRight.add(pButtons, c);

                // Table
                c.fill = GridBagConstraints.BOTH;
                c.weightx = 1;
                c.weighty = 1;
                c.gridx = 0;
                c.gridy++;
                c.gridwidth = GridBagConstraints.REMAINDER;
                this.model = new FichePayeModel(1);
                final JTable table = new JTable(this.model);
                panelRight.add(new JScrollPane(table), c);
                FichePayeRenderer rend = new FichePayeRenderer();
                table.setDefaultRenderer(String.class, rend);
                table.setDefaultRenderer(Float.class, rend);

                // Import profil
                c.gridx = 0;
                c.gridy++;
                c.weightx = 0;
                c.weighty = 0;
                c.gridwidth = 1;
                c.fill = GridBagConstraints.HORIZONTAL;
                JLabel labelProfil = new JLabel("Lié à un profil prédéfini");
                panelRight.add(labelProfil, c);
                c.gridwidth = 1;
                this.comboSelProfil = new ElementComboBox();
                // this.comboSelProfil = new ElementComboBox();
                this.comboSelProfil.setListIconVisible(false);
                c.gridx++;
                c.gridwidth = 1;
                c.weightx = 1;

                // this.comboSelProfil.init(eltProfil.getTable().getField("NOM"), null);
                panelRight.add(this.comboSelProfil, c);

                JButton buttonImportProfil = new JButton("Importer");
                c.gridx++;
                c.weightx = 0;
                panelRight.add(buttonImportProfil, c);

                // Total Periode
                JPanel panelTotal = new JPanel(new GridBagLayout());
                panelTotal.setBorder(BorderFactory.createTitledBorder("Totaux sur la période"));

                GridBagConstraints cPanel = new DefaultGridBagConstraints();

                JLabel labelInfosConges = new JLabel(getLabelFor("DETAILS_CONGES"));
                panelTotal.add(labelInfosConges, cPanel);
                JTextField textConges = new JTextField();
                cPanel.gridx++;
                cPanel.weightx = 1;
                cPanel.gridwidth = 5;
                panelTotal.add(textConges, cPanel);
                addView(textConges, "DETAILS_CONGES");

                // Salaire brut
                cPanel.weightx = 0;
                cPanel.gridwidth = 1;
                cPanel.gridy++;
                cPanel.gridx = 0;
                JLabel labelBrut = new JLabel(getLabelFor("SAL_BRUT"));
                panelTotal.add(labelBrut, cPanel);
                JTextField textSalBrut = new JTextField(10);
                cPanel.gridx++;
                cPanel.weightx = 1;
                panelTotal.add(textSalBrut, cPanel);
                textSalBrut.setEditable(false);
                textSalBrut.setEnabled(false);

                // acompte
                cPanel.gridx++;
                cPanel.weightx = 0;
                JLabel labelAcompte = new JLabel(getLabelFor("ACOMPTE"));
                panelTotal.add(labelAcompte, cPanel);
                JTextField textAcompte = new JTextField(10);
                cPanel.gridx++;
                cPanel.weightx = 1;
                panelTotal.add(textAcompte, cPanel);
                // textAcompte.setEditable(false);
                // textAcompte.setEnabled(false);

                // Conges Acquis
                cPanel.gridx++;
                cPanel.weightx = 0;
                JLabel labelCongesAcquis = new JLabel(getLabelFor("CONGES_ACQUIS"));
                panelTotal.add(labelCongesAcquis, cPanel);
                JTextField textCongesAcquis = new JTextField(10);
                cPanel.gridx++;
                cPanel.weightx = 1;
                panelTotal.add(textCongesAcquis, cPanel);

                // cotisation salariale
                cPanel.gridx = 0;
                cPanel.gridy++;
                cPanel.weightx = 0;
                JLabel labelCotSal = new JLabel(getLabelFor("COT_SAL"));
                panelTotal.add(labelCotSal, cPanel);
                JTextField textCotSal = new JTextField(10);
                cPanel.gridx++;
                cPanel.weightx = 1;
                panelTotal.add(textCotSal, cPanel);
                textCotSal.setEditable(false);
                textCotSal.setEnabled(false);

                // cotisation patronale
                cPanel.gridx++;
                cPanel.weightx = 0;
                JLabel labelCotPat = new JLabel(getLabelFor("COT_PAT"));
                panelTotal.add(labelCotPat, cPanel);
                JTextField textCotPat = new JTextField(10);
                cPanel.gridx++;
                cPanel.weightx = 1;
                panelTotal.add(textCotPat, cPanel);
                textCotPat.setEditable(false);
                textCotPat.setEnabled(false);

                JLabel labelCSG = new JLabel(getLabelFor("CSG"));
                cPanel.gridx++;
                cPanel.weightx = 0;
                panelTotal.add(labelCSG, cPanel);
                JTextField textCSG = new JTextField(10);
                cPanel.gridx++;
                cPanel.weightx = 1;
                panelTotal.add(textCSG, cPanel);
                textCSG.setEditable(false);
                textCSG.setEnabled(false);

                // net imposable
                cPanel.gridx = 0;
                cPanel.gridy++;
                cPanel.weightx = 0;
                JLabel labelNetImp = new JLabel(getLabelFor("NET_IMP"));
                panelTotal.add(labelNetImp, cPanel);
                JTextField textNetImp = new JTextField(10);
                cPanel.gridx++;
                cPanel.weightx = 1;
                panelTotal.add(textNetImp, cPanel);
                textNetImp.setEditable(false);
                textNetImp.setEnabled(false);

                cPanel.gridx++;
                cPanel.weightx = 0;
                JLabel labelNetAPayer = new JLabel(getLabelFor("NET_A_PAYER"));
                panelTotal.add(labelNetAPayer, cPanel);
                JTextField textNetAPayer = new JTextField(10);
                cPanel.gridx++;
                cPanel.weightx = 1;
                panelTotal.add(textNetAPayer, cPanel);
                textNetAPayer.setEditable(false);
                textNetAPayer.setEnabled(false);

                cPanel.gridx++;
                cPanel.weightx = 0;
                JLabel labelCice = new JLabel(getLabelFor("CICE"));
                panelTotal.add(labelCice, cPanel);
                JTextField textCice = new JTextField(10);
                cPanel.gridx++;
                cPanel.weightx = 1;
                panelTotal.add(textCice, cPanel);
                textCice.setEditable(false);
                textCice.setEnabled(false);
                this.addSQLObject(textCice, "CICE");

                c.gridx = 0;
                c.gridy++;
                c.fill = GridBagConstraints.HORIZONTAL;
                c.weightx = 1;
                c.weighty = 0;
                c.gridwidth = GridBagConstraints.REMAINDER;
                panelRight.add(panelTotal, c);

                // Cumuls

                GridBagConstraints cGlobal = new DefaultGridBagConstraints();
                cGlobal.gridx = 0;
                cGlobal.gridy = 0;
                cGlobal.gridwidth = 1;
                cGlobal.gridheight = 1;
                cGlobal.fill = GridBagConstraints.BOTH;
                cGlobal.weightx = 1;
                cGlobal.weighty = 1;
                this.add(new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, this.paneTreeLeft, panelRight), cGlobal);

                buttonUp.addActionListener(new ActionListener() {

                    public void actionPerformed(ActionEvent e) {
                        int newRowSelected = model.upRow(table.getSelectedRow());
                        if (newRowSelected >= 0) {
                            table.setRowSelectionInterval(newRowSelected, newRowSelected);
                        }
                    }
                });

                buttonDown.addActionListener(new ActionListener() {

                    public void actionPerformed(ActionEvent e) {
                        int newRowSelected = model.downRow(table.getSelectedRow());
                        if (newRowSelected >= 0) {
                            table.setRowSelectionInterval(newRowSelected, newRowSelected);
                        }
                    }
                });

                buttonRemove.addActionListener(new ActionListener() {

                    public void actionPerformed(ActionEvent e) {
                        model.removeRow(table.getSelectedRow());
                    }
                });

                tree.addMouseListener(new MouseAdapter() {

                    public void mousePressed(MouseEvent mE) {

                        TreePath path = tree.getClosestPathForLocation(mE.getPoint().x, mE.getPoint().y);

                        final Object obj = path.getLastPathComponent();

                        if (obj == null) {
                            return;
                        }

                        if (mE.getClickCount() == 2 && mE.getButton() == MouseEvent.BUTTON1) {

                            if (obj instanceof VariableRowTreeNode) {
                                model.addRowAt(((VariableRowTreeNode) obj).getRow(), table.getSelectedRow());
                            }
                        } else {

                            if (mE.getButton() == 3) {

                                if (obj instanceof VariableRowTreeNode) {

                                    final SQLRow row = ((VariableRowTreeNode) obj).getRow();

                                    JPopupMenu menuDroit = new JPopupMenu();

                                    menuDroit.add(new AbstractAction("Editer") {
                                        public void actionPerformed(ActionEvent e) {

                                            if (edit != null) {
                                                edit.dispose();
                                            }
                                            edit = new EditFrame(Configuration.getInstance().getDirectory().getElement(row.getTable()), EditFrame.MODIFICATION);
                                            edit.selectionId(row.getID(), 0);
                                            edit.pack();
                                            edit.setVisible(true);
                                        }
                                    });

                                    menuDroit.add(new AbstractAction("Nouvelle rubrique") {
                                        public void actionPerformed(ActionEvent e) {

                                            if (edit != null) {
                                                edit.dispose();
                                            }
                                            edit = new EditFrame(Configuration.getInstance().getDirectory().getElement(row.getTable()));
                                            edit.pack();
                                            edit.setVisible(true);
                                        }
                                    });

                                    menuDroit.show(mE.getComponent(), mE.getPoint().x, mE.getPoint().y);

                                }
                            }
                        }
                    }
                });

                this.dateDu.addValueListener(new PropertyChangeListener() {
                    public void propertyChange(PropertyChangeEvent evt) {
                        if (!dateDu.isEmpty()) {
                            Date d = dateDu.getValue();

                            if (d != null) {
                                Calendar cal = Calendar.getInstance();
                                cal.setTime(d);
                                if (selMois.getSelectedId() > 1 && cal.get(Calendar.MONTH) + 2 != selMois.getSelectedId()) {

                                    cal.set(Calendar.DAY_OF_MONTH, 1);
                                    cal.set(Calendar.MONTH, selMois.getSelectedId() - 2);
                                    dateDu.setValue(cal.getTime());
                                }
                                fireValidChange();
                            }
                        }
                    }
                });

                this.dateAu.addValueListener(new PropertyChangeListener() {
                    public void propertyChange(PropertyChangeEvent evt) {
                        if (!dateAu.isEmpty()) {
                            Date d = dateAu.getValue();
                            if (d != null) {
                                Calendar cal = Calendar.getInstance();
                                cal.setTime(d);
                                if (selMois.getSelectedId() > 1 && cal.get(Calendar.MONTH) + 2 != selMois.getSelectedId()) {

                                    // TODO checker l'annee
                                    // TODO ajouter dans le isValidated du au compris dans le mois
                                    // selectionne

                                    // Calendar.getInstance().set(Calendar.DAY_OF_MONTH, maxDay);
                                    cal.set(Calendar.DAY_OF_MONTH, 1);
                                    cal.set(Calendar.MONTH, selMois.getSelectedId() - 2);
                                    cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
                                    dateAu.setValue(cal.getTime());
                                }
                                fireValidChange();
                            }
                        }
                    }
                });

                this.addRequiredSQLObject(this.textAnnee, "ANNEE");
                this.addRequiredSQLObject(this.selMois, "ID_MOIS");
                this.addSQLObject(this.comboSelProfil, "ID_PROFIL_PAYE");

                this.addSQLObject(textCongesAcquis, "CONGES_ACQUIS");
                this.addSQLObject(textCotPat, "COT_PAT");
                this.addSQLObject(textCotSal, "COT_SAL");
                this.addSQLObject(textCSG, "CSG");
                this.addSQLObject(textNetAPayer, "NET_A_PAYER");
                this.addSQLObject(textNetImp, "NET_IMP");
                this.addSQLObject(textSalBrut, "SAL_BRUT");
                this.addSQLObject(textAcompte, "ACOMPTE");
                this.addSQLObject(this.selSalCombo, "ID_SALARIE");

                this.addRequiredSQLObject(this.dateDu, "DU");
                this.addRequiredSQLObject(this.dateAu, "AU");

                this.selSalCombo.setInteractionMode(InteractionMode.DISABLED);
                this.selSalCombo.setEnabled(false);
                this.selSalCombo.setButtonsVisible(false);
                // this.selSalCombo.setVisible(false);

                buttonImportProfil.addActionListener(new ActionListener() {
                    public void actionPerformed(ActionEvent e) {

                        model.loadFromProfil(comboSelProfil.getSelectedId());
                    }
                });
            }

            // private boolean isDateValid() {
            //
            // String yearS = this.textAnnee.getText().trim();
            // int annee = (yearS.length() == 0) ? 0 : Integer.parseInt(yearS);
            //
            // int mois = this.selMois.getSelectedId();
            // // System.err.println("année " + annee + " dernAnnee " + this.dernAnnee + " mois " +
            // // mois + " dernMois " + this.dernMois);
            //
            // return ((this.dernAnnee == 0) ? true : annee > this.dernAnnee) || ((this.dernMois ==
            // 0 || this.dernMois == 13) ? true : mois > this.dernMois);
            // }
            //
            // @Override
            // public synchronized ValidState getValidState() {
            // // FIXME add fireValidChange()
            // return super.getValidState().and(ValidState.createCached(isDateValid(), "Date
            // invalide"));
            // }

            public int insert(SQLRow order) {

                int id = super.insert(order);
                this.model.updateFields(id);
                return id;
            }

            @Override
            public void update() {
                super.update();
                this.model.updateFields(this.getSelectedID());
            }

            @Override
            public void select(SQLRowAccessor r) {

                // System.err.println("SELECT FICHE ID -> " + r.getID());
                super.select(r);

                if (r != null && r.getID() > 1) {
                    this.model.setFicheID(r.getID());

                    SQLTable tableSal = getTable().getBase().getTable("SALARIE");
                    SQLRow rowSal = tableSal.getRow(r.getInt("ID_SALARIE"));

                    this.dernMois = rowSal.getInt("DERNIER_MOIS");
                    this.dernAnnee = rowSal.getInt("DERNIERE_ANNEE");

                    this.selSalCombo.setVisible(((Boolean) r.getObject("VALIDE")).booleanValue());
                    this.paneTreeLeft.setVisible(!((Boolean) r.getObject("VALIDE")).booleanValue());
                    setpDateEnabled(!((Boolean) r.getObject("VALIDE")).booleanValue());
                }
                this.selSalCombo.setInteractionMode(InteractionMode.DISABLED);
                this.selSalCombo.setEnabled(false);
                this.selMois.setButtonsVisible(false);
                this.selSalCombo.setButtonsVisible(false);
            }

            private void setpDateEnabled(boolean b) {
                this.selMois.setInteractionMode((b) ? InteractionMode.READ_WRITE : InteractionMode.DISABLED);
                this.textAnnee.setEditable(b);
                this.textAnnee.setEnabled(b);
                this.dateDu.setInteractionMode((b) ? InteractionMode.READ_WRITE : InteractionMode.DISABLED);
                this.dateAu.setInteractionMode((b) ? InteractionMode.READ_WRITE : InteractionMode.DISABLED);
            }

            protected SQLRowValues createDefaults() {
                final SQLRowValues rowVals = new SQLRowValues(getTable());
                final Calendar cal = Calendar.getInstance();
                rowVals.put("ID_MOIS", cal.get(Calendar.MONTH) + 2);
                rowVals.put("ANNEE", cal.get(Calendar.YEAR));

                cal.set(Calendar.DAY_OF_MONTH, 1);
                rowVals.put("DU", new java.sql.Date(cal.getTime().getTime()));

                cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
                rowVals.put("AU", new java.sql.Date(cal.getTime().getTime()));
                return rowVals;
            }

        };
    }

    private static List<String> cumulFields = Arrays.asList("SAL_BRUT", "CSG", "COT_SAL", "COT_PAT", "NET_IMP", "HEURE_TRAV", "CICE", "AVANTAGE_NATURE", "ALLEGEMENT_COTISATION", "SAL_BASE_BRUT",
            "TAXE_CM_SAL", "TAXE_CM_PAT", "SAL_BRUT_COTISABLE", "SAL_BRUT_TAXABLE");

    @Override
    protected void archive(TreesOfSQLRows trees, boolean cutLinks) throws SQLException {
        super.archive(trees, cutLinks);
        for (SQLRow row : trees.getRows()) {
            if (row != null && row.getID() > 1) {
                if (JOptionPane.showConfirmDialog(null, "Soustraire les cumuls de cette fiche à celle en cours?", "Suppression d'une fiche de paye",
                        JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
                    // on effectue le cumul

                    SQLRow rowSal = row.getForeignRow("ID_SALARIE");

                    SQLRow rowCumuls = rowSal.getForeignRow("ID_CUMULS_PAYE");

                    SQLRowValues rowValsCumul = rowCumuls.createEmptyUpdateRow();
                    for (String string : cumulFields) {
                        float cumul = rowCumuls.getFloat(string + "_C") - row.getFloat(string);
                        rowValsCumul.put(string + "_C", new Float(cumul));
                    }
                    // TODO stocker les heures travaillées du mois pour faire déduction
                    // float heure = rowCumuls.getFloat("HEURE_TRAV_C") -
                    // row.getFloat("HEURE_TRAV");
                    float netAPayer = rowCumuls.getFloat("NET_A_PAYER_C") - row.getFloat("NET_A_PAYER") - row.getFloat("ACOMPTE");
                    rowValsCumul.put("NET_A_PAYER_C", new Float(netAPayer));
                    // rowValsCumul.put("HEURE_TRAV_C", new Float(heure));

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

                    // Calcul des congés
                    SQLRow rowCumulConge = rowSal.getForeignRow("ID_CUMULS_CONGES");
                    SQLRow rowVarSalFiche = row.getForeignRow("ID_VARIABLE_SALARIE");
                    SQLRow rowVarSal = rowSal.getForeignRow("ID_VARIABLE_SALARIE");
                    float congeCumule = rowCumulConge.getFloat("ACQUIS");
                    float congeRestant = rowCumulConge.getFloat("RESTANT");

                    float prisPeriode = rowVarSalFiche.getFloat("CONGES_PRIS");

                    congeRestant += prisPeriode;
                    congeCumule -= row.getFloat("CONGES_ACQUIS");

                    SQLRowValues rowValsCumulsConges = new SQLRowValues(rowCumulConge.getTable());
                    rowValsCumulsConges.put("ACQUIS", new Float(congeCumule));
                    rowValsCumulsConges.put("RESTANT", new Float(congeRestant));

                    try {
                        rowValsCumulsConges.update(rowCumulConge.getID());
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }

                    // Annulation du cumul des variables
                    final SQLRowValues rowVals = rowVarSal.asRowValues();
                    for (final SQLField field : rowVarSalFiche.getTable().getContentFields()) {
                        if (!field.getName().endsWith("_DEFAULT_VAL") && !field.getName().endsWith("_CUMUL_VAL")) {
                            if (rowVarSalFiche.getTable().contains(field.getName() + "_CUMUL_VAL")) {
                                final float valPeriode = rowVarSalFiche.getObject(field.getName()) == null ? 0.0F : rowVarSalFiche.getFloat(field.getName());
                                final float valCumul = rowVarSal.getObject(field.getName() + "_CUMUL_VAL") == null ? 0.0F : rowVarSal.getFloat(field.getName() + "_CUMUL_VAL");
                                rowVals.put(field.getName() + "_CUMUL_VAL", valCumul - valPeriode);
                            }

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

    /**
     * Validation de la fiche de paye en cours pour un salarié
     * 
     * @param id id de la fiche à valider
     * @throws SQLException
     */
    public static synchronized void validationFiche(int id) throws SQLException {
        final int oldID = id;

        SQLBase base = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete();
        SQLTable tableSal = base.getTable("SALARIE");
        SQLTable tableCumulConge = base.getTable("CUMULS_CONGES");
        SQLTable tableVariableSal = base.getTable("VARIABLE_SALARIE");
        SQLTable tableFiche = base.getTable("FICHE_PAYE");
        SQLTable tableFicheElt = base.getTable("FICHE_PAYE_ELEMENT");
        SQLTable tableCumuls = base.getTable("CUMULS_PAYE");

        final SQLRowValues rowValsSal = new SQLRowValues(tableSal);

        final SQLRow rowFiche = tableFiche.getRow(oldID);
        final SQLRow rowSal = tableSal.getRow(rowFiche.getInt("ID_SALARIE"));

        // On teste que la fiche est entrée dans une période non cloturée
        if (!checkDateValid(id)) {
            String msg = "Impossible de créer la fiche de paye de " + rowSal.getString("NOM") + " " + rowSal.getString("PRENOM") + ".\n La période est cloturée.";
            JOptionPane.showMessageDialog(null, msg, "Création paye impossible", JOptionPane.INFORMATION_MESSAGE);
            return;
        }

        // valider les elements de la fiche
        validElements(id);

        // Sauvegarde des valeurs de la fiche (cumuls, conges, ...)
        stockValidValues(oldID);

        // creer et associer une nouvelle fiche au salarie
        final SQLRowValues rowValsNewFiche = new SQLRowValues(tableFiche);

        SQLRow r = rowValsNewFiche.insert();
        rowValsNewFiche.put("ID", r.getID());

        // mis a jour de la periode
        int mois = rowFiche.getInt("ID_MOIS");
        int annee = rowFiche.getInt("ANNEE");
        rowValsNewFiche.put("ID_MOIS", mois);
        rowValsNewFiche.put("ANNEE", annee);
        final Calendar calDu = rowFiche.getDate("DU");
        calDu.add(Calendar.MONTH, 1);
        calDu.set(Calendar.DAY_OF_MONTH, 1);
        rowValsNewFiche.put("DU", calDu.getTime());
        calDu.set(Calendar.DAY_OF_MONTH, calDu.getActualMaximum(Calendar.DAY_OF_MONTH));
        rowValsNewFiche.put("AU", calDu.getTime());
        rowValsNewFiche.put("ID_PROFIL_PAYE", rowFiche.getInt("ID_PROFIL_PAYE"));
        rowValsNewFiche.put("ID_SALARIE", rowSal.getID());
        rowValsSal.put("ID_FICHE_PAYE", rowValsNewFiche.getID());

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
                    // FIXME: Ouch: sql in swing!
                    rowValsSal.update(rowSal.getID());

                    rowValsNewFiche.update();
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            }
        });
        // On recupere la liste des elements de la fiche de paye
        SQLSelect selAllElt = new SQLSelect();
        selAllElt.addSelect(tableFicheElt.getKey());
        selAllElt.addSelect(tableFicheElt.getField("POSITION"));
        selAllElt.addSelect(tableFicheElt.getField("SOURCE"));
        selAllElt.addSelect(tableFicheElt.getField("IDSOURCE"));
        selAllElt.setWhere(tableFicheElt.getField("ID_FICHE_PAYE"), "=", oldID);
        selAllElt.setDistinct(true);
        selAllElt.addFieldOrder(tableFicheElt.getField("POSITION"));

        for (final SQLRow rowTmpElt : SQLRowListRSH.execute(selAllElt)) {
            String source = rowTmpElt.getString("SOURCE");
            int idSource = rowTmpElt.getInt("IDSOURCE");
            int pos = rowTmpElt.getInt("POSITION");
            SQLRowValues rowValsTmp = new SQLRowValues(tableFicheElt);
            rowValsTmp.put("SOURCE", source);
            rowValsTmp.put("IDSOURCE", idSource);
            rowValsTmp.put("POSITION", pos);
            rowValsTmp.put("ID_FICHE_PAYE", rowValsNewFiche.getID());
            rowValsTmp.commit();
        }

        // on effectue le cumul
        final SQLRow rowVarSal = tableVariableSal.getRow(rowSal.getInt("ID_VARIABLE_SALARIE"));
        int idCumuls = rowSal.getInt("ID_CUMULS_PAYE");
        SQLRow rowCumuls = tableCumuls.getRow(idCumuls);

        SQLRowValues rowValsCumul = new SQLRowValues(tableCumuls);
        for (String string : cumulFields) {
            float cumul = rowCumuls.getFloat(string + "_C") + rowFiche.getFloat(string);
            rowValsCumul.put(string + "_C", new Float(cumul));
        }
        float netAPayer = rowCumuls.getFloat("NET_A_PAYER_C") + rowFiche.getFloat("NET_A_PAYER") + rowFiche.getFloat("ACOMPTE");
        rowValsCumul.put("NET_A_PAYER_C", new Float(netAPayer));

        SQLRow row = rowValsCumul.insert();
        rowValsCumul.put("ID", row.getID());

        rowValsSal.put("ID_CUMULS_PAYE", rowValsCumul.getID());

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                // FIXME: Ouch: sql in swing!
                try {
                    rowValsSal.update(rowFiche.getInt("ID_SALARIE"));
                } catch (SQLException e1) {
                    e1.printStackTrace();
                }
            }
        });
        // Calcul des congés
        final SQLRow rowCumulConge = tableCumulConge.getRow(rowSal.getInt("ID_CUMULS_CONGES"));

        float congeCumule = rowCumulConge.getFloat("ACQUIS");
        float congeRestant = rowCumulConge.getFloat("RESTANT");

        float prisPeriode = rowVarSal.getFloat("CONGES_PRIS");
        congeRestant -= prisPeriode;

        SQLTable tableInfosSalPaye = base.getTable("INFOS_SALARIE_PAYE");
        final SQLRow rowSalInfosPaye = tableInfosSalPaye.getRow(rowSal.getInt("ID_INFOS_SALARIE_PAYE"));

        congeCumule += rowFiche.getFloat("CONGES_ACQUIS");

        final SQLRowValues rowValsCumulsConges = new SQLRowValues(tableCumulConge);

        // Si on passe le 1 juin
        // FIXME est ce que les conges nonpris sont à indemniser
        /*
         * if (mois == 7) { congeRestant = congeCumule; congeCumule = 0; }
         */

        rowValsCumulsConges.put("ACQUIS", new Float(congeCumule));
        rowValsCumulsConges.put("RESTANT", new Float(congeRestant));

        SwingUtilities.invokeLater(new Runnable() {
            public void run() { // FIXME: Ouch: sql in swing!
                try {
                    rowValsCumulsConges.update(rowCumulConge.getID());
                    rowValsNewFiche.put("CONGES_ACQUIS", new Float(rowSalInfosPaye.getFloat("CONGES_PAYES")));
                    rowValsNewFiche.update();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        });
        final SQLRowValues rowValsOldFiche = new SQLRowValues(tableFiche);
        rowValsOldFiche.put("VALIDE", Boolean.TRUE);

        SwingUtilities.invokeLater(new Runnable() {
            public void run() { // FIXME: Ouch: sql in swing!
                try {
                    rowValsOldFiche.update(rowFiche.getID());
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        });
        // Remise à 0 des variables sal
        final SQLRowValues rowVals = new SQLRowValues(tableVariableSal);
        for (final SQLField field : tableVariableSal.getContentFields()) {
            if (!field.getName().endsWith("_DEFAULT_VAL") && !field.getName().endsWith("_CUMUL_VAL")) {
                if (tableVariableSal.contains(field.getName() + "_CUMUL_VAL")) {
                    final float valPeriode = rowVarSal.getObject(field.getName()) == null ? 0.0F : rowVarSal.getFloat(field.getName());
                    final float valCumul = rowVarSal.getObject(field.getName() + "_CUMUL_VAL") == null ? 0.0F : rowVarSal.getFloat(field.getName() + "_CUMUL_VAL");
                    rowVals.put(field.getName() + "_CUMUL_VAL", valCumul + valPeriode);
                }
                if (tableVariableSal.contains(field.getName() + "_DEFAULT_VAL")) {
                    rowVals.put(field.getName(), rowVarSal.getObject(field.getName() + "_DEFAULT_VAL"));
                } else {
                    if (field.getType().getJavaType() == Integer.class) {
                        rowVals.put(field.getName(), 0);
                    } else {
                        rowVals.put(field.getName(), Float.valueOf(0));
                    }
                }

            }
        }
        rowVals.put("HEURE_TRAV", rowSalInfosPaye.getObject("DUREE_MOIS"));

        if (tableVariableSal.contains("NB_JOUR_MOIS")) {
            rowVals.put("NB_JOUR_MOIS", Float.valueOf(31));
            rowVals.put("NB_JOUR_TRAV", Float.valueOf(31));
        }
        SwingUtilities.invokeLater(new Runnable() {
            public void run() { // FIXME: Ouch: sql in swing!
                try {
                    rowVals.update(rowVarSal.getID());
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public static void clotureMensuelle(int idMois, int annee, int idSal) {

        SQLBase base = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete();
        SQLRowValues rowValsSal = new SQLRowValues(base.getTable("SALARIE"));
        SQLRow rowSal = base.getTable("SALARIE").getRow(idSal);
        int ancMois = rowSal.getInt("DERNIER_MOIS");
        int ancAnnee = rowSal.getInt("DERNIERE_ANNEE");

        // on verifie que le mois et l'année sont > aux anciennes valeurs
        if (ancAnnee < annee && ancMois < idMois) {

            rowValsSal.put("DERNIER_MOIS", idMois);
            rowValsSal.put("DERNIERE_ANNEE", annee);

            try {
                rowValsSal.update(idSal);
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        }

    }

    // stocke les éléments validés (cumuls congés, paye, ...)
    private static void stockValidValues(final int id) throws SQLException {
        final ComptaPropsConfiguration conf = ComptaPropsConfiguration.getInstanceCompta();
        final SQLElementDirectory dir = conf.getDirectory();
        final SQLTable tableFiche = conf.getRootSociete().getTable("FICHE_PAYE");
        final SQLRow rowFiche = tableFiche.getRow(id);
        final SQLRow rowSal = rowFiche.getForeignRow("ID_SALARIE");

        final SQLRowValues rowValsFiche = new SQLRowValues(tableFiche);
        for (final String fk : Arrays.asList("ID_PAS", "ID_VARIABLE_SALARIE", "ID_CUMULS_CONGES", "ID_CUMULS_PAYE", "ID_REGLEMENT_PAYE")) {
            final SQLRow fRow = rowSal.getForeignRow(fk);
            final SQLRowValues copy = dir.getElement(fRow.getTable()).createCopy(fRow, null);
            // make sure the copy will be inserted by the update()
            assert copy.getIDNumber() == null;
            rowValsFiche.put(fk, copy);
        }

        final SQLRow rInfosSalPaye = rowSal.getForeignRow("ID_INFOS_SALARIE_PAYE");
        final SQLRow rContrat = rInfosSalPaye.getForeignRow("ID_CONTRAT_SALARIE");
        rowValsFiche.put("NATURE_EMPLOI", rContrat.getString("NATURE"));
        rowValsFiche.put("ID_IDCC", rInfosSalPaye.getInt("ID_IDCC"));
        rowValsFiche.put("ID_INFOS_SALARIE_PAYE", rInfosSalPaye.getID());

        rowValsFiche.update(id);

    }

    // FIXME retirer les rubriques non imprime ou pas dans de la periode de la fiche validee ??
    private static void validElements(int id) {

        SQLBase base = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete();
        String trueString = "1";
        if (Configuration.getInstance().getBase().getServer().getSQLSystem() == SQLSystem.POSTGRESQL) {
            trueString = "true";
        }
        String req = "UPDATE \"FICHE_PAYE_ELEMENT\" SET \"VALIDE\" = " + trueString + " WHERE \"FICHE_PAYE_ELEMENT\".\"ID_FICHE_PAYE\" = " + id;

        base.getDataSource().execute(req);

    }

    private static boolean checkDateValid(int idFiche) {

        SQLBase base = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete();

        SQLRow rowFiche = base.getTable("FICHE_PAYE").getRow(idFiche);
        SQLRow rowSal = base.getTable("SALARIE").getRow(rowFiche.getInt("ID_SALARIE"));
        int moisClot = rowSal.getInt("DERNIER_MOIS");
        int anneeClot = rowSal.getInt("DERNIERE_ANNEE");

        int mois = rowFiche.getInt("ID_MOIS");
        int annee = rowFiche.getInt("ANNEE");
        return ((anneeClot == 0) ? true : annee > anneeClot) || ((moisClot == 0 || moisClot == 13) ? true : mois > moisClot);
    }

    @Override
    protected String createCode() {
        return createCodeOfPackage() + ".payslip";
    }
}