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