OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Blame | 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.sales.invoice.action;

import org.openconcerto.erp.action.CreateFrameAbstractAction;
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.finance.payment.element.SDDMessageSQLElement;
import org.openconcerto.erp.core.finance.payment.element.SDDMessageSQLElement.GenerationResult;
import org.openconcerto.erp.core.finance.payment.element.SDDMessageSQLElement.IgnoreReason;
import org.openconcerto.erp.core.sales.invoice.element.EcheanceClientSQLElement;
import org.openconcerto.erp.core.sales.invoice.element.SaisieVenteFactureSQLElement;
import org.openconcerto.erp.generationEcritures.GenerationMvtSepa;
import org.openconcerto.erp.utils.TM;
import org.openconcerto.sql.model.FieldPath;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLRowValuesListFetcher;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.model.graph.Path;
import org.openconcerto.sql.request.UpdateBuilder;
import org.openconcerto.sql.view.IListFrame;
import org.openconcerto.sql.view.ListeAddPanel;
import org.openconcerto.sql.view.list.BaseSQLTableModelColumn;
import org.openconcerto.sql.view.list.IListe;
import org.openconcerto.sql.view.list.IListeAction.IListeEvent;
import org.openconcerto.sql.view.list.RowAction;
import org.openconcerto.sql.view.list.SQLTableModelSourceOnline;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.FrameUtil;
import org.openconcerto.utils.CollectionUtils;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.i18n.Grammar_fr;

import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;

import javax.swing.AbstractAction;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;

public class ListeEcheancePrelevementAction extends CreateFrameAbstractAction {

    private final EcheanceClientSQLElement elem;
    private final ComptaPropsConfiguration conf;

    public ListeEcheancePrelevementAction(ComptaPropsConfiguration conf) {
        super();
        this.elem = conf.getDirectory().getElement(EcheanceClientSQLElement.class);
        this.conf = conf;
    }

    public final EcheanceClientSQLElement getElem() {
        return this.elem;
    }

    private void setWhere(final SQLTableModelSourceOnline tableSource, boolean showHistory) {
        final SQLTable tableEcheance = this.elem.getTable();
        Where w = new Where(tableEcheance.getField("ID_SEPA_MANDATE"), "!=", (Object) null);
        if (!showHistory) {
            w = w.and(new Where(tableEcheance.getField("REGLE"), "=", Boolean.FALSE));
            w = w.and(new Where(tableEcheance.getField("REG_COMPTA"), "=", Boolean.FALSE));
        }
        tableSource.getReq().setWhere(w);
    }

    @Override
    public JFrame createFrame() {
        final SQLTableModelSourceOnline tableSource = this.elem.getTableSource(true);
        setWhere(tableSource, false);
        final TM tm = conf.getERP_TM();
        tableSource.getColumns().add(new BaseSQLTableModelColumn("Etat", String.class) {

            @Override
            protected Object show_(SQLRowAccessor r) {
                if (r.getBoolean("REGLE")) {
                    return TM.tr("sepa.deadline.done");
                } else if (r.getBoolean("REG_COMPTA")) {
                    return TM.tr("sepa.deadline.regul");
                } else if (!r.isForeignEmpty("ID_SDD_MESSAGE")) {
                    return TM.tr("sepa.deadline.filecreated");
                }
                return TM.tr("sepa.deadline.waiting");

            }

            @Override
            public Set<FieldPath> getPaths() {
                Path p = new Path(elem.getTable());
                return CollectionUtils.createSet(new FieldPath(p, "REGLE"), new FieldPath(p, "REG_COMPTA"), new FieldPath(p, "ID_SDD_MESSAGE"));
            }
        });
        tableSource.getColumns().add(new BaseSQLTableModelColumn("Fichier SEPA", String.class) {

            @Override
            protected Object show_(SQLRowAccessor r) {
                if (r.isForeignEmpty("ID_SDD_MESSAGE")) {
                    return "";
                } else {
                    return r.getForeign("ID_SDD_MESSAGE").getString("MessageIdentification");
                }

            }

            @Override
            public Set<FieldPath> getPaths() {
                Path p = new Path(elem.getTable());
                p = p.add(elem.getTable().getField("ID_SDD_MESSAGE"));
                return CollectionUtils.createSet(new FieldPath(p, "MessageIdentification"));
            }
        });

        final ListeAddPanel panel = new ListeAddPanel(this.elem, new IListe(tableSource));

        final IListFrame res = new IListFrame(panel);
        res.setTextTitle("Prélèvements SEPA");
        res.getPanel().setReadWriteButtonsVisible(false);
        GridBagConstraints c = new DefaultGridBagConstraints();
        c.gridy += 2;
        c.weighty = 0;
        c.fill = GridBagConstraints.NONE;
        c.anchor = GridBagConstraints.WEST;
        final JCheckBox checkboxHistory = new JCheckBox(TM.tr("sepa.history.hide"));
        checkboxHistory.setSelected(true);
        checkboxHistory.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                setWhere(tableSource, !checkboxHistory.isSelected());

            }
        });
        res.getPanel().add(checkboxHistory, c);

        final SDDMessageSQLElement sepaMsgElem = this.elem.getDirectory().getElement(SDDMessageSQLElement.class);
        final String aMessageLabel = this.elem.getForeignElement(SaisieVenteFactureSQLElement.MESSAGE_FIELD_NAME).getName().getVariant(Grammar_fr.INDEFINITE_ARTICLE_SINGULAR);
        RowAction actionFileCreate = new RowAction.PredicateRowAction(new AbstractAction("Générer " + aMessageLabel, null) {
            @Override
            public void actionPerformed(ActionEvent e) {
                final IListe l = IListe.get(e);
                final List<Integer> selectedIDs = new ArrayList<>();
                final Set<Integer> selectedClientIDs = new HashSet<>();
                for (SQLRowValues rowVals : l.getSelectedRows()) {
                    selectedClientIDs.add(rowVals.getForeignID("ID_CLIENT"));
                    if (rowVals.getLong("MONTANT") > 0) {
                        selectedIDs.add(rowVals.getID());
                    }
                }

                // TODO dialog with label informing of the successful creation of message for n
                // invoices/n2 messages too far in the future/n3 messages with collection date
                // changed and having a button to open the file chooser

                new SwingWorker<String, Void>() {

                    @Override
                    protected String doInBackground() throws Exception {

                        return checkSEPA(selectedClientIDs);
                    }

                    @Override
                    protected void done() {
                        try {
                            String msg = get();

                            if (msg.trim().length() > 0) {
                                msg = "Des informations nécessaires à la création du fichier sont manquantes : \n" + msg;
                                msg += "Le fichier ne pourra être créer tant que ces informations n'auront pas été renseignées.";
                                JOptionPane.showMessageDialog(null, msg, "Création du fichier SEPA annulée", JOptionPane.WARNING_MESSAGE);
                                return;
                            }
                        } catch (Exception e) {
                            ExceptionHandler.handle(l, "Impossible de générer " + aMessageLabel, e);
                            return;
                        }
                        new SwingWorker<GenerationResult, Void>() {
                            @Override
                            protected GenerationResult doInBackground() throws Exception {
                                return sepaMsgElem.generateXML(elem.getTable(), selectedIDs);
                            }

                            @Override
                            protected void done() {
                                final GenerationResult genRes;
                                try {
                                    genRes = this.get();
                                } catch (Exception e) {
                                    ExceptionHandler.handle(l, "Impossible de générer " + aMessageLabel, e);
                                    return;
                                }
                                final int includedInvoicesCount = genRes.getIncludedInvoicesCount();
                                final Map<String, Object> tmMap = new HashMap<>();
                                tmMap.put("msgElem", sepaMsgElem.getName());
                                tmMap.put("invoiceElem", elem.getName());
                                tmMap.put("invoiceElemCount", includedInvoicesCount);

                                if (genRes.getDDInvoicesWithoutMessage().isEmpty()) {
                                    JOptionPane.showMessageDialog(l, tm.trM("sddMessage.generation.noneNeeded", tmMap));
                                } else if (genRes.getIgnoredInvoices().isEmpty()) {
                                    JOptionPane.showMessageDialog(l, tm.trM("sddMessage.generation.noneIgnored", tmMap));
                                } else {
                                    final int futureCount = genRes.getIgnoredInvoices().getNonNull(IgnoreReason.TOO_FAR_IN_FUTURE).size();
                                    final int duplicateCount = genRes.getIgnoredInvoices().getNonNull(IgnoreReason.DUPLICATE_MANDATE).size();
                                    final int missingInfoCount = genRes.getIgnoredInvoices().getNonNull(IgnoreReason.MISSING_INFO).size();
                                    tmMap.put("futureCount", futureCount);
                                    tmMap.put("duplicateCount", duplicateCount);
                                    tmMap.put("missingInfoCount", missingInfoCount);
                                    final StringBuilder msg = new StringBuilder(256);
                                    msg.append(tm.trM("sddMessage.generation.someIgnored", tmMap));
                                    if (futureCount > 0) {
                                        msg.append("\n- ");
                                        msg.append(tm.trM("sddMessage.generation.someIgnored.future", tmMap));
                                    }
                                    if (duplicateCount > 0) {
                                        msg.append("\n- ");
                                        msg.append(tm.trM("sddMessage.generation.someIgnored.duplicateMandate", tmMap));
                                    }
                                    if (missingInfoCount > 0) {
                                        msg.append("\n- ");
                                        msg.append(tm.trM("sddMessage.generation.someIgnored.missingInfo", tmMap));
                                    }
                                    final int messageType = duplicateCount == 0 ? JOptionPane.WARNING_MESSAGE : JOptionPane.ERROR_MESSAGE;
                                    JOptionPane.showMessageDialog(l, msg.toString(), null, messageType);
                                }
                                if (genRes.getInsertedMessage() != null) {
                                    sepaMsgElem.exportXML(l, Collections.singletonList(genRes.getInsertedMessage()));
                                }
                            }
                        }.execute();
                    }
                }.execute();

            }
        }, true, true).setPredicate(IListeEvent.getNonEmptySelectionPredicate());

        // TODO remove once we have a join with {SENT, OK, DEFINITIVE_ERROR, TRANSIENT_ERROR}
        RowAction actionSepaAgain = new RowAction.PredicateRowAction(new AbstractAction("Prélever à nouveau", null) {
            @Override
            public void actionPerformed(ActionEvent e) {
                final IListe l = IListe.get(e);
                if (JOptionPane.showConfirmDialog(l, "Voulez-vous vraiment prélever à nouveau les factures sélectionnées ? Cette action est définitive.", "Prélever à nouveau",
                        JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) != JOptionPane.OK_OPTION)
                    return;
                final List<Integer> selectedIDs = l.getSelection().getSelectedIDs();
                final SQLTable table = l.getSource().getPrimaryTable();

                new SwingWorker<Void, Void>() {
                    @Override
                    protected Void doInBackground() throws Exception {
                        final UpdateBuilder upd = new UpdateBuilder(table);
                        upd.setObject(SaisieVenteFactureSQLElement.MESSAGE_FIELD_NAME, upd.getTable().getForeignTable(SaisieVenteFactureSQLElement.MESSAGE_FIELD_NAME).getUndefinedIDNumber());
                        upd.setObject(SaisieVenteFactureSQLElement.END2END_FIELD_NAME, "");
                        // don't allow to debit already payed invoices
                        upd.setWhere(new Where(upd.getTable().getKey(), selectedIDs).and(new Where(upd.getTable().getField("REGLE"), "=", Boolean.FALSE))
                                .and(new Where(upd.getTable().getField("REG_COMPTA"), "=", Boolean.FALSE)));

                        upd.getTable().getDBSystemRoot().getDataSource().execute(upd.asString());

                        return null;
                    }

                    @Override
                    protected void done() {
                        try {
                            get();
                            final SQLTable table = l.getSource().getPrimaryTable().getTable();
                            final List<String> modifiedFields = Arrays.asList(SaisieVenteFactureSQLElement.MESSAGE_FIELD_NAME, SaisieVenteFactureSQLElement.END2END_FIELD_NAME);
                            for (final Integer id : selectedIDs) {
                                table.fireTableModified(id, modifiedFields);
                            }
                        } catch (InterruptedException | ExecutionException e) {
                            e.printStackTrace();
                        }
                    }
                }.execute();

            }
        }, false, true).setPredicate(IListeEvent.getNonEmptySelectionPredicate());

        panel.getListe().addIListeAction(actionFileCreate);

        panel.getListe().addIListeAction(actionSepaAgain);

        RowAction actionCompta = new RowAction(new AbstractAction("Valider le paiement", null) {
            @Override
            public void actionPerformed(ActionEvent e) {
                final IListe l = IListe.get(e);
                if (JOptionPane.showConfirmDialog(l, "Voulez-vous vraiment transférer ces prélèvements en comptabilité ?", "Comptabiliser", JOptionPane.OK_CANCEL_OPTION,
                        JOptionPane.WARNING_MESSAGE) != JOptionPane.OK_OPTION)
                    return;

                List<SQLRow> rows = new ArrayList<>();
                List<Integer> ids = new ArrayList<>();
                for (SQLRowAccessor sqlRow : l.getSelectedRows()) {
                    rows.add(sqlRow.asRow());
                    ids.add(sqlRow.getID());
                }

                new SwingWorker<Void, Void>() {
                    @Override
                    protected Void doInBackground() throws Exception {
                        try {
                            GenerationMvtSepa sepa = new GenerationMvtSepa(rows);
                            sepa.genere();
                            UpdateBuilder build = new UpdateBuilder(elem.getTable());
                            build.setObject(elem.getTable().getField("REGLE"), Boolean.TRUE);
                            build.setWhere(new Where(elem.getTable().getKey(), ids));
                            elem.getTable().getDBSystemRoot().getDataSource().execute(build.asString());

                        } catch (Exception e) {
                            ExceptionHandler.handle("Erreur lors du transfert en comptabilité", e);

                        }
                        return null;
                    }

                    @Override
                    protected void done() {
                        try {
                            get();
                            for (final Integer id : ids)
                                elem.getTable().fireTableModified(id, Arrays.asList("REGLE"));
                        } catch (InterruptedException | ExecutionException e) {
                            e.printStackTrace();
                        }
                    }
                }.execute();
            }
        }, true, true) {

            @Override
            public boolean enabledFor(List<SQLRowValues> selection) {
                if (selection != null && selection.size() >= 1) {
                    for (SQLRowValues sqlRowValues : selection) {
                        if (sqlRowValues.getBoolean("REGLE")) {
                            return false;
                        }
                    }
                    return true;
                }
                return false;
            }
        };

        panel.getListe().addIListeAction(actionCompta);

        RowAction actionHistoSEPA = new RowAction.PredicateRowAction(new AbstractAction("Historique Fichiers SEPA", null) {
            @Override
            public void actionPerformed(ActionEvent e) {
                final IListFrame res = new IListFrame(new ListeAddPanel(elem.getDirectory().getElement(SDDMessageSQLElement.class)));
                res.getPanel().setReadWriteButtonsVisible(false);
                FrameUtil.showPacked(res);
            }
        }, true, true).setPredicate(IListeEvent.createSelectionCountPredicate(0, Integer.MAX_VALUE));

        panel.getListe().addIListeAction(actionHistoSEPA);

        RowAction actionRelancer = new RowAction.PredicateRowAction(new AbstractAction("Relancer", null) {
            @Override
            public void actionPerformed(ActionEvent e) {
                elem.relanceClient(IListe.get(e).getSelectedRow().asRow());
            }
        }, true, true).setPredicate(IListeEvent.getSingleSelectionPredicate());

        panel.getListe().addIListeAction(actionRelancer);

        RowAction actionCancelPaiement = new RowAction(new AbstractAction("Annuler la validation", null) {

            @Override
            public void actionPerformed(ActionEvent e) {
                final IListe l = IListe.get(e);
                if (JOptionPane.showConfirmDialog(l, "Voulez-vous vraiment annuler le transfert de ce prélèvement en comptabilité ?", "Comptabiliser", JOptionPane.OK_CANCEL_OPTION,
                        JOptionPane.WARNING_MESSAGE) != JOptionPane.OK_OPTION)
                    return;

                final SQLRowValues selectedRow = IListe.get(e).getSelectedRow();
                new SwingWorker<Void, Void>() {
                    @Override
                    protected Void doInBackground() throws Exception {
                        Collection<? extends SQLRowAccessor> res = selectedRow.asRow().getForeign("ID_MOUVEMENT")
                                .getReferentRows(elem.getTable().getTable("ENCAISSER_MONTANT_ELEMENT").getField("ID_MOUVEMENT_ECHEANCE"));
                        if (res.size() >= 1) {
                            try {
                                elem.getDirectory().getElement("MOUVEMENT").archive(res.iterator().next().getForeign("ID_ENCAISSER_MONTANT").getForeignID("ID_MOUVEMENT"));
                                UpdateBuilder build = new UpdateBuilder(elem.getTable());
                                build.setObject(elem.getTable().getField("REGLE"), Boolean.FALSE);
                                build.setWhere(new Where(elem.getTable().getKey(), "=", l.getSelectedId()));
                                elem.getTable().getDBSystemRoot().getDataSource().execute(build.asString());
                            } catch (SQLException e1) {
                                e1.printStackTrace();
                            }
                        }

                        return null;
                    }

                    @Override
                    protected void done() {
                        try {
                            get();
                            elem.getTable().fireTableModified(l.getSelectedId(), Arrays.asList("REGLE"));
                        } catch (InterruptedException | ExecutionException e) {
                            e.printStackTrace();
                        }

                    }
                }.execute();

            }

        }, false, true) {

            @Override
            public boolean enabledFor(List<SQLRowValues> selection) {
                if (selection != null && selection.size() == 1) {
                    return selection.get(0).getBoolean("REGLE");
                }
                return false;
            }

        };

        panel.getListe().addIListeAction(actionCancelPaiement);
        return res;

    }

    private String checkSEPA(Set<Integer> selectedClientIDs) {
        StringBuilder msg = new StringBuilder();

        SQLRow rowSociete = conf.getRowSociete();
        if (rowSociete.getString("IBAN").trim().length() == 0) {
            msg.append("IBAN non renseigné dans les informations de la société.\n");
        }
        if (rowSociete.getString("BIC").trim().length() == 0) {
            msg.append("BIC non renseigné dans les informations de la société.\n");
        }
        if (rowSociete.getString("SEPA_CREDITOR_ID").trim().length() == 0) {
            msg.append("Idenfiant de créancier non renseigné dans les informations de la société.\n");
        }
        if (msg.length() == 0) {
            SQLRowValues rowVals = new SQLRowValues(elem.getTable().getForeignTable("ID_CLIENT"));
            rowVals.putNulls("CODE", "NOM", "IBAN", "BIC");

            SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowVals);
            List<SQLRowValues> res = fetcher.fetch(new Where(rowVals.getTable().getKey(), selectedClientIDs));
            for (SQLRowValues r : res) {

                final int ibanLength = r.getString("IBAN").trim().length();
                final int bicLength = r.getString("BIC").trim().length();
                if (ibanLength == 0 && bicLength == 0) {
                    msg.append("IBAN et BIC non renseignés pour le client " + r.getString("NOM") + ".\n");
                } else if (ibanLength == 0) {
                    msg.append("IBAN non renseignés pour le client " + r.getString("NOM") + ".\n");
                } else if (bicLength == 0) {
                    msg.append("BIC non renseignés pour le client " + r.getString("NOM") + ".\n");
                }
            }

        }
        return msg.toString();
    }

}