OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Compare Revisions

Regard whitespace Rev 148 → Rev 149

/trunk/OpenConcerto/.settings/org.eclipse.jdt.core.prefs
1,12 → 1,12
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7
org.eclipse.jdt.core.compiler.source=1.8
/trunk/OpenConcerto/.classpath
1,7 → 1,6
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry exported="true" kind="lib" path="lib/commons-dbutils-1.0.jar"/>
<classpathentry exported="true" kind="lib" path="lib/commons-jxpath-1.3.jar"/>
<classpathentry exported="true" kind="lib" path="lib/commons-logging-1.1.jar"/>
22,7 → 21,6
<classpathentry kind="lib" path="lib/fb-annotations-2.0.0.jar"/>
<classpathentry exported="true" kind="lib" path="lib/commons-dbcp-1.4.jar"/>
<classpathentry kind="lib" path="lib/commons-pool-1.6.jar"/>
<classpathentry kind="lib" path="lib/postgresql-9.2-1003.jdbc4.jar"/>
<classpathentry kind="lib" path="lib/h2-1.3.175.jar"/>
<classpathentry kind="lib" path="lib/xercesImpl-2.9.1.jar"/>
<classpathentry kind="lib" path="lib/commons-collections-3.2.1.jar"/>
44,5 → 42,7
<classpathentry kind="lib" path="lib/javax.mail-1.6.0.jar"/>
<classpathentry kind="lib" path="lib/json-smart-2.2.1.jar"/>
<classpathentry kind="lib" path="lib/mysql-connector-java-5.1.40-bin.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="lib" path="lib/postgresql-42.2.2.jre7.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
/trunk/OpenConcerto/lib/postgresql-9.2-1003.jdbc4.jar
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/OpenConcerto/lib/postgresql-42.2.2.jre7.jar
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/OpenConcerto/lib/postgresql-42.2.2.jre7.jar
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/OpenConcerto/lib/jOpenDocument-1.4rc2.jar
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/OpenConcerto/lib/jOpenCalendar.jar
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/OpenConcerto/Configuration/Template/Default/EtatVentes.xml
3,10 → 3,10
<element0 location="A4" type="Value" ValueName="DATE">
</element0>
 
<element0 location="G54" type="Value" ValueName="TOTAL_PV_TTC">
</element0>
<!-- <element0 location="G54" type="Value" ValueName="TOTAL_PV_TTC">
</element0> -->
 
<table0 firstLine="7" endLine="51" endPageLine="54" lastColumn="E" base="Societe" table="SAISIE_VENTE_FACTURE_ELEMENT">
<table0 firstLine="7" endLine="52" endPageLine="54" lastColumn="H" base="Societe" table="SAISIE_VENTE_FACTURE_ELEMENT">
<element location="A" type="fill">
<field base="Societe" name="NOM" />
</element>
22,12 → 22,15
<element location="E" type="fill">
<field base="Societe" name="NB_ESPECES" />
</element>
<element location="F" type="fill">
<field base="Societe" name="NB_ESPECES" />
</element>
 
<element location="F" type="fill">
<element location="G" type="fill">
<field base="Societe" name="T_MARGE" />
</element>
 
<element location="G" type="fill">
<element location="H" type="fill">
<field base="Societe" name="T_PV_TTC" />
</element>
</table0>
80,4 → 83,45
<field base="Societe" name="TOTAL" />
</element>
</table2>
<element3 location="A1" type="Value" ValueName="DATE">
</element3>
<element3 location="C19" type="Value" ValueName="TOTAL_TVA">
</element3>
 
<table3 firstLine="4" endLine="52" endPageLine="54" lastColumn="I" base="Societe" table="SAISIE_VENTE_FACTURE_ELEMENT">
<element location="A" type="fill">
<field base="Societe" name="VT_TAUX_TVA" />
</element>
 
<element location="B" type="fill">
<field base="Societe" name="VT_HT" />
</element>
 
<element location="C" type="fill">
<field base="Societe" name="VT_TVA" />
</element>
 
<element location="D" type="fill">
<field base="Societe" name="VT_TTC" />
</element>
 
<element location="F" type="fill">
<field base="Societe" name="VT_TAUX_TVA" />
</element>
<element location="G" type="fill">
<field base="Societe" name="HA_HT" />
</element>
 
<element location="H" type="fill">
<field base="Societe" name="HA_TVA" />
</element>
<element location="I" type="fill">
<field base="Societe" name="HA_TTC" />
</element>
</table3>
</contentDocument>
/trunk/OpenConcerto/Configuration/Template/Default/Devis.ods
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/OpenConcerto/Configuration/Template/Default/EtatVentes.ods
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/OpenConcerto/Configuration/Template/Default/DemandePrix.ods
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/OpenConcerto/src/org/postgresql/jdbc2/AbstractJdbc2DatabaseMetaData.java
File deleted
/trunk/OpenConcerto/src/org/jopendocument/link/OOConnexion.java
82,6 → 82,15
perms.add(new FilePermission("<<ALL FILES>>", "read"));
// needed by ThreadPoolExecutor.shutdown()
perms.add(new RuntimePermission("modifyThread"));
// needed by PrinterJob.getPrinterJob()
perms.add(new RuntimePermission("queuePrintJob"));
// needed by OOConnexion.init() to find the port
perms.add(new FilePermission("/usr/bin/lsof", "execute"));
perms.add(new FilePermission("/bin/ps", "execute"));
perms.add(new FilePermission("C:/Windows/System32/tasklist.exe", "execute"));
perms.add(new RuntimePermission("getenv.*"));
// needed by OOConnexion.convertToUrl()
perms.add(new FilePermission("/usr/bin/gvfs-info", "execute"));
return perms;
}
};
/trunk/OpenConcerto/src/org/jopendocument/link/Component.java
13,6 → 13,7
package org.jopendocument.link;
 
import java.awt.print.PrinterJob;
import java.io.File;
import java.util.Map;
import java.util.concurrent.Future;
30,7 → 31,7
return this.parent;
}
 
public abstract void printDocument();
public abstract void printDocument(PrinterJob job);
 
public final void printDocument(final Map<String, ?> printProps) {
printDocument(printProps, null);
51,7 → 52,7
* par défaut du modéle
* @param printOpt
*/
public abstract void printDocument(final Map<String, ?> printProps, final Map<String, ?> printOpt);
public abstract void printDocument(final Map<String, ?> printProps, final Map<String, ?> printOpt) throws IllegalArgumentException;
 
public abstract Future<String> save();
 
/trunk/OpenConcerto/src/org/openconcerto/ftp/IFtp.java
177,20 → 177,16
 
// our __storeFile use CopyStreamListener
private boolean __storeFile(int command, String remote, InputStream local) throws IOException {
OutputStream output;
Socket socket;
 
if ((socket = _openDataConnection_(command, remote)) == null)
try (final Socket socket = _openDataConnection_(command, remote); final OutputStream output = socket == null ? null : new BufferedOutputStream(socket.getOutputStream(), getBufferSize())) {
if (socket == null)
return false;
 
output = new BufferedOutputStream(socket.getOutputStream(), getBufferSize());
 
// __fileType is private, if we really want we could subclass setFileType() to have access
// __fileType is private, if we really want we could subclass setFileType() to have
// access
// if (__fileType == ASCII_FILE_TYPE)
// output = new ToNetASCIIOutputStream(output);
 
// Treat everything else as binary for now
try {
final CopyStreamListener l = this.streamListeners.get();
final long size = CopyStreamEvent.UNKNOWN_STREAM_SIZE;
if (l != null) {
198,15 → 194,7
l.bytesTransferred(0, 0, size);
}
Util.copyStream(local, output, getBufferSize(), size, l, false);
} catch (IOException e) {
try {
socket.close();
} catch (IOException f) {
}
throw e;
}
output.close();
socket.close();
return completePendingCommand();
}
 
/trunk/OpenConcerto/src/org/openconcerto/ftp/FTPUtils.java
30,7 → 30,7
}
 
// MAYBE use recurse, but can't recursively pass local
static public final void saveR(FTPClient ftp, File local) throws IOException {
public static final void saveR(FTPClient ftp, File local) throws IOException {
local.mkdirs();
for (FTPFile child : ftp.listFiles()) {
final String childName = child.getName();
40,15 → 40,18
saveR(ftp, new File(local, childName));
ftp.changeToParentDirectory();
} else {
final OutputStream outs = new FileOutputStream(new File(local, childName));
ftp.retrieveFile(childName, outs);
outs.close();
final File file = new File(local, childName);
try (final OutputStream outs = new FileOutputStream(file)) {
final boolean ok = ftp.retrieveFile(childName, outs);
if (!ok)
throw new IOException("failed to get " + childName + " to " + file.getAbsolutePath());
}
}
}
}
}
 
static public final void rmR(final FTPClient ftp, final String toRm) throws IOException {
public static final void rmR(final FTPClient ftp, final String toRm) throws IOException {
final String cwd = ftp.printWorkingDirectory();
// si on ne peut cd, le dossier n'existe pas
if (ftp.changeWorkingDirectory(toRm)) {
69,11 → 72,11
ftp.removeDirectory(toRm);
}
 
static public final void recurse(FTPClient ftp, ExnClosure<FTPFile, ?> c) throws IOException {
public static final void recurse(FTPClient ftp, ExnClosure<FTPFile, ?> c) throws IOException {
recurse(ftp, c, RecursionType.DEPTH_FIRST);
}
 
static public final void recurse(FTPClient ftp, ExnClosure<FTPFile, ?> c, RecursionType type) throws IOException {
public static final void recurse(FTPClient ftp, ExnClosure<FTPFile, ?> c, RecursionType type) throws IOException {
for (FTPFile child : ftp.listFiles()) {
if (child.getName().indexOf('.') != 0) {
if (type == RecursionType.BREADTH_FIRST)
/trunk/OpenConcerto/src/org/openconcerto/map/ui/ITextComboVilleViewer.java
77,8 → 77,10
this.text = new ISearchableCombo<Ville>(ComboLockedMode.ITEMS_LOCKED, 0, 17) {
 
@Override
protected Ville stringToT(String t) {
protected Ville stringToT(String t) throws IllegalArgumentException {
Ville v = Ville.getVilleFromVilleEtCode(t);
if (v == null)
throw new IllegalArgumentException("Unknown city");
return v;
}
};
/trunk/OpenConcerto/src/org/openconcerto/openoffice/generation/desc/ReportTypes.java
135,4 → 135,8
return this.defines.get(name);
}
 
@Override
public String toString() {
return this.getClass().getSimpleName() + " with base dir : " + this.baseDir + "\nwith types : " + this.types.keySet();
}
}
/trunk/OpenConcerto/src/org/openconcerto/ui/list/CheckListItem.java
14,6 → 14,7
package org.openconcerto.ui.list;
 
import java.awt.Color;
import java.util.Objects;
 
public class CheckListItem {
private final Object object;
33,6 → 34,10
return object;
}
 
public Object getKey() {
return this.getObject();
}
 
public boolean isSelected() {
return isSelected;
}
49,6 → 54,27
this.color = color;
}
 
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.object == null) ? 0 : this.object.hashCode());
return result;
}
 
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CheckListItem other = (CheckListItem) obj;
return Objects.equals(this.object, other.object);
}
 
@Override
public String toString() {
return object.toString();
}
/trunk/OpenConcerto/src/org/openconcerto/ui/date/EventProviders.java
59,7 → 59,7
// we want a different day
c.add(Calendar.DAY_OF_WEEK, 1);
}
while (c.get(Calendar.WEEK_OF_YEAR) == currentWeekNumber) {
while (c.get(Calendar.WEEK_OF_YEAR) == currentWeekNumber || initialValue) {
if (this.days.contains(DayOfWeek.fromCalendar(c))) {
return;
}
94,7 → 94,7
if (!initialValue || currentPeriodBefore(c)) {
// GregorianCalendar calls pinDayOfMonth() so that January the 31st + 1 month stays
// in February
c.add(this.period.getCalendarField(), this.increment);
c.add(this.period.getCalendarField(), initialValue ? 1 : this.increment);
}
setDate(c);
}
/trunk/OpenConcerto/src/org/openconcerto/ui/date/DateRangeTable.java
14,15 → 14,22
package org.openconcerto.ui.date;
 
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.DisplayabilityListener;
import org.openconcerto.ui.PositiveIntegerTableCellEditor;
import org.openconcerto.ui.table.FocusAwareEditor;
import org.openconcerto.ui.table.TimestampTableCellEditor;
import org.openconcerto.utils.StringUtils;
 
import java.applet.Applet;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.KeyboardFocusManager;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
47,6 → 54,83
import javax.swing.table.TableColumn;
 
public class DateRangeTable extends JPanel {
 
private static final List<JTable> FOCUS_TABLES = new ArrayList<>();
/**
* En remplacement de
* <code>this.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);</code>
* <p>
* Permet l'utilisation de {@link TimestampTableCellEditor}
*
* Arret de l'edition si la table perd le focus La perte de focus est ignorée sur le CellEditor
* gère lui même la perte de focus (FocusAwareEditor)
*
*/
private static final PropertyChangeListener FOCUS_LISTENER = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
Component c = ((KeyboardFocusManager) evt.getSource()).getPermanentFocusOwner();
if (c == null) {
// Personne n'a encore le focus, on ne stoppe pas l'édition dans les tables
// car on est dans ce cas quand on démarre l'édition
return;
}
final Component rootOfNewFocusOwner = SwingUtilities.getRoot(c);
for (final JTable t : FOCUS_TABLES) {
final Component rootOfTable = SwingUtilities.getRoot(t);
if (rootOfNewFocusOwner != rootOfTable) {
// le focus est dans un autre fenetre, la table doit donc stopper son édition
stopTableCellEditing(t);
} else {
while (c != null) {
if (c == t) {
// le focus reste "dans" la table, on ne fait rien
return;
} else if ((c instanceof Window) || (c instanceof Applet && c.getParent() == null)) {
if (c == rootOfTable) {
// le focus est dans un parent de la table, on stoppe l'édition
stopTableCellEditing(t);
}
break;
}
c = c.getParent();
}
}
}
}
 
public void stopTableCellEditing(final JTable t) {
if (t.getCellEditor() != null && !(t.getCellEditor() instanceof FocusAwareEditor) && !t.getCellEditor().stopCellEditing()) {
t.getCellEditor().cancelCellEditing();
}
}
};
 
private static final DisplayabilityListener DISP_FOCUS_LISTENER = new DisplayabilityListener() {
@Override
protected void displayabilityChanged(Component c) {
final String propertyName = "permanentFocusOwner";
if (c.isDisplayable()) {
final boolean wasEmpty = FOCUS_TABLES.isEmpty();
FOCUS_TABLES.add((JTable) c);
if (wasEmpty) {
final KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.addPropertyChangeListener(propertyName, FOCUS_LISTENER);
}
} else {
FOCUS_TABLES.remove(c);
if (FOCUS_TABLES.isEmpty()) {
final KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.removePropertyChangeListener(propertyName, FOCUS_LISTENER);
}
}
}
};
 
public static final void fixEditorFocus(final JTable t) {
t.addHierarchyListener(DISP_FOCUS_LISTENER);
}
 
private static final long serialVersionUID = 351767837995219468L;
public JButton bAdd = new JButton("Ajouter une plage horaire");
public JButton bRemove = new JButton("Supprimer");
70,6 → 154,7
};
};
this.rangeTable.setRowHeight((int) (new JLabel("A").getPreferredSize().height * 1.8));
DateRangeTable.fixEditorFocus(this.rangeTable);
 
// Start
final TableColumn columnStart = this.rangeTable.getColumnModel().getColumn(0);
232,7 → 317,7
}
 
public List<DateRange> getRanges() {
List<DateRange> result = new ArrayList<DateRange>();
List<DateRange> result = new ArrayList<>();
DateRangeTableModel model = getDateRangeTableModel();
for (int i = 0; i < model.getRowCount(); i++) {
result.add(model.getRange(i));
/trunk/OpenConcerto/src/org/openconcerto/ui/RangedIntegerTableCellEditor.java
New file
0,0 → 1,67
/*
* 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.ui;
 
import javax.swing.DefaultCellEditor;
import javax.swing.JTextField;
 
public class RangedIntegerTableCellEditor extends DefaultCellEditor {
private int min, max;
 
public RangedIntegerTableCellEditor(int min, int max) {
super(new JTextField());
this.min = min;
this.max = max;
}
 
@Override
public boolean stopCellEditing() {
try {
// try to get the value
this.getCellEditorValue();
return super.stopCellEditing();
} catch (Exception ex) {
return false;
}
 
}
 
@Override
public Object getCellEditorValue() {
final String str = (String) super.getCellEditorValue();
if (str == null || str.length() == 0) {
return min;
}
try {
int i = Integer.parseInt(str);
if (i < min) {
i = min;
} else if (i > max) {
i = max;
}
return i;
} catch (Exception ex) {
throw new IllegalStateException();
}
 
}
 
public void setMax(int max) {
this.max = max;
}
 
public void setMin(int min) {
this.min = min;
}
}
/trunk/OpenConcerto/src/org/openconcerto/ui/validate_popup.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/OpenConcerto/src/org/openconcerto/ui/validate_popup.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIRawHMTL.java
New file
0,0 → 1,53
/*
* 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.ui.light;
 
import org.openconcerto.utils.io.HTMLable;
 
import net.minidev.json.JSONObject;
 
public class LightUIRawHMTL extends LightUIElement implements HTMLable {
 
private String html = "";
 
public LightUIRawHMTL(final JSONObject json) {
super(json);
}
 
public LightUIRawHMTL(final String id) {
super(id);
this.setType(TYPE_RAW_HTML);
}
 
public LightUIRawHMTL(final String id, String html) {
super(id);
this.setType(TYPE_RAW_HTML);
this.html = html;
}
 
@Override
public JSONToLightUIConvertor getConvertor() {
return new JSONToLightUIConvertor() {
@Override
public LightUIElement convert(JSONObject json) {
return new LightUIRawHMTL(json);
}
};
}
 
@Override
public String getHTML() {
return this.html;
}
}
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIElement.java
13,6 → 13,7
package org.openconcerto.ui.light;
 
import org.openconcerto.utils.io.HTMLable;
import org.openconcerto.utils.io.JSONConverter;
import org.openconcerto.utils.io.Transferable;
 
21,7 → 22,7
 
import net.minidev.json.JSONObject;
 
public class LightUIElement implements Transferable {
public abstract class LightUIElement implements Transferable {
 
private static final String HORIZONTALLY_RESIZABLE = "horizontally-resizable";
private static final String VERTICALLY_SCROLLABLE = "vertically-scrollable";
82,6 → 83,7
public static final int TYPE_AUTOCOMPLETE_COMBOBOX = 31;
public static final int TYPE_COLOR_PICKER = 32;
public static final int TYPE_HOUR_EDITOR = 33;
public static final int TYPE_RADIO_BUTTONS = 34;
// valueType
public static final int VALUE_TYPE_STRING = 0;
public static final int VALUE_TYPE_INTEGER = 1;
195,12 → 197,13
 
// Clone constructor
public LightUIElement(final LightUIElement element) {
this.id = element.id;
this.parent = element.parent;
this.UUID = element.UUID;
this.type = element.type;
 
this.copy(element);
throw new IllegalAccessError("??");
// this.id = element.id;
// this.parent = element.parent;
// this.UUID = element.UUID;
// this.type = element.type;
//
// this.copy(element);
}
 
public int getFontSize() {
778,15 → 781,15
return this.getClass().getName();
}
 
public JSONToLightUIConvertor getConvertor() {
return new JSONToLightUIConvertor() {
@Override
public LightUIElement convert(final JSONObject json) {
return new LightUIElement(json);
}
};
}
public abstract JSONToLightUIConvertor getConvertor();
 
/**
* { return new JSONToLightUIConvertor() {
*
* @Override public LightUIElement convert(final JSONObject json) { return new
* LightUIElement(json); } }; }
*/
 
protected void copy(final LightUIElement element) {
if (element == null) {
throw new IllegalArgumentException("Try to copy attributes of null element in " + this.getId());
1011,7 → 1014,9
if (this.foreColor != null) {
result.put("fore-color", JSONConverter.getJSON(this.foreColor));
}
 
if (this instanceof HTMLable) {
result.put("html", ((HTMLable) this).getHTML());
}
return result;
}
 
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIFrame.java
30,6 → 30,7
 
private Boolean active = false;
private LightUIPanel titlePanel = null;
private LightUIPanel contentPanel;
private LightUIPanel footerPanel = new LightUIPanel(this.getId() + ".footer.panel");
 
private List<LightUIFrame> childrenFrame;
45,7 → 46,7
this.active = frame.active;
this.titlePanel = frame.titlePanel;
this.childrenFrame = frame.childrenFrame;
 
this.contentPanel = frame.contentPanel;
this.setFooterPanel(frame.footerPanel);
}
 
57,16 → 58,24
public LightUIFrame(final String id) {
super(id);
this.setType(TYPE_FRAME);
 
this.childrenFrame = new ArrayList<LightUIFrame>();
this.addChild(new LightUIPanel(this.getId() + ".main.panel"));
this.childrenFrame = new ArrayList<>();
this.contentPanel = new LightUIPanel(this.getId() + ".main.panel");
this.addChild(contentPanel);
this.footerPanel.setParent(this);
this.footerPanel.setFillHeight(false);
this.footerPanel.setHeight(50);
 
this.createTitlePanel();
}
 
public LightUIPanel getContentPanel() {
return this.contentPanel;
}
 
public void setContentPanel(LightUIPanel contentPanel) {
this.contentPanel = contentPanel;
this.addChild(contentPanel);
}
 
public LightUIPanel createTitlePanel(final String title) {
this.createTitlePanel();
final LightUILabel titleLabel = new LightUILabel(this.titlePanel.getId() + ".label", title, true);
86,6 → 95,11
return this.titlePanel;
}
 
public void setTitlePanel(LightUIPanel titlePanel) {
titlePanel.setId(this.getId() + ".title.panel");
this.titlePanel = titlePanel;
}
 
public LightUIPanel getFooterPanel() {
return this.footerPanel;
}
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIBadge.java
New file
0,0 → 1,41
/*
* 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.ui.light;
 
import net.minidev.json.JSONObject;
 
public class LightUIBadge extends LightUIElement {
 
public LightUIBadge(final JSONObject json) {
super(json);
}
 
public LightUIBadge(final String id, String label) {
super(id);
this.setType(TYPE_BADGE);
this.setVerticalAlignement(VALIGN_CENTER);
this.setHorizontalAlignement(HALIGN_CENTER);
this.setLabel(label);
}
 
@Override
public JSONToLightUIConvertor getConvertor() {
return new JSONToLightUIConvertor() {
@Override
public LightUIElement convert(JSONObject json) {
return new LightUIBadge(json);
}
};
}
}
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIButton.java
85,4 → 85,14
super.destroy();
this.clickListeners.clear();
}
 
@Override
public JSONToLightUIConvertor getConvertor() {
return new JSONToLightUIConvertor() {
@Override
public LightUIElement convert(JSONObject json) {
return new LightUIButton(json);
}
};
}
}
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIColorPicker.java
54,4 → 54,14
public Object getValueForContext() {
return this.getValue();
}
 
@Override
public JSONToLightUIConvertor getConvertor() {
return new JSONToLightUIConvertor() {
@Override
public LightUIElement convert(JSONObject json) {
return new LightUIColorPicker(json);
}
};
}
}
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIButtonWithContext.java
15,7 → 15,7
 
import net.minidev.json.JSONObject;
 
public abstract class LightUIButtonWithContext extends LightUIButton {
public class LightUIButtonWithContext extends LightUIButton {
public LightUIButtonWithContext(final JSONObject json) {
super(json);
}
28,6 → 28,4
super(button);
}
 
@Override
public abstract LightUIElement clone();
}
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIRadioButtons.java
New file
0,0 → 1,112
/*
* 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.ui.light;
 
import java.util.ArrayList;
import java.util.List;
 
import net.minidev.json.JSONArray;
import net.minidev.json.JSONObject;
 
public class LightUIRadioButtons extends LightUserControl {
private final List<String> choices = new ArrayList<>();
 
// Init from json constructor
public LightUIRadioButtons(final JSONObject json) {
super(json);
}
 
// Clone constructor
public LightUIRadioButtons(final LightUIRadioButtons labelElement) {
super(labelElement);
}
 
public LightUIRadioButtons(final String id, final String label, final List<String> choices) {
this(id, label, choices, -1);
}
 
/**
*
* @param selectedIndex index of the selected value (-1 if nothing is selected)
*/
public LightUIRadioButtons(final String id, final String label, final List<String> choices, int selectedIndex) {
super(id);
this.setType(LightUIElement.TYPE_RADIO_BUTTONS);
this.setLabel(label);
if (selectedIndex >= choices.size()) {
throw new IllegalArgumentException("invalid index " + selectedIndex + ", it must be between 0 and " + choices.size());
}
if (selectedIndex < 0) {
this.setValue(null);
} else {
this.setValue(String.valueOf(selectedIndex));
}
this.setChoices(choices);
}
 
public void setChoices(List<String> choices) {
this.choices.clear();
this.choices.addAll(choices);
}
 
@Override
public JSONObject toJSON() {
final JSONObject json = super.toJSON();
final JSONArray array = new JSONArray();
for (String choice : choices) {
array.add(choice);
}
json.put("choices", array);
return json;
}
 
@Override
public void fromJSON(final JSONObject json) {
super.fromJSON(json);
final JSONArray array = (JSONArray) json.get("choices");
this.choices.clear();
for (Object o : array) {
this.choices.add(o.toString());
}
}
 
@Override
public JSONToLightUIConvertor getConvertor() {
return new JSONToLightUIConvertor() {
@Override
public LightUIElement convert(final JSONObject json) {
return new LightUIRadioButtons(json);
}
};
}
 
@Override
public void _setValueFromContext(Object value) {
if (value instanceof Number) {
this.setValue(value.toString());
} else {
throw new IllegalArgumentException("Incorrect value " + value + "type for ui element: " + this.getId());
}
}
 
@Override
public Object getValueForContext() {
if (this.getValue() == null) {
return null;
} else {
return Integer.parseInt(this.getValue());
}
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUISlider.java
15,12 → 15,16
 
import org.openconcerto.utils.io.JSONConverter;
 
import java.util.HashMap;
import java.util.Map;
 
import net.minidev.json.JSONObject;
 
public class LightUISlider extends LightUserControl {
Integer maxValue = 1;
Integer minValue = 0;
Integer increment = 1;
private Integer maxValue = 1;
private Integer minValue = 0;
private Integer increment = 1;
private Map<Integer, String> mapLabels = new HashMap<>();
 
public LightUISlider(final String id) {
super(id);
40,13 → 44,27
this.increment = slider.increment;
}
 
public void setLabel(int value, String label) {
mapLabels.put(Integer.valueOf(value), label);
}
 
public String getLabelForValue(int value) {
return mapLabels.get(Integer.valueOf(value));
}
 
public Integer getMaxValue() {
return this.maxValue;
}
 
public void setMaxValue(final int maxValue) {
if (maxValue < this.minValue) {
throw new IllegalArgumentException("max cannot be < " + this.minValue);
}
this.maxValue = maxValue;
if (this.getMinWidth() == null) {
this.setMinWidth((this.maxValue - this.minValue) * 50);
}
}
 
public Integer getMinValue() {
return this.minValue;
53,8 → 71,14
}
 
public void setMinValue(final int minValue) {
if (minValue > this.maxValue) {
throw new IllegalArgumentException("min cannot be > " + this.maxValue);
}
this.minValue = minValue;
if (this.getMinWidth() == null) {
this.setMinWidth((this.maxValue - this.minValue) * 50);
}
}
 
public Integer getIncrement() {
return this.increment;
64,6 → 88,14
this.increment = increment;
}
 
public void setSelectedValue(int value) {
setValue(String.valueOf(value));
}
 
public int getSelectedValue() {
return Integer.parseInt(getValue());
}
 
@Override
public JSONObject toJSON() {
final JSONObject json = super.toJSON();
70,7 → 102,15
json.put("max-value", this.maxValue);
json.put("min-value", this.minValue);
json.put("increment", this.increment);
 
if (!this.mapLabels.isEmpty()) {
final JSONObject labels = new JSONObject();
for (Map.Entry<Integer, String> entry : mapLabels.entrySet()) {
final Integer key = entry.getKey();
final String value = entry.getValue();
labels.put(String.valueOf(key), value);
}
json.put("labels", labels);
}
return json;
}
 
80,7 → 120,15
this.maxValue = JSONConverter.getParameterFromJSON(json, "max-value", Integer.class, 1);
this.minValue = JSONConverter.getParameterFromJSON(json, "min-value", Integer.class, 0);
this.increment = JSONConverter.getParameterFromJSON(json, "increment", Integer.class, 1);
this.mapLabels.clear();
if (json.containsKey("labels")) {
final JSONObject labels = (JSONObject) json.get("labels");
for (String key : labels.keySet()) {
final String v = labels.getAsString(key);
mapLabels.put(Integer.parseInt(key), v);
}
}
}
 
@Override
public void _setValueFromContext(Object value) {
99,4 → 147,14
return Integer.parseInt(this.getValue());
}
}
 
@Override
public JSONToLightUIConvertor getConvertor() {
return new JSONToLightUIConvertor() {
@Override
public LightUIElement convert(JSONObject json) {
return new LightUISlider(json);
}
};
}
}
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIHTMLStrippedPanel.java
59,4 → 59,20
}
return b.toString();
}
 
@Override
public void addLine(LightUILine line) {
if (!(line instanceof HTMLable)) {
throw new IllegalArgumentException("line must be a subclass of be HTMLable");
}
super.addLine(line);
}
 
@Override
public void addChild(LightUIElement e) {
if (!(e instanceof LightUILine)) {
throw new IllegalArgumentException("line must be a subclass of LightUILine");
}
super.addLine((LightUILine) e);
}
}
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIContainer.java
285,4 → 285,14
child.destroy();
}
}
 
@Override
public JSONToLightUIConvertor getConvertor() {
return new JSONToLightUIConvertor() {
@Override
public LightUIElement convert(JSONObject json) {
return new LightUIContainer(json);
}
};
}
}
/trunk/OpenConcerto/src/org/openconcerto/ui/light/LightUIText.java
New file
0,0 → 1,45
/*
* 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.ui.light;
 
import net.minidev.json.JSONObject;
 
public class LightUIText extends LightUIElement {
// Init from json constructor
public LightUIText(final JSONObject json) {
super(json);
}
 
public LightUIText(final String id) {
this(id, "");
}
 
public LightUIText(final String id, final String label) {
super(id);
this.setType(TYPE_LABEL);
this.setLabel(label);
 
}
 
@Override
public JSONToLightUIConvertor getConvertor() {
return new JSONToLightUIConvertor() {
@Override
public LightUIElement convert(final JSONObject json) {
return new LightUIText(json);
}
};
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/ui/light/SearchSpec.java
19,9 → 19,10
import org.openconcerto.utils.io.JSONConverter;
import org.openconcerto.utils.io.Transferable;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONAware;
import net.minidev.json.JSONObject;
 
public class SearchSpec implements Transferable {
public class SearchSpec implements Transferable, JSONAware {
private String tableId;
private List<SearchContent> content = new ArrayList<SearchContent>();
 
60,4 → 61,12
}
}
}
 
/*
* JSONAware pour que le JSONArray.toString() fonctionne quand cet objet est dans un JSONArray
*/
@Override
public String toJSONString() {
return toJSON().toJSONString();
}
}
/trunk/OpenConcerto/src/org/openconcerto/ui/TimestampEditorPanel.java
23,17 → 23,17
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Vector;
 
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
55,7 → 55,7
private TimeTextField timeText;
private JPanel panelHour;
private DatePickerPanel pickerPanel;
private List<ActionListener> listeners = new Vector<ActionListener>();
private List<ActionListener> listeners = new ArrayList<>();
private TimestampTableCellEditor aCellEditor;
private Calendar calendar = Calendar.getInstance();
private JDate dateEditor;
96,7 → 96,7
}
c.gridx++;
 
final JButton buttonClose = new JButton(new ImageIcon(TimestampEditorPanel.class.getResource("close_popup_gray.png")));
final JButton buttonClose = new JButton(new ImageIcon(TimestampEditorPanel.class.getResource("validate_popup.png")));
buttonClose.addActionListener(new ActionListener() {
 
public void actionPerformed(ActionEvent e) {
118,13 → 118,9
c.gridx++;
c.gridwidth = 2;
dateEditor = new JDate(true, true);
dateEditor.getTextComp().addFocusListener(new FocusListener() {
dateEditor.getTextComp().addFocusListener(new FocusAdapter() {
 
@Override
public void focusLost(FocusEvent e) {
}
 
@Override
public void focusGained(FocusEvent e) {
 
final JTextComponent textComp = dateEditor.getTextComp();
206,26 → 202,15
dateOrTimeChanged();
}
});
this.timeText.addKeyListener(new KeyListener() {
this.timeText.addKeyListener(new KeyAdapter() {
 
@Override
public void keyTyped(KeyEvent e) {
 
}
 
@Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_TAB || e.getKeyCode() == KeyEvent.VK_ENTER) {
if (aCellEditor != null) {
if ((e.getKeyCode() == KeyEvent.VK_TAB || e.getKeyCode() == KeyEvent.VK_ENTER) && aCellEditor != null) {
aCellEditor.stopCellEditing();
}
}
}
 
@Override
public void keyPressed(KeyEvent e) {
 
}
});
 
}
273,7 → 258,7
private void fireTimeChangedPerformed() {
final int size = this.listeners.size();
for (int i = 0; i < size; i++) {
final ActionListener element = (ActionListener) this.listeners.get(i);
final ActionListener element = this.listeners.get(i);
element.actionPerformed(null);
}
 
/trunk/OpenConcerto/src/org/openconcerto/ui/touch/ScrollableList.java
343,20 → 343,26
}
}
 
public void setSelectedValue(Object articleSelected, boolean scroll) {
if (articleSelected == null) {
/**
* Select a value
*
* @return true if the object is not null and was found in the model
*/
public boolean setSelectedValue(Object obj, boolean scroll) {
if (obj == null) {
clearSelection();
return;
return true;
}
 
int size = model.getSize();
for (int i = 0; i < size; i++) {
Object o = model.getElementAt(i);
if (o.equals(articleSelected)) {
if (o.equals(obj)) {
this.setSelectedIndex(i);
break;
return true;
}
}
return false;
}
 
public void addListSelectionListener(ListSelectionListener selectionListener) {
/trunk/OpenConcerto/src/org/openconcerto/ui/table/TimestampTableCellEditor.java
15,6 → 15,7
 
import org.openconcerto.ui.EnhancedTable;
import org.openconcerto.ui.FormatEditor;
import org.openconcerto.ui.Log;
import org.openconcerto.ui.TimestampEditorPanel;
 
import java.awt.BorderLayout;
27,6 → 28,8
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.util.Calendar;
33,6 → 36,7
import java.util.Date;
import java.util.EventObject;
 
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
87,6 → 91,17
 
this.aPopup = new JPopupMenu();
this.aPopup.add(this.content);
// JPopupMenu is hidden by Swing if the user clicks outside of it, but we still need to
// commit the value
this.aPopup.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("visible") && Boolean.FALSE.equals(evt.getNewValue())) {
stopCellEditing();
}
}
});
 
this.popupOpen = true;
t.addMouseListener(new MouseAdapter() {
@Override
149,6 → 164,16
if (aPopup != null) {
try {
this.aPopup.show(c, p.x, p.y);
// if the user dismisses the popup (e.g. escape), revert the value
final String cancelName = "cancel";
if (this.aPopup.getRootPane().getActionMap().get(cancelName) == null)
Log.get().warning("missing cancel action, value won't be reverted");
this.aPopup.getRootPane().getActionMap().put(cancelName, new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
cancelCellEditing();
}
});
} catch (Exception e) {
// Se produit quand c n'est pas visible
System.err.println("cannot show popup : " + e.getMessage());
/trunk/OpenConcerto/src/org/openconcerto/ui/table/IconTableCellRenderer.java
65,6 → 65,10
}
 
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
if (value == null) {
// Bug remonté sur Linux
value = Integer.valueOf(0);
}
this.va = ((Integer) value).intValue();
final JImage image = this.images.get(this.va);
return image;
/trunk/OpenConcerto/src/org/openconcerto/ui/component/ITextCombo.java
335,7 → 335,7
if (!this.completing) {
this.completing = true;
// ne completer que si le texte fait plus de 2 char et n'est pas que des chiffres
if (originalText.length() > 2 && !DIGIT_PATTERN.matcher(originalText).matches()) {
if (canComplete(originalText)) {
String completion = this.getCompletion(originalText);
if (completion != null && !originalText.trim().equalsIgnoreCase(completion.trim())) {
fb.replace(0, fb.getDocument().getLength(), completion, null);
351,6 → 351,15
}
 
/**
* hook to activate or not complete for a given text
*
* @return true if completion must occur
*/
public boolean canComplete(final String originalText) {
return originalText.length() > 2 && !DIGIT_PATTERN.matcher(originalText).matches();
}
 
/**
* Recherche si on peut completer la string avec les items de completion
*
* @param string the start
569,8 → 578,16
 
public String getCurrentValue() {
// this.getSelectedItem() renvoie vide quand on tape du texte sans sélection
return (String) (this.isLocked() ? this.getSelectedItem() : this.getEditor().getItem());
final Object res;
if (this.isLocked()) {
res = this.getSelectedItem();
} else {
final ComboBoxEditor editor = this.getEditor();
// as documented in the constructor, the editor can sometimes be null
res = editor == null ? null : editor.getItem();
}
return (String) res;
}
 
public JComponent getComp() {
return this;
/trunk/OpenConcerto/src/org/openconcerto/ui/component/combo/ISearchableCombo.java
681,7 → 681,15
this.iconTransf = t;
}
 
protected T stringToT(final String t) {
/**
* Parse the passed string.
*
* @param t the string to parse.
* @return the parsed value.
* @throws IllegalArgumentException if <code>t</code> cannot be parsed.
* @see java.lang.Integer#parseInt(String)
*/
protected T stringToT(final String t) throws IllegalArgumentException {
throw new IllegalStateException("use " + ISearchableTextCombo.class);
}
 
/trunk/OpenConcerto/src/org/openconcerto/ui/component/combo/ISearchableComboCompletionThread.java
14,7 → 14,6
package org.openconcerto.ui.component.combo;
 
import org.openconcerto.ui.component.combo.SearchMode.ComboMatcher;
import org.openconcerto.utils.IFutureTask;
import org.openconcerto.utils.RTInterruptedException;
import org.openconcerto.utils.model.IListModel;
import org.openconcerto.utils.model.ISearchable;
22,10 → 21,12
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
 
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
 
public class ISearchableComboCompletionThread<T> extends SwingWorker<List<ISearchableComboItem<T>>, Object> {
38,7 → 39,7
public ISearchableComboCompletionThread(final ISearchableCombo<T> combo, final String t) {
this.combo = combo;
this.sourceModel = combo.getCache();
this.toProcess = new ArrayList<>(combo.getModelValues());
this.toProcess = this.getModelValues();
this.t = t;
this.maxResults = this.getCombo().getMaximumResult();
}
47,6 → 48,11
return this.combo;
}
 
private final List<ISearchableComboItem<T>> getModelValues() {
assert SwingUtilities.isEventDispatchThread();
return new ArrayList<>(this.getCombo().getModelValues());
}
 
private final boolean isShowAll() {
return this.t == null;
}
99,6 → 105,7
// true : search changed
// false : search didn't change
Boolean searched = null;
List<ISearchableComboItem<T>> cache = this.toProcess;
// If there was a search and now the text is below minimum, we must unset the search
// Efficient since setSearch() only carry out its action if the search changes
if (this.sourceModel instanceof ISearchable) {
105,10 → 112,15
final ISearchable searchableListModel = (ISearchable) this.sourceModel;
if (searchableListModel.isSearchable()) {
// Wait for the new values, which will be added to the model by a listener
final FutureTask<Object> noOp = IFutureTask.createNoOp();
searched = searchableListModel.setSearch(normalizedText, noOp);
final FutureTask<List<ISearchableComboItem<T>>> searchedValues = new FutureTask<>(new Callable<List<ISearchableComboItem<T>>>() {
@Override
public List<ISearchableComboItem<T>> call() throws Exception {
return getModelValues();
}
});
searched = searchableListModel.setSearch(normalizedText, searchedValues);
try {
noOp.get();
cache = searchedValues.get();
} catch (InterruptedException e) {
throw new RTInterruptedException(e);
} catch (ExecutionException e) {
117,7 → 129,6
}
}
if (!normalizedText.isEmpty() && searched != Boolean.FALSE) {
final List<ISearchableComboItem<T>> cache = this.toProcess;
// don't filter twice
final ComboMatcher search = Boolean.TRUE.equals(searched) ? null : getCombo().getCompletionMode().matcher(normalizedText.toLowerCase());
final int maximumResult = this.maxResults;
/trunk/OpenConcerto/src/org/openconcerto/sql/view/IListPanel.java
240,7 → 240,8
private EditFrame listeningFrame = null;
 
private final EditFrame createFrame(final boolean listening) {
final EditFrame res = new EditFrame(getElement(), EditPanel.READONLY);
Boolean rw = Boolean.getBoolean("org.openconcerto.sql.listPanel.rwOnDoubleClick");
final EditFrame res = new EditFrame(getElement(), !rw ? EditPanel.READONLY : EditPanel.MODIFICATION);
if (listening)
getListe().addIListener(res);
res.selectionId(getListe().getSelectedId());
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/RowValuesTableControlPanel.java
13,11 → 13,11
package org.openconcerto.sql.view.list;
 
import org.openconcerto.sql.TM;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.view.IListFrame;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.JComponentUtils;
import org.openconcerto.sql.TM;
 
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
198,6 → 198,10
this.model.addRow(rowValsBis);
}
 
public void setButtonAjouterEnabled(boolean b) {
this.buttonAjouter.setEnabled(b);
}
 
public void setVisibleButtonClone(boolean b) {
this.buttonClone.setVisible(b);
}
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/SQLTableElement.java
26,6 → 26,7
import org.openconcerto.ui.TextAreaTableCellEditor;
import org.openconcerto.ui.table.TimestampTableCellEditor;
import org.openconcerto.utils.CompareUtils;
import org.openconcerto.utils.StringUtils;
 
import java.awt.event.ActionEvent;
import java.sql.Timestamp;
132,6 → 133,9
this.field = field;
 
this.name = Configuration.getInstance().getTranslator().getTitleFor(field);
if (name == null || name.trim().length() == 0) {
this.name = StringUtils.firstUp(field.getName().toLowerCase());
}
this.isEditable = (field != null);
}
 
200,9 → 204,11
if (this.field.getType().getJavaType() == String.class) {
final TextAreaTableCellEditor textEditor = new TextAreaTableCellEditor(table);
textEditor.setLimitedSize(this.field.getType().getSize());
this.editor = textEditor;
return textEditor;
} else if (this.field.getType().getJavaType() == Timestamp.class) {
final TimestampTableCellEditor textEditor = new TimestampTableCellEditor(false);
this.editor = textEditor;
return textEditor;
}
}
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/RowValuesTable.java
23,24 → 23,20
import org.openconcerto.sql.view.IListPanel;
import org.openconcerto.ui.EnhancedTable;
import org.openconcerto.ui.component.InteractionMode;
import org.openconcerto.ui.date.DateRangeTable;
import org.openconcerto.ui.state.JTableStateManager;
import org.openconcerto.ui.table.AlternateTableCellRenderer;
import org.openconcerto.ui.table.FocusAwareEditor;
import org.openconcerto.ui.table.XTableColumnModel;
import org.openconcerto.utils.checks.EmptyListener;
import org.openconcerto.utils.checks.ValidListener;
import org.openconcerto.utils.checks.ValidState;
 
import java.applet.Applet;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
53,7 → 49,6
import javax.swing.JComponent;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
import javax.swing.event.TableModelEvent;
145,38 → 140,8
}
});
 
/**
* En remplacement de : this.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
*
* Arret de l'edition si la table perd le focus La perte de focus est ignorée sur le
* CellEditor gère lui même la perte de focus (FocusAwareEditor)
*
*/
final KeyboardFocusManager focusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener() {
 
@Override
public void propertyChange(PropertyChangeEvent evt) {
 
Component c = focusManager.getPermanentFocusOwner();
while (c != null) {
if (c == RowValuesTable.this) {
// focus remains inside the table
return;
} else if ((c instanceof Window) || (c instanceof Applet && c.getParent() == null)) {
if (c == SwingUtilities.getRoot(RowValuesTable.this)) {
if (getCellEditor() != null && !(getCellEditor() instanceof FocusAwareEditor))
if (!getCellEditor().stopCellEditing()) {
getCellEditor().cancelCellEditing();
DateRangeTable.fixEditorFocus(this);
}
}
break;
}
c = c.getParent();
}
}
});
}
 
@Override
public void paint(Graphics g) {
/trunk/OpenConcerto/src/org/openconcerto/sql/PropsConfiguration.java
37,11 → 37,15
import org.openconcerto.utils.ProductInfo;
import org.openconcerto.utils.RTInterruptedException;
import org.openconcerto.utils.StreamUtils;
import org.openconcerto.utils.Tuple2;
import org.openconcerto.utils.Value;
import org.openconcerto.utils.cc.IClosure;
import org.openconcerto.utils.cc.IPredicate;
import org.openconcerto.utils.i18n.TranslationManager;
 
import java.awt.Dialog.ModalityType;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
76,6 → 80,11
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
 
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
 
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
 
210,7 → 219,9
@GuardedBy("treeLock")
private Session conn;
@GuardedBy("treeLock")
private boolean isUsingSSH;
private int tunnelLocalPort = -1;
@GuardedBy("treeLock")
private Thread sslThread;
 
private FieldMapper fieldMapper;
 
436,10 → 447,16
 
public final boolean isUsingSSH() {
synchronized (this.treeLock) {
return this.isUsingSSH;
return this.sslThread != null;
}
}
 
public final int getTunnelLocalPort() {
synchronized (this.treeLock) {
return this.tunnelLocalPort;
}
}
 
public final boolean hasWANProperties() {
final String wanAddr = getProperty("server.wan.addr");
final String wanPort = getProperty("server.wan.port");
456,21 → 473,17
if (!hasWANProperties(wanAddr, wanPort))
return doCreateServer();
 
final String serverPropVal = getProperty("server.ip");
// TODO add and use server.port
final List<String> serverAndPort = Arrays.asList(serverPropVal.split(":"));
if (serverAndPort.size() != 2)
throw new IllegalStateException("Not in 'host:port' format : " + serverPropVal);
final Tuple2<String, Integer> serverAndPort = parseServerAddressAndPort();
final String serverAndPortString = serverAndPort.get0() + ":" + serverAndPort.get1();
 
// if wanAddr is specified, always include it in ID, that way if we connect through the LAN
// or through the WAN we have the same ID
final String serverID = "tunnel to " + wanAddr + ":" + wanPort + " then " + serverPropVal;
final String serverID = "tunnel to " + wanAddr + ":" + wanPort + " then " + serverAndPortString;
final Logger log = Log.get();
Exception origExn = null;
final SQLServer defaultServer;
if (!"true".equals(getProperty("server.wan.only"))) {
try {
defaultServer = doCreateServer(serverID);
final SQLServer defaultServer = doCreateServer(serverAndPortString, null, serverID);
// works since all ds params are provided by doCreateServer()
defaultServer.getSystemRoot(getSystemRootName());
// ok
484,27 → 497,64
}
assert origExn != null;
}
this.openSSLConnection(wanAddr, Integer.valueOf(wanPort));
this.isUsingSSH = true;
log.info("ssl connection to " + this.conn.getHost() + ":" + this.conn.getPort());
final int localPort = NetUtils.findFreePort(5436);
final SQLServer serverThruSSL;
try {
log.info("ssl tunnel from local port " + localPort + " to remote " + serverAndPort);
this.conn.setPortForwardingL(localPort, serverAndPort.get(0), Integer.valueOf(serverAndPort.get(1)));
} catch (final Exception e1) {
throw new IllegalStateException("Impossible de créer la liaison sécurisée. Vérifier que le logiciel n'est pas déjà lancé.", e1);
}
final SQLServer serverThruSSL = doCreateServer("localhost:" + localPort, null, serverID);
try {
log.info("Connecting with SSL to " + wanAddr + ":" + wanPort);
this.openSSLConnection(wanAddr, Integer.valueOf(wanPort), serverAndPort.get0(), serverAndPort.get1());
serverThruSSL = doCreateServer("localhost:" + this.tunnelLocalPort, null, serverID);
serverThruSSL.getSystemRoot(getSystemRootName());
} catch (final Exception e) {
// even if the tunnel was set up successfully, close it if the SQLServer couldn't be
// created, that way the next time createServer() is called, we can start again the
// whole process (e.g. checking properties, retrying non-WAN server) without having to
// worry about a lingering tunnel.
this.closeSSLConnection();
throw new IllegalStateException("Couldn't connect through SSL : " + e.getLocalizedMessage(), origExn);
// no datasource will remain that uses the port, so forget about it and find a new one
// the next time
this.tunnelLocalPort = -1;
final IllegalStateException exn = new IllegalStateException("Couldn't connect to the DB through SSL", e);
if (origExn != null)
exn.addSuppressed(origExn);
throw exn;
}
return serverThruSSL;
 
}
 
// TODO add and use server.port
public final Tuple2<String, Integer> parseServerAddressAndPort() {
final String serverPropVal = getProperty("server.ip");
final List<String> serverAndPort = Arrays.asList(serverPropVal.split(":"));
if (serverAndPort.size() != 2)
throw new IllegalStateException("Not in 'host:port' format : " + serverPropVal);
return Tuple2.create(serverAndPort.get(0), Integer.valueOf(serverAndPort.get(1)));
}
 
protected final void reconnectSSL() throws Exception {
synchronized (this.treeLock) {
// already destroyed or still OK
if (this.conn == null || this.conn.isConnected())
return;
 
Log.get().log(Level.WARNING, "SSL disconnected, trying to reconnect");
 
final String wanAddr = getProperty("server.wan.addr");
final String wanPort = getProperty("server.wan.port");
final Tuple2<String, Integer> serverAndPort = parseServerAddressAndPort();
 
try {
// cannot just call connect() again, as Session is one-time use
// http://flyingjxswithjava.blogspot.fr/2015/03/comjcraftjschjschexception-packet.html
this.openSSLConnection(wanAddr, Integer.valueOf(wanPort), serverAndPort.get0(), serverAndPort.get1());
Log.get().log(Level.WARNING, "SSL successfully reconnected to " + this.conn.getHost() + ":" + this.conn.getPort());
} catch (Exception e) {
// don't leave an SSL connection without a tunnel
this.conn.disconnect();
throw e;
}
}
}
 
private SQLServer doCreateServer() {
return doCreateServer(null);
}
533,10 → 583,11
return res;
}
 
private void openSSLConnection(final String addr, final int port) {
private void openSSLConnection(final String addr, final int port, final String tunnelRemoteHost, final int tunnelRemotePort) {
checkDestroyed();
final String username = getSSLUserName();
final String pass = getSSLPassword();
final boolean reconnect = this.tunnelLocalPort > 0;
boolean isAuthenticated = false;
 
final JSch jsch = new JSch();
563,10 → 614,54
config.put("compression.c2s", "zlib@openssh.com,zlib,none");
this.conn.setConfig(config);
// wait no more than 6 seconds for TCP connection
this.conn.connect(6000);
this.conn.setTimeout(6000);
// ATTN for now this just calls setTimeout()
this.conn.setServerAliveInterval(6000);
this.conn.setServerAliveCountMax(1);
this.conn.connect();
 
afterSSLConnect(this.conn);
 
isAuthenticated = true;
 
// keep same local port so that we don't have to change the datasource
final int localPort = reconnect ? this.tunnelLocalPort : NetUtils.findFreePort(5436);
try {
Log.get().info("Creating SSL tunnel from local port " + localPort + " to remote " + tunnelRemoteHost + ":" + tunnelRemotePort);
this.conn.setPortForwardingL(localPort, tunnelRemoteHost, tunnelRemotePort);
} catch (final Exception e1) {
throw new IllegalStateException("Impossible de créer le tunnel sécurisé", e1);
}
assert reconnect == (this.sslThread != null);
if (!reconnect) {
this.tunnelLocalPort = localPort;
// With ServerAliveInterval & ServerAliveCount, the connection should disconnect
// itself in case of network failure, so we try to reconnect it
final Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(2000);
try {
reconnectSSL();
} catch (Exception e) {
// re-try later
Log.get().log(Level.WARNING, "Error while checking SSL connection", e);
}
} catch (InterruptedException e) {
// used by destroy()
break;
}
}
}
});
t.setDaemon(true);
t.setName("SSL connection watcher");
t.start();
this.sslThread = t;
}
assert this.sslThread != null;
} catch (final Exception e) {
throw new IllegalStateException("Connection failed", e);
}
587,6 → 682,10
 
private void closeSSLConnection() {
synchronized (this.treeLock) {
if (this.sslThread != null) {
this.sslThread.interrupt();
this.sslThread = null;
}
if (this.conn != null) {
this.conn.disconnect();
this.conn = null;
1077,6 → 1176,70
}
}
 
public final Thread createDBCheckThread(final JFrame mainFrame, final Runnable quitRunnable) {
final DBSystemRoot sysRoot = this.getSystemRoot();
final String quit = "Quitter le logiciel";
final JOptionPane optionPane = new JOptionPane("Impossible de contacter la base. Cette fenêtre se fermera dès le rétablissement de la connexion. Sinon vous pouvez quitter le logiciel.",
JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE, null, new Object[] { quit }, null);
final JDialog dialog = optionPane.createDialog(mainFrame, "Erreur de connexion");
dialog.setModalityType(ModalityType.APPLICATION_MODAL);
// can only be closed by us (if connection is restored) or by choosing quit
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.addComponentListener(new ComponentAdapter() {
@Override
public void componentHidden(ComponentEvent e) {
if (optionPane.getValue().equals(quit))
quitRunnable.run();
else
// only the thread can change the dialog, otherwise pb would be incoherent
dialog.setVisible(true);
}
});
dialog.pack();
final Thread dbConn = new Thread(new Runnable() {
@Override
public void run() {
boolean pb = false;
while (true) {
try {
Thread.sleep((pb ? 4 : 20) * 1000);
} catch (InterruptedException e1) {
// ignore
e1.printStackTrace();
}
try {
sysRoot.getDataSource().validateDBConnectivity();
if (pb) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// don't use setVisible(false) otherwise
// componentHidden() will be called
dialog.dispose();
}
});
pb = false;
}
} catch (Exception e) {
if (!pb) {
pb = true;
e.printStackTrace();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
dialog.setLocationRelativeTo(dialog.getOwner());
dialog.setVisible(true);
}
});
}
}
}
}
}, "databaseConnectivity");
dbConn.setDaemon(true);
return dbConn;
}
 
/**
* Get the node of the asked class, creating just the necessary instances (ie getNode(Server)
* won't do a getBase().getServer()).
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/SoftwareInfoPanel.java
25,6 → 25,7
import org.openconcerto.utils.BaseDirs;
import org.openconcerto.utils.ProductInfo;
import org.openconcerto.utils.SystemInfo;
import org.openconcerto.utils.Tuple2;
import org.openconcerto.utils.cc.IFactory;
import org.openconcerto.utils.i18n.I18nUtils;
 
86,7 → 87,8
res.put(Info.APP_NAME, name);
res.put(Info.APP_VERSION, version);
if (propsConf != null && propsConf.isUsingSSH()) {
res.put(Info.SECURE_LINK, propsConf.getWanHostAndPort());
final Tuple2<String, Integer> serverAddressAndPort = propsConf.parseServerAddressAndPort();
res.put(Info.SECURE_LINK, "localhost:" + propsConf.getTunnelLocalPort() + " ⟷ (" + propsConf.getWanHostAndPort() + ") " + serverAddressAndPort.get0() + ":" + serverAddressAndPort.get1());
}
if (conf != null)
res.put(Info.DB_URL, conf.getSystemRoot().getDataSource().getUrl());
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/GroupToLightUIConvertor.java
77,7 → 77,7
}
 
final LightEditFrame editFrame = new LightEditFrame(this.configuration, group, defaultRow.asRowValues(), parentFrame, editMode);
final LightUIPanel framePanel = editFrame.getFirstChild(LightUIPanel.class);
final LightUIPanel framePanel = editFrame.getContentPanel();
append(sqlElement, framePanel, group);
 
String frameTitle = TranslationManager.getInstance().getTranslationForItem(group.getId());
/trunk/OpenConcerto/src/org/openconcerto/sql/element/JoinSQLElement.java
166,7 → 166,7
 
@Override
protected DBRoot getOwnerRoot() {
return this.ownedT.getDBRoot();
return this.ownerT.getDBRoot();
}
 
@Override
202,7 → 202,7
 
@Override
protected DBRoot getOwnerRoot() {
return this.ownedT.getRoot();
return this.ownerT.getRoot();
}
 
@Override
/trunk/OpenConcerto/src/org/openconcerto/sql/element/SQLElement.java
336,10 → 336,10
editFrame.createTitlePanel(this.getCreationFrameTitle());
} else if (editMode.equals(EditMode.MODIFICATION)) {
editFrame.createTitlePanel(this.getModificationFrameTitle(sqlRow));
new LightUIPanelFiller(editFrame.getFirstChild(LightUIPanel.class)).fillFromRow(configuration, sqlRow);
new LightUIPanelFiller(editFrame.getContentPanel()).fillFromRow(configuration, sqlRow);
} else if (editMode.equals(EditMode.READONLY)) {
editFrame.createTitlePanel(this.getReadOnlyFrameTitle(sqlRow));
new LightUIPanelFiller(editFrame.getFirstChild(LightUIPanel.class)).fillFromRow(configuration, sqlRow);
new LightUIPanelFiller(editFrame.getContentPanel()).fillFromRow(configuration, sqlRow);
}
 
this.setEditFrameModifiers(editFrame, sessionSecurityToken);
/trunk/OpenConcerto/src/org/openconcerto/sql/model/Where.java
115,6 → 115,31
return new Where(ref, "is not", (Object) null);
}
 
static public Where between(final FieldRef ref, final FieldRef lowerBound, final FieldRef upperBound) {
return Where.createRaw(ref.getFieldRef() + " BETWEEN " + lowerBound.getFieldRef() + " AND " + upperBound.getFieldRef(), ref, lowerBound, upperBound);
}
 
static public Where inSubqueries(final FieldRef ref, final List<String> subQueries) {
return subqueries(ref, true, subQueries);
}
 
static public Where notInSubqueries(final FieldRef ref, final List<String> subQueries) {
return subqueries(ref, false, subQueries);
}
 
/**
* Create a Where for a field value contained or not contained in sub-queries.
*
* @param ref the field.
* @param in <code>true</code> if the field should be contained in the sub-queries.
* @param subQueries the sub-queries to use.
* @return a new Where.
* @see Where#Where(FieldRef, boolean, SQLSelect)
*/
static public Where subqueries(final FieldRef ref, final boolean in, final List<String> subQueries) {
return createRaw(getInClause(ref, in, CollectionUtils.join(subQueries, "\nUNION\n")), ref);
}
 
static public Where createRaw(final String clause, final FieldRef... refs) {
return createRaw(clause, Arrays.asList(refs));
}
/trunk/OpenConcerto/src/org/openconcerto/sql/model/AliasedField.java
20,6 → 20,17
*/
public class AliasedField implements FieldRef {
 
// only create instance if needed
static public FieldRef getFieldRef(final SQLField f, final String alias) {
return alias == null || alias.equals(f.getTable().getName()) ? f : new AliasedField(f, alias);
}
 
static public FieldRef getFieldRef(final SQLField f, final TableRef t) {
if (t.getTable() != f.getTable())
throw new IllegalArgumentException("Table mismatch");
return getFieldRef(f, t.getAlias());
}
 
private final TableRef t;
private final SQLField f;
 
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLSyntaxPG.java
515,7 → 515,8
private final int getIndex(Map<String, Object> o) {
final int colNum = ((Number) o.get("colNum")).intValue();
try {
final Integer[] array = (Integer[]) ((Array) o.get("colsNum")).getArray();
// Integer for driver version 9, Short for version 42
final Number[] array = (Number[]) ((Array) o.get("colsNum")).getArray();
for (int i = 0; i < array.length; i++) {
if (array[i].intValue() == colNum)
return i;
/trunk/OpenConcerto/src/org/openconcerto/utils/SystemInfo.java
15,6 → 15,7
 
import static org.openconcerto.utils.CollectionUtils.join;
import static java.lang.System.getProperty;
 
import org.openconcerto.utils.cc.ITransformer;
import org.openconcerto.utils.i18n.TM;
 
26,9 → 27,9
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Formatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.TreeMap;
 
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
46,8 → 47,8
 
public static final String CLASS_PROTOCOL = "class";
 
static public Map<Info, String> get(final boolean html) {
final Map<Info, String> res = new HashMap<Info, String>(Info.values().length);
static public NavigableMap<Info, String> get(final boolean html) {
final NavigableMap<Info, String> res = new TreeMap<Info, String>();
 
final String lineBreak = getLineBreak(html);
 
76,8 → 77,7
res.put(Info.OS, "<b>" + getProperty("os.name") + "</b> " + getProperty("os.version") + " (" + getProperty("os.arch") + ")");
 
// * Sylvain ; C:\Documents and Settings\Sylvain ; D:\workspace\CTech
res.put(Info.USER,
getProperty("user.name") + " ; " + getLink(TM.tr("home.dir"), new File(getProperty("user.home")).toURI(), html) + " ; "
res.put(Info.USER, getProperty("user.name") + " ; " + getLink(TM.tr("home.dir"), new File(getProperty("user.home")).toURI(), html) + " ; "
+ getLink(TM.tr("cwd"), new File(getProperty("user.dir")).toURI(), html));
 
// * eth0 192.168.28.52/24, état: inactif, nom complet: ""
/trunk/OpenConcerto/src/org/openconcerto/utils/FileUtils.java
403,10 → 403,7
* @throws IOException if an error occurs.
*/
public static void copyFile(File in, File out, long maxCount) throws IOException {
final FileInputStream sourceIn = new FileInputStream(in);
FileOutputStream sourceOut = null;
try {
sourceOut = new FileOutputStream(out);
try (final FileInputStream sourceIn = new FileInputStream(in); final FileOutputStream sourceOut = new FileOutputStream(out);) {
final FileChannel sourceChannel = sourceIn.getChannel();
final long size = sourceChannel.size();
if (maxCount == 0)
416,10 → 413,6
while (position < size) {
position += sourceChannel.transferTo(position, maxCount, destinationChannel);
}
} finally {
sourceIn.close();
if (sourceOut != null)
sourceOut.close();
}
}
 
679,16 → 672,9
}
 
public static void write(String s, File f, Charset charset, boolean append) throws IOException {
final FileOutputStream fileStream = new FileOutputStream(f, append);
final OutputStreamWriter out = charset == null ? new OutputStreamWriter(fileStream) : new OutputStreamWriter(fileStream, charset);
final BufferedWriter w = new BufferedWriter(out);
try {
try (final FileOutputStream fileStream = new FileOutputStream(f, append);
final BufferedWriter w = new BufferedWriter(charset == null ? new OutputStreamWriter(fileStream) : new OutputStreamWriter(fileStream, charset))) {
w.write(s);
} finally {
w.close();
// should have already been closed by the writer but the documentation is vague and
// there's no way to check
fileStream.close();
}
}
 
788,13 → 774,8
// perhaps a thread to delete the file after a certain amount of time
shortcutFile.deleteOnExit();
files.put(url, shortcutFile);
final InputStream stream = url.openStream();
final FileOutputStream out = new FileOutputStream(shortcutFile);
try {
try (final InputStream stream = url.openStream(); final FileOutputStream out = new FileOutputStream(shortcutFile);) {
StreamUtils.copy(stream, out);
} finally {
out.close();
stream.close();
}
} else
shortcutFile = currentFile;
860,9 → 841,10
}
try {
ps.getErrorStream().close();
final BufferedReader reader = new BufferedReader(new InputStreamReader(ps.getInputStream()));
final String res = reader.readLine();
reader.close();
final String res;
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(ps.getInputStream()));) {
res = reader.readLine();
}
if (ps.waitFor() != 0 || res == null || res.length() == 0)
return null;
else
/trunk/OpenConcerto/src/org/openconcerto/utils/PropertiesUtils.java
18,6 → 18,7
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
25,13 → 26,32
public class PropertiesUtils {
 
public static final Properties createFromMap(final Map<String, String> map) {
final Properties res = new Properties();
return loadFromMap(new Properties(), map);
}
 
public static final Properties loadFromMap(final Properties res, final Map<String, String> map) {
for (final Entry<String, String> e : map.entrySet()) {
res.setProperty(e.getKey(), e.getValue());
final String key = e.getKey();
if (key == null)
throw new NullPointerException("Null key : " + e);
final String val = e.getValue();
// Properties doesn't support nulls
if (val != null)
res.setProperty(key, val);
}
return res;
}
 
public static final Map<String, String> toMap(final Properties props) {
final Map<String, String> res = new HashMap<>();
for (final String key : props.stringPropertyNames()) {
final String value = props.getProperty(key);
assert value != null;
res.put(key, value);
}
return res;
}
 
public static final Properties createFromFile(final File f) throws IOException {
return create(new BufferedInputStream(new FileInputStream(f)));
}
/trunk/OpenConcerto/src/org/openconcerto/utils/prog/SVNUtils.java
16,6 → 16,8
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class SVNUtils {
 
47,4 → 49,23
return res;
}
 
// match placeholder $Rev$ fixed length $Rev:: $ and of course with value $Rev: 12 $
private static final Pattern KEYWORD_PATTERN = Pattern.compile("^\\$\\p{Alpha}+:{0,2}\\p{Blank}*(.*?)\\p{Blank}*\\$$");
 
/**
* Return the value of the svn keyword. E.g. use with
* <code>private static final String REV = getKeywordValue("$Rev$")</code> (don't forget to
* <code>svn propset svn:keywords</code>).
*
* @param substitute the svn substitute, e.g. "$Rev: 12 $".
* @return the value, empty string if none, e.g. "12".
* @throws IllegalArgumentException if substitute is not valid.
*/
public static String getKeywordValue(String substitute) throws IllegalArgumentException {
final Matcher matcher = KEYWORD_PATTERN.matcher(substitute);
if (!matcher.matches())
throw new IllegalArgumentException("SVN format not recognized");
 
return matcher.group(1);
}
}
/trunk/OpenConcerto/src/org/openconcerto/utils/ProductInfo.java
14,7 → 14,6
package org.openconcerto.utils;
 
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;
 
44,7 → 43,7
if (INSTANCE == null) {
try {
setInstance(createDefault());
} catch (IOException e) {
} catch (final IOException e) {
throw new IllegalStateException("unable to load default product properties", e);
}
}
56,7 → 55,7
*
* @param i the new instance, can be <code>null</code>.
*/
public synchronized static void setInstance(ProductInfo i) {
public synchronized static void setInstance(final ProductInfo i) {
INSTANCE = i;
}
 
82,13 → 81,17
private final Properties props;
 
public ProductInfo(final String name) {
this(name, "ILM Informatique", "fr.ilm-informatique");
this(name, null);
}
 
public ProductInfo(final String name, final String orgName, final String orgID) {
this(CollectionUtils.createMap(NAME, name, ORGANIZATION_NAME, orgName, ORGANIZATION_ID, orgID));
public ProductInfo(final String name, final String version) {
this(name, version, "ILM Informatique", "fr.ilm-informatique");
}
 
public ProductInfo(final String name, final String version, final String orgName, final String orgID) {
this(CollectionUtils.createMapFromList(NAME, name, VERSION, version, ORGANIZATION_NAME, orgName, ORGANIZATION_ID, orgID));
}
 
public ProductInfo(final Map<String, String> map) {
this(PropertiesUtils.createFromMap(map));
}
110,11 → 113,11
return this.props;
}
 
public final String getProperty(String name) {
public final String getProperty(final String name) {
return this.getProps().getProperty(name);
}
 
public final String getProperty(String name, String def) {
public final String getProperty(final String name, final String def) {
final String res = this.getProperty(name);
return StringUtils.isEmpty(res, true) ? def : res;
}
/trunk/OpenConcerto/src/org/openconcerto/utils/cc/IncludeExclude.java
28,6 → 28,7
* A class to specify which objects to include or exclude.
*
* @author Sylvain
* @param <T> type of items
* @see #isIncluded(Object)
*/
@Immutable
46,11 → 47,11
return (IncludeExclude<T>) FULL;
}
 
public static <T> IncludeExclude<T> getNormalized(Collection<? extends T> includes) {
public static <T> IncludeExclude<T> getNormalized(final Collection<? extends T> includes) {
return getNormalized(includes, Collections.<T> emptySet());
}
 
public static <T> IncludeExclude<T> getNormalized(Collection<? extends T> includes, Collection<? extends T> excludes) {
public static <T> IncludeExclude<T> getNormalized(final Collection<? extends T> includes, final Collection<? extends T> excludes) {
return new IncludeExclude<T>(includes, excludes).normal;
}
 
58,7 → 59,7
private final Set<T> excludes;
private final IncludeExclude<T> normal;
 
public IncludeExclude(Collection<? extends T> includes) {
public IncludeExclude(final Collection<? extends T> includes) {
this(includes, Collections.<T> emptySet());
}
 
68,20 → 69,27
* @param includes which objects to include, <code>null</code> meaning all.
* @param excludes which objects to exclude, <code>null</code> meaning all.
*/
public IncludeExclude(Collection<? extends T> includes, Collection<? extends T> excludes) {
public IncludeExclude(final Collection<? extends T> includes, final Collection<? extends T> excludes) {
this(includes, excludes, false);
}
 
private IncludeExclude(Collection<? extends T> includes, Collection<? extends T> excludes, final boolean isNormal) {
private IncludeExclude(final Collection<? extends T> includes, final Collection<? extends T> excludes, final boolean isNormal) {
this(includes == null ? null : Collections.unmodifiableSet(new HashSet<T>(includes)), excludes == null ? null : Collections.unmodifiableSet(new HashSet<T>(excludes)), false, isNormal);
}
 
private IncludeExclude(final Set<T> includes, final Set<T> excludes, final boolean areMutable, final boolean isNormal) {
super();
this.includes = includes == null ? null : Collections.unmodifiableSet(new HashSet<T>(includes));
this.excludes = excludes == null ? null : Collections.unmodifiableSet(new HashSet<T>(excludes));
// parameter just to overload constructor
if (areMutable)
throw new IllegalStateException();
this.includes = includes;
this.excludes = excludes;
this.normal = isNormal ? this : this.normalize();
assert this.normal.excludes.isEmpty() || this.normal.includes == null;
}
 
private final IncludeExclude<T> normalize() {
if (this.excludes == null)
if (this.excludes == null || (this.includes != null && this.includes.isEmpty()))
return getEmpty();
if (this.excludes.isEmpty() && this.includes == null)
return getFull();
109,6 → 117,53
return (this.normal.includes == null || this.normal.includes.contains(s)) && !this.normal.excludes.contains(s);
}
 
public final <S extends T> Collection<S> getExcluded(final Collection<S> items) {
if (this.areNoneIncluded(items))
return items;
else if (this.areAllIncluded(items))
return Collections.emptySet();
 
final Set<S> res = new HashSet<>(items);
// avoid checks of getIncluded()
res.removeAll(this.createIncluded(items));
return res;
}
 
public final <S extends T> Collection<S> getIncluded(final Collection<S> items) {
if (this.areAllIncluded(items))
return items;
else if (this.isNoneIncluded())
return Collections.emptySet();
else
return createIncluded(items);
}
 
private <S extends T> Collection<S> createIncluded(final Collection<S> items) {
final Set<S> res = new HashSet<>(items);
if (this.normal.includes != null)
res.retainAll(this.normal.includes);
res.removeAll(this.normal.excludes);
return res;
}
 
public final boolean areAllIncluded(final Collection<? extends T> items) {
if (this.isAllIncluded() || items.isEmpty())
return true;
else if (this.isNoneIncluded())
return false;
else
return (this.normal.includes == null || this.normal.includes.containsAll(items)) && Collections.disjoint(this.normal.excludes, items);
}
 
public final boolean areNoneIncluded(final Collection<? extends T> items) {
if (this.isNoneIncluded() || items.isEmpty())
return true;
else if (this.isAllIncluded())
return false;
else
return (this.normal.includes != null && Collections.disjoint(this.normal.includes, items)) || this.normal.excludes.containsAll(items);
}
 
/**
* Whether this includes all objects.
*
157,17 → 212,54
return ifNoSole;
}
 
public final IncludeExclude<T> include(final Collection<? extends T> items) {
if (this.areAllIncluded(items))
return this;
else if (this.excludes == null)
throw new IllegalStateException("Cannot include an item when excluding all");
 
Set<T> newIncludes;
if (this.includes == null || this.includes.containsAll(items)) {
newIncludes = this.includes;
} else {
newIncludes = new HashSet<>(this.includes);
newIncludes.addAll(items);
newIncludes = Collections.unmodifiableSet(newIncludes);
}
Set<T> newExcludes;
if (Collections.disjoint(this.excludes, items)) {
newExcludes = this.excludes;
} else {
newExcludes = new HashSet<>(this.excludes);
newExcludes.removeAll(items);
newExcludes = Collections.unmodifiableSet(newExcludes);
}
 
return new IncludeExclude<T>(newIncludes, newExcludes, false, false);
}
 
public final IncludeExclude<T> exclude(final Collection<? extends T> items) {
if (this.areNoneIncluded(items))
return this;
 
assert this.excludes != null : "!areNoneIncluded() but this.excludes == null";
Set<T> newExcludes = new HashSet<>(this.excludes);
newExcludes.addAll(items);
newExcludes = Collections.unmodifiableSet(newExcludes);
return new IncludeExclude<T>(this.includes, Collections.unmodifiableSet(newExcludes), false, false);
}
 
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((excludes == null) ? 0 : excludes.hashCode());
result = prime * result + ((includes == null) ? 0 : includes.hashCode());
result = prime * result + ((this.excludes == null) ? 0 : this.excludes.hashCode());
result = prime * result + ((this.includes == null) ? 0 : this.includes.hashCode());
return result;
}
 
@Override
public boolean equals(Object obj) {
public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
178,4 → 270,15
return CompareUtils.equals(this.includes, other.includes) && CompareUtils.equals(this.excludes, other.excludes);
}
 
@Override
public String toString() {
final String suffix;
if (this == FULL)
suffix = " ALL";
else if (this == EMPTY)
suffix = " NONE";
else
suffix = " includes " + this.includes + " except " + this.excludes;
return this.getClass().getSimpleName() + suffix;
}
}
/trunk/OpenConcerto/src/org/openconcerto/utils/CollectionUtils.java
912,6 → 912,23
return res;
}
 
@SafeVarargs
public static <T> Map<T, T> createMapFromList(final T... keyAndVal) {
return createMapFromList(Arrays.asList(keyAndVal));
}
 
public static <T> Map<T, T> createMapFromList(final List<T> keyAndVal) {
final int size = keyAndVal.size();
if (size % 2 != 0)
throw new IllegalArgumentException(size + " is not an even number of values : " + keyAndVal);
// arguments are ordered, so should the result
final Map<T, T> res = new LinkedHashMap<>(size);
for (int i = 0; i < size; i += 2) {
res.put(keyAndVal.get(i), keyAndVal.get(i + 1));
}
return res;
}
 
/**
* Creates a map with null values.
*
/trunk/OpenConcerto/src/org/openconcerto/utils/Value.java
145,6 → 145,19
public abstract V getValue() throws IllegalStateException;
 
/**
* Return the value if {@link #hasValue()}, otherwise the passed one, never throws an exception.
*
* @param def the default value.
* @return either {@link #getValue()} or <code>def</code>.
*/
public final V getValue(final V def) {
if (this.hasValue())
return this.getValue();
else
return def;
}
 
/**
* Return <code>null</code> if and only if this has no value.
*
* @return non <code>null</code> {@link #getValue()} if {@link #hasValue()}, otherwise
/trunk/OpenConcerto/src/org/openconcerto/utils/TimeUtils.java
368,4 → 368,34
cal.clear(Calendar.MILLISECOND);
return cal;
}
 
/**
* Whether 2 dates are in the same day.
*
* @param date1 the first date, it won't be modified (it will be {@link Calendar#clone()
* cloned}).
* @param date2 the second date.
* @return <code>true</code> if both dates are in the same day according to the passed calendar.
*/
static public final boolean isSameDay(final Calendar date1, final Date date2) {
return isSameDay((Calendar) date1.clone(), date1.getTime(), date2);
}
 
/**
* Whether 2 dates are in the same day.
*
* @param cal the calendar to use, it will be modified.
* @param date1 the first date.
* @param date2 the second date.
* @return <code>true</code> if both dates are in the same day according to the passed calendar.
*/
static public final boolean isSameDay(final Calendar cal, final Date date1, final Date date2) {
cal.setTime(date1);
TimeUtils.clearTime(cal);
final long day1 = cal.getTimeInMillis();
cal.setTime(date2);
TimeUtils.clearTime(cal);
final long day2 = cal.getTimeInMillis();
return day1 == day2;
}
}
/trunk/OpenConcerto/src/org/openconcerto/utils/EmailClient.java
37,7 → 37,7
public abstract class EmailClient {
 
public static enum EmailClientType {
Thunderbird, AppleMail, Outlook
Thunderbird, AppleMail, Outlook, XDG
}
 
private static EmailClient PREFERRED = null;
134,7 → 134,11
// see http://kb.mozillazine.org/Command_line_arguments_(Thunderbird)
// The escape mechanism isn't specified, it turns out we can pass percent encoded strings
private final static String getTBParam(final String to, final String subject, final String body, final File... attachments) {
// "to='john@example.com,kathy@example.com',cc='britney@example.com',subject='dinner',body='How about dinner tonight?',attachment='file:///C:/cygwin/Cygwin.bat,file:///C:/cygwin/Cygwin.ico'";
/**
* <pre>
"to='john@example.com,kathy@example.com',cc='britney@example.com',subject='dinner',body='How about dinner tonight?',attachment='file:///C:/cygwin/Cygwin.bat,file:///C:/cygwin/Cygwin.ico'";
* </pre>
*/
 
final List<String> l = new ArrayList<String>(4);
if (to != null)
277,15 → 281,19
return new ThunderbirdPath(exe);
}
} else if (de instanceof Gnome) {
if (de.getVersion().startsWith("2.")) {
// evolution %s
final String cmdLine = cmdSubstitution("gconftool", "-g", "/desktop/gnome/url-handlers/mailto/command");
if (cmdLine.contains("thunderbird")) {
return new ThunderbirdCommandLine(cmdLine, "%s");
}
}
return XDG;
} else if (de instanceof KDE) {
// TODO look for EmailClient=/usr/bin/thunderbird in
// ~/.kde/share/config/emaildefaults or /etc/kde (ou /usr/share/config qui est un
// lien symbolique vers /etc/kde)
return XDG;
}
 
return MailTo;
298,6 → 306,33
}
};
 
public static final EmailClient XDG = new EmailClient(EmailClientType.XDG) {
@Override
public boolean composeNative(String to, String subject, String body, File... attachments) throws IOException, InterruptedException {
final ProcessBuilder pb = new ProcessBuilder("xdg-email");
if (subject != null) {
pb.command().add("--subject");
pb.command().add(subject);
}
if (body != null) {
pb.command().add("--body");
pb.command().add(body);
}
for (File attachment : attachments) {
pb.command().add("--attach");
pb.command().add(attachment.getAbsolutePath());
}
pb.command().add(to);
pb.inheritIO();
final Process process = pb.start();
process.getOutputStream().close();
final int returnCode = process.waitFor();
if (returnCode != 0)
throw new IllegalStateException("Non zero return code: " + returnCode);
return true;
}
};
 
public static final EmailClient Outlook = new EmailClient(EmailClientType.Outlook) {
@Override
protected boolean composeNative(String to, String subject, String body, File... attachments) throws IOException, InterruptedException {
371,7 → 406,12
protected Thunderbird() {
super(EmailClientType.Thunderbird);
}
 
@Override
public String toString() {
return this.getClass().getSimpleName();
}
}
 
private static final class ThunderbirdCommandLine extends Thunderbird {
 
390,7 → 430,12
// (BTW return code of 1 means the program was already launched)
return true;
}
 
@Override
public String toString() {
return super.toString() + " " + this.cmdLine;
}
}
 
private static final class ThunderbirdPath extends Thunderbird {
 
406,7 → 451,12
Runtime.getRuntime().exec(new String[] { this.exe.getPath(), "-compose", composeArg });
return true;
}
 
@Override
public String toString() {
return super.toString() + " " + this.exe;
}
}
 
private final EmailClientType type;
 
420,6 → 470,12
 
protected abstract boolean composeNative(final String to, final String subject, final String body, final File... attachments) throws IOException, InterruptedException;
 
@Override
public String toString() {
final EmailClientType t = this.getType();
return t == null ? "mailto" : t.toString();
}
 
public final static void main(String[] args) throws Exception {
if (args.length == 1 && "--help".equals(args[0])) {
System.out.println("Usage: java [-Dparam=value] " + EmailClient.class.getName() + " [EmailClientType args]");
429,6 → 485,7
}
 
final EmailClient client = createFromString(args);
System.out.println("Using " + (args.length == 0 ? "preferred" : "passed") + " client : " + client);
final String to = System.getProperty("to", "Pierre Dupond <p.dupond@example.com>, p.dupont@server.com");
// ',to=' to test escaping of Thunderbird (passing subject='foo'bar' works)
final String subject = System.getProperty("subject", "Sujé € du courrier ',to='&;\\<> \"autre'\n2nd line");
451,6 → 508,8
 
final EmailClientType t = EmailClientType.valueOf(args[0]);
switch (t) {
case XDG:
return XDG;
case Outlook:
return Outlook;
case AppleMail:
/trunk/OpenConcerto/src/org/openconcerto/utils/StringUtils.java
789,4 → 789,35
return s;
return null;
}
 
public static String toAsciiString(String str) {
if (str == null) {
return null;
}
final int length = str.length();
final StringBuilder b = new StringBuilder(length);
for (int i = 0; i < length; i++) {
final char c = str.charAt(i);
final char newChar;
if (c < 128) {
newChar = c;
} else if (c == 'é' || c == 'è' || c == 'ê') {
newChar = 'e';
} else if (c == 'â' || c == 'à') {
newChar = 'a';
} else if (c == 'î') {
newChar = 'i';
} else if (c == 'ù' || c == 'û') {
newChar = 'u';
} else if (c == 'ô') {
newChar = 'o';
} else if (c == 'ç') {
newChar = 'c';
} else {
newChar = ' ';
}
b.append(newChar);
}
return b.toString();
}
}
/trunk/OpenConcerto/src/org/openconcerto/utils/io/MailAccount.java
39,6 → 39,27
}
 
/**
* Workaround for <code>ATT######.dat</code> attachments.
*
* @param props must currently be {@link System#getProperties()}.
*/
static public final void setEncodedParametersForOutlook(final Properties props) {
// don't use RFC 2231 for all parameters for 2 reasons :
// 1. Outlook (at least 2007) doesn't support it. Thunderbird seems to get around this by
// encoding the filename of Content-Disposition according to RFC 2231 and also encoding it
// in Content-Type using the old de facto standard.
// 2. Java Mail 1.6.0 doesn't always use Parameter Value Continuations (not for filenames :
// javax.mail.internet.MimeBodyPart.setFileName() uses ParameterList.Value which isn't
// split by toString())
// used in ParameterList.encodeParameters
props.setProperty("mail.mime.encodeparameters", "false");
// since we don't use RFC 2231, use the old de facto standard to have a charset specified
// somewhere.
// used in MimeBodyPart.encodeFileName
props.setProperty("mail.mime.encodefilename", "true");
}
 
/**
* Parse the given exception to a more human readable format.
*
* @param mex an exception.
/trunk/OpenConcerto/src/org/openconcerto/task/config/ComptaBasePropsConfiguration.java
31,11 → 31,9
import org.openconcerto.task.element.TaskSQLElement;
import org.openconcerto.utils.BaseDirs;
import org.openconcerto.utils.DesktopEnvironment;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.LogUtils;
import org.openconcerto.utils.ProductInfo;
 
import java.awt.GraphicsEnvironment;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
45,11 → 43,6
import java.util.Collections;
import java.util.Properties;
 
import javax.swing.JFrame;
import javax.swing.JOptionPane;
 
import com.jcraft.jsch.Session;
 
public abstract class ComptaBasePropsConfiguration extends PropsConfiguration {
 
public abstract void setUpSocieteDataBaseConnexion(int base);
104,7 → 97,6
private int idSociete = SQLRow.NONEXISTANT_ID;
private SQLRow rowSociete = null;
private DBRoot baseSociete;
private Thread sslThread = null;
 
{
// * logs
126,49 → 118,6
}
 
 
@Override
protected void afterSSLConnect(final Session conn) {
if (conn.isConnected()) {
final Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
if (!conn.isConnected()) {
if (!GraphicsEnvironment.isHeadless()) {
JOptionPane.showMessageDialog(null, "Liaison sécurisée déconnectée!\nVérifiez votre connexion internet et relancez le logiciel.");
} else {
ExceptionHandler.die("Liaison sécurisée déconnectée!\nVérifiez votre connexion internet et relancez le logiciel.");
}
break;
}
} catch (InterruptedException e) {
// used by destroy()
break;
}
}
}
});
t.setDaemon(true);
t.setName("SSL connection watcher");
t.start();
assert this.sslThread == null;
this.sslThread = t;
} else {
ExceptionHandler.die("Impossible d'établir la liaison sécurisée!\nVérifiez votre connexion internet et relancez le logiciel.");
}
}
 
@Override
public void destroy() {
if (this.sslThread != null) {
this.sslThread.interrupt();
this.sslThread = null;
}
super.destroy();
}
 
// use Configuration directory if it exists
@Override
protected FileMode getFileMode() {
/trunk/OpenConcerto/src/org/openconcerto/erp/core/reports/history/ui/ListeHistoriquePanel.java
20,6 → 20,7
import org.openconcerto.erp.core.finance.accounting.ui.SuppressionEcrituresPanel;
import org.openconcerto.erp.core.sales.invoice.report.VenteFactureElementXmlSheet;
import org.openconcerto.erp.core.sales.quote.ui.EtatDevisRenderer;
import org.openconcerto.erp.core.supplychain.order.action.ImportProductsToOrder;
import org.openconcerto.erp.generationDoc.AbstractSheetXml;
import org.openconcerto.erp.model.MouseSheetXmlListeListener;
import org.openconcerto.sql.Configuration;
41,20 → 42,31
import org.openconcerto.sql.view.IListPanel;
import org.openconcerto.sql.view.ListeAddPanel;
import org.openconcerto.sql.view.list.IListe;
import org.openconcerto.sql.view.list.IListeAction.IListeEvent;
import org.openconcerto.sql.view.list.ITableModel;
import org.openconcerto.sql.view.list.RowAction.PredicateRowAction;
import org.openconcerto.sql.view.list.SQLTableModelSourceOnline;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.FrameUtil;
import org.openconcerto.ui.SwingThreadUtils;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.cc.ITransformer;
 
import java.awt.Color;
import java.awt.Component;
import java.awt.FileDialog;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.math.BigInteger;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
64,6 → 76,7
import java.util.Set;
import java.util.Vector;
 
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
361,8 → 374,51
}
}
};
if (createTableSource.getPrimaryTable().getName().equals("DEMANDE_ACHAT_ELEMENT")) {
final ListeAddPanel listeDmd = (ListeAddPanel) liste;
PredicateRowAction actionDrop = new PredicateRowAction(new AbstractAction("Importer depuis Fichier Inventor") {
 
@Override
public void actionPerformed(ActionEvent e) {
final Frame frame = SwingThreadUtils.getAncestorOrSelf(Frame.class, (Component) e.getSource());
final FileDialog fd = new FileDialog(frame, "Import fichier inventor", FileDialog.LOAD);
fd.setFilenameFilter(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".xls");
}
});
fd.setVisible(true);
if (fd.getFile() != null) {
 
ImportProductsToOrder importer = new ImportProductsToOrder();
if (getSelectedRow() == null) {
JOptionPane.showMessageDialog(frame, "Import impossible! Aucune affaire sélectionnée.");
} else {
int a = JOptionPane.showConfirmDialog(frame,
"Etes vous sûr de vouloir importer ces éléments dans l'affaire N°" + getSelectedRow().getString("NUMERO") + "?", "Import invertor",
JOptionPane.YES_NO_OPTION);
if (a == JOptionPane.YES_OPTION) {
importer.setRowAffaire(getSelectedRow());
importer.setRowFamille(sqlRow);
try {
importer.importFile(new File(fd.getDirectory(), fd.getFile()), createTableSource.getPrimaryTable().getDBRoot());
listeDmd.getListe().getModel().updateAll();
} catch (IOException e1) {
ExceptionHandler.handle("Erreur lors de l'import du fichier!", e1);
} catch (SQLException e1) {
ExceptionHandler.handle("Erreur lors de l'import du fichier!", e1);
}
}
}
}
}
}, true);
actionDrop.setPredicate(IListeEvent.createSelectionCountPredicate(0, Integer.MAX_VALUE));
liste.getListe().addIListeAction(actionDrop);
}
}
 
this.vectListePanel.add(liste);
 
setRenderer(liste);
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/supplier/component/FournisseurSQLComponent.java
321,8 → 321,9
 
// Contact
JPanel panelContact = new JPanel(new GridBagLayout());
 
panelContact.setOpaque(false);
this.table = new ContactItemTable(this.defaultContactRowVals);
this.table.setOpaque(false);
this.table.setPreferredSize(new Dimension(this.table.getSize().width, 150));
GridBagConstraints cContact = new DefaultGridBagConstraints();
cContact.fill = GridBagConstraints.BOTH;
332,14 → 333,14
tabbedPane.add("Contacts", panelContact);
c.gridx = 0;
c.gridy++;
c.anchor = GridBagConstraints.WEST;
c.anchor = GridBagConstraints.NORTHWEST;
c.fill = GridBagConstraints.BOTH;
c.gridwidth = GridBagConstraints.REMAINDER;
this.add(tabbedPane, c);
 
// Mode de régelement
// Mode de réglement
TitledSeparator reglSep = new TitledSeparator(getLabelFor("ID_MODE_REGLEMENT"));
c.gridwidth = GridBagConstraints.REMAINDER;
c.gridwidth = 2;
c.gridy++;
c.gridx = 0;
this.add(reglSep, c);
351,6 → 352,48
ElementSQLObject eltModeRegl = (ElementSQLObject) this.getView("ID_MODE_REGLEMENT");
this.add(eltModeRegl, c);
 
//
{
c.gridx = 2;
c.gridy--;
c.gridwidth = 2;
c.fill = GridBagConstraints.BOTH;
TitledSeparator ribSep = new TitledSeparator("Coordonnées bancaires");
 
this.add(ribSep, c);
 
final JPanel pCoordonneesBancaires = new JPanel();
pCoordonneesBancaires.setLayout(new GridBagLayout());
GridBagConstraints c2 = new DefaultGridBagConstraints();
 
c2.gridy++;
// IBAN
JLabel labelIBAN = new JLabel("IBAN", SwingConstants.RIGHT);
JTextField textIBAN = new JTextField(40);
c2.weightx = 0;
pCoordonneesBancaires.add(labelIBAN, c2);
c2.gridx++;
c2.weightx = 1;
pCoordonneesBancaires.add(textIBAN, c2);
 
// BIC
JLabel labelBIC = new JLabel("BIC", SwingConstants.RIGHT);
JTextField textBIC = new JTextField(12);
c2.gridx = 0;
c2.gridy++;
c2.weightx = 0;
pCoordonneesBancaires.add(labelBIC, c2);
c2.gridx++;
c2.weightx = 1;
c2.fill = GridBagConstraints.NONE;
pCoordonneesBancaires.add(textBIC, c2);
c.gridy++;
c.fill = GridBagConstraints.HORIZONTAL;
this.add(pCoordonneesBancaires, c);
 
this.addView(textIBAN, "IBAN");
this.addView(textBIC, "BIC");
}
// Compte associé
 
c.gridx = 0;
379,8 → 422,6
panel.add(compteSelCharge, c2);
addView(compteSelCharge, "ID_COMPTE_PCE_CHARGE");
 
 
 
c.gridwidth = GridBagConstraints.REMAINDER;
c.gridy++;
c.gridx = 0;
388,6 → 429,12
c.anchor = GridBagConstraints.NORTHWEST;
this.add(panel, c);
 
c.gridwidth = 1;
c.gridy++;
c.gridx = 0;
c.weightx = 1;
c.anchor = GridBagConstraints.NORTHWEST;
 
// INfos
c.gridx = 0;
c.gridy++;
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/element/DemandeAchatItemSQLElement.java
18,26 → 18,25
 
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.common.element.StyleSQLElement;
import org.openconcerto.erp.core.common.ui.DeviseTableCellRenderer;
import org.openconcerto.erp.core.finance.tax.model.TaxeCache;
import org.openconcerto.erp.core.sales.product.element.ReferenceArticleSQLElement;
import org.openconcerto.erp.core.supplychain.order.ui.EtatDemandeAchatRenderer;
import org.openconcerto.sql.element.SQLComponent;
import org.openconcerto.sql.model.FieldPath;
import org.openconcerto.sql.model.SQLInjector;
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.SQLSelect;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.model.graph.Path;
import org.openconcerto.sql.view.EditFrame;
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.RowAction.PredicateRowAction;
import org.openconcerto.sql.view.list.SQLTableModelSource;
import org.openconcerto.ui.FrameUtil;
import org.openconcerto.utils.CollectionUtils;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.ListMap;
import org.openconcerto.utils.cc.ITransformer;
50,7 → 49,6
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Set;
 
import javax.swing.AbstractAction;
 
58,7 → 56,37
 
public DemandeAchatItemSQLElement() {
super("DEMANDE_ACHAT_ELEMENT", "une demande d'achat", "demandes d'achat");
{
PredicateRowAction actionP = new PredicateRowAction(new AbstractAction("Créer à partir de") {
 
@Override
public void actionPerformed(ActionEvent e) {
SQLRow row = IListe.get(e).getSelectedRow().asRow();
SQLRowValues rowDupl = new SQLRowValues(row.getTable());
List<String> copyFields = Arrays.asList("COLOR", "NUMERO_SE", "DESCRIPTIF_SE", "REVISION", "P_HT", "T_HT", "REPERE_SOURCE", "CODE_SOURCE", "NOM_SOURCE", "CODE", "NOM", "QTE",
"QTE_UNITAIRE", "REPERE", "REFERENCE", "ID_FABRICANT", "ID_UNITE_VENTE", "ID_ARTICLE", "ID_FOURNISSEUR", "ID_FAMILLE_ARTICLE", "ID_AFFAIRE");
// "CODE" character varying(256) NOT NULL DEFAULT ''::character varying,
//
// "DATE" date,
// "ID_ETAT_DEMANDE_ACHAT_ELEMENT" integer DEFAULT 1,
// "REPRISE" boolean NOT NULL DEFAULT false,
for (String string : copyFields) {
if (string.startsWith("ID_")) {
rowDupl.put(string, row.getForeignID(string));
} else {
rowDupl.put(string, row.getObject(string));
}
}
rowDupl.put("DATE", new Date());
EditFrame frame = new EditFrame(getDirectory().getElement("DEMANDE_ACHAT_ELEMENT"));
frame.getSQLComponent().select(rowDupl);
FrameUtil.showPacked(frame);
}
}, true);
 
actionP.setPredicate(IListeEvent.getSingleSelectionPredicate());
getRowActions().add(actionP);
}
{
RowAction actionP = new RowAction(new AbstractAction("Transfert en demande de prix") {
 
77,6 → 105,7
rowVals.put("ID_AFFAIRE", row.getForeignID("ID_AFFAIRE"));
SQLRowValues rowValsCmdElt = inj.createRowValuesFrom(row);
rowValsCmdElt.put("ID_STYLE", idNormal);
rowValsCmdElt.put("ID_MODE_VENTE_ARTICLE", ReferenceArticleSQLElement.A_LA_PIECE);
rowValsCmdElt.put("ID_TAXE", TaxeCache.getCache().getFirstTaxe().getID());
rowValsCmdElt.put("ID_DEMANDE_PRIX", rowVals);
rowValsCmdElt.put("ID_DEMANDE_ACHAT_ELEMENT", row.getID());
136,6 → 165,7
rowVals.put("ID_AFFAIRE", row.getForeignID("ID_AFFAIRE"));
SQLRowValues rowValsCmdElt = inj.createRowValuesFrom(row);
rowValsCmdElt.put("ID_STYLE", idNormal);
rowValsCmdElt.put("ID_MODE_VENTE_ARTICLE", ReferenceArticleSQLElement.A_LA_PIECE);
rowValsCmdElt.put("ID_TAXE", TaxeCache.getCache().getFirstTaxe().getID());
rowValsCmdElt.put("ID_COMMANDE", rowVals);
rowValsCmdElt.put("ID_DEMANDE_ACHAT_ELEMENT", row.getID());
209,6 → 239,7
 
SQLRowValues rowVals = new SQLRowValues(getTable());
rowVals.put("QTE", null);
rowVals.put("QTE_UNITAIRE", null);
rowVals.put("ID_ETAT_DEMANDE_ACHAT_ELEMENT", null);
 
final List<String> refTable = Arrays.asList("COMMANDE_ELEMENT", "DEMANDE_PRIX_ELEMENT", "BON_RECEPTION_ELEMENT");
215,6 → 246,7
for (String tableName : refTable) {
SQLRowValues rowValsRef = new SQLRowValues(getTable().getTable(tableName));
rowValsRef.put("QTE", null);
rowValsRef.put("PA_HT", null);
rowValsRef.put("ID_DEMANDE_ACHAT_ELEMENT", rowVals);
rowValsRef.put("QTE_UNITAIRE", null);
rowValsRef.put("ID_" + tableName.replaceAll("_ELEMENT", ""), null);
244,13 → 276,17
if (!rowValsBR.isEmpty()) {
int qte = 0;
int idBR = 1;
BigDecimal prix = BigDecimal.ZERO;
for (SQLRowValues sqlRowValues : rowValsBR) {
qte += sqlRowValues.getInt("QTE");
idBR = sqlRowValues.getForeignID("ID_BON_RECEPTION");
prix = sqlRowValues.getBigDecimal("PA_HT");
}
if (qte > 0) {
createEmptyUpdateRow.put("ID_BON_RECEPTION", idBR);
createEmptyUpdateRow.put("QTE_RECUE", qte);
createEmptyUpdateRow.put("P_HT", prix);
createEmptyUpdateRow.put("T_HT", prix.multiply(rowValsDmd.getBigDecimal("QTE_UNITAIRE").multiply(new BigDecimal(rowValsDmd.getInt("QTE")))));
if (qte >= rowValsDmd.getInt("QTE")) {
newStatus = EtatDemandeAchatItemSQLElement.RECPETION;
} else {
260,7 → 296,10
} else {
Collection<SQLRowValues> rowValsCmd = rowValsDmd.getReferentRows(getTable().getTable("COMMANDE_ELEMENT"));
if (!rowValsCmd.isEmpty()) {
createEmptyUpdateRow.put("ID_COMMANDE", rowValsCmd.iterator().next().getForeignID("ID_COMMANDE"));
final SQLRowValues next = rowValsCmd.iterator().next();
createEmptyUpdateRow.put("ID_COMMANDE", next.getForeignID("ID_COMMANDE"));
createEmptyUpdateRow.put("P_HT", next.getBigDecimal("PA_HT"));
createEmptyUpdateRow.put("T_HT", next.getBigDecimal("PA_HT").multiply(rowValsDmd.getBigDecimal("QTE_UNITAIRE").multiply(new BigDecimal(rowValsDmd.getInt("QTE")))));
newStatus = EtatDemandeAchatItemSQLElement.COMMANDE;
} else {
Collection<SQLRowValues> rowValsDmdElt = rowValsDmd.getReferentRows(getTable().getTable("DEMANDE_PRIX_ELEMENT"));
284,13 → 323,17
@Override
protected List<String> getListFields() {
final List<String> l = new ArrayList<String>();
 
l.add("DATE");
l.add("REVISION");
l.add("CODE");
l.add("NOM");
l.add("IMPORT");
l.add("REPRISE");
l.add("QTE_UNITAIRE");
l.add("ID_UNITE_VENTE");
l.add("P_HT");
l.add("QTE");
l.add("T_HT");
l.add("ID_FABRICANT");
l.add("ID_FOURNISSEUR");
l.add("CODE_SOURCE");
308,30 → 351,35
res.init();
res.getColumn(foreignTable.getField("NOM")).setRenderer(new EtatDemandeAchatRenderer(foreignTable));
 
BaseSQLTableModelColumn dpt = new BaseSQLTableModelColumn("Prix", BigDecimal.class) {
res.getColumn(getTable().getField("P_HT")).setRenderer(new DeviseTableCellRenderer());
res.getColumn(getTable().getField("T_HT")).setRenderer(new DeviseTableCellRenderer());
res.getColumn(getTable().getField("QTE_UNITAIRE")).setRenderer(new DeviseTableCellRenderer());
 
@Override
protected Object show_(SQLRowAccessor r) {
// BaseSQLTableModelColumn dpt = new BaseSQLTableModelColumn("Prix Total", BigDecimal.class)
// {
//
// @Override
// protected Object show_(SQLRowAccessor r) {
//
// if (r.getObject("ID_ARTICLE") != null && !r.isForeignEmpty("ID_ARTICLE")) {
// SQLRowAccessor rA = r.getForeign("ID_ARTICLE");
// return rA.getBigDecimal("PA_HT");
// } else {
// return null;
// }
// }
//
// @Override
// public Set<FieldPath> getPaths() {
// Path p = new Path(getTable());
// final SQLTable clientT = getTable().getForeignTable("ID_ARTICLE");
// p = p.add(clientT);
// return CollectionUtils.createSet(new FieldPath(p, "PA_HT"));
// }
// };
//
// res.getColumns().add(dpt);
 
if (r.getObject("ID_ARTICLE") != null && !r.isForeignEmpty("ID_ARTICLE")) {
SQLRowAccessor rA = r.getForeign("ID_ARTICLE");
return rA.getBigDecimal("PA_HT");
} else {
return null;
}
}
 
@Override
public Set<FieldPath> getPaths() {
Path p = new Path(getTable());
final SQLTable clientT = getTable().getForeignTable("ID_ARTICLE");
p = p.add(clientT);
return CollectionUtils.createSet(new FieldPath(p, "PA_HT"));
}
};
 
res.getColumns().add(dpt);
 
super._initTableSource(res);
}
 
345,7 → 393,14
@Override
protected List<String> getComboFields() {
final List<String> l = new ArrayList<String>();
l.add("ID_FOURNISSEUR");
if (getTable().contains("ID_AFFAIRE")) {
l.add("ID_AFFAIRE");
}
l.add("DATE");
l.add("REVISION");
l.add("CODE");
l.add("NOM");
 
return l;
}
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/element/DemandeAchatItemSQLComponent.java
78,7 → 78,7
c.weightx = 1;
final ElementComboBox boxCmd = new ElementComboBox();
this.add(boxCmd, c);
this.addView(boxCmd, "ID_ETAT_DEMANDE_ACHAT_ELEMENT", REQ);
this.addView(boxCmd, "ID_ETAT_DEMANDE_ACHAT_ELEMENT");
 
c.gridx = 0;
c.gridy++;
201,8 → 201,21
 
c.gridx++;
c.weightx = 0;
this.add(new JCheckBox("En stock"), c);
final JCheckBox checkReprise = new JCheckBox("Reprise");
this.add(checkReprise, c);
addView(checkReprise, "REPRISE");
 
c.weightx = 0;
c.gridy++;
c.gridx = 0;
c.weightx = 0;
this.add(new JLabel(getLabelFor("REVISION"), SwingConstants.RIGHT), c);
c.gridx++;
c.weightx = 1;
final JTextField textRev = new JTextField(15);
this.add(textRev, c);
this.addView(textRev, "REVISION");
 
boxArticle.addValueListener(new PropertyChangeListener() {
 
@Override
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/action/ImportProductsToOrder.java
14,7 → 14,6
package org.openconcerto.erp.core.supplychain.order.action;
 
import org.openconcerto.erp.core.sales.product.element.UniteVenteArticleSQLElement;
import org.openconcerto.erp.core.supplychain.order.element.EtatDemandeAchatItemSQLElement;
import org.openconcerto.erp.importer.ArrayTableModel;
import org.openconcerto.erp.importer.DataImporter;
import org.openconcerto.sql.model.DBRoot;
52,7 → 51,6
public static void main(String[] args) throws IOException, SQLException {
ImportProductsToOrder importer = new ImportProductsToOrder();
importer.importFile(new File("export-inventor-17-819.xls"), null);
 
}
 
private SQLRowAccessor rowAffaire = null;
61,6 → 59,12
this.rowAffaire = rowAffaire;
}
 
private SQLRowAccessor rowFamille = null;
 
public void setRowFamille(SQLRowAccessor rowFamille) {
this.rowFamille = rowFamille;
}
 
public void importFile(File file, DBRoot root) throws IOException, SQLException {
this.root = root;
DataImporter importer = new DataImporter();
106,8 → 110,9
importer.map(10, table.getField("REPERE_SOURCE"));
importer.map(11, table.getField("CODE_SOURCE"));
importer.map(12, table.getField("NOM_SOURCE"));
importer.map(13, table.getField("ID_FAMILLE_ARTICLE"));
if (table.contains("ID_AFFAIRE")) {
importer.map(13, table.getField("ID_AFFAIRE"));
importer.map(14, table.getField("ID_AFFAIRE"));
}
importer.importFromModel(cleanModel);
// importer.commit();
128,7 → 133,7
for (SQLRowValues rowValsToInsert : rowsToInsert) {
 
String query = "INSERT INTO " + rowValsToInsert.getTable().getSQLName();
query += " (\"REPERE\", \"QTE\", \"QTE_UNITAIRE\", \"ID_UNITE_VENTE\", \"NOM\", \"CODE\", \"ID_FABRICANT\", \"ID_ETAT_DEMANDE_ACHAT_ELEMENT\", \"ID_ARTICLE\",\"REVISION\",\"REPERE_SOURCE\",\"CODE_SOURCE\",\"NOM_SOURCE\", ";
query += " (\"REPERE\", \"QTE\", \"QTE_UNITAIRE\", \"ID_UNITE_VENTE\", \"NOM\", \"CODE\", \"ID_FABRICANT\", \"ID_ETAT_DEMANDE_ACHAT_ELEMENT\", \"ID_ARTICLE\",\"REVISION\",\"REPERE_SOURCE\",\"CODE_SOURCE\",\"NOM_SOURCE\",\"IMPORT\",\"ID_FAMILLE_ARTICLE\", ";
if (table.contains("ID_AFFAIRE")) {
query += "\"ID_AFFAIRE\",";
}
148,9 → 153,16
query += foreignID + ", ";
query += SQLBase.quoteStringStd(rowValsToInsert.getString("REVISION")) + ", ";
query += SQLBase.quoteStringStd(rowValsToInsert.getString("REPERE_SOURCE")) + ", ";
query += SQLBase.quoteStringStd(rowValsToInsert.getString("CODE_SOURCE")) + ", ";
String codeSource = rowValsToInsert.getString("CODE_SOURCE");
if (table.contains("ID_AFFAIRE")) {
if (codeSource == null || codeSource.trim().length() == 0) {
codeSource = rowValsToInsert.getForeign("ID_AFFAIRE").getString("NUMERO") + "_000";
}
}
query += SQLBase.quoteStringStd(codeSource) + ", ";
query += SQLBase.quoteStringStd(rowValsToInsert.getString("NOM_SOURCE")) + ", ";
 
query += "true" + ", ";
query += rowValsToInsert.getForeignID("ID_FAMILLE_ARTICLE") + ", ";
if (table.contains("ID_AFFAIRE")) {
query += rowValsToInsert.getForeignID("ID_AFFAIRE") + ", ";
}
176,13 → 188,25
return size;
}
 
// - NORMAL: Ligne Appparente dans ERP
//
// - ACHETE: 1ere Ligne Apparente Uniquement
//
// - INDIVISIBLE: Ne doit PAS Apparaitre Dans l'ERP
 
while (index < size) {
List<Object> line = m.getLineValuesAt(index);
String structure = (line.get(6) == null ? "" : line.get(6)).toString();
// repere
String repere = line.get(0).toString();
if (repere.trim().length() == 0) {
return size;
}
 
if (repere.endsWith(".0")) {
repere = repere.replaceAll(".0", "");
}
 
// qty
Object c1 = line.get(1);
int qty = 1;
212,8 → 236,8
// ref
Object des = line.get(2);
Object ref = line.get(3);
if (parent == null || parent.get0() == null || repere.startsWith(parent.get0())) {
if (repereNext != null && repereNext.startsWith(repere)) {
if (parent == null || parent.get0() == null || repere.startsWith(parent.get0() + ".")) {
if (repereNext != null && repereNext.startsWith(repere + ".") && !structure.equalsIgnoreCase("Acheté") && !structure.equalsIgnoreCase("Indivisible")) {
BigDecimal qtyMultChild = qtyMult.multiply(uQty).multiply(new BigDecimal(qty));
index = fetch(result, m, index + 1, qtyMultChild, Tuple3.create(repere, ref.toString(), des.toString()));
} else {
281,15 → 305,37
cleanLine.add(repereSource.toString());
cleanLine.add(refSource.toString());
cleanLine.add(desSource.toString());
 
if (this.rowFamille != null) {
cleanLine.add(this.rowFamille.getID());
} else {
cleanLine.add(1);
}
if (this.rowAffaire != null) {
cleanLine.add(this.rowAffaire.getID());
}
 
if (!structure.equalsIgnoreCase("Indivisible")) {
result.add(cleanLine);
}
if (structure.equalsIgnoreCase("Acheté") || structure.equalsIgnoreCase("Indivisible")) {
String repereOrigin = repere;
while (index < size && (repere.equalsIgnoreCase(repereOrigin) || repere.startsWith(repereOrigin + "."))) {
index++;
if (index < size) {
line = m.getLineValuesAt(index);
repere = line.get(0).toString();
if (repere.trim().length() == 0) {
return size;
}
}
}
 
} else {
 
index++;
}
}
} else {
return index;
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/ui/EtatDemandeAchatRenderer.java
14,9 → 14,13
package org.openconcerto.erp.core.supplychain.order.ui;
 
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.view.list.ITableModel;
import org.openconcerto.sql.view.list.ListSQLLine;
import org.openconcerto.ui.table.TableCellRendererUtils;
 
import java.awt.Color;
28,6 → 32,8
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
 
import com.ibm.icu.util.Calendar;
 
public class EtatDemandeAchatRenderer extends DefaultTableCellRenderer {
Map<String, Color> map = new HashMap<String, Color>();
 
51,6 → 57,22
this.setBackground(c);
}
 
final ListSQLLine line = ITableModel.getLine(table.getModel(), row);
final SQLRowValues rowAt = line.getRow();
SQLRowAccessor rowCmd = rowAt.getForeign("ID_COMMANDE");
SQLRowAccessor rowBl = rowAt.getForeign("ID_BON_RECEPTION");
if (rowCmd != null && !rowCmd.isUndefined() && (rowBl == null || rowBl.isUndefined())) {
Calendar cal = Calendar.getInstance();
 
if (rowCmd.getDate("DATE_RECEPTION_DEMANDEE") != null && rowCmd.getDate("DATE_RECEPTION_DEMANDEE").getTime().before(cal.getTime())) {
this.setText("A Relancer");
final Color c2 = map.get("A Relancer");
if (c2 != null) {
this.setBackground(c2);
}
}
}
 
return this;
 
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/component/CommandeSQLComponent.java
23,6 → 23,7
import org.openconcerto.erp.core.common.ui.TotalPanel;
import org.openconcerto.erp.core.finance.tax.model.TaxeCache;
import org.openconcerto.erp.core.sales.product.element.ReferenceArticleSQLElement;
import org.openconcerto.erp.core.supplychain.order.element.DemandeAchatItemSQLElement;
import org.openconcerto.erp.core.supplychain.order.ui.CommandeItemTable;
import org.openconcerto.erp.core.supplychain.stock.element.StockItemsUpdater;
import org.openconcerto.erp.core.supplychain.stock.element.StockItemsUpdater.TypeStockUpdate;
91,7 → 92,7
private final SQLTable tableNum = getTable().getBase().getTable("NUMEROTATION_AUTO");
private final ITextArea infos = new ITextArea(3, 3);
private ElementComboBox fourn = new ElementComboBox();
final JCheckBox boxLivrClient = new JCheckBox("Livrer directement le client");
private final JCheckBox boxLivrClient = new JCheckBox("Livrer directement le client");
private DefaultElementSQLObject compAdr;
final JPanel panelAdrSpec = new JPanel(new GridBagLayout());
protected ElementComboBox boxAdr;
166,6 → 167,7
c.weighty = 0;
c.fill = GridBagConstraints.NONE;
this.add(this.fourn, c);
addRequiredSQLObject(this.fourn, "ID_FOURNISSEUR");
 
if (!getTable().getFieldsName().contains("LIVRER")) {
// Commande en cours
347,9 → 349,8
} else {
 
c.gridy++;
c.gridx = 0;
this.add(new JLabel(TM.tr("address.type.delivery"), SwingConstants.RIGHT), c);
c.gridx++;
c.gridx = 1;
c.gridwidth = GridBagConstraints.REMAINDER;
this.add(boxLivrClient, c);
c.gridwidth = 1;
584,7 → 585,6
this.panelOO = new PanelOOSQLComponent(this);
this.add(this.panelOO, c);
 
addRequiredSQLObject(this.fourn, "ID_FOURNISSEUR");
addSQLObject(textNom, "NOM");
addRequiredSQLObject(dateCommande, "DATE");
// addRequiredSQLObject(radioEtat, "ID_ETAT_DEVIS");
675,10 → 675,12
}
 
DeviseField textPortHT = new DeviseField();
DeviseField textRemiseHT = new DeviseField();
ElementComboBox comboTaxePort = new ElementComboBox(false, 10);
 
if (getTable().contains("PORT_HT")) {
addRequiredSQLObject(textPortHT, "PORT_HT");
 
addSQLObject(textPortHT, "PORT_HT");
final JPanel panelPoids = new JPanel(new GridBagLayout());
GridBagConstraints cPort = new DefaultGridBagConstraints();
cPort.gridx = 0;
699,6 → 701,17
cPort.weightx = 1;
panelPoids.add(comboTaxePort, cPort);
 
addSQLObject(textRemiseHT, "REMISE_HT");
cPort.gridy++;
cPort.gridx = 0;
cPort.fill = GridBagConstraints.NONE;
cPort.weightx = 0;
panelPoids.add(new JLabel(getLabelFor("REMISE_HT")), cPort);
textRemiseHT.setHorizontalAlignment(JTextField.RIGHT);
cPort.gridx++;
cPort.weightx = 1;
panelPoids.add(textRemiseHT, cPort);
 
c.gridx++;
c.gridy = 0;
c.weightx = 0;
712,7 → 725,6
}
// Total
 
DeviseField textRemiseHT = new DeviseField();
DeviseField fieldHT = new DeviseField();
DeviseField fieldEco = new DeviseField();
DeviseField fieldTVA = new DeviseField();
870,6 → 882,9
e.printStackTrace();
}
}
DemandeAchatItemSQLElement elt = getElement().getDirectory().getElement(DemandeAchatItemSQLElement.class);
elt.updateStatus(getTable(), getTable().getTable("COMMANDE_ELEMENT"), idCommande);
 
if (attempt > 0) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
934,6 → 949,10
}
}
});
 
DemandeAchatItemSQLElement elt = getElement().getDirectory().getElement(DemandeAchatItemSQLElement.class);
elt.updateStatus(getTable(), getTable().getTable("COMMANDE_ELEMENT"), getSelectedID());
 
// generation du document
final CommandeXmlSheet sheet = new CommandeXmlSheet(getTable().getRow(id));
sheet.createDocumentAsynchronous();
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/component/FactureFournisseurSQLComponent.java
439,9 → 439,10
 
DeviseField textPortHT = new DeviseField();
ElementComboBox comboTaxePort = new ElementComboBox();
DeviseField textRemiseHT = new DeviseField();
 
if (getTable().contains("PORT_HT")) {
addRequiredSQLObject(textPortHT, "PORT_HT");
addSQLObject(textPortHT, "PORT_HT");
final JPanel panelPoids = new JPanel(new GridBagLayout());
GridBagConstraints cPort = new DefaultGridBagConstraints();
cPort.gridx = 0;
471,10 → 472,21
c.anchor = GridBagConstraints.NORTHEAST;
panel.add(panelPoids, c);
DefaultGridBagConstraints.lockMinimumSize(panelPoids);
 
addSQLObject(textRemiseHT, "REMISE_HT");
cPort.gridy++;
cPort.gridx = 0;
cPort.fill = GridBagConstraints.NONE;
cPort.weightx = 0;
panelPoids.add(new JLabel(getLabelFor("REMISE_HT")), cPort);
textRemiseHT.setHorizontalAlignment(JTextField.RIGHT);
cPort.gridx++;
cPort.weightx = 1;
panelPoids.add(textRemiseHT, cPort);
 
}
// Total
 
DeviseField textRemiseHT = new DeviseField();
DeviseField fieldHT = new DeviseField();
DeviseField fieldEco = new DeviseField();
DeviseField fieldTVA = new DeviseField();
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/order/table/ChiffrageCommandeTable.java
32,11 → 32,15
 
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
 
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
187,7 → 191,16
 
c.gridy++;
c.gridx = 0;
final JPanel control = new RowValuesTableControlPanel(this.table);
JButton loadDefaultButton = new JButton(new AbstractAction("Charger les valeurs par défaut") {
 
@Override
public void actionPerformed(ActionEvent e) {
for (SQLRowValues sqlRowValues : lists) {
getModel().addRow(sqlRowValues);
}
}
});
final JPanel control = new RowValuesTableControlPanel(this.table, Arrays.asList(loadDefaultButton));
control.setOpaque(false);
this.add(control, c);
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/supplychain/receipt/component/BonReceptionSQLComponent.java
19,6 → 19,7
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement;
import org.openconcerto.erp.core.common.ui.DeviseField;
import org.openconcerto.erp.core.common.ui.TotalPanel;
import org.openconcerto.erp.core.finance.tax.model.TaxeCache;
import org.openconcerto.erp.core.sales.product.element.ReferenceArticleSQLElement;
import org.openconcerto.erp.core.sales.product.ui.ReliquatRowValuesTable;
import org.openconcerto.erp.core.supplychain.order.element.DemandeAchatItemSQLElement;
29,6 → 30,7
import org.openconcerto.erp.core.supplychain.stock.element.StockLabel;
import org.openconcerto.erp.generationDoc.gestcomm.BonReceptionXmlSheet;
import org.openconcerto.erp.panel.PanelOOSQLComponent;
import org.openconcerto.erp.preferences.DefaultNXProps;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.model.SQLRow;
44,10 → 46,12
import org.openconcerto.ui.JDate;
import org.openconcerto.ui.TitledSeparator;
import org.openconcerto.ui.component.ITextArea;
import org.openconcerto.ui.preferences.DefaultProps;
import org.openconcerto.utils.DecimalUtils;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.NumberUtils;
 
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
66,6 → 70,10
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
 
public class BonReceptionSQLComponent extends TransfertBaseSQLComponent {
private BonReceptionItemTable tableBonItem;
91,6 → 99,9
if (getTable().contains("CREATE_VIRTUAL_STOCK")) {
rowVals.put("CREATE_VIRTUAL_STOCK", Boolean.TRUE);
}
if (getTable().contains("ID_TAXE_PORT")) {
rowVals.put("ID_TAXE_PORT", TaxeCache.getCache().getFirstTaxe().getID());
}
return rowVals;
}
 
185,6 → 196,9
c.fill = GridBagConstraints.NONE;
this.add(this.fournisseur, c);
 
this.tableBonItem = new BonReceptionItemTable();
this.addRequiredSQLObject(this.fournisseur, "ID_FOURNISSEUR");
 
// Devise
c.gridx = 0;
c.gridy++;
214,7 → 228,7
});
 
// Element du bon
this.tableBonItem = new BonReceptionItemTable();
 
boxDevise.addValueListener(new PropertyChangeListener() {
 
@Override
240,62 → 254,15
 
c.anchor = GridBagConstraints.EAST;
 
// Poids Total
c.gridx = 0;
c.gridy++;
c.gridx = 1;
c.weightx = 0;
c.weighty = 0;
c.anchor = GridBagConstraints.EAST;
c.gridwidth = 1;
c.fill = GridBagConstraints.NONE;
 
c.gridx = 2;
c.gridwidth = GridBagConstraints.REMAINDER;
c.weightx = 0;
c.weighty = 0;
c.anchor = GridBagConstraints.EAST;
c.fill = GridBagConstraints.HORIZONTAL;
 
DeviseField fieldHT = new DeviseField();
DeviseField fieldEco = new DeviseField();
DeviseField fieldTVA = new DeviseField();
DeviseField fieldTTC = new DeviseField();
DeviseField fieldDevise = new DeviseField();
JTextField fieldPoids = new JTextField();
fieldHT.setOpaque(false);
fieldTVA.setOpaque(false);
fieldTTC.setOpaque(false);
addRequiredSQLObject(fieldEco, "T_ECO_CONTRIBUTION");
addRequiredSQLObject(fieldDevise, "T_DEVISE");
addRequiredSQLObject(fieldHT, "TOTAL_HT");
addRequiredSQLObject(fieldTVA, "TOTAL_TVA");
addRequiredSQLObject(fieldPoids, "TOTAL_POIDS");
 
addRequiredSQLObject(fieldTTC, "TOTAL_TTC");
 
// Disable
this.allowEditable("TOTAL_HT", false);
this.allowEditable("TOTAL_TVA", false);
this.allowEditable("TOTAL_TTC", false);
this.allowEditable("T_ECO_CONTRIBUTION", false);
this.allowEditable("TOTAL_POIDS", false);
 
DeviseField textRemiseHT = new DeviseField();
DeviseField fieldService = new DeviseField();
DeviseField textPortHT = new DeviseField();
 
final TotalPanel totalTTC = new TotalPanel(this.tableBonItem, fieldEco, fieldHT, fieldTVA, fieldTTC, textPortHT, textRemiseHT, fieldService, null, fieldDevise, fieldPoids, null, null, null);
 
c.gridx++;
c.gridy++;
c.gridwidth = GridBagConstraints.REMAINDER;
c.gridheight = 2;
c.anchor = GridBagConstraints.NORTHEAST;
c.fill = GridBagConstraints.BOTH;
c.weighty = 0;
DefaultGridBagConstraints.lockMinimumSize(totalTTC);
 
this.add(totalTTC, c);
this.add(getBottomPanel(), c);
c.gridy++;
c.gridheight = 1;
c.anchor = GridBagConstraints.WEST;
324,34 → 291,8
this.tableBonItem.setReliquatTable(tableBonReliquatItem);
}
 
/*******************************************************************************************
* * INFORMATIONS COMPLEMENTAIRES
******************************************************************************************/
c.gridwidth = GridBagConstraints.REMAINDER;
c.weightx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy++;
TitledSeparator sep = new TitledSeparator("Informations complémentaires");
c.insets = new Insets(10, 2, 1, 2);
this.add(sep, c);
c.insets = new Insets(2, 2, 1, 2);
 
c.gridx = 0;
c.gridy++;
c.gridheight = 1;
c.gridwidth = GridBagConstraints.REMAINDER;
c.weightx = 1;
c.weighty = 0;
c.fill = GridBagConstraints.BOTH;
final ITextArea textInfos = new ITextArea(4, 4);
JScrollPane scrollPane = new JScrollPane(textInfos);
DefaultGridBagConstraints.lockMinimumSize(scrollPane);
 
this.add(textInfos, c);
 
c.gridx = 0;
c.gridy++;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.SOUTHEAST;
c.gridwidth = GridBagConstraints.REMAINDER;
360,11 → 301,9
this.add(this.panelOO, c);
 
this.addRequiredSQLObject(date, "DATE");
this.addSQLObject(textInfos, "INFOS");
this.addSQLObject(this.textReference, "NOM");
this.addSQLObject(this.selectCommande, "ID_COMMANDE");
this.addRequiredSQLObject(this.textNumeroUnique, "NUMERO");
this.addRequiredSQLObject(this.fournisseur, "ID_FOURNISSEUR");
 
this.textNumeroUnique.setText(NumerotationAutoSQLElement.getNextNumero(getElement().getClass()));
 
373,6 → 312,191
 
}
 
private JPanel getBottomPanel() {
final JPanel panel = new JPanel(new GridBagLayout());
final GridBagConstraints c = new DefaultGridBagConstraints();
ITextArea infos = new ITextArea(3, 3);
addView(infos, "INFOS");
// Colonne 1 : Infos
c.gridx = 0;
c.weightx = 1;
c.anchor = GridBagConstraints.WEST;
c.fill = GridBagConstraints.HORIZONTAL;
 
panel.add(new TitledSeparator(getLabelFor("INFOS")), c);
 
c.gridy++;
c.weighty = 0;
c.weightx = 1;
c.fill = GridBagConstraints.BOTH;
final JScrollPane scrollPane = new JScrollPane(infos);
scrollPane.setBorder(null);
panel.add(scrollPane, c);
 
// Colonne 2 : Poids & autres
DefaultProps props = DefaultNXProps.getInstance();
Boolean b = props.getBooleanValue("ArticleShowPoids");
final JTextField textPoidsTotal = new JTextField(8);
JTextField poids = new JTextField();
if (b) {
final JPanel panelPoids = new JPanel(new GridBagLayout());
GridBagConstraints cPoids = new DefaultGridBagConstraints();
cPoids.weightx = 0;
panelPoids.add(new JLabel(getLabelFor("TOTAL_POIDS")), cPoids);
cPoids.weightx = 1;
textPoidsTotal.setEnabled(false);
textPoidsTotal.setHorizontalAlignment(JTextField.RIGHT);
textPoidsTotal.setDisabledTextColor(Color.BLACK);
cPoids.gridx++;
panelPoids.add(textPoidsTotal, cPoids);
 
c.gridx++;
c.gridy = 0;
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.gridheight = 2;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.NORTHEAST;
panel.add(panelPoids, c);
DefaultGridBagConstraints.lockMinimumSize(panelPoids);
addSQLObject(textPoidsTotal, "TOTAL_POIDS");
} else {
addSQLObject(poids, "TOTAL_POIDS");
}
 
DeviseField textPortHT = new DeviseField();
DeviseField textRemiseHT = new DeviseField();
ElementComboBox comboTaxePort = new ElementComboBox(false, 10);
 
if (getTable().contains("PORT_HT")) {
 
addSQLObject(textPortHT, "PORT_HT");
final JPanel panelPoids = new JPanel(new GridBagLayout());
GridBagConstraints cPort = new DefaultGridBagConstraints();
cPort.gridx = 0;
cPort.fill = GridBagConstraints.NONE;
cPort.weightx = 0;
panelPoids.add(new JLabel(getLabelFor("PORT_HT")), cPort);
textPortHT.setHorizontalAlignment(JTextField.RIGHT);
cPort.gridx++;
cPort.weightx = 1;
panelPoids.add(textPortHT, cPort);
 
cPort.gridy++;
cPort.gridx = 0;
cPort.weightx = 0;
addRequiredSQLObject(comboTaxePort, "ID_TAXE_PORT");
panelPoids.add(new JLabel(getLabelFor("ID_TAXE_PORT")), cPort);
cPort.gridx++;
cPort.weightx = 1;
panelPoids.add(comboTaxePort, cPort);
 
addSQLObject(textRemiseHT, "REMISE_HT");
cPort.gridy++;
cPort.gridx = 0;
cPort.fill = GridBagConstraints.NONE;
cPort.weightx = 0;
panelPoids.add(new JLabel(getLabelFor("REMISE_HT")), cPort);
textRemiseHT.setHorizontalAlignment(JTextField.RIGHT);
cPort.gridx++;
cPort.weightx = 1;
panelPoids.add(textRemiseHT, cPort);
 
c.gridx++;
c.gridy = 0;
c.weightx = 0;
c.weighty = 0;
c.gridwidth = 1;
c.gridheight = 2;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.NORTHEAST;
panel.add(panelPoids, c);
DefaultGridBagConstraints.lockMinimumSize(panelPoids);
}
// Total
 
DeviseField fieldHT = new DeviseField();
DeviseField fieldEco = new DeviseField();
DeviseField fieldTVA = new DeviseField();
DeviseField fieldTTC = new DeviseField();
DeviseField fieldDevise = new DeviseField();
DeviseField fieldService = new DeviseField();
fieldHT.setOpaque(false);
fieldTVA.setOpaque(false);
fieldTTC.setOpaque(false);
fieldService.setOpaque(false);
addRequiredSQLObject(fieldEco, "T_ECO_CONTRIBUTION");
addRequiredSQLObject(fieldDevise, "T_DEVISE");
addRequiredSQLObject(fieldHT, "TOTAL_HT");
addRequiredSQLObject(fieldTVA, "TOTAL_TVA");
addRequiredSQLObject(fieldTTC, "TOTAL_TTC");
 
// Disable
this.allowEditable("T_ECO_CONTRIBUTION", false);
this.allowEditable("TOTAL_HT", false);
this.allowEditable("TOTAL_TVA", false);
this.allowEditable("TOTAL_TTC", false);
 
final TotalPanel totalTTC = new TotalPanel(this.tableBonItem, fieldEco, fieldHT, fieldTVA, fieldTTC, textPortHT, textRemiseHT, fieldService, null, fieldDevise, null, null,
(getTable().contains("ID_TAXE_PORT") ? comboTaxePort : null), null);
 
c.gridx++;
c.gridy--;
c.gridwidth = GridBagConstraints.REMAINDER;
c.gridheight = 2;
c.anchor = GridBagConstraints.NORTHEAST;
c.fill = GridBagConstraints.BOTH;
c.weighty = 0;
c.weightx = 0;
DefaultGridBagConstraints.lockMinimumSize(totalTTC);
 
panel.add(totalTTC, c);
tableBonItem.getModel().addTableModelListener(new TableModelListener() {
 
public void tableChanged(TableModelEvent e) {
textPoidsTotal.setText(String.valueOf(tableBonItem.getPoidsTotal()));
}
});
 
textPortHT.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
totalTTC.updateTotal();
}
 
public void removeUpdate(DocumentEvent e) {
totalTTC.updateTotal();
}
 
public void insertUpdate(DocumentEvent e) {
totalTTC.updateTotal();
}
});
 
comboTaxePort.addValueListener(new PropertyChangeListener() {
 
@Override
public void propertyChange(PropertyChangeEvent evt) {
totalTTC.updateTotal();
}
});
 
textRemiseHT.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
totalTTC.updateTotal();
}
 
public void removeUpdate(DocumentEvent e) {
totalTTC.updateTotal();
}
 
public void insertUpdate(DocumentEvent e) {
totalTTC.updateTotal();
}
});
return panel;
}
 
public int insert(SQLRow order) {
 
int idBon = SQLRow.NONEXISTANT_ID;
539,6 → 663,9
}
});
 
DemandeAchatItemSQLElement elt = getElement().getDirectory().getElement(DemandeAchatItemSQLElement.class);
elt.updateStatus(getTable(), getTable().getTable("BON_RECEPTION_ELEMENT"), id);
 
// generation du document
final BonReceptionXmlSheet sheet = new BonReceptionXmlSheet(getTable().getRow(id));
sheet.createDocumentAsynchronous();
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/element/ContactSQLElementBase.java
13,12 → 13,6
package org.openconcerto.erp.core.customerrelationship.customer.element;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
 
import org.openconcerto.sql.element.ConfSQLElement;
import org.openconcerto.sql.element.SQLComponent;
import org.openconcerto.sql.element.SQLElement;
27,9 → 21,17
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.ui.EmailComposer;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.ListMap;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.StringUtils;
import org.openconcerto.utils.Value;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
 
public abstract class ContactSQLElementBase extends ConfSQLElement {
 
public ContactSQLElementBase() {
45,6 → 47,13
return this.getTable().getName();
}
 
// @Override
// public String getDescription(SQLRowValues r, DescLength l) {
// final Value<String> firstName = r.getNonDefaultObject("PRENOM", String.class);
// return (firstName.hasValue() && !StringUtils.isEmpty(firstName.getValue()) ?
// firstName.getValue() + " " : "") + r.getString("NOM");
// }
 
protected List<String> getListFields() {
final List<String> l = new ArrayList<String>();
if (getTable().contains("ID_TITRE_PERSONNEL")) {
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/element/ClientNormalSQLElement.java
154,6 → 154,7
l.add("ID_COMPTE_PCE");
l.add("ID_MODE_REGLEMENT");
l.add("INFOS");
l.add("ID_COMMERCIAL");
return l;
}
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/customerrelationship/customer/report/FicheClientXmlSheet.java
23,7 → 23,7
public class FicheClientXmlSheet extends AbstractSheetXMLWithDate {
 
public static final String TEMPLATE_ID = "FicheClient";
public static final String TEMPLATE_PROPERTY_NAME = DEFAULT_PROPERTY_NAME;
public static final String TEMPLATE_PROPERTY_NAME = "LocationFicheClient";
 
public FicheClientXmlSheet(SQLRow row) {
super(row);
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/element/ComptePCESQLElement.java
19,6 → 19,7
import org.openconcerto.sql.element.BaseSQLComponent;
import org.openconcerto.sql.element.SQLComponent;
import org.openconcerto.sql.element.TreesOfSQLRows;
import org.openconcerto.sql.model.DBRoot;
import org.openconcerto.sql.model.DBSystemRoot;
import org.openconcerto.sql.model.SQLBackgroundTableCache;
import org.openconcerto.sql.model.SQLBackgroundTableCacheItem;
152,6 → 153,8
protected void _initComboRequest(ComboSQLRequest req) {
super._initComboRequest(req);
req.setWhere(new Where(getTable().getField("OBSOLETE"), "=", Boolean.FALSE));
// Ne pas écraser l'ordre de la base (equals, startwith, etc..)
req.setItemsOrder(null);
}
 
protected List<String> getListFields() {
325,9 → 328,13
}
 
public static SQLRow getRow(String numero, String nom) {
SQLBase base = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete();
SQLTable compteTable = base.getTable("COMPTE_PCE");
return getRow(numero, nom, ((ComptaPropsConfiguration) Configuration.getInstance()).getRootSociete());
}
 
public static SQLRow getRow(String numero, String nom, DBRoot root) {
 
SQLTable compteTable = root.getTable("COMPTE_PCE");
 
final SQLBackgroundTableCacheItem cacheForTable = SQLBackgroundTableCache.getInstance().getCacheForTable(compteTable);
if (numero == null) {
throw new IllegalArgumentException("null numero");
423,4 → 430,5
protected String createCode() {
return createCodeFromPackage() + ".code.enterprise";
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/report/GrandLivreSheetXML.java
100,7 → 100,9
this.excludeCompteSolde = excludeCptSolde;
this.centralClient = centralClient;
this.centralFourn = centralFourn;
 
Map<String, Object> map = new HashMap<>();
recapSousTotaux.add(map);
map.put("DATE", "Récapitulatif");
// createMap();
}
 
120,8 → 122,9
// this.mCell.put("E" + row, "Période du " + dateFormatEcr.format(this.dateDu) + " au " +
// dateFormatEcr.format(this.dateAu));
// }
private List<Map<String, Object>> recapSousTotaux = new ArrayList<>();
 
private void makeSousTotal(Map<String, Object> line, Map<Integer, String> style, int pos, long debit, long credit) {
private void makeSousTotal(String numCpt, String nomCpt, Map<String, Object> line, Map<Integer, String> style, int pos, long debit, long credit) {
style.put(pos, "Titre 1");
 
line.put("DATE", "");
131,6 → 134,14
line.put("DEBIT", Double.valueOf(GestionDevise.currencyToString(debit, false)));
line.put("CREDIT", Double.valueOf(GestionDevise.currencyToString(credit, false)));
line.put("SOLDE", Double.valueOf(GestionDevise.currencyToString(debit - credit, false)));
 
Map<String, Object> lineRecap = new HashMap<>();
lineRecap.putAll(line);
lineRecap.put("DATE", numCpt);
lineRecap.put("JOURNAL", nomCpt);
lineRecap.put("LIBELLE", "");
recapSousTotaux.add(lineRecap);
 
}
 
protected void createListeValues() {
271,6 → 282,8
setTitle = true;
// ligne vide avant de mettre le setTitle
setLine = false;
String nomCpt = "";
String numCpt = "";
for (int i = 0; i < size;) {
// System.err.println(i);
// // System.err.println("START NEW PAGE; POS : " + posLine);
289,8 → 302,8
SQLRowValues rowEcr = list.get(i);
 
int idCpt = rowEcr.getInt("ID_COMPTE_PCE");
String nomCpt = rowEcr.getString("COMPTE_NOM");
String numCpt = rowEcr.getString("COMPTE_NUMERO");
nomCpt = rowEcr.getString("COMPTE_NOM");
numCpt = rowEcr.getString("COMPTE_NUMERO");
 
Map<String, Object> ooLine = new HashMap<String, Object>();
tableauVals.add(ooLine);
373,7 → 386,7
rowFirstEcr = rowEcr;
idCptFirstEcr = rowFirstEcr.getInt("ID_COMPTE_PCE");
numCptFirstEcr = rowEcr.getString("COMPTE_NUMERO");
makeSousTotal(ooLine, style, tableauVals.size() - 1, sousTotalDebit, sousTotalCredit);
makeSousTotal(numCpt, nomCpt, ooLine, style, tableauVals.size() - 1, sousTotalDebit, sousTotalCredit);
 
sousTotalCredit = 0;
sousTotalDebit = 0;
507,14 → 520,32
this.mapAllSheetValues.put(0, sheetVals);
 
if (size > 0) {
 
Map<String, Object> ooLine = new HashMap<String, Object>();
tableauVals.add(ooLine);
makeSousTotal(ooLine, style, tableauVals.size() - 1, sousTotalDebit, sousTotalCredit);
makeSousTotal(numCpt, nomCpt, ooLine, style, tableauVals.size() - 1, sousTotalDebit, sousTotalCredit);
 
sheetVals.put("TOTAL_DEBIT", (totalDebit == 0) ? 0 : new Double(GestionDevise.currencyToString(totalDebit, false)));
sheetVals.put("TOTAL_CREDIT", (totalCredit == 0) ? 0 : new Double(GestionDevise.currencyToString(totalCredit, false)));
sheetVals.put("TOTAL_SOLDE", (totalDebit - totalCredit == 0) ? 0 : new Double(GestionDevise.currencyToString(totalDebit - totalCredit, false)));
 
Map<String, Object> emptyLine = new HashMap<String, Object>();
style.put(tableauVals.size(), "Normal");
tableauVals.add(emptyLine);
for (Map<String, Object> recap : recapSousTotaux) {
style.put(tableauVals.size(), "Titre 1");
tableauVals.add(recap);
}
Map<String, Object> lineRecap = new HashMap<>();
lineRecap.put("DEBIT", (totalDebit == 0) ? 0 : new Double(GestionDevise.currencyToString(totalDebit, false)));
lineRecap.put("CREDIT", (totalCredit == 0) ? 0 : new Double(GestionDevise.currencyToString(totalCredit, false)));
lineRecap.put("SOLDE", (totalDebit - totalCredit == 0) ? 0 : new Double(GestionDevise.currencyToString(totalDebit - totalCredit, false)));
lineRecap.put("DATE", "");
lineRecap.put("JOURNAL", "");
lineRecap.put("LIBELLE", "Global");
style.put(tableauVals.size(), "Titre 1");
tableauVals.add(lineRecap);
}
 
sheetVals.put("TITRE_1", "GRAND LIVRE " + this.rowSociete.getString("TYPE") + " " + this.rowSociete.getString("NOM"));
sheetVals.put("DATE_EDITION", new Date());
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/report/Map2033B.java
431,12 → 431,12
******************************************************************************************/
// 312
// 374 SommeSoldeDebit( 4457, 4457* )
// TODO répartir les comptes crediteurs
long v374 = this.sommeCompte.soldeCompteDebiteur(4457, 4457, true, this.dateDeb, this.dateFin);
// TODO répartir les comptes débiteurs
long v374 = this.sommeCompte.soldeCompteCrediteur(4457, 4457, true, this.dateDeb, this.dateFin);
this.m.put("T1.41", GestionDevise.currencyToString(v374, false));
 
// 378 SommeSoldeCredit( 44566 )
long v378 = this.sommeCompte.soldeCompteCrediteur(44566, 44566, true, this.dateDeb, this.dateFin);
long v378 = this.sommeCompte.soldeCompteDebiteur(44566, 44566, true, this.dateDeb, this.dateFin);
this.m.put("T1.42", GestionDevise.currencyToString(v378, false));
 
SwingUtilities.invokeLater(new Runnable() {
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/PointagePanel.java
22,11 → 22,15
import org.openconcerto.erp.model.ISQLCompteSelector;
import org.openconcerto.erp.rights.ComptaUserRight;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.element.SQLElementDirectory;
import org.openconcerto.sql.model.SQLBase;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLSystem;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.request.ComboSQLRequest;
import org.openconcerto.sql.users.rights.UserRightsManager;
import org.openconcerto.sql.view.list.IListe;
import org.openconcerto.ui.DefaultGridBagConstraints;
95,7 → 99,7
public PointagePanel() {
this.setLayout(new GridBagLayout());
final GridBagConstraints c = new DefaultGridBagConstraints();
 
final SQLElementDirectory directory = Configuration.getInstance().getDirectory();
this.modeSelect = allEcriture;
 
// Selection du compte à pointer
106,8 → 110,14
this.add(labelPointageCompte, c);
 
this.selCompte = new ISQLCompteSelector();
 
this.selCompte.init();
SQLElement eltCpt = directory.getElement("COMPTE_PCE");
final ComboSQLRequest createComboRequest = eltCpt.createComboRequest();
String function = "REGEXP";
if (Configuration.getInstance().getBase().getServer().getSQLSystem() == SQLSystem.POSTGRESQL) {
function = "~";
}
createComboRequest.setWhere(new Where(eltCpt.getTable().getField("NUMERO"), function, "^5.*$"));
this.selCompte.init(eltCpt, createComboRequest);
new SwingWorker<Integer, Object>() {
 
@Override
257,7 → 267,7
this.add(sepEcriture, c);
 
// Liste des ecritures
final EcritureSQLElement ecritureElem = Configuration.getInstance().getDirectory().getElement(EcritureSQLElement.class);
final EcritureSQLElement ecritureElem = directory.getElement(EcritureSQLElement.class);
this.ecriturePanel = new ListPanelEcritures(ecritureElem, new IListe(ecritureElem.createPointageTableSource()));
this.ecriturePanel.setShowReadOnlyFrameOnDoubleClick(false);
c.gridx = 0;
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/SelectionJournalImportPanel.java
54,7 → 54,6
button.setEnabled(false);
tableJrnl.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
 
button.setEnabled(true);
}
});
66,14 → 65,7
public void actionPerformed(ActionEvent e) {
int id = model.getIdForRow(tableJrnl.getSelectedRow());
m.put(journalTitle, new Integer(id));
// synchronized (t) {
// System.err.println("Notify");
// t.notify();
// }
//
// sema.release();
((Window) SwingUtilities.getRoot(SelectionJournalImportPanel.this)).dispose();
 
}
});
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/SaisieJournalItemTable.java
New file
0,0 → 1,684
/*
* 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.finance.accounting.ui;
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.ui.DeviseCellEditor;
import org.openconcerto.erp.core.common.ui.MultiLineTableCellEditor;
import org.openconcerto.erp.core.common.ui.RowValuesMultiLineEditTable;
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement;
import org.openconcerto.erp.generationEcritures.GenerationMvtSaisieKm;
import org.openconcerto.erp.preferences.DefaultNXProps;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.sqlobject.ITextWithCompletion;
import org.openconcerto.sql.view.list.AutoCompletionManager;
import org.openconcerto.sql.view.list.RowValuesTable;
import org.openconcerto.sql.view.list.RowValuesTableControlPanel;
import org.openconcerto.sql.view.list.RowValuesTableModel;
import org.openconcerto.sql.view.list.SQLTableElement;
import org.openconcerto.sql.view.list.TextTableCellEditorWithCompletion;
import org.openconcerto.sql.view.list.ValidStateChecker;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.RangedIntegerTableCellEditor;
import org.openconcerto.utils.DecimalUtils;
import org.openconcerto.utils.GestionDevise;
import org.openconcerto.utils.Tuple2;
import org.openconcerto.utils.checks.ValidState;
 
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Vector;
 
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
 
public class SaisieJournalItemTable extends JPanel implements MouseListener {
 
private final RowValuesTable table;
private final SQLTableElement debit;
private final SQLTableElement credit;
private JLabel labelTotalDebit;
private JLabel labelTotalCredit;
private JLabel labelTotalSolde;
private final SQLTableElement tableElementNumeroCompte;
private final CompteRowValuesRenderer numeroCompteRenderer = new CompteRowValuesRenderer();
private final DeviseKmRowValuesRenderer deviseRenderer = new DeviseKmRowValuesRenderer();
final RangedIntegerTableCellEditor rangedIntegerTableCellEditor = new RangedIntegerTableCellEditor(1, 31);
private final RowValuesTableControlPanel controlPanel;
 
private SaisieJournalPanel panel;
private final JCheckBox boxAutoInsert;
private boolean hideAnalytique = false;
 
public SaisieJournalItemTable(final SQLRowValues defaultRowVals, JCheckBox boxAutoInsert) {
setLayout(new GridBagLayout());
this.boxAutoInsert = boxAutoInsert;
final GridBagConstraints c = new DefaultGridBagConstraints();
c.weightx = 1;
 
final SQLElement elt = Configuration.getInstance().getDirectory().getElement("SAISIE_KM_ELEMENT");
 
// TODO Obligation de choisir un compte correct
final List<SQLTableElement> list = new Vector<SQLTableElement>();
final SQLTable tableElement = elt.getTable();
final SQLTableElement tableElementJour = new SQLTableElement(tableElement.getField("JOUR"), Integer.class, rangedIntegerTableCellEditor) {
@Override
public boolean isCellEditable(SQLRowValues vals, int rowIndex, int columnIndex) {
 
return super.isCellEditable(vals, rowIndex, columnIndex) && rowIndex == 0;
}
 
@Override
protected Object getDefaultNullValue() {
return 1;
}
 
};
 
list.add(tableElementJour);
 
this.tableElementNumeroCompte = new SQLTableElement(tableElement.getField("NUMERO"));
list.add(this.tableElementNumeroCompte);
 
final SQLTableElement tableElementNomCompte = new SQLTableElement(tableElement.getField("NOM"));
list.add(tableElementNomCompte);
 
final SQLTableElement tableElementNomPiece = new SQLTableElement(tableElement.getField("NOM_PIECE"));
list.add(tableElementNomPiece);
 
final SQLTableElement tableElementNomEcriture = new SQLTableElement(tableElement.getField("NOM_ECRITURE"));
list.add(tableElementNomEcriture);
 
//
DeviseCellEditor deviseDebitEditor = new DeviseCellEditor();
DeviseCellEditor deviseCreditEditor = new DeviseCellEditor();
this.debit = new SQLTableElement(tableElement.getField("DEBIT"), Long.class, deviseDebitEditor);
list.add(this.debit);
this.credit = new SQLTableElement(tableElement.getField("CREDIT"), Long.class, deviseCreditEditor);
list.add(this.credit);
this.hideAnalytique = DefaultNXProps.getInstance().getBooleanValue("HideAnalytique");
if (!this.hideAnalytique) {
final AnalytiqueItemTable analytiqueAssocTable = new AnalytiqueItemTable(true, new AbstractAction() {
 
@Override
public void actionPerformed(ActionEvent e) {
montantValid(defaultRowVals, true);
}
});
final MultiLineTableCellEditor multiLineTableCellEditor = new MultiLineTableCellEditor((RowValuesMultiLineEditTable) analytiqueAssocTable.getTable(), analytiqueAssocTable);
 
SQLTableElement eltPourcentAnalytique = new SQLTableElement(tableElement.getField("ANALYTIQUE"), String.class, multiLineTableCellEditor) {
public boolean isCellEditable(SQLRowValues vals, int rowIndex, int columnIndex) {
return vals.getString("NUMERO") != null && (vals.getString("NUMERO").startsWith("6") || vals.getString("NUMERO").startsWith("7"));
};
};
list.add(eltPourcentAnalytique);
}
 
final RowValuesTableModel model = new RowValuesTableModel(elt, list, tableElement.getField("NUMERO"), false, defaultRowVals) {
@Override
public void setValueAt(final Object aValue, final int rowIndex, final int columnIndex) {
super.setValueAt(aValue, rowIndex, columnIndex);
 
final int debitIndex = getColumnIndexForElement(SaisieJournalItemTable.this.debit);
final int creditIndex = getColumnIndexForElement(SaisieJournalItemTable.this.credit);
 
// float debitVal = ((Float) model.getValueAt(rowIndex, debitIndex);
 
if (debitIndex == columnIndex && ((Long) aValue).longValue() != 0 && ((Long) getValueAt(rowIndex, creditIndex)).longValue() != 0) {
setValueAt(Long.valueOf(0), rowIndex, creditIndex);
} else {
if (creditIndex == columnIndex && ((Long) aValue).longValue() != 0 && ((Long) getValueAt(rowIndex, debitIndex)).longValue() != 0) {
setValueAt(Long.valueOf(0), rowIndex, debitIndex);
}
}
}
};
 
this.table = new RowValuesTable(model, null);
ToolTipManager.sharedInstance().unregisterComponent(this.table);
ToolTipManager.sharedInstance().unregisterComponent(this.table.getTableHeader());
 
tableElementNomEcriture.getTableCellEditor(table).addCellEditorListener(new CellEditorListener() {
 
@Override
public void editingStopped(ChangeEvent e) {
e.getSource();
int row = table.getSelectedRow();
int col = 4;
if (table.getValueAt(row, col) != null) {
defaultRowVals.put("NOM_ECRITURE", table.getValueAt(row, col));
}
// defaultRowVals.put
}
 
@Override
public void editingCanceled(ChangeEvent e) {
// TODO Auto-generated method stub
 
}
});
tableElementNomPiece.getTableCellEditor(table).addCellEditorListener(new CellEditorListener() {
 
@Override
public void editingStopped(ChangeEvent e) {
e.getSource();
int row = table.getSelectedRow();
int col = 3;
if (table.getValueAt(row, col) != null) {
defaultRowVals.put("NOM_PIECE", table.getValueAt(row, col));
}
// defaultRowVals.put
}
 
@Override
public void editingCanceled(ChangeEvent e) {
// TODO Auto-generated method stub
 
}
});
 
tableElementJour.getTableCellEditor(table).addCellEditorListener(new CellEditorListener() {
 
@Override
public void editingStopped(ChangeEvent e) {
final Object valueAt = table.getValueAt(0, 0);
defaultRowVals.put("JOUR", valueAt);
if (table.getRowCount() > 1) {
for (int i = 1; i < table.getRowCount(); i++) {
table.getRowValuesTableModel().putValue(valueAt, i, "JOUR");
}
}
}
 
@Override
public void editingCanceled(ChangeEvent e) {
// TODO Auto-generated method stub
 
}
});
;
 
final KeyListener keyListenerContrepartie = new KeyListener() {
 
@Override
public void keyTyped(KeyEvent e) {
 
}
 
@Override
public void keyReleased(KeyEvent e) {
 
}
 
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
montantValid(defaultRowVals, false);
}
}
};
deviseCreditEditor.addKeyListener(keyListenerContrepartie);
deviseDebitEditor.addKeyListener(keyListenerContrepartie);
 
// Autocompletion
final AutoCompletionManager m = new AutoCompletionManager(this.tableElementNumeroCompte,
((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete().getField("COMPTE_PCE.NUMERO"), this.table, this.table.getRowValuesTableModel(),
ITextWithCompletion.MODE_STARTWITH, true, false, new ValidStateChecker() {
 
ComptePCESQLElement elt = Configuration.getInstance().getDirectory().getElement(ComptePCESQLElement.class);
 
@Override
public ValidState getValidState(Object o) {
if (o != null) {
return elt.getCompteNumeroValidState(o.toString());
}
return super.getValidState(o);
}
});
m.fill("NOM", "NOM");
m.setFillWithField("NUMERO");
final Where w = new Where(elt.getTable().getTable("COMPTE_PCE").getField("OBSOLETE"), "=", Boolean.FALSE);
m.setWhere(w);
 
// FIXME erreur fill numero
final AutoCompletionManager m2 = new AutoCompletionManager(tableElementNomCompte, ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete().getField("COMPTE_PCE.NOM"),
this.table, this.table.getRowValuesTableModel(), ITextWithCompletion.MODE_CONTAINS, true);
m2.fill("NUMERO", "NUMERO");
m2.setFillWithField("NOM");
m2.setWhere(w);
 
TextTableCellEditorWithCompletion t = (TextTableCellEditorWithCompletion) this.tableElementNumeroCompte.getTableCellEditor(this.table);
 
this.controlPanel = new RowValuesTableControlPanel(this.table);
controlPanel.setButtonAjouterEnabled(false);
this.add(controlPanel, c);
 
c.gridy++;
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 1;
this.add(new JScrollPane(this.table), c);
 
this.tableElementNumeroCompte.setRenderer(this.numeroCompteRenderer);
this.debit.setRenderer(this.deviseRenderer);
this.credit.setRenderer(this.deviseRenderer);
 
this.table.addMouseListener(this);
this.table.getModel().addTableModelListener(new TableModelListener() {
 
@Override
public void tableChanged(TableModelEvent e) {
// Sélectionne automatiquement la ligne ajoutée
if (e.getType() == TableModelEvent.INSERT) {
if (table.getRowCount() == 1) {
editCellAt(e.getFirstRow(), 0);
} else {
editCellAt(e.getFirstRow(), 1);
}
}
refreshTotal();
}
});
 
// Initialisation du panel des Totaux
this.labelTotalCredit = new JLabel("0.00", SwingConstants.RIGHT);
this.labelTotalDebit = new JLabel("0.00", SwingConstants.RIGHT);
this.labelTotalSolde = new JLabel("0.00", SwingConstants.RIGHT);
JPanel panelTotal = new JPanel();
panelTotal.setLayout(new GridBagLayout());
panelTotal.setBorder(BorderFactory.createTitledBorder("Totaux"));
final GridBagConstraints cc = new DefaultGridBagConstraints();
cc.anchor = GridBagConstraints.EAST;
 
// Total Debit
cc.fill = GridBagConstraints.NONE;
panelTotal.add(new JLabel("Débit"), cc);
cc.fill = GridBagConstraints.HORIZONTAL;
cc.gridx++;
cc.weightx = 1;
 
panelTotal.add(this.labelTotalDebit, cc);
 
// Total Credit
cc.gridy++;
cc.gridx = 0;
cc.weightx = 0;
cc.fill = GridBagConstraints.NONE;
panelTotal.add(new JLabel("Crédit"), cc);
cc.weightx = 1;
cc.gridx++;
cc.fill = GridBagConstraints.HORIZONTAL;
panelTotal.add(this.labelTotalCredit, cc);
 
// Total Credit
cc.gridy++;
cc.gridx = 0;
cc.weightx = 0;
cc.fill = GridBagConstraints.NONE;
panelTotal.add(new JLabel("Solde"), cc);
cc.weightx = 1;
cc.gridx++;
cc.fill = GridBagConstraints.HORIZONTAL;
panelTotal.add(this.labelTotalSolde, cc);
 
c.gridy++;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.EAST;
c.weightx = 1;
c.weighty = 0;
this.add(panelTotal, c);
}
 
public void setPanel(final SaisieJournalPanel panel) {
this.panel = panel;
 
final PropertyChangeListener lActiveAddButton = new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
controlPanel.setButtonAjouterEnabled(!panel.getBoxJournal().isEmpty() && !panel.getBoxMois().isEmpty());
}
};
panel.getBoxJournal().addModelListener("wantedID", lActiveAddButton);
panel.getBoxMois().addModelListener("wantedID", lActiveAddButton);
 
final PropertyChangeListener l = new PropertyChangeListener() {
 
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (!SaisieJournalItemTable.this.panel.boxMois.isEmpty()) {
final SQLRow selectedRow = SaisieJournalItemTable.this.panel.boxMois.getSelectedRow();
if (selectedRow != null && !selectedRow.isUndefined()) {
Calendar c = Calendar.getInstance();
c.set(Calendar.DAY_OF_MONTH, 1);
c.set(Calendar.YEAR, (Integer) SaisieJournalItemTable.this.panel.spin.getValue());
c.set(Calendar.MONTH, SaisieJournalItemTable.this.panel.getSelectedMonth());
rangedIntegerTableCellEditor.setMax(c.getActualMaximum(Calendar.DAY_OF_MONTH));
}
}
}
 
};
panel.boxMois.addModelListener("wantedID", l);
 
}
 
public void refreshTotal() {
 
long totalD = 0L;
long totalC = 0L;
 
for (int i = 0; i < table.getRowCount(); i++) {
Long c = (Long) table.getRowValuesTableModel().getValueAt(i, table.getRowValuesTableModel().getColumnForField("DEBIT"));
Long d = (Long) table.getRowValuesTableModel().getValueAt(i, table.getRowValuesTableModel().getColumnForField("CREDIT"));
if (c != null) {
totalC += c;
}
if (d != null) {
totalD += d;
}
 
}
this.labelTotalCredit.setText(GestionDevise.currencyToString(totalC));
this.labelTotalDebit.setText(GestionDevise.currencyToString(totalD));
this.labelTotalSolde.setText(GestionDevise.currencyToString(totalD - totalC));
 
}
 
public boolean isSaisieValid() {
// Check if partie double
 
long totalD = 0L;
long totalC = 0L;
boolean cptOK = true;
String lib = null;
for (int i = 0; i < table.getRowCount(); i++) {
Long c = (Long) table.getRowValuesTableModel().getValueAt(i, table.getRowValuesTableModel().getColumnForField("DEBIT"));
Long d = (Long) table.getRowValuesTableModel().getValueAt(i, table.getRowValuesTableModel().getColumnForField("CREDIT"));
if (c != null) {
totalC += c;
}
if (d != null) {
totalD += d;
}
if (lib == null) {
lib = (String) table.getRowValuesTableModel().getValueAt(i, table.getRowValuesTableModel().getColumnForField("NOM"));
}
String cptNUmber = (String) table.getRowValuesTableModel().getValueAt(i, table.getRowValuesTableModel().getColumnForField("NUMERO"));
cptOK = cptOK && cptNUmber != null && ComptePCESQLElement.isExist(cptNUmber);
}
return totalD + totalC != 0 && totalD == totalC && cptOK;
}
 
private Tuple2<Date, String> getDateAndLabelFromSaisie() {
int day = 1;
String lib = null;
 
for (int i = 0; i < table.getRowCount(); i++) {
day = (Integer) table.getRowValuesTableModel().getValueAt(i, table.getRowValuesTableModel().getColumnForField("JOUR"));
if (lib == null) {
lib = (String) table.getRowValuesTableModel().getValueAt(i, table.getRowValuesTableModel().getColumnForField("NOM"));
}
}
// Create saisieKM
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, SaisieJournalItemTable.this.panel.getSelectedYear());
c.set(Calendar.MONTH, SaisieJournalItemTable.this.panel.getSelectedMonth());
c.set(Calendar.DAY_OF_MONTH, day);
return Tuple2.create(c.getTime(), lib);
}
 
public void montantValid(final SQLRowValues defaultRowVals, final boolean fromAnalytique) {
System.err.println("Enter");
final SQLRowValues vals = SaisieJournalItemTable.this.table.getSelectedRowValues();
final int selectedRow = SaisieJournalItemTable.this.table.getSelectedRow();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
 
if (boxAutoInsert.isSelected() && isSaisieValid()) {
if (SaisieJournalItemTable.this.panel.getSelectedJournal() == SQLRow.NONEXISTANT_ID || SaisieJournalItemTable.this.panel.getSelectedMonth() == -1) {
JOptionPane.showMessageDialog(SaisieJournalItemTable.this.panel, "Impossible de créer la saisie si aucun journal ou aucun mois n'est sélectionné!");
} else {
createSaisie(defaultRowVals);
}
} else {
if (!fromAnalytique && !hideAnalytique && vals.getString("NUMERO") != null && (vals.getString("NUMERO").startsWith("6") || vals.getString("NUMERO").startsWith("7"))) {
 
// Update montant
Collection<SQLRowValues> rowsLinked = vals.getReferentRows(vals.getTable().getTable("ASSOCIATION_ANALYTIQUE"));
long montant = vals.getLong("DEBIT") - vals.getLong("CREDIT");
for (SQLRowValues sqlRowValues : rowsLinked) {
sqlRowValues.put("MONTANT", sqlRowValues.getBigDecimal("POURCENT").movePointLeft(2).multiply(new BigDecimal(montant), DecimalUtils.HIGH_PRECISION)
.setScale(0, RoundingMode.HALF_UP).longValue());
}
 
editCellAt(selectedRow, table.getRowValuesTableModel().getColumnForField("ANALYTIQUE"));
} else {
 
long l = getContrepartie();
SQLRowValues rowVals = new SQLRowValues(defaultRowVals);
if (l > 0) {
rowVals.put("DEBIT", 0L);
rowVals.put("CREDIT", l);
} else {
rowVals.put("DEBIT", -l);
rowVals.put("CREDIT", 0L);
}
SaisieJournalItemTable.this.table.getRowValuesTableModel().addRow(rowVals);
}
}
 
}
});
 
}
 
public synchronized void createSaisie(final SQLRowValues defaultRowVals) {
 
Tuple2<Date, String> t = getDateAndLabelFromSaisie();
final Date d = t.get0();
final String lib = t.get1();
 
// Create saisieKM
SQLRowValues rowVAlsKM = new SQLRowValues(SaisieJournalItemTable.this.table.getRowValuesTableModel().getSQLElement().getTable().getForeignTable("ID_SAISIE_KM"));
 
rowVAlsKM.put("DATE", d);
rowVAlsKM.put("NOM", lib);
rowVAlsKM.put("ID_JOURNAL", SaisieJournalItemTable.this.panel.getSelectedJournal());
int id;
try {
id = rowVAlsKM.insert().getID();
 
table.updateField("ID_SAISIE_KM", id);
table.clear();
GenerationMvtSaisieKm gen = new GenerationMvtSaisieKm(id);
gen.genereMouvement();
 
defaultRowVals.put("NOM_PIECE", "");
defaultRowVals.put("NOM_ECRITURE", "");
table.getRowValuesTableModel().addNewRow();
 
} catch (SQLException e) {
e.printStackTrace();
}
 
}
 
public void updateField(final String field, final int id) {
this.table.updateField(field, id);
}
 
public void insertFrom(final String field, final int id) {
this.table.insertFrom(field, id);
}
 
public void insertFrom(final SQLRowAccessor row) {
this.table.insertFrom(row);
}
 
public RowValuesTableModel getModel() {
return this.table.getRowValuesTableModel();
}
 
public SQLTableElement getCreditElement() {
return this.credit;
}
 
public SQLTableElement getDebitElement() {
return this.debit;
}
 
public SQLTableElement getNumeroCompteElement() {
return this.tableElementNumeroCompte;
}
 
public void setCreateAutoActive(final boolean b) {
this.numeroCompteRenderer.setCreateActive(b);
this.table.revalidate();
this.table.repaint();
}
 
public void setRowDeviseValidAt(final boolean b, final int index) {
this.deviseRenderer.setValid(b, index);
 
}
 
public void editCellAt(final int row, final int column) {
assert SwingUtilities.isEventDispatchThread();
this.table.setColumnSelectionInterval(column, column);
this.table.setRowSelectionInterval(row, row);
this.table.editCellAt(row, column);
}
 
private long getContrepartie() {
assert SwingUtilities.isEventDispatchThread();
long totalCred = 0;
long totalDeb = 0;
final RowValuesTableModel model = this.table.getRowValuesTableModel();
final int creditIndex = model.getColumnIndexForElement(getCreditElement());
final int debitIndex = model.getColumnIndexForElement(getDebitElement());
for (int i = 0; i < this.table.getRowCount(); i++) {
if (model.isRowValid(i)) {
final Long fTc = (Long) model.getValueAt(i, creditIndex);
if (fTc != null) {
totalCred += fTc.longValue();
}
final Long fTd = (Long) model.getValueAt(i, debitIndex);
if (fTd != null) {
totalDeb += fTd.longValue();
}
}
}
return totalDeb - totalCred;
}
 
private long getSoldeRow(final int index) {
assert SwingUtilities.isEventDispatchThread();
if (index >= 0 && index < this.table.getRowCount()) {
final SQLRowValues rowVals = this.table.getRowValuesTableModel().getRowValuesAt(index);
return rowVals.getLong("DEBIT") - rowVals.getLong("CREDIT");
} else {
return 0;
}
}
 
public void fillEmptyEntryLabel(String previousText, String text) {
assert SwingUtilities.isEventDispatchThread();
if (text == null)
return;
RowValuesTableModel model = table.getRowValuesTableModel();
int size = model.getRowCount();
for (int i = 0; i < size; i++) {
SQLRowValues r = model.getRowValuesAt(i);
if (r.getString("NOM_ECRITURE") == null || r.getString("NOM_ECRITURE").trim().isEmpty() || r.getString("NOM_ECRITURE").trim().equals(previousText)) {
r.put("NOM_ECRITURE", text);
}
}
model.fireTableDataChanged();
}
 
public void mousePressed(final MouseEvent e) {
final int rowSel = this.table.getSelectedRow();
if (e.getButton() == MouseEvent.BUTTON3 && rowSel >= 0 && rowSel < this.table.getRowCount()) {
final JPopupMenu menuDroit = new JPopupMenu();
 
menuDroit.add(new AbstractAction("Contrepartie") {
public void actionPerformed(final ActionEvent ev) {
 
long l = getContrepartie();
if (SaisieJournalItemTable.this.table.getRowValuesTableModel().isRowValid(rowSel)) {
l += getSoldeRow(rowSel);
}
 
if (l > 0) {
SaisieJournalItemTable.this.table.getRowValuesTableModel().putValue(Long.valueOf(0), rowSel, "DEBIT");
SaisieJournalItemTable.this.table.getRowValuesTableModel().putValue(l, rowSel, "CREDIT");
} else {
SaisieJournalItemTable.this.table.getRowValuesTableModel().putValue(Long.valueOf(0), rowSel, "CREDIT");
SaisieJournalItemTable.this.table.getRowValuesTableModel().putValue(-l, rowSel, "DEBIT");
}
}
});
menuDroit.pack();
menuDroit.show(e.getComponent(), e.getPoint().x, e.getPoint().y);
menuDroit.setVisible(true);
}
}
 
public void mouseReleased(final MouseEvent e) {
}
 
public void mouseClicked(final MouseEvent e) {
}
 
public void mouseEntered(final MouseEvent e) {
}
 
public void mouseExited(final MouseEvent e) {
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/CompteCloturePreferencePanel.java
15,6 → 15,7
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement;
import org.openconcerto.erp.core.finance.accounting.element.JournalSQLElement;
import org.openconcerto.erp.model.ISQLCompteSelector;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.model.SQLBase;
22,6 → 23,8
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.sqlobject.ElementComboBox;
import org.openconcerto.sql.sqlobject.SQLRequestComboBox;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.preferences.DefaultPreferencePanel;
 
29,11 → 32,14
import java.awt.GridBagLayout;
import java.sql.SQLException;
 
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
 
public class CompteCloturePreferencePanel extends DefaultPreferencePanel {
private ISQLCompteSelector selCompteOuverture, selCompteFermeture, selCompteResultat, selCompteResultatPerte;
private SQLRequestComboBox selJournal;
private JCheckBox boxCompteSolde;
private final static SQLBase base = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete();
private static final SQLTable tablePrefCompte = base.getTable("PREFS_COMPTE");
private SQLRowValues rowPrefCompteVals = new SQLRowValues(tablePrefCompte);
88,6 → 94,28
this.selCompteResultatPerte.init();
this.add(this.selCompteResultatPerte, c);
 
// Compte résultat
c.gridy++;
c.gridx = 0;
c.weightx = 0;
this.add(new JLabel("Journal des à nouveaux"), c);
c.weightx = 1;
c.gridx++;
this.selJournal = new SQLRequestComboBox(false);
this.selJournal.uiInit(Configuration.getInstance().getDirectory().getElement("JOURNAL").createComboRequest());
this.add(this.selJournal, c);
 
// Compte résultat
c.gridy++;
c.gridx = 0;
c.weightx = 0;
this.add(new JLabel("Générer des écritures de fermetures et d'à nouveaux pour les comptes soldés"), c);
c.weightx = 1;
c.gridx++;
this.boxCompteSolde = new JCheckBox();
this.boxCompteSolde.setSelected(true);
this.add(this.boxCompteSolde, c);
 
// Spacer
 
JPanel p = new JPanel();
104,6 → 132,8
this.rowPrefCompteVals.put("ID_COMPTE_PCE_BILAN_F", this.selCompteFermeture.getValue());
this.rowPrefCompteVals.put("ID_COMPTE_PCE_RESULTAT", this.selCompteResultat.getValue());
this.rowPrefCompteVals.put("ID_COMPTE_PCE_RESULTAT_PERTE", this.selCompteResultat.getValue());
this.rowPrefCompteVals.put("ID_JOURNAL_AN", this.selJournal.getValue());
this.rowPrefCompteVals.put("CREATE_NUL_SOLDE_ECR", this.boxCompteSolde.isSelected());
 
try {
this.rowPrefCompteVals.update();
137,6 → 167,11
value = ComptePCESQLElement.getId(compte);
this.selCompteResultatPerte.setValue(value);
 
// AN
this.selJournal.setValue(JournalSQLElement.OD);
 
this.boxCompteSolde.setSelected(true);
 
} catch (Exception e) {
e.printStackTrace();
}
190,6 → 225,22
}
this.selCompteResultatPerte.setValue(value);
 
// Journal
SQLRowAccessor rowJ = this.rowPrefCompteVals.getForeign("ID_JOURNAL_AN");
if (rowJ == null || rowJ.isUndefined()) {
value = JournalSQLElement.OD;
} else {
value = rowJ.getID();
}
this.selJournal.setValue(value);
 
// Journal
boolean b = true;
if (this.rowPrefCompteVals.getObject("CREATE_NUL_SOLDE_ECR") != null) {
b = this.rowPrefCompteVals.getBoolean("CREATE_NUL_SOLDE_ECR");
}
this.boxCompteSolde.setSelected(b);
 
} catch (Exception e) {
e.printStackTrace();
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/CompteGestCommPreferencePanel.java
48,7 → 48,7
private SQLRowValues rowPrefCompteVals = new SQLRowValues(tablePrefCompte);
private JCheckBox checkHideCompteFacture = new JCheckBox("Ne pas afficher les comptes dans les factures.");
private JCheckBox checkHideCompteClient = new JCheckBox("Ne pas afficher les comptes dans les clients.");
private JCheckBox checkHideAnalytique = new JCheckBox("Ne pas afficher l'analityque dans les saisies au kilomètre.");
private JCheckBox checkHideAnalytique = new JCheckBox("Ne pas afficher l'analytique dans les saisies au kilomètre.");
 
public CompteGestCommPreferencePanel() {
super();
147,6 → 147,7
 
// Avance Compte client
c.gridy++;
c.gridx = 0;
c.weightx = 0;
this.add(new JLabel("Compte Avance Client"), c);
c.weightx = 1;
158,6 → 159,7
 
// Valeur à l'encaissement
c.gridy++;
c.gridx = 0;
c.weightx = 0;
this.add(new JLabel("Compte dépôt chèque"), c);
c.weightx = 1;
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/SaisieJournalAction.java
New file
0,0 → 1,33
/*
* 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.finance.accounting.ui;
 
import org.openconcerto.erp.action.CreateFrameAbstractAction;
import org.openconcerto.erp.core.common.ui.PanelFrame;
import org.openconcerto.sql.Configuration;
 
import javax.swing.Action;
import javax.swing.JFrame;
 
public class SaisieJournalAction extends CreateFrameAbstractAction {
 
public SaisieJournalAction() {
super();
this.putValue(Action.NAME, "Saisie au journal");
}
 
public JFrame createFrame() {
return new PanelFrame(new SaisieJournalPanel(Configuration.getInstance().getDirectory().getElement("ECRITURE")), "Saisie au journal");
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/ImportEcriturePanel.java
15,16 → 15,16
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement;
import org.openconcerto.erp.core.finance.accounting.element.JournalSQLElement;
import org.openconcerto.erp.generationEcritures.GenerationEcritures;
import org.openconcerto.erp.importer.ArrayTableModel;
import org.openconcerto.erp.importer.DataImporter;
import org.openconcerto.openoffice.ContentTypeVersioned;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.model.ConnectionHandlerNoSetup;
import org.openconcerto.sql.model.DBRoot;
import org.openconcerto.sql.model.SQLDataSource;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowListRSH;
import org.openconcerto.sql.model.SQLSelect;
import org.openconcerto.sql.utils.SQLUtils;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.ReloadPanel;
46,6 → 46,7
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import javax.swing.JButton;
57,20 → 58,12
 
public class ImportEcriturePanel extends JPanel {
 
private final Map<String, Integer> mapJournal;
private final SQLTable tableEcr;
private final Map<String, Integer> mapJournal = new HashMap<>();
private final Map<String, Integer> mapCompte = new HashMap<>();
 
public ImportEcriturePanel() {
super(new GridBagLayout());
 
this.tableEcr = Configuration.getInstance().getDirectory().getElement("ECRITURE").getTable();
this.mapJournal = new HashMap<String, Integer>();
this.mapJournal.put("HA", JournalSQLElement.ACHATS);
this.mapJournal.put("VE", JournalSQLElement.VENTES);
this.mapJournal.put("BA", JournalSQLElement.BANQUES);
this.mapJournal.put("CA", JournalSQLElement.CAISSES);
this.mapJournal.put("OD", JournalSQLElement.OD);
 
JLabel label = new JLabel("Import depuis un fichier CSV, XLS ou ODT.");
JLabel label2 = new JLabel("Le fichier doit contenir les colonnes :");
JLabel label3 = new JLabel(" - Date dd/MM/yyyy (dd/MM/yy pour le CSV)");
128,32 → 121,56
rlPanel.setMode(ReloadPanel.MODE_ROTATE);
if (fd.getFile() != null) {
 
final DBRoot rootSociete = ((ComptaPropsConfiguration) ComptaPropsConfiguration.getInstance()).getRootSociete();
new Thread() {
@Override
public void run() {
final File fileToImport = new File(fd.getDirectory(), fd.getFile());
try {
final ArrayTableModel model = loadData(fileToImport);
try {
final DBRoot rootSociete = ((ComptaPropsConfiguration) ComptaPropsConfiguration.getInstance()).getRootSociete();
SQLUtils.executeAtomic(rootSociete.getDBSystemRoot().getDataSource(), new ConnectionHandlerNoSetup<Object, IOException>() {
@Override
public Object handle(final SQLDataSource ds) throws SQLException, IOException {
 
try {
DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
importData(new File(fd.getDirectory(), fd.getFile()), "Import " + format.format(new Date()), frame);
SQLSelect sel = new SQLSelect();
sel.addSelectStar(rootSociete.getTable("JOURNAL"));
List<SQLRow> rowsJrnl = SQLRowListRSH.execute(sel);
for (SQLRow sqlRow : rowsJrnl) {
mapJournal.put(sqlRow.getString("CODE"), sqlRow.getID());
}
final DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
final String mouvementName = "Import " + format.format(new Date());
// Vérification des données
boolean ok = importTableModel(model, mouvementName, frame, true);
if (ok) {
// Importation des données
importTableModel(model, mouvementName, frame, false);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JOptionPane.showMessageDialog(null, "Importation des écritures terminée");
}
});
}
} catch (Exception exn) {
if (exn.getMessage().toLowerCase().contains("file format")) {
JOptionPane.showMessageDialog(ImportEcriturePanel.this, "Mauvais format de fichier");
} else {
ExceptionHandler.handle("Erreur pendant l'importation", exn);
}
}
return null;
}
});
} catch (IOException exn) {
ExceptionHandler.handle(frame, "Erreur lors de la lecture du fichier", exn);
} catch (SQLException exn) {
} catch (Exception exn) {
ExceptionHandler.handle(frame, "Erreur lors de l'insertion dans la base", exn);
}
 
} catch (Exception e) {
if (e.getMessage().toLowerCase().contains("file format")) {
JOptionPane.showMessageDialog(ImportEcriturePanel.this, "Format de fichier non pris en charge");
} else {
ExceptionHandler.handle(frame, "Erreur lors de la lecture du fichier " + fileToImport.getAbsolutePath(), e);
}
}
 
frame.dispose();
}
}.start();
162,106 → 179,145
});
}
 
public void importData(File f, String mvtName, final Frame owner) throws Exception {
DataImporter importer = new DataImporter(this.tableEcr);
public ArrayTableModel loadData(File f) throws IOException {
final DataImporter importer = new DataImporter();
importer.setSkipFirstLine(false);
DateFormat dF = new SimpleDateFormat("dd/MM/yyyy");
ArrayTableModel m = importer.createModelFrom(f);
return importer.createModelFrom(f);
}
 
GenerationEcritures gen = new GenerationEcritures();
int idMvt = gen.getNewMouvement("", 1, 1, mvtName);
 
long solde = 0;
for (int i = 0; i < m.getRowCount(); i++) {
 
final Object valueAt = m.getValueAt(i, 0);
 
if (valueAt == null) {
public boolean importTableModel(ArrayTableModel m, String mvtName, final Frame owner, boolean dryRun) throws Exception {
final DateFormat dF = new SimpleDateFormat("dd/MM/yyyy");
final GenerationEcritures gen = new GenerationEcritures();
int idMvt = -1;
if (!dryRun) {
idMvt = gen.getNewMouvement("", 1, 1, mvtName);
}
long soldeGlobal = 0;
String dateOrigin = null;
final int rowCount = m.getRowCount();
for (int i = 0; i < rowCount; i++) {
int column = 0;
try {
// Column 0
final Object firstValue = m.getValueAt(i, column);
if (firstValue == null) {
break;
}
final Date dateValue;
if (valueAt.getClass().isAssignableFrom(Date.class)) {
dateValue = (Date) valueAt;
if (firstValue.getClass().isAssignableFrom(Date.class)) {
dateValue = (Date) firstValue;
} else if (firstValue.toString().trim().isEmpty()) {
break;
} else {
if (valueAt.toString().trim().length() == 0) {
break;
dateValue = dF.parse(firstValue.toString());
}
dateValue = dF.parse(valueAt.toString());
final String dateStringValue = dF.format(dateValue);
if (dateOrigin == null) {
dateOrigin = dateStringValue;
}
// Mouvement
gen.mEcritures.put("ID_MOUVEMENT", idMvt);
// Date
gen.putValue("DATE", dateValue);
column++;
 
// Cpt
final String trim = m.getValueAt(i, 2).toString().trim();
String numCompt = trim;
if (trim.contains(".")) {
numCompt = trim.substring(0, trim.indexOf('.'));
if (!dateOrigin.equals(dateStringValue)) {
dateOrigin = dateStringValue;
if (!dryRun) {
idMvt = gen.getNewMouvement("", 1, 1, mvtName);
} else if (soldeGlobal != 0) {
final double soldeMvt = soldeGlobal / 100.0;
SwingUtilities.invokeLater(new Runnable() {
 
@Override
public void run() {
JOptionPane.showMessageDialog(null,
"Le mouvement du " + dateStringValue + " ne respecte pas la partie double (Solde du mouvement : " + soldeMvt + ")!\nImport annulé!");
}
int idCpt = ComptePCESQLElement.getId(numCompt);
gen.mEcritures.put("ID_COMPTE_PCE", idCpt);
});
return false;
}
}
 
// Montant
final String stringValueD = m.getValueAt(i, 5).toString();
long montantD = GestionDevise.parseLongCurrency(stringValueD);
final String stringValueC = m.getValueAt(i, 6).toString();
long montantC = GestionDevise.parseLongCurrency(stringValueC);
gen.mEcritures.put("CREDIT", montantC);
gen.mEcritures.put("DEBIT", montantD);
solde += montantD;
solde -= montantC;
 
System.err.println("(" + stringValueD + " : " + stringValueC + ") ---- (" + montantD + " : " + montantC + ")");
// Journal
 
final String valueJrnl = m.getValueAt(i, 1).toString();
if (mapJournal.get(valueJrnl) == null) {
 
try {
System.err.println("LOCKED");
 
// Column 1
final String valueJrnl = m.getValueAt(i, column).toString();
if (!dryRun && mapJournal.get(valueJrnl) == null) {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
// try {
JDialog diag = new JDialog(owner);
final JDialog diag = new JDialog(owner);
diag.setModal(true);
diag.setContentPane(new SelectionJournalImportPanel(valueJrnl, mapJournal, null));
diag.setTitle("Import écritures");
diag.setTitle("Import d'écritures");
diag.setLocationRelativeTo(null);
diag.pack();
diag.setVisible(true);
}
});
}
gen.putValue("ID_JOURNAL", this.mapJournal.get(valueJrnl));
column++;
 
System.err.println("PASSED");
} catch (InterruptedException e1) {
e1.printStackTrace();
// Compte
// Column 2
final String trim = m.getValueAt(i, column).toString().trim();
String numCompt = trim;
if (trim.contains(".")) {
numCompt = trim.substring(0, trim.indexOf('.'));
}
numCompt = numCompt.trim();
if (!dryRun) {
int idCpt = getOrCreateCompte(numCompt);
gen.putValue("ID_COMPTE_PCE", idCpt);
}
column++;
 
// Nom de la pièce
// Column 3
String stringPiece = m.getValueAt(i, column).toString();
if (stringPiece != null && stringPiece.length() > 0 && stringPiece.contains(".")) {
stringPiece = stringPiece.substring(0, stringPiece.indexOf('.'));
}
column++;
// Column 4
gen.putValue("NOM", m.getValueAt(i, column).toString() + " " + stringPiece);
column++;
 
gen.mEcritures.put("ID_JOURNAL", this.mapJournal.get(valueJrnl));
// Montants
// Column 5
final String stringValueD = m.getValueAt(i, column).toString();
long montantD = GestionDevise.parseLongCurrency(stringValueD);
column++;
// Column 6
final String stringValueC = m.getValueAt(i, column).toString();
long montantC = GestionDevise.parseLongCurrency(stringValueC);
gen.putValue("CREDIT", montantC);
gen.putValue("DEBIT", montantD);
soldeGlobal += montantD;
soldeGlobal -= montantC;
 
// Date
gen.mEcritures.put("DATE", dateValue);
// Mouvement
gen.putValue("ID_MOUVEMENT", idMvt);
 
String stringPiece = m.getValueAt(i, 3).toString();
if (stringPiece != null && stringPiece.length() > 0 && stringPiece.contains(".")) {
stringPiece = stringPiece.substring(0, stringPiece.indexOf('.'));
gen.putValue("NOM", m.getValueAt(i, 4).toString() + " " + stringPiece);
} catch (Exception e) {
throw new IllegalStateException("Donnée invalide sur la ligne " + (i + 1) + " , colonne " + (column + 1), e);
}
gen.mEcritures.put("NOM", m.getValueAt(i, 4).toString() + " " + stringPiece);
 
if (!dryRun) {
gen.ajoutEcriture();
}
if (solde != 0) {
throw new IllegalArgumentException("La partie double n'est respectée (solde = " + solde + "). Import annulé!");
}
SwingUtilities.invokeLater(new Runnable() {
 
@Override
public void run() {
JOptionPane.showMessageDialog(owner, "Importation des écritures terminée");
if (soldeGlobal != 0) {
throw new IllegalArgumentException("La partie double n'est respectée (solde = " + soldeGlobal + "). Import annulé!");
}
});
return true;
}
 
private int getOrCreateCompte(String numeroCompte) {
if (mapCompte.containsKey(numeroCompte)) {
return mapCompte.get(numeroCompte);
}
int id = ComptePCESQLElement.getId(numeroCompte);
mapCompte.put(numeroCompte, id);
return id;
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/LettragePanel.java
25,11 → 25,14
import org.openconcerto.erp.utils.UpperCaseFormatFilter;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.element.SQLElementDirectory;
import org.openconcerto.sql.model.SQLBase;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLSystem;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.request.ComboSQLRequest;
import org.openconcerto.sql.users.rights.UserRightsManager;
import org.openconcerto.sql.view.list.IListe;
import org.openconcerto.ui.DefaultGridBagConstraints;
102,6 → 105,7
public LettragePanel() {
this.setLayout(new GridBagLayout());
GridBagConstraints c = new DefaultGridBagConstraints();
final SQLElementDirectory directory = Configuration.getInstance().getDirectory();
 
this.modeSelect = allEcriture;
 
111,8 → 115,15
 
this.add(labelPointageCompte, c);
this.selCompte = new ISQLCompteSelector();
this.selCompte.init();
this.selCompte.setValue(ComptePCESQLElement.getId("5"));
SQLElement eltCpt = directory.getElement("COMPTE_PCE");
final ComboSQLRequest createComboRequest = eltCpt.createComboRequest();
String function = "REGEXP";
if (Configuration.getInstance().getBase().getServer().getSQLSystem() == SQLSystem.POSTGRESQL) {
function = "~";
}
createComboRequest.setWhere(new Where(eltCpt.getTable().getField("NUMERO"), function, "^4.*$"));
this.selCompte.init(eltCpt, createComboRequest);
this.selCompte.setValue(ComptePCESQLElement.getId("4"));
 
c.gridx++;
c.weightx = 1;
253,7 → 264,7
this.add(sepEcriture, c);
 
// Liste des ecritures
final EcritureSQLElement ecritureElem = Configuration.getInstance().getDirectory().getElement(EcritureSQLElement.class);
final EcritureSQLElement ecritureElem = directory.getElement(EcritureSQLElement.class);
this.ecriturePanel = new ListPanelEcritures(ecritureElem, new IListe(ecritureElem.createLettrageTableSource()));
c.gridx = 0;
c.gridy++;
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/SaisieJournalPanel.java
New file
0,0 → 1,281
/*
* 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.finance.accounting.ui;
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.ui.IListFilterDatePanel;
import org.openconcerto.erp.core.common.ui.IListTotalPanel;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.model.SQLField;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLSelect;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.sqlobject.SQLRequestComboBox;
import org.openconcerto.sql.view.list.IListe;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.ISpinnerIntegerModel;
import org.openconcerto.ui.coreanimation.Animator;
import org.openconcerto.utils.cc.ITransformer;
 
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
 
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
 
import com.ibm.icu.util.Calendar;
 
public class SaisieJournalPanel extends JPanel {
final SQLRequestComboBox boxMois = new SQLRequestComboBox();
final SQLRequestComboBox boxJournal = new SQLRequestComboBox();
final Calendar cal = Calendar.getInstance();
final JSpinner spin = new JSpinner(new ISpinnerIntegerModel(2000, cal.get(Calendar.YEAR) + 3, cal.get(Calendar.YEAR)));
 
public SaisieJournalPanel(SQLElement ecrElt) {
super(new GridBagLayout());
 
boxMois.uiInit(ecrElt.getDirectory().getElement("MOIS").createComboRequest());
 
boxJournal.uiInit(ecrElt.getDirectory().getElement("JOURNAL").createComboRequest());
 
animate();
 
final IListe listeEcr = new IListe(ecrElt.createTableSource());
listeEcr.getSource().getReq().setSelectTransf(new ITransformer<SQLSelect, SQLSelect>() {
 
@Override
public SQLSelect transformChecked(SQLSelect input) {
input.setWhere(Where.FALSE);
return input;
}
});
GridBagConstraints cListe = new DefaultGridBagConstraints();
cListe.fill = GridBagConstraints.BOTH;
cListe.gridwidth = 1;
cListe.weightx = 1;
cListe.weighty = 1;
 
JPanel panelEcr = new JPanel(new GridBagLayout());
panelEcr.add(listeEcr, cListe);
cListe.weighty = 0;
cListe.weightx = 0;
cListe.gridy = 4;
cListe.gridx = 0;
cListe.fill = GridBagConstraints.NONE;
cListe.anchor = GridBagConstraints.EAST;
 
List<SQLField> lFields = new ArrayList<SQLField>();
lFields.add(ecrElt.getTable().getField("DEBIT"));
lFields.add(ecrElt.getTable().getField("CREDIT"));
 
IListTotalPanel comp2 = new IListTotalPanel(listeEcr, lFields);
panelEcr.add(comp2, cListe);
 
final PropertyChangeListener l = new PropertyChangeListener() {
 
@Override
public void propertyChange(PropertyChangeEvent evt) {
final int wantedID = boxMois.getWantedID();
final int journalID = boxJournal.getSelectedId();
final Integer year = (Integer) spin.getValue();
setFilter(listeEcr, wantedID, journalID, year);
animate();
}
 
};
boxMois.addModelListener("wantedID", l);
boxJournal.addModelListener("wantedID", l);
spin.getModel().addChangeListener(new ChangeListener() {
 
@Override
public void stateChanged(ChangeEvent e) {
l.propertyChange(null);
 
}
});
 
JPanel headerPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 6, 4));
headerPanel.add(new JLabel("Journal"));
headerPanel.add(boxJournal);
headerPanel.add(new JLabel("Mois"));
headerPanel.add(boxMois);
headerPanel.add(new JLabel("Année"));
headerPanel.add(spin);
 
GridBagConstraints c = new DefaultGridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.gridx = 0;
c.weightx = 0;
c.weighty = 0;
c.fill = GridBagConstraints.BOTH;
this.add(headerPanel, c);
 
JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
 
c.gridwidth = GridBagConstraints.REMAINDER;
c.gridx = 0;
c.gridy++;
c.weightx = 1;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
split.setTopComponent(panelEcr);
final SQLRowValues defaultRowVals = new SQLRowValues(ecrElt.getTable().getTable("SAISIE_KM_ELEMENT"));
defaultRowVals.put("DEBIT", 0L);
defaultRowVals.put("CREDIT", 0L);
 
final JCheckBox boxAutoInsert = new JCheckBox("Insertion automatique");
 
final SaisieJournalItemTable table = new SaisieJournalItemTable(defaultRowVals, boxAutoInsert);
table.setPanel(this);
 
split.setBottomComponent(table);
 
this.add(split, c);
 
c.weightx = 0;
c.weighty = 0;
 
JPanel footerPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 6, 4));
 
//
 
boxAutoInsert.setSelected(true);
footerPanel.add(boxAutoInsert);
 
final JButton buttonAdd = new JButton("Ajouter");
buttonAdd.setEnabled(false);
buttonAdd.setVisible(false);
boxAutoInsert.addActionListener(new ActionListener() {
 
@Override
public void actionPerformed(ActionEvent e) {
buttonAdd.setVisible(!boxAutoInsert.isSelected());
buttonAdd.setEnabled(!boxAutoInsert.isSelected() && table.isSaisieValid());
}
});
footerPanel.add(buttonAdd);
 
final JButton buttonClose = new JButton("Fermer");
footerPanel.add(buttonClose);
 
c.gridwidth = GridBagConstraints.REMAINDER;
c.gridx = 0;
c.gridy++;
c.weightx = 0;
c.weighty = 0;
c.fill = GridBagConstraints.HORIZONTAL;
this.add(footerPanel, c);
buttonAdd.addActionListener(new ActionListener() {
 
@Override
public void actionPerformed(ActionEvent e) {
table.createSaisie(defaultRowVals);
}
});
buttonClose.addActionListener(new ActionListener() {
 
@Override
public void actionPerformed(ActionEvent e) {
((Window) SwingUtilities.getRoot(buttonClose)).dispose();
}
});
table.getModel().addTableModelListener(new TableModelListener() {
 
@Override
public void tableChanged(TableModelEvent e) {
buttonAdd.setEnabled(!boxAutoInsert.isSelected() && table.isSaisieValid());
 
}
});
}
 
public SQLRequestComboBox getBoxMois() {
return boxMois;
}
 
public SQLRequestComboBox getBoxJournal() {
return boxJournal;
}
 
private void animate() {
Animator.getInstance().animate(boxJournal, boxJournal.isEmpty());
Animator.getInstance().animate(boxMois, boxMois.isEmpty());
}
 
public int getSelectedYear() {
return (Integer) this.spin.getValue();
}
 
public int getSelectedMonth() {
return this.boxMois.getSelectedId() - 2;
}
 
public int getSelectedJournal() {
return this.boxJournal.getSelectedId();
}
 
public void setFilter(final IListe listeEcr, final int wantedID, final int journalID, final Integer year) {
if (wantedID != SQLRow.NONEXISTANT_ID && wantedID >= SQLRow.MIN_VALID_ID && journalID > 1) {
listeEcr.getSource().getReq().setSelectTransf(new ITransformer<SQLSelect, SQLSelect>() {
 
@Override
public SQLSelect transformChecked(SQLSelect input) {
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, year);
c.set(Calendar.MONTH, wantedID - 2);
c.set(Calendar.DAY_OF_MONTH, 1);
c.set(Calendar.HOUR, 0);
c.set(Calendar.MINUTE, 0);
Date d1 = c.getTime();
c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
c.set(Calendar.HOUR, 23);
c.set(Calendar.MINUTE, 59);
Date d2 = c.getTime();
input.setWhere(new Where(input.getTable("ECRITURE").getField("ID_JOURNAL"), "=", journalID).and(new Where(input.getTable("ECRITURE").getField("DATE"), d1, d2)));
return input;
}
});
} else {
listeEcr.getSource().getReq().setSelectTransf(new ITransformer<SQLSelect, SQLSelect>() {
 
@Override
public SQLSelect transformChecked(SQLSelect input) {
input.setWhere(Where.FALSE);
return input;
}
});
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/CloturePanel.java
323,6 → 323,7
if (myList.size() != 0) {
GenerationMvtVirement gen = new GenerationMvtVirement(1, id_Compte_Bilan_Cloture, 0, 0, "Fermeture du compte ", CloturePanel.this.rowExercice.getDate("DATE_FIN").getTime(),
JournalSQLElement.OD, "Fermeture des comptes");
gen.setFermeture(true);
for (int i = 0; i < myList.size(); i++) {
 
Object[] objTmp = (Object[]) myList.get(i);
357,8 → 358,12
 
// A nouveaux
Object[] compteAnouveau = CloturePanel.this.mRAN.keySet().toArray();
GenerationMvtVirement genAnouveaux = new GenerationMvtVirement(id_Compte_Bilan_Ouverture, 1, 0, 0, "A nouveaux", CloturePanel.this.dateOuv.getValue(), JournalSQLElement.OD,
"A nouveaux");
int journalAN = JournalSQLElement.OD;
if (rowPrefCompte.getObject("ID_JOURNAL_AN") != null && !rowPrefCompte.isForeignEmpty("ID_JOURNAL_AN")) {
journalAN = rowPrefCompte.getForeignID("ID_JOURNAL_AN");
}
GenerationMvtVirement genAnouveaux = new GenerationMvtVirement(id_Compte_Bilan_Ouverture, 1, 0, 0, "A nouveaux", CloturePanel.this.dateOuv.getValue(), journalAN, "A nouveaux");
genAnouveaux.setOuverture(true);
for (int i = 0; i < CloturePanel.this.mRAN.keySet().size(); i++) {
 
long solde = CloturePanel.this.mRAN.get(compteAnouveau[i]).longValue();
366,10 → 371,10
// if (solde != 0) {
if (solde > 0) {
genAnouveaux.setValues(id_Compte_Bilan_Ouverture, Integer.parseInt(compteAnouveau[i].toString()), 0, Math.abs(solde), "A nouveaux", CloturePanel.this.dateOuv.getValue(),
JournalSQLElement.OD, false);
journalAN, false);
} else {
genAnouveaux.setValues(id_Compte_Bilan_Ouverture, Integer.parseInt(compteAnouveau[i].toString()), Math.abs(solde), 0, "A nouveaux", CloturePanel.this.dateOuv.getValue(),
JournalSQLElement.OD, false);
journalAN, false);
}
genAnouveaux.genereMouvement();
// }
472,9 → 477,13
List myList = (List) ob;
 
if (myList != null && myList.size() != 0) {
 
boolean genSoldeNul = true;
if (rowPrefCompte.getObject("CREATE_NUL_SOLDE_ECR") != null) {
genSoldeNul = rowPrefCompte.getBoolean("CREATE_NUL_SOLDE_ECR");
}
GenerationMvtVirement genFerm = new GenerationMvtVirement(1, compteDest, 0, 0, "Fermeture du compte ", this.rowExercice.getDate("DATE_FIN").getTime(), JournalSQLElement.OD,
"Fermeture des comptes");
genFerm.setFermeture(true);
for (int i = 0; i < myList.size(); i++) {
 
Object[] objTmp = (Object[]) myList.get(i);
482,21 → 491,22
 
long solde = cptTmp.getTotalDebit() - cptTmp.getTotalCredit();
 
// if (solde != 0) {
if (genSoldeNul || solde != 0) {
if (compteBilan) {
this.mRAN.put(objTmp[0], Long.valueOf(solde));
}
 
if (solde > 0) {
genFerm.setValues(cptTmp.getId(), compteDest, 0, Math.abs(solde), "Fermeture du compte " + cptTmp.getNumero(), this.rowExercice.getDate("DATE_FIN").getTime(), JournalSQLElement.OD,
false);
genFerm.setValues(cptTmp.getId(), compteDest, 0, Math.abs(solde), "Fermeture du compte " + cptTmp.getNumero(), this.rowExercice.getDate("DATE_FIN").getTime(),
JournalSQLElement.OD, false);
} else {
 
genFerm.setValues(cptTmp.getId(), compteDest, Math.abs(solde), 0, "Fermeture du compte " + cptTmp.getNumero(), this.rowExercice.getDate("DATE_FIN").getTime(), JournalSQLElement.OD,
false);
genFerm.setValues(cptTmp.getId(), compteDest, Math.abs(solde), 0, "Fermeture du compte " + cptTmp.getNumero(), this.rowExercice.getDate("DATE_FIN").getTime(),
JournalSQLElement.OD, false);
}
genFerm.genereMouvement();
}
}
// }
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/accounting/ui/AnalytiqueItemTable.java
43,10 → 43,13
import java.util.List;
import java.util.Vector;
 
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ToolTipManager;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
 
public class AnalytiqueItemTable extends JPanel {
 
57,11 → 60,17
private static final SQLElement elt = Configuration.getInstance().getDirectory().getElement("ASSOCIATION_ANALYTIQUE");
private final SQLRowValues rowVals = new SQLRowValues(UndefinedRowValuesCache.getInstance().getDefaultRowValues(elt.getTable()));
 
private long totalArepartir;
 
public SQLRowValues getDefaultRowValues() {
return this.rowVals;
}
 
public AnalytiqueItemTable(boolean multilineEditor) {
this(multilineEditor, null);
}
 
public AnalytiqueItemTable(boolean multilineEditor, final AbstractAction actionOnValidate) {
setLayout(new GridBagLayout());
final GridBagConstraints c = new DefaultGridBagConstraints();
c.weightx = 1;
76,7 → 85,12
tableElementPourcent.setRenderer(new PercentTableCellRenderer());
list.add(tableElementPourcent);
 
final SQLTableElement tableElementMontant = new SQLTableElement(tableElement.getField("MONTANT"), Long.class, this.deviseCellEditor);
final SQLTableElement tableElementMontant = new SQLTableElement(tableElement.getField("MONTANT"), Long.class, this.deviseCellEditor) {
@Override
protected Object getDefaultNullValue() {
return 0L;
}
};
list.add(tableElementMontant);
 
rowVals.put("POURCENT", BigDecimal.ONE.movePointRight(2));
93,8 → 107,10
rowEcr = row;
getDefaultRowValues().put("POURCENT", BigDecimal.TEN.movePointRight(1));
getDefaultRowValues().put("MONTANT", rowEcr.getLong("DEBIT") - rowEcr.getLong("CREDIT"));
totalArepartir = rowEcr.getLong("DEBIT") - rowEcr.getLong("CREDIT");
super.insertFrom(row);
}
 
};
 
ToolTipManager.sharedInstance().unregisterComponent(this.table);
126,10 → 142,27
c.fill = GridBagConstraints.NONE;
c.gridwidth = GridBagConstraints.REMAINDER;
final JPanel panelButton = new JPanel();
buttonValider.setEnabled(false);
panelButton.add(buttonValider);
panelButton.add(buttonFermer);
this.add(panelButton, c);
model.addTableModelListener(new TableModelListener() {
 
@Override
public void tableChanged(TableModelEvent e) {
long totalReparti = 0;
if (totalArepartir != 0) {
for (int i = 0; i < model.getRowCount(); i++) {
totalReparti += model.getRowValuesAt(i).getLong("MONTANT");
}
 
getDefaultRowValues().put("POURCENT", new BigDecimal(totalReparti).divide(new BigDecimal(totalArepartir), DecimalUtils.HIGH_PRECISION).setScale(6, RoundingMode.HALF_UP));
getDefaultRowValues().put("MONTANT", totalArepartir - totalReparti);
}
buttonValider.setEnabled(totalReparti == totalArepartir);
 
}
});
final RowValuesMultiLineEditTable multiTable = (RowValuesMultiLineEditTable) this.table;
buttonValider.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent event) {
136,7 → 169,10
multiTable.updateField(multiTable.getForeignField(), multiTable.getRowValuesRoot());
// buttonValider.setEnabled(false);
multiTable.closeTable();
if (actionOnValidate != null) {
actionOnValidate.actionPerformed(null);
}
}
});
buttonFermer.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent event) {
172,8 → 208,8
BigDecimal pourcent = BigDecimal.ZERO;
 
if (total != 0) {
pourcent = new BigDecimal(montant).divide(new BigDecimal(total), DecimalUtils.HIGH_PRECISION).abs().movePointRight(2)
.setScale(tableElementPourcent.getDecimalDigits(), RoundingMode.HALF_UP);
pourcent = new BigDecimal(montant).divide(new BigDecimal(total), DecimalUtils.HIGH_PRECISION).abs().movePointRight(2).setScale(tableElementPourcent.getDecimalDigits(),
RoundingMode.HALF_UP);
}
return pourcent;
}
226,6 → 262,7
}
getDefaultRowValues().put("POURCENT", BigDecimal.TEN.movePointRight(1));
getDefaultRowValues().put("MONTANT", rowEcr.getLong("DEBIT") - rowEcr.getLong("CREDIT"));
this.totalArepartir = rowEcr.getLong("DEBIT") - rowEcr.getLong("CREDIT");
}
this.table.insertFrom(row);
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/payment/element/EncaisserMontantSQLElement.java
17,8 → 17,10
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.finance.accounting.element.EcritureSQLElement;
import org.openconcerto.erp.core.finance.payment.component.EncaisserMontantSQLComponent;
import org.openconcerto.erp.preferences.GestionCommercialeGlobalPreferencePanel;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.element.SQLComponent;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.element.TreesOfSQLRows;
import org.openconcerto.sql.model.FieldPath;
import org.openconcerto.sql.model.SQLRow;
30,10 → 32,19
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.model.graph.Path;
import org.openconcerto.sql.model.graph.PathBuilder;
import org.openconcerto.sql.preferences.SQLPreferences;
import org.openconcerto.sql.view.EditFrame;
import org.openconcerto.sql.view.EditPanel.EditMode;
import org.openconcerto.sql.view.EditPanelListener;
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.PredicateRowAction;
import org.openconcerto.sql.view.list.SQLTableModelSource;
import org.openconcerto.utils.CollectionUtils;
import org.openconcerto.utils.ExceptionHandler;
 
import java.awt.event.ActionEvent;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
43,12 → 54,39
import java.util.List;
import java.util.Set;
 
import javax.swing.AbstractAction;
 
public class EncaisserMontantSQLElement extends ComptaSQLConfElement {
 
public EncaisserMontantSQLElement() {
super("ENCAISSER_MONTANT", "un encaissement de montant", "encaissements de montant");
 
SQLPreferences prefs = new SQLPreferences(getTable().getDBRoot());
if (prefs.getBoolean(GestionCommercialeGlobalPreferencePanel.ACOMPTE_DEVIS, false)) {
PredicateRowAction actionClient = new PredicateRowAction(new AbstractAction("Annuler l'acompte") {
 
public void actionPerformed(ActionEvent e) {
final SQLRow selRow = IListe.get(e).getSelectedRow().asRow();
if (selRow.getBoolean("ACOMPTE")) {
int idDevis = selRow.getForeignID("ID_DEVIS");
try {
archive(selRow.getID());
String up = "UPDATE " + getTable().getTable("DEVIS").getSQLName().quote() + " set \"T_ACOMPTE\"=(SELECT COALESCE(SUM(\"MONTANT\"),0) from "
+ getTable().getSQLName().quote() + " where \"ID_DEVIS\"=" + idDevis + " AND \"ARCHIVE\"=0) where \"ID_DEVIS\"=" + idDevis;
getTable().getDBSystemRoot().getDataSource().execute(up);
} catch (SQLException e1) {
e1.printStackTrace();
ExceptionHandler.handle("Erreur lors de l'annulation de l'acompte!", e1);
}
}
}
}, false);
actionClient.setPredicate(IListeEvent.getSingleSelectionPredicate());
getRowActions().add(actionClient);
}
 
}
 
@Override
protected List<String> getListFields() {
final List<String> l = new ArrayList<String>();
58,6 → 96,10
// l.add("ID_MOUVEMENT");
l.add("ID_MODE_REGLEMENT");
l.add("MONTANT");
SQLPreferences prefs = new SQLPreferences(getTable().getDBRoot());
if (prefs.getBoolean(GestionCommercialeGlobalPreferencePanel.ACOMPTE_DEVIS, false)) {
l.add("ACOMPTE");
}
return l;
}
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/payment/ui/EncaisseMontantTable.java
17,6 → 17,7
import org.openconcerto.erp.core.common.ui.DeviseNiceTableCellRenderer;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.view.list.KeyTableCellRenderer;
import org.openconcerto.sql.view.list.RowValuesTable;
import org.openconcerto.sql.view.list.RowValuesTableModel;
126,6 → 127,10
this.table.insertFrom(field, id);
}
 
public void insertFrom(SQLRowValues rowVals) {
this.table.insertFrom(rowVals);
}
 
public RowValuesTableModel getModel() {
return this.table.getRowValuesTableModel();
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/finance/payment/component/EncaisserMontantSQLComponent.java
52,6 → 52,7
import java.util.Comparator;
import java.util.List;
 
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
117,6 → 118,10
this.add(this.date, c);
 
this.addSQLObject(comboClient, "ID_CLIENT");
 
final ElementComboBox comboD = new ElementComboBox();
this.addSQLObject(comboD, "ID_DEVIS");
 
// Nom
c.gridy++;
c.gridx = 0;
125,8 → 130,14
this.add(label, c);
c.gridx++;
c.weightx = 1;
c.gridwidth = 2;
this.add(this.nom, c);
c.gridx += 2;
c.gridwidth = GridBagConstraints.REMAINDER;
this.add(this.nom, c);
JCheckBox box = new JCheckBox(getLabelFor("ACOMPTE"));
box.setEnabled(false);
this.add(box, c);
addView(box, "ACOMPTE");
 
// Montant
c.gridwidth = 1;
192,7 → 203,7
 
// Selection du mode de reglement
if (getMode() == SQLComponent.Mode.INSERTION) {
if (rowCount >= 1) {
if (rowCount >= 1 && model.getRowValuesAt(0).getObject("ID_MOUVEMENT_ECHEANCE") != null && !model.getRowValuesAt(0).isForeignEmpty("ID_MOUVEMENT_ECHEANCE")) {
final int idScr = MouvementSQLElement.getSourceId(model.getRowValuesAt(0).getInt("ID_MOUVEMENT_ECHEANCE"));
SQLTable tableMvt = Configuration.getInstance().getDirectory().getElement("MOUVEMENT").getTable();
if (idScr > 1) {
210,7 → 221,7
int idTypeRegl = rowModeRegl.getInt("ID_TYPE_REGLEMENT");
SQLTable tableModeRegl = Configuration.getInstance().getDirectory().getElement("MODE_REGLEMENT").getTable();
SQLRowValues rowVals = new SQLRowValues(tableModeRegl);
if (idTypeRegl > TypeReglementSQLElement.TRAITE) {
if (idTypeRegl == TypeReglementSQLElement.INDEFINI) {
idTypeRegl = TypeReglementSQLElement.CHEQUE;
}
rowVals.put("ID_TYPE_REGLEMENT", idTypeRegl);
279,6 → 290,9
super.select(r);
if (r != null && r.getID() > 1) {
this.table.insertFrom("ID_ENCAISSER_MONTANT", r.getID());
} else if (r != null && r instanceof SQLRowValues) {
this.table.insertFrom((SQLRowValues) r);
 
}
}
 
312,6 → 326,8
 
// Mise a jour du montant de l'echeance
boolean supplement = false;
 
if (!row.getBoolean("ACOMPTE")) {
// On marque les echeances comme reglees
for (SQLRow sqlRow : l) {
 
329,6 → 345,7
// this.comboEcheance.rowDeleted(tableEch, rowEch.getID());
// getTable().fireTableModified(rowEch.getID());
}
}
// si le montant réglé est supérieur, on crée une facture de complément
if (supplement) {
SQLElement elt = Configuration.getInstance().getDirectory().getElement("SAISIE_VENTE_FACTURE");
/trunk/OpenConcerto/src/org/openconcerto/erp/core/humanresources/payroll/report/FichePayeSheetXML.java
15,6 → 15,7
 
import org.openconcerto.erp.core.common.element.StyleSQLElement;
import org.openconcerto.erp.generationDoc.AbstractSheetXMLWithDate;
import org.openconcerto.erp.preferences.PayeGlobalPreferencePanel;
import org.openconcerto.erp.preferences.PrinterNXProps;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.model.SQLRow;
23,6 → 24,7
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLSelect;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.preferences.SQLPreferences;
import org.openconcerto.utils.cc.ITransformer;
 
import java.math.BigDecimal;
39,8 → 41,7
 
public class FichePayeSheetXML extends AbstractSheetXMLWithDate {
 
private static boolean prefBulletinSimpl = true;
public static final String TEMPLATE_ID = prefBulletinSimpl ? "FichePayeSimplifiee" : "FichePaye";
public static final String TEMPLATE_ID = "FichePayeSimplifiee";
public static final String TEMPLATE_PROPERTY_NAME = "LocationFichePaye";
final Map<Integer, String> cotisationSimplifieeLink = new HashMap<>();
 
48,6 → 49,9
super(row);
this.printer = PrinterNXProps.getInstance().getStringProperty("FichePayePrinter");
this.elt = Configuration.getInstance().getDirectory().getElement("FICHE_PAYE");
SQLPreferences prefs = new SQLPreferences(elt.getTable().getDBRoot());
boolean prefBulletinSimpl = !prefs.getBoolean(PayeGlobalPreferencePanel.NOT_PAYE_SIMPL, Boolean.FALSE);
 
if (prefBulletinSimpl) {
SQLSelect sel = new SQLSelect();
sel.addSelect(row.getTable().getDBRoot().findTable("RUBRIQUE_COTISATION").getField("LIGNE_PAYE_SIMPLIFIEE"));
189,13 → 193,14
if (sqlRowAccessor.getBigDecimal("MONTANT_PAT") != null) {
montantPatLigne = sqlRowAccessor.getBigDecimal("MONTANT_PAT");
}
if (montantPatLigne.add(montantSalLigne).signum() != 0) {
ligneSimplifiee.put("NB_BASE", sqlRowAccessor.getBigDecimal("NB_BASE"));
ligneSimplifiee.put("MONTANT_SAL_DED", montantSalBulletinSimpl.add(montantSalLigne));
ligneSimplifiee.put("MONTANT_PAT", montantPatBulletinSimpl.add(montantPatLigne));
 
}
}
}
}
 
private StyleSQLElement eltStyle = Configuration.getInstance().getDirectory().getElement(StyleSQLElement.class);
 
260,10 → 265,15
 
@Override
public String getName() {
SQLPreferences prefs = new SQLPreferences(elt.getTable().getDBRoot());
boolean prefNomSal = prefs.getBoolean(PayeGlobalPreferencePanel.SALARIE_NOM_FICHIER, Boolean.FALSE);
SQLRow rowSal = row.getForeign("ID_SALARIE");
SQLRow rowMois = row.getForeign("ID_MOIS");
Calendar du = row.getDate("DU");
String suffix = "";
if (prefNomSal) {
suffix = "_" + rowSal.getString("NOM");
}
if (du != null && du.get(Calendar.DAY_OF_MONTH) != 1) {
suffix = "_" + du.get(Calendar.DAY_OF_MONTH);
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/humanresources/payroll/report/GroupePayeSimplifiee.java
30,7 → 30,7
Arrays.asList(LignePayeSimplifiee.RETRAITE_SECURITE_PLAF, LignePayeSimplifiee.RETRAITE_SECURITE_NON_PLAF, LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_TA,
LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_GMP, LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_TB, LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_TC,
LignePayeSimplifiee.RETRAITE_SUPPLEMENTAIRE)), FAMILLE("famille", false, Arrays.asList(LignePayeSimplifiee.FAMILLE_ALLOCATIONS)), CHOMAGE_NON_CADRE(
"chomage.noncadre", false, Arrays.asList(LignePayeSimplifiee.ASSURANCE_CHOMAGE_CHOMAGE)), CHOMAGE_CADRE("chomage.cadre", false,
"chomage.noncadre", false, Arrays.asList(LignePayeSimplifiee.ASSURANCE_CHOMAGE_CHOMAGE)), CHOMAGE_CADRE("chomage.cadre", true,
Arrays.asList(LignePayeSimplifiee.ASSURANCE_CHOMAGE_CHOMAGE, LignePayeSimplifiee.ASSURANCE_CHOMAGE_APEC)), AUTRES_CONTRIBUTIONS("autres",
false, Arrays.asList(LignePayeSimplifiee.AUTRES_CONTRIBUTIONS)), COTISATIONS_CONVENTION("cotisations.convention", false,
Arrays.asList(LignePayeSimplifiee.COTISATIONS_STATUAIRES)), CSG_NON_IMP("csg.nonimp", false,
/trunk/OpenConcerto/src/org/openconcerto/erp/core/humanresources/payroll/ui/EditionFichePayePanel.java
23,6 → 23,7
import org.openconcerto.ui.JDate;
import org.openconcerto.ui.preferences.DefaultProps;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.TableSorter;
 
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
33,8 → 34,10
import java.awt.event.MouseListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
 
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
128,7 → 131,10
 
// Liste des salariés
c.gridy++;
this.table = new JTable(this.model);
TableSorter s = new TableSorter(this.model);
this.table = new JTable(s);
s.setTableHeader(this.table.getTableHeader());
// this.table = new JTable(this.model);
this.table.addMouseListener(this);
c.fill = GridBagConstraints.BOTH;
c.weighty = 1;
160,6 → 166,7
@Override
public void propertyChange(PropertyChangeEvent evt) {
buttonValid.setEnabled(dateDeb.getValue() != null && dateFin.getValue() != null && dateDeb.getValue().before(dateFin.getValue()));
model.setDateLimit(dateDeb.getValue());
}
};
dateDeb.addValueListener(dateListener);
269,6 → 276,46
frameModifySal.setVisible(true);
}
});
 
menuDroit.add(new AbstractAction("Marquer tout \"A créer\"") {
 
public void actionPerformed(ActionEvent e) {
int rows = table.getModel().getRowCount();
for (int i = 0; i < rows; i++) {
table.getModel().setValueAt(Boolean.TRUE, i, 0);
}
model.fireTableDataChanged();
}
});
 
menuDroit.add(new AbstractAction("Désélectionner tout \"A créer\"") {
 
public void actionPerformed(ActionEvent e) {
int rows = table.getModel().getRowCount();
for (int i = 0; i < rows; i++) {
table.getModel().setValueAt(Boolean.FALSE, i, 0);
}
model.fireTableDataChanged();
}
});
 
menuDroit.add(new AbstractAction("Marquer la sélection \"A créer\"") {
 
public void actionPerformed(ActionEvent e) {
int[] selectedRows = table.getSelectedRows();
 
List<Integer> l = new ArrayList<>(selectedRows.length);
for (int i : selectedRows) {
l.add(i);
}
int rows = table.getModel().getRowCount();
for (int i = 0; i < rows; i++) {
table.setValueAt(l.contains(i), i, 0);
}
model.fireTableDataChanged();
}
});
 
menuDroit.show(e.getComponent(), e.getPoint().x, e.getPoint().y);
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/edm/folder-icon.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/OpenConcerto/src/org/openconcerto/erp/core/edm/folder-icon.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/OpenConcerto/src/org/openconcerto/erp/core/edm/AttachmentPanel.java
43,10 → 43,17
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
 
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
58,12 → 65,20
public class AttachmentPanel extends JPanel {
 
private final SQLRowAccessor rowSource;
private List<ListDataListener> listeners = new ArrayList<ListDataListener>();
private List<ListDataListener> listeners = new ArrayList<>();
 
private int idParent = 1;
private List<Integer> parents = new ArrayList<>();
private List<String> parentsNames = new ArrayList<>();
private Set<Attachment> selectedAttachments = new HashSet<>();
private List<FilePanel> filePanels = new ArrayList<>();
 
public AttachmentPanel(SQLRowAccessor rowSource) {
super();
this.rowSource = rowSource;
this.setLayout(new GridBagLayout());
this.parents.add(1);
this.parentsNames.add("Racine");
initUI();
setFocusable(true);
}
83,6 → 98,7
}
 
public void initUI() {
filePanels.clear();
this.invalidate();
this.removeAll();
GridBagConstraints c = new DefaultGridBagConstraints();
97,31 → 113,118
SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowVals);
Where where = new Where(tableAttachment.getField("SOURCE_TABLE"), "=", this.rowSource.getTable().getName());
where = where.and(new Where(tableAttachment.getField("SOURCE_ID"), "=", this.rowSource.getID()));
// TODO en premier les dossier, puis trier par nom
List<SQLRowValues> attachments = fetcher.fetch(where);
 
// AJout d'un fichier
final JButton addButton = new JButton("Ajouter un fichier");
this.add(addButton, c);
where = where.and(new Where(tableAttachment.getField("ID_PARENT"), "=", this.idParent));
 
c.gridx++;
c.weightx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
final List<SQLRowValues> rAttachments = fetcher.fetch(where);
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.WEST;
c.gridx = 0;
c.gridy = 0;
// Folder paths
if (this.parents.size() > 1) {
JPanel navPanel = new JPanel();
navPanel.setBackground(Color.WHITE);
navPanel.setBorder(BorderFactory.createLineBorder(Color.GRAY));
navPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 8, 2));
 
for (int i = 0; i < this.parents.size(); i++) {
JLabel b = new JLabel(" " + this.parentsNames.get(i) + " ");
b.setOpaque(true);
b.setBackground(new Color(230, 240, 255));
navPanel.add(b);
final int id = this.parents.get(i);
final int index = i;
if (i < this.parents.size() - 1) {
b.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
AttachmentPanel.this.idParent = id;
int nb = AttachmentPanel.this.parents.size() - index - 1;
for (int n = 0; n < nb; n++) {
final int pos = AttachmentPanel.this.parents.size() - 1;
AttachmentPanel.this.parents.remove(pos);
AttachmentPanel.this.parentsNames.remove(pos);
}
clearSelection();
initUI();
}
});
}
if (i < this.parents.size() - 1) {
b.setDropTarget(new DropTarget() {
 
@Override
public synchronized void drop(DropTargetDropEvent dtde) {
dtde.acceptDrop(DnDConstants.ACTION_MOVE);
Transferable t = dtde.getTransferable();
try {
for (int i = 0; i < t.getTransferDataFlavors().length; i++) {
final DataFlavor dataFlavor = t.getTransferDataFlavors()[i];
if (dataFlavor.isMimeTypeEqual(DataFlavor.javaSerializedObjectMimeType)) {
@SuppressWarnings("unchecked")
List<Attachment> attachments = (List<Attachment>) t.getTransferData(dataFlavor);
AttachmentUtils utils = new AttachmentUtils();
for (Attachment a : attachments) {
if (a.getParentId() != id) {
utils.move(a, id);
}
}
initUI();
break;
}
}
 
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
 
}
this.add(navPanel, c);
c.gridy++;
}
 
// Tools
final JPanel toolbar = new JPanel();
toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));
final JButton addFolderButton = new JButton("Nouveau dossier");
toolbar.add(addFolderButton);
final JButton addFileButton = new JButton("Ajouter un fichier");
toolbar.add(addFileButton);
 
final JProgressBar progressBar = new JProgressBar(0, 100);
progressBar.setValue(100);
progressBar.setStringPainted(true);
progressBar.setVisible(false);
this.add(progressBar, c);
c.fill = GridBagConstraints.BOTH;
c.gridx = 0;
toolbar.add(progressBar);
 
this.add(toolbar, c);
 
c.gridy++;
 
addButton.addActionListener(new ActionListener() {
addFolderButton.addActionListener(new ActionListener() {
 
@Override
public void actionPerformed(ActionEvent e) {
AttachmentUtils utils = new AttachmentUtils();
try {
utils.createFolder("Nouveau dossier", rowSource, idParent);
} catch (SQLException e1) {
JOptionPane.showMessageDialog(null, "Impossible de créer le dossier.", "Erreur", JOptionPane.ERROR_MESSAGE);
}
initUI();
 
}
});
 
addFileButton.addActionListener(new ActionListener() {
 
@Override
public void actionPerformed(ActionEvent e) {
final Frame frame = SwingThreadUtils.getAncestorOrSelf(Frame.class, (Component) e.getSource());
 
final FileDialog fd = new FileDialog(frame, "Ajouter un fichier", FileDialog.LOAD);
fd.setVisible(true);
final String fileName = fd.getFile();
128,7 → 231,7
if (fileName != null) {
File inFile = new File(fd.getDirectory(), fileName);
AttachmentUtils utils = new AttachmentUtils();
utils.uploadFile(inFile, rowSource);
utils.uploadFile(inFile, rowSource, idParent);
initUI();
}
}
138,7 → 241,7
@Override
public Dimension getPreferredSize() {
int w = getSize().width;
int nbPerRow = (w - 5) / (FilePanel.WIDTH + 5);
int nbPerRow = (w - 5) / (FilePanel.PREFERRED_WIDTH + 5);
if (nbPerRow < 1) {
nbPerRow = 1;
}
146,7 → 249,7
if (nbRow < 1) {
nbRow = 1;
}
return new Dimension(w, 5 + nbRow * (FilePanel.HEIGHT + 5));
return new Dimension(w, 5 + nbRow * (FilePanel.PREFERRED_HEIGHT + 5));
}
 
};
155,19 → 258,41
files.setScrollableWidth(ScrollablePanel.ScrollableSizeHint.FIT);
files.setScrollableHeight(ScrollablePanel.ScrollableSizeHint.NONE);
files.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
final List<Attachment> attachments = new ArrayList<>(rAttachments.size());
for (final SQLRowValues sqlRowValues : rAttachments) {
final Attachment a = new Attachment(sqlRowValues);
attachments.add(a);
}
Collections.sort(attachments, new Comparator<Attachment>() {
 
@Override
public int compare(Attachment o1, Attachment o2) {
if (o1.isFolder() && !o2.isFolder()) {
return -1;
}
if (!o1.isFolder() && o2.isFolder()) {
return 1;
}
return o1.getName().compareTo(o2.getName());
}
});
 
// Liste des fichiers
for (final SQLRowValues sqlRowValues : attachments) {
 
final FilePanel filePanel = new FilePanel(sqlRowValues, this);
for (final Attachment a : attachments) {
final FilePanel filePanel = new FilePanel(a, this);
this.filePanels.add(filePanel);
filePanel.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
if (e.getClickCount() == 2) {
Thread t = new Thread() {
if (a.isFolder()) {
openFolder(a);
} else {
final Thread t = new Thread() {
@Override
public void run() {
AttachmentUtils utils = new AttachmentUtils();
File f = utils.getFile(sqlRowValues);
File f = utils.getFile(a);
if (f == null) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
174,7 → 299,6
JOptionPane.showMessageDialog(null, "Impossible de récupérer le fichier.", "Erreur", JOptionPane.ERROR_MESSAGE);
}
});
System.err.println("Impossible de récupérer le fichier.");
} else {
try {
FileUtils.openFile(f);
181,6 → 305,7
} catch (IOException e1) {
ExceptionHandler.handle("Erreur lors de l'ouverture du fichier.", e1);
}
 
}
}
};
187,16 → 312,19
t.start();
}
}
}
 
});
files.add(filePanel);
 
}
c.gridwidth = 2;
 
c.gridx = 0;
c.gridy++;
c.weightx = 1;
c.weighty = 1;
JScrollPane scroll = new JScrollPane(files);
 
final JScrollPane scroll = new JScrollPane(files);
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scroll.setMinimumSize(new Dimension((int) (400 * 1.618), 400));
204,11 → 332,19
scroll.setBackground(Color.WHITE);
scroll.getViewport().setBackground(Color.WHITE);
this.add(scroll, c);
scroll.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
clearSelection();
updatePanels();
}
});
 
this.validate();
this.repaint();
 
DropTarget dt = new DropTarget() {
 
@Override
public synchronized void drop(DropTargetDropEvent dtde) {
dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
226,12 → 362,13
if (cancelledByUser) {
break;
}
utils.uploadFile(f, rowSource);
if (!f.isDirectory()) {
utils.uploadFile(f, rowSource, idParent);
}
}
initUI();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
241,4 → 378,40
fireDataChanged();
}
 
public Set<Attachment> getSelectedAttachments() {
return selectedAttachments;
}
 
public void select(Attachment a) {
this.selectedAttachments.add(a);
}
 
public void deselect(Attachment a) {
this.selectedAttachments.remove(a);
}
 
public boolean isSelected(Attachment a) {
return this.selectedAttachments.contains(a);
}
 
public void clearSelection() {
this.selectedAttachments.clear();
}
 
public void updatePanels() {
for (FilePanel p : this.filePanels) {
p.updateBackgroundFromState();
}
}
 
public void openFolder(final Attachment a) {
if (!a.isFolder()) {
throw new IllegalStateException(a.getName() + " is not a folder");
}
clearSelection();
this.idParent = a.getId();
this.parents.add(a.getId());
this.parentsNames.add(a.getName());
initUI();
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/edm/AttachmentUtils.java
13,18 → 13,6
package org.openconcerto.erp.core.edm;
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.generationDoc.DocumentLocalStorageManager;
import org.openconcerto.erp.storage.StorageEngine;
import org.openconcerto.erp.storage.StorageEngines;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.FileUtils;
import org.openconcerto.utils.sync.SyncClient;
 
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
37,10 → 25,21
 
import eu.medsea.mimeutil.MimeType;
import eu.medsea.mimeutil.MimeUtil;
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.generationDoc.DocumentLocalStorageManager;
import org.openconcerto.erp.storage.StorageEngine;
import org.openconcerto.erp.storage.StorageEngines;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.FileUtils;
import org.openconcerto.utils.sync.SyncClient;
 
public class AttachmentUtils {
 
public void uploadFile(File inFile, SQLRowAccessor rowSource) {
public void uploadFile(File inFile, SQLRowAccessor rowSource, int idParent) {
try {
 
// Création de la row attachment
47,11 → 46,12
SQLRowValues rowValsAttachment = new SQLRowValues(rowSource.getTable().getTable("ATTACHMENT"));
rowValsAttachment.put("SOURCE_TABLE", rowSource.getTable().getName());
rowValsAttachment.put("SOURCE_ID", rowSource.getID());
 
rowValsAttachment.put("ID_PARENT", idParent);
SQLRow rowAttachment = rowValsAttachment.insert();
int id = rowAttachment.getID();
 
String subDir = "EDM" + File.separator + String.valueOf((id / 1000) * 1000);
final String folderId = String.valueOf((id / 1000) * 1000);
String subDir = "EDM" + File.separator + folderId;
String fileNameID = String.valueOf(id);
String ext = "";
 
73,9 → 73,10
for (StorageEngine storageEngine : engines) {
if (storageEngine.isConfigured() && storageEngine.allowAutoStorage()) {
final String path = remotePath;
try {
 
try (FileInputStream in = new FileInputStream(inFile)) {
storageEngine.connect();
final BufferedInputStream inStream = new BufferedInputStream(new FileInputStream(inFile));
final BufferedInputStream inStream = new BufferedInputStream(in);
storageEngine.store(inStream, path, fileWithIDNAme, true);
inStream.close();
storageEngine.disconnect();
142,22 → 143,20
// needed for update count
 
rowValsAttachment.commit();
 
updateAttachmentsCountFromAttachment(rowValsAttachment);
} catch (IOException e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
final Attachment a = new Attachment(rowValsAttachment);
updateAttachmentsCountFromAttachment(a);
} catch (Exception e) {
e.printStackTrace();
}
}
 
public File getFile(SQLRowAccessor rowAttachment) {
public File getFile(Attachment attachment) {
 
final ComptaPropsConfiguration config = ComptaPropsConfiguration.getInstanceCompta();
boolean isOnCloud = config.isOnCloud();
 
String subDir = rowAttachment.getString("STORAGE_PATH");
String fileName = rowAttachment.getString("STORAGE_FILENAME");
String subDir = attachment.getStoragePath();
String fileName = attachment.getStorageFileName();
 
String remotePath = config.getSocieteID() + File.separator + subDir;
 
209,14 → 208,14
 
}
 
public void deleteFile(SQLRowAccessor rowAttachment) throws SQLException, IllegalStateException {
public void deleteFile(Attachment rowAttachment) throws SQLException, IllegalStateException {
 
final ComptaPropsConfiguration config = ComptaPropsConfiguration.getInstanceCompta();
if (!rowAttachment.isFolder()) {
boolean isOnCloud = config.isOnCloud();
 
// Delete File
String subDir = rowAttachment.getString("STORAGE_PATH");
String fileName = rowAttachment.getString("STORAGE_FILENAME");
String subDir = rowAttachment.getStoragePath();
String fileName = rowAttachment.getStorageFileName();
 
String remotePath = config.getSocieteID() + File.separator + subDir;
if (isOnCloud) {
238,21 → 237,23
}
}
}
 
}
// Delete Row
config.getDirectory().getElement(rowAttachment.getTable()).archive(rowAttachment.getID());
config.getDirectory().getElement(AttachmentSQLElement.class).archive(rowAttachment.getId());
updateAttachmentsCountFromAttachment(rowAttachment);
}
 
public void updateAttachmentsCountFromAttachment(SQLRowAccessor rowAttachment) {
SQLTable table = rowAttachment.getTable().getTable(rowAttachment.getString("SOURCE_TABLE"));
SQLRow source = table.getRow(rowAttachment.getInt("SOURCE_ID"));
private void updateAttachmentsCountFromAttachment(Attachment rowAttachment) {
final ComptaPropsConfiguration config = ComptaPropsConfiguration.getInstanceCompta();
final SQLTable attachmentTable = config.getDirectory().getElement(AttachmentSQLElement.class).getTable();
final SQLTable table = attachmentTable.getTable(rowAttachment.getSourceTable());
final SQLRow source = table.getRow(rowAttachment.getSourceId());
updateAttachmentsCountFromSource(source);
}
 
public void updateAttachmentsCountFromSource(SQLRow rowSource) {
SQLTable tableSource = rowSource.getTable();
SQLTable tableAtt = rowSource.getTable().getTable("ATTACHMENT");
private void updateAttachmentsCountFromSource(SQLRow rowSource) {
final SQLTable tableSource = rowSource.getTable();
final SQLTable tableAtt = rowSource.getTable().getTable("ATTACHMENT");
 
String req = "UPDATE " + tableSource.getSQLName().quote() + " SET " + tableSource.getField("ATTACHMENTS").getQuotedName() + "=(SELECT COUNT(*) FROM " + tableAtt.getSQLName().quote();
req += " WHERE " + tableAtt.getArchiveField().getQuotedName() + "=0 AND " + tableAtt.getField("SOURCE_TABLE").getQuotedName() + "='" + tableSource.getName() + "'";
261,4 → 262,44
tableSource.getDBSystemRoot().getDataSource().execute(req);
}
 
public static void rename(Attachment rowAttachment, String newName) {
rowAttachment.setName(newName);
final ComptaPropsConfiguration config = ComptaPropsConfiguration.getInstanceCompta();
final SQLTable attachmentTable = config.getDirectory().getElement(AttachmentSQLElement.class).getTable();
final String req = "UPDATE " + attachmentTable.getSQLName().quote() + " SET " + attachmentTable.getField("NAME").getQuotedName() + "=" + attachmentTable.getBase().quoteString(newName)
+ " WHERE " + attachmentTable.getKey().getQuotedName() + "=" + rowAttachment.getId();
attachmentTable.getDBSystemRoot().getDataSource().execute(req);
}
 
public void createFolder(String folderName, SQLRowAccessor rowSource, int idParent) throws SQLException {
final SQLRowValues rowValsAttachment = new SQLRowValues(rowSource.getTable().getTable("ATTACHMENT"));
rowValsAttachment.put("SOURCE_TABLE", rowSource.getTable().getName());
rowValsAttachment.put("SOURCE_ID", rowSource.getID());
rowValsAttachment.put("ID_PARENT", idParent);
rowValsAttachment.put("NAME", folderName);
rowValsAttachment.put("SOURCE_TABLE", rowSource.getTable().getName());
rowValsAttachment.put("SOURCE_ID", rowSource.getID());
rowValsAttachment.put("MIMETYPE", Attachment.MIMETYPE_FOLDER);
rowValsAttachment.put("FILENAME", "");
rowValsAttachment.put("FILESIZE", 0);
rowValsAttachment.put("STORAGE_PATH", "");
rowValsAttachment.put("STORAGE_FILENAME", "");
rowValsAttachment.commit();
}
 
public void move(Attachment a, Attachment folder) {
if (!folder.isFolder()) {
throw new IllegalArgumentException(folder + " is not a folder");
}
move(a, folder.getId());
}
 
public void move(Attachment a, int folderId) {
final ComptaPropsConfiguration config = ComptaPropsConfiguration.getInstanceCompta();
final SQLTable attachmentTable = config.getDirectory().getElement(AttachmentSQLElement.class).getTable();
final String req = "UPDATE " + attachmentTable.getSQLName().quote() + " SET " + attachmentTable.getField("ID_PARENT").getQuotedName() + "=" + folderId + " WHERE "
+ attachmentTable.getKey().getQuotedName() + "=" + a.getId();
attachmentTable.getDBSystemRoot().getDataSource().execute(req);
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/edm/AttachmentTransferable.java
New file
0,0 → 1,54
/*
* 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.edm;
 
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.List;
 
public class AttachmentTransferable implements Transferable {
 
private final List<Attachment> attachments;
private static final DataFlavor[] FLAVORS = new DataFlavor[] { new DataFlavor(String.class, "id") };
 
public AttachmentTransferable(List<Attachment> a) {
this.attachments = a;
}
 
public List<Attachment> getA() {
return attachments;
}
 
@Override
public DataFlavor[] getTransferDataFlavors() {
return FLAVORS;
}
 
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return FLAVORS[0].equals(flavor);
}
 
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
return attachments;
}
 
@Override
public String toString() {
return super.toString() + " " + this.attachments.size() + " attachements";
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/edm/AttachmentSQLElement.java
13,27 → 13,23
package org.openconcerto.erp.core.edm;
 
import java.util.ArrayList;
import java.util.List;
 
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.sql.element.BaseSQLComponent;
import org.openconcerto.sql.element.SQLComponent;
import org.openconcerto.ui.DefaultGridBagConstraints;
 
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.ArrayList;
import java.util.List;
 
public class AttachmentSQLElement extends ComptaSQLConfElement {
 
public final static String DIRECTORY_PREFS = "EDMdirectory";
public static final String DIRECTORY_PREFS = "EDMdirectory";
 
public AttachmentSQLElement() {
super("ATTACHMENT", "un attachement", "attachements");
 
}
 
protected List<String> getListFields() {
final List<String> l = new ArrayList<String>();
final List<String> l = new ArrayList<>(10);
l.add("SOURCE_TABLE");
l.add("SOURCE_ID");
l.add("NAME");
47,31 → 43,21
return l;
}
 
@Override
protected List<String> getComboFields() {
final List<String> l = new ArrayList<String>();
final List<String> l = new ArrayList<>(1);
l.add("NAME");
return l;
}
 
@Override
protected String getParentFFName() {
return "ID_PARENT";
}
 
public SQLComponent createComponent() {
return new BaseSQLComponent(this) {
public void addViews() {
this.setLayout(new GridBagLayout());
 
final GridBagConstraints c = new DefaultGridBagConstraints();
c.anchor = GridBagConstraints.NORTHEAST;
c.gridwidth = 1;
 
// // Numero
// JLabel labelNumero = new JLabel("Numéro ");
// this.add(labelNumero, c);
//
// JTextField textNumero = new JTextField();
// c.gridx++;
// c.weightx = 1;
// this.add(textNumero, c);
 
// this.addRequiredSQLObject(textNumero, "NUMERO");
}
};
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/edm/Attachment.java
New file
0,0 → 1,115
/*
* 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.edm;
 
import org.openconcerto.sql.model.SQLRowValues;
 
import java.io.Serializable;
 
public class Attachment implements Serializable {
private final int id;
private String name;
private String mimeType;
private String fileName;
private int fileSize;
private String storagePath;
private String storageFileName;
private String sourceTable;
private int sourceId;
private int parentId;
 
public static final String MIMETYPE_FOLDER = "inode/directory";
 
public Attachment(SQLRowValues rowAttachment) {
this.id = rowAttachment.getID();
this.name = rowAttachment.getString("NAME");
this.mimeType = rowAttachment.getString("MIMETYPE");
this.fileName = rowAttachment.getString("FILENAME");
this.fileSize = rowAttachment.getInt("FILESIZE");
this.storagePath = rowAttachment.getString("STORAGE_PATH");
this.storageFileName = rowAttachment.getString("STORAGE_FILENAME");
this.sourceTable = rowAttachment.getString("SOURCE_TABLE");
this.sourceId = rowAttachment.getInt("SOURCE_ID");
this.parentId = rowAttachment.getInt("ID_PARENT");
}
 
public int getId() {
return id;
}
 
public String getName() {
return name;
}
 
public void setName(String newName) {
this.name = newName;
}
 
public String getMimeType() {
return mimeType;
}
 
public String getFileName() {
return fileName;
}
 
public int getFileSize() {
return fileSize;
}
 
public String getStorageFileName() {
return storageFileName;
}
 
public String getStoragePath() {
return storagePath;
}
 
public String getSourceTable() {
return sourceTable;
}
 
public int getSourceId() {
return sourceId;
}
 
public int getParentId() {
return parentId;
}
 
public boolean isFolder() {
return this.mimeType.equals(MIMETYPE_FOLDER);
}
 
@Override
public String toString() {
return super.toString() + " attachment id:" + this.getId() + " name:" + this.getName();
}
 
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
 
if (this.getClass() != obj.getClass())
return false;
 
return this.getId() == ((Attachment) obj).getId();
}
 
@Override
public int hashCode() {
return getId();
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/edm/FilePanel.java
13,7 → 13,6
package org.openconcerto.erp.core.edm;
 
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.JImage;
23,6 → 22,7
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
31,8 → 31,11
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.sql.SQLException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
 
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
41,20 → 44,29
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
 
public class FilePanel extends JPanel {
JImage image = null;
private static final Color HOVER_COLOR = new Color(230, 240, 255);
private static final Color SELECTED_COLOR = new Color(193, 220, 252);
 
public static final int WIDTH = 128;
public static final int HEIGHT = 80;
JLabel label;
public static final int PREFERRED_WIDTH = 128;
public static final int PREFERRED_HEIGHT = 74;
 
public FilePanel(final SQLRowValues rowAttachment, final AttachmentPanel panelSource) {
final String name = rowAttachment.getString("NAME");
private final JLabel label;
private JImage image;
private AttachmentPanel attachmentPanel;
private Attachment attachment;
 
public FilePanel(final Attachment attachment, final AttachmentPanel panelSource) {
this.attachment = attachment;
this.attachmentPanel = panelSource;
final String name = attachment.getName();
this.setOpaque(true);
this.setLayout(new BorderLayout());
try {
String type = rowAttachment.getString("MIMETYPE");
String type = attachment.getMimeType();
if (type == null || type.trim().isEmpty() || type.equals("application/octet-stream")) {
image = new JImage(this.getClass().getResource("data-icon.png"));
} else if (type.equals("application/msword")) {
75,36 → 87,151
image = new JImage(this.getClass().getResource("xls-icon.png"));
} else if (type.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
image = new JImage(this.getClass().getResource("xlsx-icon.png"));
} else if (type.equals(Attachment.MIMETYPE_FOLDER)) {
image = new JImage(this.getClass().getResource("folder-icon.png"));
} else {
image = new JImage(this.getClass().getResource("data-icon.png"));
}
image.setOpaque(true);
 
image.setCenterImage(true);
this.add(image, BorderLayout.CENTER);
} catch (Exception e) {
e.printStackTrace();
ExceptionHandler.handle("image error", e);
}
setBackground(Color.WHITE);
label = new JLabel(name, SwingConstants.CENTER);
label.setOpaque(false);
label.setPreferredSize(new Dimension(label.getPreferredSize().width, new JTextField("a").getPreferredSize().height));
this.add(label, BorderLayout.SOUTH);
 
this.setPreferredSize(new Dimension(WIDTH, HEIGHT));
this.setMinimumSize(new Dimension(WIDTH, HEIGHT));
this.setPreferredSize(new Dimension(PREFERRED_WIDTH, PREFERRED_HEIGHT));
this.setMinimumSize(new Dimension(PREFERRED_WIDTH, PREFERRED_HEIGHT));
updateBackgroundFromState();
this.addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseDragged(MouseEvent e) {
final JComponent lab = (JComponent) e.getSource();
final TransferHandler handle = lab.getTransferHandler();
handle.exportAsDrag(lab, e, TransferHandler.MOVE);
}
});
this.addMouseListener(new MouseAdapter() {
 
@Override
public void mouseExited(MouseEvent e) {
setBackground(Color.WHITE);
updateBackgroundFromState();
}
 
@Override
public void mouseEntered(MouseEvent e) {
setBackground(new Color(230, 240, 255));
if (panelSource.isSelected(attachment)) {
setBackground(SELECTED_COLOR);
} else {
setBackground(HOVER_COLOR);
}
}
 
@Override
public void mousePressed(MouseEvent e) {
final boolean ctrlPressed = (e.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK;
if (!ctrlPressed) {
panelSource.select(attachment);
updateBackgroundFromState();
} else {
if (!panelSource.isSelected(FilePanel.this.attachment)) {
// Add to selection if selected
panelSource.select(attachment);
} else {
panelSource.deselect(attachment);
}
updateBackgroundFromState();
}
}
 
@Override
public void mouseReleased(MouseEvent e) {
final boolean ctrlPressed = (e.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK;
if (!ctrlPressed) {
panelSource.clearSelection();
panelSource.select(attachment);
panelSource.updatePanels();
}
}
});
initMenu(attachment, panelSource, name);
 
this.setTransferHandler(new TransferHandler("id") {
 
@SuppressWarnings("unchecked")
@Override
public boolean canImport(TransferSupport support) {
if (!attachment.isFolder())
return false;
try {
final List<Attachment> attachmentsToImport = (List<Attachment>) support.getTransferable().getTransferData(support.getDataFlavors()[0]);
for (Attachment a : attachmentsToImport) {
if (a.getId() == attachment.getId()) {
return false;
}
}
} catch (UnsupportedFlavorException | IOException e) {
e.printStackTrace();
}
return true;
}
 
@Override
public boolean importData(TransferSupport support) {
if (!canImport(support)) {
return false;
}
try {
@SuppressWarnings("unchecked")
final List<Attachment> attachmentsToImport = (List<Attachment>) support.getTransferable().getTransferData(support.getDataFlavors()[0]);
final AttachmentUtils utils = new AttachmentUtils();
for (Attachment a : attachmentsToImport) {
utils.move(a, attachment);
}
SwingUtilities.invokeLater(new Runnable() {
 
@Override
public void run() {
panelSource.initUI();
 
}
});
} catch (Exception e) {
e.printStackTrace();
}
 
return true;
}
 
@Override
protected java.awt.datatransfer.Transferable createTransferable(JComponent c) {
return new AttachmentTransferable(new ArrayList<>(attachmentPanel.getSelectedAttachments()));
}
 
@Override
public int getSourceActions(JComponent c) {
return MOVE;
}
 
}
 
);
 
}
 
public void updateBackgroundFromState() {
if (this.attachmentPanel.isSelected(this.attachment)) {
setBackground(SELECTED_COLOR);
} else {
setBackground(Color.WHITE);
}
}
 
private void initMenu(final Attachment attachment, final AttachmentPanel panelSource, final String name) {
final JPopupMenu menu = new JPopupMenu();
final JMenuItem menuItemDelete = new JMenuItem("Supprimer");
menuItemDelete.addActionListener(new ActionListener() {
111,17 → 238,21
 
@Override
public void actionPerformed(ActionEvent e) {
 
int value = JOptionPane.showConfirmDialog(FilePanel.this, "Voulez-vous vraiment supprimer ce fichier ?\n" + rowAttachment.getString("NAME") + "\nFichier orignal : "
+ rowAttachment.getString("FILENAME") + "\nType : " + rowAttachment.getString("MIMETYPE"), "Supprimer le ficher", JOptionPane.YES_NO_OPTION);
 
int value = 0;
if (attachment.isFolder()) {
value = JOptionPane.showConfirmDialog(FilePanel.this, "Voulez-vous vraiment supprimer ce dossier ?\n" + attachment.getName(), "Supprimer le dossier", JOptionPane.YES_NO_OPTION);
} else {
value = JOptionPane.showConfirmDialog(FilePanel.this,
"Voulez-vous vraiment supprimer ce fichier ?\n" + attachment.getName() + "\nFichier original : " + attachment.getFileName() + "\nType : " + attachment.getMimeType(),
"Supprimer le fichier", JOptionPane.YES_NO_OPTION);
}
if (value == JOptionPane.YES_OPTION) {
AttachmentUtils utils = new AttachmentUtils();
try {
utils.deleteFile(rowAttachment);
utils.deleteFile(attachment);
panelSource.initUI();
} catch (Exception e1) {
ExceptionHandler.handle("Erreur lors de la suppression du fichier!", e1);
ExceptionHandler.handle("Erreur lors de la suppression", e1);
}
}
 
141,15 → 272,15
FilePanel.this.repaint();
}
 
public void validText(final SQLRowValues rowAttachment, final String name, final JTextField text) {
public void validText(final Attachment attachment, final String name, final JTextField text) {
try {
String newName = text.getText();
if (newName.trim().isEmpty()) {
newName = name;
}
rowAttachment.put("NAME", newName).commit();
AttachmentUtils.rename(attachment, newName);
label.setText(newName);
} catch (SQLException e1) {
} catch (Exception e1) {
ExceptionHandler.handle("Erreur lors du renommage du fichier!", e1);
}
}
156,13 → 287,13
 
@Override
public void actionPerformed(ActionEvent e) {
final String name = rowAttachment.getString("NAME");
final String name = attachment.getName();
 
text.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
validText(rowAttachment, name, text);
validText(attachment, name, text);
stopNameEditing();
} else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
stopNameEditing();
174,12 → 305,13
 
@Override
public void focusLost(FocusEvent e) {
validText(rowAttachment, name, text);
validText(attachment, name, text);
stopNameEditing();
}
 
@Override
public void focusGained(FocusEvent e) {
// Nothing to do here
}
 
});
187,7 → 319,7
 
@Override
public void mouseExited(MouseEvent e) {
validText(rowAttachment, name, text);
validText(attachment, name, text);
stopNameEditing();
}
 
206,6 → 338,7
 
});
menu.add(menuItemRename);
if (!attachment.isFolder()) {
menu.addSeparator();
JMenuItem menuItemProperties = new JMenuItem("Propriétés");
menuItemProperties.addActionListener(new ActionListener() {
213,7 → 346,7
@Override
public void actionPerformed(ActionEvent e) {
JFrame f = new JFrame();
f.setTitle("Propriétés de " + rowAttachment.getString("NAME"));
f.setTitle("Propriétés de " + attachment.getName());
JPanel p = new JPanel();
p.setLayout(new GridBagLayout());
GridBagConstraints c = new DefaultGridBagConstraints();
222,7 → 355,7
p.add(new JLabel("Nom : ", SwingConstants.RIGHT), c);
c.gridx++;
c.weightx = 1;
p.add(new JLabel(rowAttachment.getString("NAME")), c);
p.add(new JLabel(attachment.getName()), c);
c.gridy++;
// Type
c.gridx = 0;
230,7 → 363,7
p.add(new JLabel("Type : ", SwingConstants.RIGHT), c);
c.gridx++;
c.weightx = 1;
p.add(new JLabel(rowAttachment.getString("MIMETYPE")), c);
p.add(new JLabel(attachment.getMimeType()), c);
c.gridy++;
// FileName
c.gridx = 0;
238,7 → 371,7
p.add(new JLabel("Fichier original : ", SwingConstants.RIGHT), c);
c.gridx++;
c.weightx = 1;
p.add(new JLabel(rowAttachment.getString("FILENAME")), c);
p.add(new JLabel(attachment.getFileName()), c);
c.gridy++;
// Size
c.gridx = 0;
246,7 → 379,7
p.add(new JLabel("Taille : ", SwingConstants.RIGHT), c);
c.gridx++;
c.weightx = 1;
p.add(new JLabel(rowAttachment.getInt("FILESIZE") + " octets"), c);
p.add(new JLabel(attachment.getFileSize() + " octets"), c);
 
// Spacer
c.gridx = 1;
266,6 → 399,7
}
});
menu.add(menuItemProperties);
}
setComponentPopupMenu(menu);
}
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/product/component/ReferenceArticleSQLComponent.java
426,8 → 426,20
panel.add(textTare, c);
addView(textTare, "TARE");
 
c.weightx = 0;
c.gridy++;
c.gridx = 0;
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;
1340,6 → 1352,7
}
 
private void setTextHT() {
if (!isFilling()) {
this.textPVHT.getDocument().removeDocumentListener(this.htDocListener);
final BigDecimal ttc = StringUtils.getBigDecimalFromUserText(this.textPVTTC.getText());
if (ttc != null) {
1353,8 → 1366,10
}
this.textPVHT.getDocument().addDocumentListener(this.htDocListener);
}
}
 
private void setTextTTC() {
if (!isFilling()) {
this.textPVTTC.getDocument().removeDocumentListener(this.ttcDocListener);
final BigDecimal ht = StringUtils.getBigDecimalFromUserText(this.textPVHT.getText());
if (ht != null) {
1368,6 → 1383,7
}
this.textPVTTC.getDocument().addDocumentListener(this.ttcDocListener);
}
}
 
/**
* calcul du prix achat et vente ainsi que le poids total pour la piece
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/POSConfiguration.java
21,6 → 21,7
import org.openconcerto.erp.core.finance.accounting.element.JournalSQLElement;
import org.openconcerto.erp.core.finance.payment.element.TypeReglementSQLElement;
import org.openconcerto.erp.core.finance.tax.model.TaxeCache;
import org.openconcerto.erp.core.sales.pos.io.Printable;
import org.openconcerto.erp.core.sales.pos.io.TicketPrinter;
import org.openconcerto.erp.core.sales.pos.model.Article;
import org.openconcerto.erp.core.sales.pos.model.Client;
40,7 → 41,6
import org.openconcerto.erp.preferences.DefaultNXProps;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.model.SQLBackgroundTableCache;
import org.openconcerto.sql.model.SQLBase;
import org.openconcerto.sql.model.SQLDataSource;
import org.openconcerto.sql.model.SQLRow;
298,7 → 298,6
}
 
public final int importReceipts(final List<Ticket> tickets, final List<ReceiptEntry> entries) throws SQLException {
 
if (entries != null && entries.size() != tickets.size())
throw new IllegalArgumentException("Size mismatch");
 
685,12 → 684,19
 
}
 
public void print(Ticket ticket) {
public void print(Printable ticket) {
print(ticket, this.ticketPrinterConf1);
print(ticket, this.ticketPrinterConf2);
}
 
public void print(Ticket ticket, TicketPrinterConfiguration conf) {
public void printOnceOnFirstPrinter(Printable ticket) {
if (this.ticketPrinterConf1.isValid()) {
final TicketPrinter prt = this.ticketPrinterConf1.createTicketPrinter();
ticket.print(prt, this.ticketPrinterConf1.getTicketWidth());
}
}
 
public void print(Printable ticket, TicketPrinterConfiguration conf) {
if (conf.isValid() && conf.getCopyCount() > 0) {
final TicketPrinter prt = conf.createTicketPrinter();
for (int i = 0; i < conf.getCopyCount(); i++) {
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/ui/FilteredListModel.java
27,11 → 27,12
import javax.swing.SwingUtilities;
 
public class FilteredListModel extends AbstractListModel {
private final List<Object> items = new ArrayList<Object>();
private final Stack<String> searches = new Stack<String>();
Thread t;
private final List<Object> items = new ArrayList<>();
private final Stack<String> searches = new Stack<>();
private final Thread t;
 
FilteredListModel() {
public FilteredListModel() {
items.addAll(Categorie.getFavoriteProducts());
final List<Categorie> l = new ArrayList<Categorie>(Categorie.getAllCategories());
Collections.sort(l, new Comparator<Categorie>() {
 
103,6 → 104,7
@Override
public void run() {
items.clear();
items.addAll(Categorie.getFavoriteProducts());
items.addAll(newitems);
fireContentsChanged(this, 0, items.size());
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/ui/TextAreaTicketPrinter.java
16,16 → 16,21
import org.openconcerto.erp.core.sales.pos.io.TicketPrinter;
import org.openconcerto.erp.core.sales.pos.model.TicketLine;
 
import javax.swing.JTextArea;
import java.awt.Font;
 
public class TextAreaTicketPrinter extends JTextArea implements TicketPrinter {
import javax.swing.JEditorPane;
 
public class TextAreaTicketPrinter extends JEditorPane implements TicketPrinter {
 
private String docName = "unknown doc";
private StringBuffer text = new StringBuffer();
private String retour = "\n";
private final String retour = "<br/>";
 
public TextAreaTicketPrinter() {
super();
this.setContentType("text/html");
this.setEditable(false);
this.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 14));
}
 
@Override
40,10 → 45,24
final boolean barCode = mode == TicketPrinter.BARCODE;
if (barCode) {
this.text.append("* ");
} else if (mode == TicketPrinter.BOLD) {
this.text.append("<b>");
} else if (mode == TicketPrinter.BOLD_LARGE) {
this.text.append("<big>");
this.text.append("<b>");
} else if (mode == TicketPrinter.UNDERLINE) {
this.text.append("<u>");
}
this.text.append(t);
if (barCode) {
this.text.append(" *");
} else if (mode == TicketPrinter.BOLD) {
this.text.append("</b>");
} else if (mode == TicketPrinter.BOLD_LARGE) {
this.text.append("</b>");
this.text.append("</big>");
} else if (mode == TicketPrinter.UNDERLINE) {
this.text.append("</u>");
}
 
this.text.append(this.retour);
51,7 → 70,7
 
@Override
public void printBuffer() throws Exception {
setText(this.text.toString());
setText("<pre>" + this.text.toString() + "</pre>");
}
 
public void clear() {
70,7 → 89,12
}
 
@Override
public void clearBuffer() {
public void clearBuffer(final String docName) {
this.clear();
this.docName = docName;
}
 
public final String getDocName() {
return this.docName;
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/ui/PriceEditorPanel.java
205,11 → 205,7
if (this.rHT.isSelected()) {
r = this.htTextField.getValue();
} else if (this.rTTC.isSelected()) {
final BigDecimal value = this.ttcTextField.getValue();
if (value != null)
r = Article.computePriceWithoutTax(value, this.article.getIdTaxe());
else
r = BigDecimal.ZERO;
r = Article.computePriceWithoutTax(this.ttcTextField.getValue(), this.article.getIdTaxe());
} else if (this.rDiscountPercent.isSelected()) {
r = this.article.getPriceWithoutTax().subtract(this.article.getPriceWithoutTax().multiply(this.discountPercentTextField.getValue().divide(new BigDecimal(100))));
} else if (this.rDiscount.isSelected()) {
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/ui/ArticleSearchPanel.java
49,6 → 49,7
public class ArticleSearchPanel extends JPanel implements ListSelectionListener, CaisseListener {
private final ScrollableList list;
private final CaisseControler controler;
private final JTextField textField = new JTextField();
 
public ArticleSearchPanel(final CaisseControler controler) {
this.controler = controler;
72,6 → 73,10
if (object instanceof Article) {
Article article = (Article) object;
ArticleSelector.paintArticle(f1, g, article, isSelected, posY, this.getWidth(), this.getCellHeight(), 36, 10);
if (Categorie.getFavoriteProducts().contains(article)) {
g.setColor(Color.ORANGE);
g.fillRect(0, posY, 6, this.getCellHeight());
}
} else if (object instanceof Categorie) {
Categorie c = (Categorie) object;
paintCategorie(f1, f2, g, c, isSelected, posY, this.getWidth(), this.getCellHeight());
78,6 → 83,22
 
}
}
 
@Override
public void mouseReleased(MouseEvent event) {
if ((event.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK) {
final Object obj = getSelectedValue();
if (obj != null && obj instanceof Article) {
Article product = (Article) obj;
Categorie.toggleFavoriteState(product);
controler.saveFavoriteProductsIds(Categorie.getFavoriteProducts());
model.setFilter(textField.getText());
list.scrollToOffset(0);
}
} else {
super.mouseReleased(event);
}
}
};
 
// Bar
100,6 → 121,13
});
 
bar.setTitle("Articles");
bar.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
list.scrollToOffset(0);
}
});
 
c.fill = GridBagConstraints.BOTH;
c.gridwidth = 2;
this.add(bar, c);
121,7 → 149,7
c.gridwidth = 1;
c.weightx = 0;
this.add(label, c);
final JTextField textField = new JTextField();
 
textField.setBorder(BorderFactory.createLineBorder(CaissePanel.DARK_BLUE, 1));
textField.setFont(f1);
c.weightx = 1;
144,6 → 172,7
@Override
public void changedUpdate(DocumentEvent e) {
model.setFilter(textField.getText());
controler.setArticleSelected(null);
}
});
list.addListSelectionListener(this);
250,9 → 279,10
 
@Override
public void caisseStateChanged() {
 
final Article articleSelected = controler.getArticleSelected();
System.err.println("ArticleSearchPanel.caisseStateChanged() article selected : " + articleSelected);
if (articleSelected == null) {
list.clearSelection();
return;
}
Object selectedValue = null;
261,9 → 291,11
} catch (Exception e) {
e.printStackTrace();
}
if (articleSelected != null && !articleSelected.equals(selectedValue)) {
list.setSelectedValue(articleSelected, true);
if (selectedValue == null || !articleSelected.equals(selectedValue)) {
boolean found = list.setSelectedValue(articleSelected, true);
if (!found) {
list.clearSelection();
}
 
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/ui/CaisseControler.java
27,10 → 27,15
import org.openconcerto.erp.core.sales.pos.model.RegisterLogEntry.ReceiptEntry;
import org.openconcerto.erp.core.sales.pos.model.RegisterState.Status;
import org.openconcerto.erp.core.sales.pos.model.Ticket;
import org.openconcerto.erp.preferences.TemplateNXProps;
import org.openconcerto.sql.element.SQLElementDirectory;
import org.openconcerto.utils.FileUtils;
import org.openconcerto.utils.Pair;
import org.openconcerto.utils.StringUtils;
 
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
38,7 → 43,9
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
 
94,6 → 101,10
this.setLCDDefaultDisplay(0);
}
 
public final CaisseFrame getCaisseFrame() {
return this.caisseFrame;
}
 
public Article getArticleSelected() {
return this.articleSelected;
}
326,15 → 337,12
return s;
}
 
public void setTicketDate() {
public Ticket saveAndClearTicket(final RegisterFiles files, final SQLElementDirectory dir) throws IOException, SQLException {
if (!this.isTicketValid())
return null;
this.t.setCreationCal(Calendar.getInstance());
}
 
public void saveAndClearTicket(final RegisterFiles files, final SQLElementDirectory dir) throws IOException, SQLException {
if (this.t.getTotalInCents() > 0) {
if (this.getPaidTotal() >= this.getTotal()) {
 
final String fileHash = this.t.save(files, dir);
final Ticket res = this.t;
final int newIndex = this.t.getNumber() + 1;
t = new Ticket(POSConfiguration.getInstance().getPosID(), newIndex, fileHash);
p1 = new Paiement(Paiement.ESPECES);
346,26 → 354,13
this.setPaiementSelected(null);
this.setArticleSelected(null);
client = Client.NONE;
return res;
}
}
}
 
public int getTicketNumber() {
return this.t.getNumber();
}
 
public void printTicket() {
if (this.t.getTotalInCents() > 0) {
if (this.getPaidTotal() >= this.getTotal()) {
POSConfiguration.getInstance().print(this.t);
} else {
System.err.println("Ticket not printed because not paid");
}
} else {
System.err.println("Ticket not printed total <= 0");
}
}
 
public void openDrawer() {
try {
final TicketPrinter prt = POSConfiguration.getInstance().getTicketPrinterConfiguration1().createTicketPrinter();
476,6 → 471,43
}
 
public boolean isTicketValid() {
return (this.t.getTotalInCents() > 0) && (this.getPaidTotal() >= this.getTotal());
return (!this.t.getArticles().isEmpty()) && (this.getPaidTotal() >= this.getTotal());
}
 
public Set<Integer> loadFavoriteProductsIds() {
final TemplateNXProps nxprops = (TemplateNXProps) TemplateNXProps.getInstance();
final File f = new File(nxprops.getDefaultStringValue(), "favorites.txt");
System.out.println("CaisseControler.saveFavoriteProductsIds() loading favorites from " + f.getAbsolutePath());
final Set<Integer> result = new HashSet<>();
if (f.exists()) {
try {
String s = FileUtils.read(f);
List<String> sIds = StringUtils.fastSplit(s, ',');
for (String string : sIds) {
if (!string.isEmpty()) {
result.add(Integer.parseInt(string));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
 
public void saveFavoriteProductsIds(List<Article> products) {
final TemplateNXProps nxprops = (TemplateNXProps) TemplateNXProps.getInstance();
final File f = new File(nxprops.getDefaultStringValue(), "favorites.txt");
System.out.println("CaisseControler.saveFavoriteProductsIds() saving favorites to " + f.getAbsolutePath());
try (FileOutputStream fOut = new FileOutputStream(f);) {
for (Article product : products) {
fOut.write(String.valueOf(product.getId()).getBytes());
fOut.write(',');
}
fOut.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/ui/RegisterSummary.java
New file
0,0 → 1,166
/*
* 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.pos.ui;
 
import org.openconcerto.erp.core.sales.pos.POSConfiguration;
import org.openconcerto.erp.core.sales.pos.io.DefaultTicketPrinter;
import org.openconcerto.erp.core.sales.pos.io.Printable;
import org.openconcerto.erp.core.sales.pos.io.TicketPrinter;
import org.openconcerto.erp.core.sales.pos.model.Paiement;
import org.openconcerto.erp.core.sales.pos.model.RegisterLog;
import org.openconcerto.erp.core.sales.pos.model.RegisterState;
import org.openconcerto.erp.core.sales.pos.model.Ticket;
import org.openconcerto.erp.core.sales.pos.model.RegisterState.Status;
 
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.Map.Entry;
import java.util.logging.Level;
 
abstract class RegisterSummary implements Printable {
 
private final String name;
private final RegisterLog log;
 
protected RegisterSummary(final String name, final RegisterLog log) {
super();
this.name = name;
this.log = log;
}
 
public boolean isPrintingTicketsList() {
return true;
}
 
public final RegisterLog getLog() {
return this.log;
}
 
public abstract String getLabel();
 
protected abstract List<Ticket> getReceipts() throws ParseException;
 
@Override
public void print(TicketPrinter prt, int ticketWidth) {
final DateFormat dateFormat = new SimpleDateFormat("dd/MM/YYYY à HH:mm:ss");
final String title = this.name + " de la caisse " + getLog().getRegisterID();
prt.clearBuffer(title);
try {
final List<Ticket> receipts = this.getReceipts();
 
final Map<Ticket, Map<String, BigDecimal>> typesByReceipt = new LinkedHashMap<>();
final Map<Ticket, BigDecimal> paidByReceipt = new LinkedHashMap<>();
final Map<Ticket, BigDecimal> valueByReceipt = new LinkedHashMap<>();
 
final Map<String, BigDecimal> totalByType = new TreeMap<>();
BigDecimal total = BigDecimal.ZERO;
BigDecimal totalPaid = BigDecimal.ZERO;
 
for (final Ticket t : receipts) {
final int receiptInCents = t.getTotalInCents();
final BigDecimal receiptValue = BigDecimal.valueOf(receiptInCents).movePointLeft(2);
 
BigDecimal receiptPaid = BigDecimal.ZERO;
final Map<String, BigDecimal> byType = new TreeMap<>();
for (final Paiement p : t.getPaiements()) {
final BigDecimal paid = BigDecimal.valueOf(p.getMontantInCents()).movePointLeft(2);
receiptPaid = receiptPaid.add(paid);
addInMap(byType, p.getTypeAsString(), paid);
addInMap(totalByType, p.getTypeAsString(), paid);
}
typesByReceipt.put(t, byType);
valueByReceipt.put(t, receiptValue);
paidByReceipt.put(t, receiptPaid);
total = total.add(receiptValue);
totalPaid = totalPaid.add(receiptPaid);
}
 
prt.addToBuffer(title, TicketPrinter.BOLD_LARGE);
prt.addToBuffer("");
prt.addToBuffer("Edité le " + dateFormat.format(new Date()));
final RegisterState registerState = getLog().getRegisterState();
prt.addToBuffer((registerState.getStatus() == Status.OPEN ? "Ouvert" : "Fermé") + " le " + registerState.formatDate(dateFormat));
prt.addToBuffer("");
prt.addToBuffer("");
prt.addToBuffer("Tickets de caisse", TicketPrinter.BOLD_LARGE);
prt.addToBuffer("");
 
Paiement espece = new Paiement(Paiement.ESPECES);
prt.addToBuffer(DefaultTicketPrinter.formatSides(ticketWidth, "Total des ventes", totalPaid.toPlainString()), TicketPrinter.BOLD);
for (final Entry<String, BigDecimal> e2 : totalByType.entrySet()) {
final String typePayment = e2.getKey();
if (typePayment.equals(espece.getTypeAsString())) {
BigDecimal value = e2.getValue();
BigDecimal rendu = totalPaid.subtract(total);
value = value.subtract(rendu);
prt.addToBuffer(DefaultTicketPrinter.formatSides(ticketWidth, " " + typePayment, value.toPlainString()));
} else {
prt.addToBuffer(DefaultTicketPrinter.formatSides(ticketWidth, " " + typePayment, e2.getValue().toPlainString()));
}
}
 
prt.addToBuffer(DefaultTicketPrinter.formatSides(ticketWidth, "Total des paiements", totalPaid.toPlainString()), TicketPrinter.BOLD);
for (final Entry<String, BigDecimal> e2 : totalByType.entrySet()) {
prt.addToBuffer(DefaultTicketPrinter.formatSides(ticketWidth, " " + e2.getKey(), e2.getValue().toPlainString()));
}
prt.addToBuffer("");
prt.addToBuffer(DefaultTicketPrinter.formatSides(ticketWidth, "Total rendu", totalPaid.subtract(total).toPlainString()), TicketPrinter.BOLD);
prt.addToBuffer("");
prt.addToBuffer(DefaultTicketPrinter.formatSides(ticketWidth, "Total TTC (Euros)", total.toPlainString()), TicketPrinter.BOLD);
prt.addToBuffer(DefaultTicketPrinter.formatSides(ticketWidth, "Nombre de tickets", "" + receipts.size()));
final long avg = receipts.isEmpty() ? 0 : total.movePointRight(2).longValueExact() / receipts.size();
prt.addToBuffer(DefaultTicketPrinter.formatSides(ticketWidth, "Panier moyen (Euros)", BigDecimal.valueOf(avg).movePointLeft(2).toPlainString()));
prt.addToBuffer("");
if (isPrintingTicketsList()) {
prt.addToBuffer("");
prt.addToBuffer("Liste des tickets", TicketPrinter.BOLD_LARGE);
prt.addToBuffer("");
for (final Entry<Ticket, Map<String, BigDecimal>> e : typesByReceipt.entrySet()) {
final Ticket t = e.getKey();
final BigDecimal receiptValue = valueByReceipt.get(t);
prt.addToBuffer(DefaultTicketPrinter.formatSides(ticketWidth, t.getCode(), receiptValue.toPlainString()), TicketPrinter.BOLD);
for (final Entry<String, BigDecimal> e2 : e.getValue().entrySet()) {
prt.addToBuffer(DefaultTicketPrinter.formatSides(ticketWidth, " " + e2.getKey(), e2.getValue().toPlainString()));
}
// rendu
final BigDecimal receiptChange = paidByReceipt.get(t).subtract(receiptValue);
if (receiptChange.signum() != 0)
prt.addToBuffer(DefaultTicketPrinter.formatSides(ticketWidth, " rendu", receiptChange.toPlainString()));
 
prt.addToBuffer("");
}
}
} catch (Exception e) {
POSConfiguration.getLogger().log(Level.WARNING, "Couldn't fill " + this.name, e);
prt.addToBuffer("Erreur");
}
try {
prt.printBuffer();
} catch (Exception e) {
POSConfiguration.getLogger().log(Level.WARNING, "Couldn't print " + this.name, e);
}
}
 
static private final <K> void addInMap(final Map<K, BigDecimal> m, final K key, final BigDecimal val) {
final BigDecimal prev = m.get(key);
m.put(key, prev == null ? val : prev.add(val));
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/ui/TicketPanel.java
13,7 → 13,10
package org.openconcerto.erp.core.sales.pos.ui;
 
import org.openconcerto.erp.core.sales.pos.POSConfiguration;
import org.openconcerto.erp.core.sales.pos.model.Article;
import org.openconcerto.erp.core.sales.pos.model.RegisterState;
import org.openconcerto.erp.core.sales.pos.model.RegisterState.Status;
import org.openconcerto.ui.touch.ScrollableList;
import org.openconcerto.utils.Pair;
 
24,8 → 27,11
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
 
import javax.swing.ImageIcon;
import javax.swing.JLabel;
38,6 → 44,9
import javax.swing.event.ListSelectionListener;
 
public class TicketPanel extends JPanel implements CaisseListener {
 
static private final DateFormat DF = new SimpleDateFormat("' le' EEEE d MMMM à H:mm:ss");
 
private final Image bg;
 
private final ListModel dataModel;
127,6 → 136,14
protected void paintComponent(final Graphics g) {
g.drawImage(this.bg, 0, 0, null);
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
try {
g.setColor(Color.LIGHT_GRAY);
g.setFont(getFont().deriveFont(18.0f));
final RegisterState registerState = this.controler.getCaisseFrame().getFiles().getLastLog().getRegisterState();
g.drawString("Caisse " + (registerState.getStatus() == Status.OPEN ? "ouverte" : "fermée") + registerState.formatDate(DF), 20, this.getHeight() - 25);
} catch (Exception e) {
POSConfiguration.getLogger().log(Level.WARNING, "Couldn't find register state", e);
}
super.paintComponent(g);
}
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/ui/CaisseMenuPanel.java
14,20 → 14,24
package org.openconcerto.erp.core.sales.pos.ui;
 
import org.openconcerto.erp.core.sales.pos.POSConfiguration;
import org.openconcerto.erp.core.sales.pos.io.Printable;
import org.openconcerto.erp.core.sales.pos.io.TicketPrinter;
import org.openconcerto.erp.core.sales.pos.model.RegisterLog;
import org.openconcerto.task.config.ComptaBasePropsConfiguration;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.FileUtils;
import org.openconcerto.utils.JImage;
import org.openconcerto.utils.StringUtils;
 
import java.awt.Color;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Set;
import java.util.logging.Level;
import java.io.File;
import java.io.IOException;
import java.util.List;
 
import javax.swing.JPanel;
 
51,7 → 55,61
final JImage image = new JImage(ComptaBasePropsConfiguration.class.getResource("logo.png"));
this.add(image, c);
c.gridx++;
File testTicketDir = new File("test");
if (testTicketDir.exists() && testTicketDir.isDirectory()) {
File[] files = testTicketDir.listFiles();
for (int i = 0; i < files.length; i++) {
final File f = files[i];
if (f.getName().endsWith(".txt")) {
final POSButton b = new POSButton(f.getName().substring(0, f.getName().length() - 4));
this.add(b, c);
c.gridy++;
b.addActionListener(new ActionListener() {
 
@Override
public void actionPerformed(ActionEvent e) {
System.err.println("CaisseMenuPanel.CaisseMenuPanel(...).new ActionListener() {...}.actionPerformed()");
POSConfiguration.getInstance().printOnceOnFirstPrinter(new Printable() {
 
@Override
public void print(TicketPrinter prt, int ticketWidth) {
prt.clearBuffer(f.getName());
System.err.println("CaisseMenuPanel.CaisseMenuPanel(...)print()");
String content = f.getName();
try {
content = FileUtils.read(f);
List<String> lines = StringUtils.splitIntoLines(content);
for (String line : lines) {
line = line.trim();
System.err.println("CaisseMenuPanel.CaisseMenuPanel(...)print()" + line);
if (line.startsWith("[bl]")) {
prt.addToBuffer(line.substring(3), TicketPrinter.BOLD_LARGE);
} else if (line.startsWith("[b]")) {
prt.addToBuffer(line.substring(3), TicketPrinter.BOLD);
} else {
prt.addToBuffer(line);
}
}
} catch (IOException e1) {
prt.addToBuffer(content);
prt.addToBuffer(e1.getMessage());
e1.printStackTrace();
}
try {
prt.printBuffer();
} catch (final Exception e) {
e.printStackTrace();
}
}
});
 
}
});
}
 
}
}
 
final POSButton bTickets = new POSButton("Liste des tickets");
this.add(bTickets, c);
c.gridy++;
76,12 → 134,34
}
}
});
 
bCloture.addActionListener(new ActionListener() {
 
@Override
public void actionPerformed(ActionEvent e) {
JPanel p = new JPanel();
p.setOpaque(true);
p.setLayout(new GridBagLayout());
final GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.WEST;
c.weightx = 0;
c.weighty = 0;
c.gridx = 0;
c.gridy = 0;
c.insets = new Insets(20, 20, 30, 20);
c.gridwidth = 2;
p.add(new POSLabel("Voulez vous clôturer la caisse ?"), c);
c.gridy++;
c.gridwidth = 1;
POSButton bOkCloture = new POSButton("Clôturer");
bOkCloture.addActionListener(new ActionListener() {
 
@Override
public void actionPerformed(ActionEvent e) {
try {
 
final boolean quit = caisseFrame.getDB().fetchRegisterState().checkIfMoved();
if (!quit) {
frame.getControler().setLCD("Cloture", "En cours...", 0);
final int userID = POSConfiguration.getInstance().getUserID();
final RegisterLog newLog = caisseFrame.getFiles().close(userID);
88,12 → 168,33
caisseFrame.getDB().close(userID, newLog);
frame.getControler().setLCD("Cloture", "Terminee", 0);
// TODO lock down the UI until open again
}
quit();
} catch (Exception ex) {
ExceptionHandler.handle("Erreur", ex);
}
System.err.println("CLOTURE");
frame.showCaisse();
}
});
p.add(bOkCloture, c);
c.gridx++;
POSButton bCancelCloture = new POSButton("Annuler");
bCancelCloture.addActionListener(new ActionListener() {
 
@Override
public void actionPerformed(ActionEvent e) {
p.setVisible(false);
System.err.println("CANCEL CLOTURE");
frame.showCaisse();
}
});
p.add(bCancelCloture, c);
 
frame.showPanel(p);
}
});
 
bQuit.addActionListener(new ActionListener() {
 
@Override
109,22 → 210,8
}
 
private void quit() {
POSConfiguration.getLogger().log(Level.INFO, "User exit");
POSConfiguration.getInstance().closeConnexion();
// Fermeture
frame.getControler().setLCD(" CAISSE FERMEE ", "", 0);
frame.dispose();
Frame[] l = Frame.getFrames();
for (int i = 0; i < l.length; i++) {
Frame f = l[i];
System.err.println(f.getName() + " " + f + " Displayable: " + f.isDisplayable() + " Valid: " + f.isValid() + " Active: " + f.isActive());
}
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for (Thread thread : threadSet) {
if (!thread.isDaemon()) {
System.err.println(thread.getName() + " " + thread.getId() + " not daemon");
}
}
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/ui/PaiementPanel.java
390,13 → 390,13
}
controller.autoFillPaiement(p);
this.calculatorValue = TicketCellRenderer.centsToString(p.getMontantInCents());
 
if (p.getType() == Paiement.ESPECES) {
try {
controller.openDrawer();
} catch (Throwable ex) {
JOptionPane.showMessageDialog(PaiementPanel.this, "Ouverture du tiroir caisse impossible");
}
if (p.getType() == Paiement.CB) {
} else if (p.getType() == Paiement.CB) {
controller.sendCBRequest(p);
}
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/ui/CaisseFrame.java
39,6 → 39,7
 
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
49,6 → 50,7
import java.text.ParseException;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.logging.Level;
89,7 → 91,6
}
 
public static void main(String[] args) {
ComptaPropsConfiguration.checkJava();
System.setProperty(SQLRowAccessor.ACCESS_DB_IF_NEEDED_PROP, "true");
try {
System.out.println("Lancement du module de caisse");
126,6 → 127,14
final int userID = POSConfiguration.getInstance().getUserID();
final RegisterFiles registerFiles = new RegisterFiles(POSConfiguration.getInstance().getRootDir(), true, POSConfiguration.getInstance().getPosID());
final RegisterDB registerDB = new RegisterDB(conf.getDirectory(), conf.getProductInfo(), POSConfiguration.getInstance().getPosID());
 
// check before changing any state
final boolean quit = registerDB.fetchRegisterState().checkIfMoved();
if (quit) {
quit();
return;
}
 
final RegisterState reconciledState = registerFiles.doWithLock(new ExnTransformer<RegisterFiles, RegisterState, IOException>() {
@Override
public RegisterState transformChecked(RegisterFiles input) throws IOException {
334,12 → 343,43
return remoteState;
}
 
static public void quit() {
POSConfiguration.getLogger().log(Level.INFO, "User exit");
POSConfiguration.getInstance().closeConnexion();
Frame[] l = Frame.getFrames();
for (int i = 0; i < l.length; i++) {
Frame f = l[i];
System.err.println(f.getName() + " " + f + " Displayable: " + f.isDisplayable() + " Valid: " + f.isValid() + " Active: " + f.isActive());
}
Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for (Thread thread : threadSet) {
if (!thread.isDaemon()) {
System.err.println(thread.getName() + " " + thread.getId() + " not daemon");
}
}
}
 
@Override
public void dispose() {
quit();
// Fermeture
this.getControler().setLCD(" CAISSE FERMEE ", "", 0);
super.dispose();
}
 
public void showMenu() {
System.out.println("CaisseFrame.showMenu()");
this.invalidate();
final CaisseMenuPanel panel = new CaisseMenuPanel(this);
showPanel(panel);
this.getControler().setLCD("OpenConcerto", "Menu", 0);
 
final POSGlassPane glassPane2 = new POSGlassPane(panel, (getWidth() - panel.getPreferredSize().width) / 2, 100) {
}
 
public void showPanel(JPanel panel) {
this.invalidate();
final int x = (getWidth() - panel.getPreferredSize().width) / 2;
final int y = 100;
final POSGlassPane glassPane2 = new POSGlassPane(panel, x, y) {
@Override
public void mousePressed(MouseEvent e) {
Point containerPoint = SwingUtilities.convertPoint(this, e.getPoint(), panel);
355,8 → 395,6
this.getGlassPane().setVisible(true);
this.validate();
this.repaint();
this.getControler().setLCD("OpenConcerto", "Menu", 0);
 
}
 
public void showPriceEditor(Article article, CaisseControler caisseControler) {
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/ui/ListeDesTicketsPanel.java
15,7 → 15,14
 
import org.openconcerto.erp.core.sales.pos.POSConfiguration;
import org.openconcerto.erp.core.sales.pos.TicketPrinterConfiguration;
import org.openconcerto.erp.core.sales.pos.io.DefaultTicketPrinter;
import org.openconcerto.erp.core.sales.pos.io.Printable;
import org.openconcerto.erp.core.sales.pos.io.TicketPrinter;
import org.openconcerto.erp.core.sales.pos.model.Paiement;
import org.openconcerto.erp.core.sales.pos.model.RegisterFiles;
import org.openconcerto.erp.core.sales.pos.model.RegisterLog;
import org.openconcerto.erp.core.sales.pos.model.RegisterState;
import org.openconcerto.erp.core.sales.pos.model.RegisterState.Status;
import org.openconcerto.erp.core.sales.pos.model.Ticket;
import org.openconcerto.ui.DefaultListModel;
import org.openconcerto.ui.touch.ScrollableList;
34,6 → 41,19
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.logging.Level;
 
import javax.swing.JLabel;
import javax.swing.JList;
44,9 → 64,74
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
 
import org.jdom2.JDOMException;
 
public class ListeDesTicketsPanel extends JPanel implements ListSelectionListener {
 
private static final String ARIAL_FONT = "Arial";
 
static private final class X extends RegisterSummary {
 
private final List<Ticket> receipts;
 
protected X(final RegisterLog log, final List<Ticket> receipts) {
super("X", log);
this.receipts = receipts;
}
 
@Override
protected final List<Ticket> getReceipts() {
return this.receipts;
}
 
@Override
public String getLabel() {
return "Synthèse actuelle (X)";
}
}
 
static private final class XLite extends RegisterSummary {
 
private final List<Ticket> receipts;
 
protected XLite(final RegisterLog log, final List<Ticket> receipts) {
super("X", log);
this.receipts = receipts;
}
 
@Override
public boolean isPrintingTicketsList() {
return false;
}
 
@Override
protected final List<Ticket> getReceipts() {
return this.receipts;
}
 
@Override
public String getLabel() {
return "Synthèse actuelle simplifiée (résumé du X)";
}
}
 
static private final class Z extends RegisterSummary {
 
protected Z(final RegisterFiles files, final Calendar day) throws IOException, JDOMException {
super("Z", new RegisterLog(files.getLogFile(day)).parse());
}
 
@Override
protected final List<Ticket> getReceipts() throws ParseException {
return this.getLog().parseReceipts();
}
 
@Override
public String getLabel() {
return "Synthèse précédente (Z)";
}
}
 
private JList l;
private CaisseFrame frame;
 
83,9 → 168,20
c.weighty = 1;
c.gridheight = 2;
 
try {
final RegisterLog lastLog = this.frame.getFiles().getLastLog();
final List<Ticket> receipts = lastLog.parseReceipts();
ticketLlistModel = new DefaultListModel();
try {
ticketLlistModel.addAll(this.frame.getFiles().getLastLog().parseReceipts());
ticketLlistModel.addElement(new X(lastLog, receipts));
ticketLlistModel.addElement(new XLite(lastLog, receipts));
final Date previousDate = lastLog.getFirstRegisterEvent().getPreviousDate();
if (previousDate != null) {
final Calendar cal = Calendar.getInstance();
cal.setTime(previousDate);
ticketLlistModel.addElement(new Z(this.frame.getFiles(), cal));
}
ticketLlistModel.addAll(receipts);
 
} catch (Exception exn) {
ExceptionHandler.handle(this.frame, "Impossible de charger les tickets", exn);
}
112,6 → 208,7
g.setColor(Color.GRAY);
}
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (object instanceof Ticket) {
Ticket article = (Ticket) object;
String label = "Ticket " + article.getCode();
 
120,8 → 217,10
int wEuro = (int) g.getFontMetrics().getStringBounds(euro, g).getWidth();
g.drawString(label, 10, posY + 39);
g.drawString(euro, getWidth() - 5 - wEuro, posY + 39);
 
} else {
g.drawString(((RegisterSummary) object).getLabel(), 10, posY + 39);
}
}
};
this.add(ticketList, c);
// Ticket
199,7 → 298,7
Object selectedValue = ticketList.getSelectedValue();
int selectedIndex = l.getSelectedIndex();
if (selectedIndex == 0 && selectedValue != null) {
POSConfiguration.getInstance().print(((Ticket) selectedValue));
POSConfiguration.getInstance().printOnceOnFirstPrinter(((Printable) selectedValue));
}
l.clearSelection();
}
207,7 → 306,7
public void setSelectedTicket(Object selectedValue) {
ticketP.clear();
if (selectedValue != null) {
POSConfiguration.getInstance().print(((Ticket) selectedValue), new TicketPrinterConfiguration() {
POSConfiguration.getInstance().print(((Printable) selectedValue), new TicketPrinterConfiguration() {
@Override
public TicketPrinter createTicketPrinter() {
return ticketP;
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/ui/ArticleSelector.java
130,8 → 130,13
 
}
});
 
comp.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
list.scrollToOffset(0);
}
});
}
 
@Override
public void valueChanged(ListSelectionEvent e) {
162,7 → 167,7
} catch (Exception e) {
e.printStackTrace();
}
if (articleSelected != null && !articleSelected.equals(selectedValue)) {
if (!articleSelected.equals(selectedValue)) {
Categorie c = articleSelected.getCategorie();
model.setCategorie(c);
list.setSelectedValue(articleSelected, true);
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/ui/CaissePanel.java
16,6 → 16,8
import org.openconcerto.erp.core.sales.pos.POSConfiguration;
import org.openconcerto.erp.core.sales.pos.model.Article;
import org.openconcerto.erp.core.sales.pos.model.Categorie;
import org.openconcerto.erp.core.sales.pos.model.RegisterFiles.DifferentDayException;
import org.openconcerto.erp.core.sales.pos.model.Ticket;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.element.SQLElementDirectory;
import org.openconcerto.sql.model.SQLRow;
39,9 → 41,12
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
 
import javax.swing.JOptionPane;
import javax.swing.JPanel;
135,24 → 140,32
 
@Override
public void actionPerformed(ActionEvent e) {
if (CaissePanel.this.controler.isTicketValid()) {
final Ticket savedReceipt;
try {
savedReceipt = CaissePanel.this.controler.saveAndClearTicket(caisseFrame.getFiles(), caisseFrame.getConf().getDirectory());
} catch (DifferentDayException ex) {
JOptionPane.showMessageDialog(CaissePanel.this, "Impossible de laisser la caisse ouverte plusieurs jours. Veuillez la clôturer pour pouvoir faire de nouveaux tickets.", "Erreur",
JOptionPane.ERROR_MESSAGE);
return;
} catch (Throwable ex) {
ExceptionHandler.handle(CaissePanel.this, "Erreur de sauvegarde des informations du ticket", ex);
return;
}
if (savedReceipt != null) {
// Valider
CaissePanel.this.controler.setTicketDate();
CaissePanel.this.controler.setLCD("Impression de", "votre ticket...", 0);
try {
CaissePanel.this.controler.printTicket();
POSConfiguration.getInstance().print(savedReceipt);
} catch (UnsatisfiedLinkError ex) {
JOptionPane.showMessageDialog(CaissePanel.this, "Erreur de configuration de la liaison à l'imprimante");
} catch (Throwable ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(CaissePanel.this, "Erreur d'impression du ticket");
}
try {
CaissePanel.this.controler.saveAndClearTicket(caisseFrame.getFiles(), caisseFrame.getConf().getDirectory());
} catch (Throwable ex) {
ExceptionHandler.handle("Erreur de sauvegardes des informations du ticket", ex);
}
 
CaissePanel.this.controler.setLCDDefaultDisplay(2);
}
 
}
});
bClients.addActionListener(new ActionListener() {
188,6 → 201,9
 
private void loadArticles(final SQLElementDirectory dir) {
 
final Set<Integer> favoriteProductsIds = controler.loadFavoriteProductsIds();
final List<Article> favoriteProducts = new ArrayList<>();
 
final Map<Integer, Categorie> categoriesMap = new HashMap<Integer, Categorie>();
 
SQLElement eltFam = dir.getElement("FAMILLE_ARTICLE");
196,6 → 212,7
final SQLSelect selFamille = new SQLSelect();
selFamille.addSelectStar(eltFam.getTable());
selFamille.addFieldOrder(eltFam.getTable().getField("CODE"));
 
for (SQLRow row : SQLRowListRSH.execute(selFamille)) {
// Map id -> Category
final Categorie cP = categoriesMap.get(row.getInt("ID_FAMILLE_ARTICLE_PERE"));
214,9 → 231,10
final SQLTable tableArticle = eltArticle.getTable();
selArticle.addAllSelect(tableArticle.getFields(VirtualFields.PRIMARY_KEY.union(VirtualFields.ARCHIVE)));
selArticle.addAllSelect(tableArticle, Arrays.asList("ID_FAMILLE_ARTICLE", "NOM", "CODE", "CODE_BARRE", "ID_TAXE", "PV_HT", "PV_TTC"));
selArticle.setWhere(new Where(tableArticle.getField("OBSOLETE"), "=", Boolean.FALSE));
selArticle.setWhere(new Where(tableArticle.getField("OBSOLETE"), "=", Boolean.FALSE).and(new Where(tableArticle.getField("MASQUE_CAISSE"), "=", Boolean.FALSE)));
 
final Categorie cUnclassified = new Categorie("Non classés", true);
cUnclassified.setUnknown();
for (SQLRow row : SQLRowListRSH.execute(selArticle)) {
final int idFamilleArticle = row.getInt("ID_FAMILLE_ARTICLE");
Categorie s1 = categoriesMap.get(idFamilleArticle);
234,10 → 252,15
a.setIdTaxe(row.getInt("ID_TAXE"));
a.setPriceWithoutTax(row.getBigDecimal("PV_HT"));
a.setPriceWithTax(row.getBigDecimal("PV_TTC"));
final Integer idProduct = a.getId();
if (favoriteProductsIds.contains(idProduct)) {
favoriteProducts.add(a);
}
}
 
}
}
Categorie.setFavoriteProducts(favoriteProducts);
}
 
@Override
public void paint(Graphics g) {
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/TicketPrinterConfiguration.java
16,10 → 16,14
import org.openconcerto.erp.core.sales.pos.io.ESCSerialPrinter;
import org.openconcerto.erp.core.sales.pos.io.ESCStandardPrinter;
import org.openconcerto.erp.core.sales.pos.io.JPOSTicketPrinter;
import org.openconcerto.erp.core.sales.pos.io.StringStandardPrinter;
import org.openconcerto.erp.core.sales.pos.io.SwingPrinter;
import org.openconcerto.erp.core.sales.pos.io.TicketPrinter;
 
public class TicketPrinterConfiguration {
public static final String STANDARD_PRINTER = "std";
public static final String STANDARD_STRING_PRINTER = "stdString";
public static final String SWING_PRINTER = "swing";
public static final String SERIAL_PRINTER = "serial";
public static final String JPOS_PRINTER = "jpos";
private String type = STANDARD_PRINTER;
38,7 → 42,7
}
 
public void setType(String type) {
if (STANDARD_PRINTER.equals(type) || SERIAL_PRINTER.equals(type) || JPOS_PRINTER.equals(type)) {
if (STANDARD_PRINTER.equals(type) || STANDARD_STRING_PRINTER.equals(type) || SWING_PRINTER.equals(type) || SERIAL_PRINTER.equals(type) || JPOS_PRINTER.equals(type)) {
this.type = type;
} else {
throw new IllegalArgumentException("Unknown type " + type);
87,6 → 91,10
final TicketPrinter prt;
if (STANDARD_PRINTER.equals(getType())) {
prt = new ESCStandardPrinter(getName());
} else if (STANDARD_STRING_PRINTER.equals(getType())) {
prt = new StringStandardPrinter(getName());
} else if (SWING_PRINTER.equals(getType())) {
prt = new SwingPrinter(getName());
} else if (SERIAL_PRINTER.equals(getType())) {
prt = new ESCSerialPrinter(getName());
} else if (JPOS_PRINTER.equals(getType())) {
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/model/DBState.java
13,13 → 13,27
package org.openconcerto.erp.core.sales.pos.model;
 
import org.openconcerto.erp.core.sales.pos.POSConfiguration;
import org.openconcerto.erp.core.sales.pos.model.RegisterState.Status;
import org.openconcerto.erp.utils.TM;
import org.openconcerto.sql.PropsConfiguration;
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.ui.SwingThreadUtils;
import org.openconcerto.utils.CollectionUtils;
 
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.logging.Level;
 
import javax.swing.JOptionPane;
 
import net.jcip.annotations.Immutable;
 
/**
30,11 → 44,20
@Immutable
public final class DBState {
 
private static final Status getStatus(final SQLRowAccessor entry) {
final Status res = Status.valueOf(entry.getString("EVT"));
if (res != Status.OPEN && res != Status.CLOSED)
throw new IllegalStateException("Invalid status : " + res);
return res;
}
 
// used not for requests but for tables and paths
private final RegisterDB registerDB;
private final SQLRowValues registerVals;
private final SQLRowValues lastReceiptVals;
private final RegisterState registerState;
// first is the latest
private final List<SQLRowValues> lastEntries;
 
protected DBState(final RegisterDB registerDB, final SQLRowValues registerR) {
super();
43,6 → 66,7
if (this.getPosID() != registerDB.getPosID())
throw new IllegalArgumentException("Not same register");
this.lastReceiptVals = CollectionUtils.getSole(this.registerVals.getReferentRows(this.registerDB.getReceiptElement().getTable().getField("ID_CAISSE")));
this.lastEntries = Collections.unmodifiableList(new ArrayList<>(this.registerVals.getReferentRows(this.registerDB.getLogElement().getTable().getField("ID_CAISSE"))));
 
final SQLRowAccessor lastEntry = getLastEntry();
if (lastEntry == null) {
50,9 → 74,7
} else {
if (lastEntry.getForeignID("ID_CAISSE") != this.getPosID())
throw new IllegalStateException("Incoherent register IDs");
final Status status = Status.valueOf(lastEntry.getString("EVT"));
if (status != Status.OPEN && status != Status.CLOSED)
throw new IllegalStateException("Invalid status : " + status);
final Status status = getStatus(lastEntry);
this.registerState = new RegisterState(status, lastEntry.getDate("DATE").getTime());
}
}
69,14 → 91,37
return this.registerVals;
}
 
public final SQLRowValues getLastClosure() {
return this.registerVals.followPath(this.registerDB.getRegisterToLastClosureEntry().minusLast());
}
 
public final SQLRowValues getLastClosureEntry() {
return this.registerVals.followPath(this.registerDB.getRegisterToLastClosureEntry());
}
 
public final SQLRowValues getLastOpeningEntry() {
final List<SQLRowValues> entries = this.getLastEntries();
if (entries.isEmpty()) {
// never opened
assert !this.getRegisterState().hasDate();
return null;
} else if (getStatus(entries.get(0)).equals(Status.OPEN)) {
return entries.get(0);
} else if (entries.size() > 1 && getStatus(entries.get(1)).equals(Status.OPEN)) {
return entries.get(1);
} else {
throw new IllegalStateException("Two consecutive non-open entries : " + entries);
}
}
 
public final SQLRowValues getLastEntry() {
return (SQLRowValues) this.registerVals.getNonEmptyForeign("ID_DERNIERE_ENTREE_JOURNAL");
return CollectionUtils.getFirst(this.getLastEntries());
}
 
public final List<SQLRowValues> getLastEntries() {
return this.lastEntries;
}
 
public final SQLRowValues getLastReceiptRow() {
return this.lastReceiptVals;
}
86,7 → 131,54
return lastReceiptRow == null ? null : new ReceiptCode(lastReceiptRow.getString("NUMERO"));
}
 
public final SQLRowValues fillHostValues(final SQLRowValues logVals) {
logVals.put("HOST_NAME", PropsConfiguration.getHostname());
logVals.put("HOST_USER", System.getProperty("user.name"));
return logVals;
}
 
// initial values for entries created before this version
private static final Map<String, ?> NULL_VALUES = CollectionUtils.createMap("HOST_NAME", null, "HOST_USER", null);
 
/**
* Check if the register installation has moved and ask the user about it if it did. This can be
* called from outside the EDT.
*
* @return <code>true</code> if the user wants to quit.
* @throws InterruptedException if this thread was interrupted while waiting on the EDT.
* @throws ExecutionException if there was an error while asking the user.
*/
public final boolean checkIfMoved() throws InterruptedException, ExecutionException {
final SQLRowValues lastEntry = this.getLastEntry();
if (lastEntry == null) {
return false;
}
 
final Map<String, Object> currentValues = fillHostValues(new SQLRowValues(lastEntry.getTable())).getAbsolutelyAll();
final Map<String, Object> dbValues = lastEntry.getValues(currentValues.keySet());
if (dbValues.equals(currentValues) || NULL_VALUES.equals(dbValues)) {
return false;
} else {
final String message = TM.tr("register.moved", getPosID());
final String[] options = new String[] { TM.tr("register.moved.ignore"), TM.tr("register.moved.quit") };
final FutureTask<Boolean> askUserCallable = new FutureTask<>(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
// quit by default
final int ans = JOptionPane.showOptionDialog(null, message, TM.tr("register.moved.title"), JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[1]);
// CLOSED_OPTION also means quit, only clicking "ignore" means don't quit
return ans != 0;
}
});
SwingThreadUtils.invoke(askUserCallable);
final boolean quit = askUserCallable.get();
if (!quit)
POSConfiguration.getLogger().log(Level.WARNING, "User choose to ignore changed host,\nDB values : {0}\ncurrent values : {1}", new Object[] { dbValues, currentValues });
return quit;
}
}
 
@Override
public String toString() {
return this.getClass().getSimpleName() + " for register " + this.getPosID() + " in state " + this.getRegisterState();
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/model/RegisterLog.java
43,8 → 43,16
REGISTER_OPENING, RECEIPT_CREATION, REGISTER_CLOSURE;
}
 
static private final int VERSION = 2;
static private final String VERSION_ATTR_NAME = "version";
 
static final Element createRootElement() {
return new Element("registerLog").setAttribute(VERSION_ATTR_NAME, String.valueOf(VERSION));
}
 
private final Path logFile;
private Document parsed;
private int version;
private RegisterEntry opening;
 
public RegisterLog(Path logFile) {
71,6 → 79,7
throw new IllegalStateException("Do not begin with " + EventType.REGISTER_OPENING + " : " + firstEntry);
this.opening = (RegisterEntry) firstEntry;
this.parsed = doc;
this.version = Integer.parseInt(doc.getRootElement().getAttributeValue(VERSION_ATTR_NAME, "1"));
return this;
}
 
78,6 → 87,10
return this.parsed;
}
 
public final int getVersion() {
return this.version;
}
 
public final RegisterLogEntry getLastEvent() throws ParseException {
return this.getEvent(-1);
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/model/RegisterFiles.java
21,6 → 21,7
import org.openconcerto.utils.FileUtils;
import org.openconcerto.utils.MessageDigestUtils;
import org.openconcerto.utils.StringUtils;
import org.openconcerto.utils.TimeUtils;
import org.openconcerto.utils.cc.ExnTransformer;
import org.openconcerto.utils.checks.ValidState;
 
230,6 → 231,15
return dayDirToUse == null ? null : dayDirToUse.resolve(code.getFileName());
}
 
public final Path getLogFile(final Calendar day) throws IOException {
return getLogFile(getDayDir(day, false));
}
 
private final Path getLogFile(final Path dayDir) throws IOException {
final Path dayDirToUse = getDayDirToUse(dayDir);
return dayDirToUse == null ? null : dayDirToUse.resolve(LOG_FILENAME);
}
 
public final int getPosID() {
return this.posID;
}
305,9 → 315,9
 
private Path getLogToUse(final SortedSet<Path> sortedDays) throws IOException {
for (final Path dayDir : sortedDays) {
final Path dayDirToUse = getDayDirToUse(dayDir);
if (dayDirToUse != null)
return dayDirToUse.resolve(LOG_FILENAME);
final Path logFile = getLogFile(dayDir);
if (logFile != null)
return logFile;
}
return null;
}
315,9 → 325,9
public final List<Path> findLogFiles() throws IOException {
final List<Path> res = new ArrayList<>();
for (final Path dayDir : getSortedDays(true)) {
final Path dayDirToUse = getDayDirToUse(dayDir);
if (dayDirToUse != null)
res.add(dayDirToUse.resolve(LOG_FILENAME));
final Path logFile = getLogFile(dayDir);
if (logFile != null)
res.add(logFile);
}
return res;
}
366,8 → 376,10
POSConfiguration.checkRegisterID(input.getPosID(), registerDB.getPosID());
final RegisterLog lastLog = input.checkStatus(true);
final String lastLocalHash;
final Date prevDate;
if (lastLog == null) {
lastLocalHash = null;
prevDate = null;
} else {
try {
lastLocalHash = lastLog.getLastReceiptHash();
374,6 → 386,9
} catch (ParseException e) {
throw new IOException("Couldn't parse last receipt of log", e);
}
prevDate = lastLog.getFirstRegisterEvent().getDate();
if (lastLocalHash != null && prevDate == null)
throw new IOException("There's a receipt, but no previous closure date");
}
 
final DBState dbState;
406,8 → 421,8
FileUtils.rm_R(prevDir);
Files.createDirectory(stagingDir);
 
final Element rootElem = new Element("registerLog");
rootElem.addContent(new RegisterLogEntry.RegisterEntry(EventType.REGISTER_OPENING, cal.getTime(), userID, input.getPosID(), lastLocalHash).toXML());
final Element rootElem = RegisterLog.createRootElement();
rootElem.addContent(new RegisterLogEntry.RegisterEntry(EventType.REGISTER_OPENING, cal.getTime(), userID, input.getPosID(), lastLocalHash, prevDate).toXML());
save(new Document(rootElem), stagingDir.resolve(LOG_FILENAME));
 
Files.move(stagingDir, currentDir, StandardCopyOption.ATOMIC_MOVE);
507,7 → 522,7
}
// TODO verify that receipts' files match the log's content
final Document doc = lastLog.getDocument().clone();
doc.getRootElement().addContent(new RegisterLogEntry.RegisterEntry(EventType.REGISTER_CLOSURE, new Date(), userID, getPosID(), lastHash).toXML());
doc.getRootElement().addContent(new RegisterLogEntry.RegisterEntry(EventType.REGISTER_CLOSURE, new Date(), userID, getPosID(), lastHash, null).toXML());
save(doc, stagingDir.resolve(LOG_FILENAME));
return null;
}
524,6 → 539,12
});
}
 
public static final class DifferentDayException extends IllegalStateException {
protected DifferentDayException(final RegisterLog lastLog) {
super("Cannot save a receipt for a different day than the register opening : " + lastLog.getFirstRegisterEvent());
}
}
 
public final String save(final Ticket t) throws IOException, SQLException {
return this.doWithLock(new UpdateDir<String, String>("saving receipt") {
@Override
533,6 → 554,8
 
@Override
protected String updateDir(final Path stagingDir, final RegisterLog lastLog) throws IOException {
if (!TimeUtils.isSameDay(t.getCreationCal(), lastLog.getFirstRegisterEvent().getDate()))
throw new DifferentDayException(lastLog);
try {
final ReceiptEntry lastReceipt = lastLog.getLastReceiptCreationEvent();
final int expectedIndex;
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/model/RegisterLogEntry.java
29,16 → 29,20
static private final String USER_ATTR_NAME = "userID";
static private final String REGISTER_ATTR_NAME = "registerID";
static private final String LAST_HASH_ATTR_NAME = "lastReceiptHash";
static private final String PREVIOUS_DATE_ATTR_NAME = "previousDate";
 
static private final RegisterEntry _parseEntry(final Element elem, final EventType evtType, final Date date) {
static private final RegisterEntry _parseEntry(final Element elem, final EventType evtType, final Date date) throws ParseException {
final String lastDateAttr = elem.getAttributeValue(PREVIOUS_DATE_ATTR_NAME);
final Date prevDate = lastDateAttr == null ? null : (Date) DATE_FMT.parseObject(lastDateAttr);
return new RegisterEntry(evtType, date, Integer.parseInt(elem.getAttributeValue(USER_ATTR_NAME)), Integer.parseInt(elem.getAttributeValue(REGISTER_ATTR_NAME)),
elem.getAttributeValue(LAST_HASH_ATTR_NAME));
elem.getAttributeValue(LAST_HASH_ATTR_NAME), prevDate);
}
 
private final int userID, registerID;
private final String lastReceiptHash;
private final Date previousDate;
 
public RegisterEntry(final EventType type, final Date date, final int userID, final int registerID, final String lastReceiptHash) {
public RegisterEntry(final EventType type, final Date date, final int userID, final int registerID, final String lastReceiptHash, final Date previousDate) {
super(type, date);
if (type != EventType.REGISTER_OPENING && type != EventType.REGISTER_CLOSURE)
throw new IllegalArgumentException("Wrong type : " + type);
45,6 → 49,7
this.userID = userID;
this.registerID = registerID;
this.lastReceiptHash = lastReceiptHash;
this.previousDate = previousDate;
}
 
public final String getLastReceiptHash() {
59,6 → 64,19
return this.registerID;
}
 
/**
* If this is {@link EventType#REGISTER_OPENING}, date of the previous opening. Useful to
* find the previous {@link RegisterFiles#getLogFile(java.util.Calendar) log}. Also makes
* sure that a log without any receipts can't just be deleted.
*
* @return the date of the previous event, <code>null</code> if
* {@link EventType#REGISTER_CLOSURE} or if {@link RegisterLog#getVersion() format
* version} 1.
*/
public final Date getPreviousDate() {
return this.previousDate;
}
 
@Override
protected void fillXML(Element res) {
res.setAttribute(USER_ATTR_NAME, String.valueOf(this.userID));
65,6 → 83,8
res.setAttribute(REGISTER_ATTR_NAME, String.valueOf(this.registerID));
if (this.lastReceiptHash != null)
res.setAttribute(LAST_HASH_ATTR_NAME, this.lastReceiptHash);
if (this.previousDate != null)
res.setAttribute(PREVIOUS_DATE_ATTR_NAME, DATE_FMT.format(this.previousDate));
}
 
@Override
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/model/RegisterDB.java
36,6 → 36,7
import org.openconcerto.sql.model.graph.PathBuilder;
import org.openconcerto.sql.utils.SQLUtils;
import org.openconcerto.sql.utils.SQLUtils.SQLFactory;
import org.openconcerto.utils.CollectionUtils;
import org.openconcerto.utils.CompareUtils;
import org.openconcerto.utils.ProductInfo;
import org.openconcerto.utils.TimeUtils;
96,10 → 97,19
return fetchRegisterState(LockStrength.SHARE);
}
 
private final SQLSelect createMostRecentSelect(final SQLTable t, final int limit) {
final SQLSelect res = new SQLSelect();
res.addSelectStar(t);
res.setWhere(new Where(t.getField("ID_CAISSE"), "=", this.getPosID()));
res.addFieldOrder(t.getField("DATE"), Order.desc());
res.setLimit(limit);
res.setLockStrength(LockStrength.SHARE);
return res;
}
 
private final DBState fetchRegisterState(final LockStrength lockStrength) throws SQLException {
final SQLRowValues registerVals = new SQLRowValues(getRegisterTable());
registerVals.setAllToNull();
registerVals.putRowValues("ID_DERNIERE_ENTREE_JOURNAL").setAllToNull();
registerVals.assurePath(getRegisterToLastClosureEntry()).setAllToNull();
final SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(registerVals);
fetcher.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() {
111,11 → 121,8
}
});
 
final SQLSelect selLastReceipt = new SQLSelect();
selLastReceipt.addSelectStar(this.receiptElem.getTable());
selLastReceipt.setWhere(new Where(this.receiptElem.getTable().getField("ID_CAISSE"), "=", this.getPosID()));
selLastReceipt.addFieldOrder(this.receiptElem.getTable().getField("DATE"), Order.desc());
selLastReceipt.setLimit(1);
final SQLSelect selLastReceipt = createMostRecentSelect(this.receiptElem.getTable(), 1);
final SQLSelect selLastEntries = createMostRecentSelect(this.getLogElement().getTable(), 3);
 
final SQLRowValues registerR = SQLUtils.executeAtomic(getRegisterTable().getDBSystemRoot().getDataSource(), new SQLFactory<SQLRowValues>() {
@Override
124,6 → 131,12
if (res == null)
throw new IllegalStateException("Register not found : " + getPosID());
 
final List<SQLRow> lastEntries = SQLRowListRSH.execute(selLastEntries);
for (final SQLRow r : lastEntries) {
final SQLRowValues vals = r.asRowValues();
vals.put("ID_CAISSE", res);
}
 
final List<SQLRow> receipts = SQLRowListRSH.execute(selLastReceipt);
if (receipts.size() == 1)
receipts.get(0).asRowValues().put("ID_CAISSE", res);
150,6 → 163,11
// E.g. if a work day starts 25/01 at 15h, even if the register is opened 26/01 at
// 01h then openDay is 25/01
final Date openDay = new Date();
 
final SQLRowValues lastOpeningEntry = fetchedState.getLastOpeningEntry();
if (lastOpeningEntry != null && TimeUtils.isSameDay(lastOpeningEntry.getDate("DATE"), openDay))
throw new IllegalStateException("The state to be created would be in the same day as the previous : " + lastOpeningEntry + " ; " + openDay);
 
// verifications OK, proceed to actually open
createUpdateVals(fetchedState, userID, Status.OPEN, openDay).commit();
 
172,7 → 190,7
throw new IllegalStateException("last DB receipt (" + lastDBHash + ") doesn't match last local receipt (" + lastLocalHash + ")");
}
 
private final void checkDate(final DBState fetchedState, final Date date, final boolean sameDayAllowed) {
private final void checkDate(final DBState fetchedState, final Date date) {
final SQLRowValues lastEntry = fetchedState.getLastEntry();
if (lastEntry == null)
return;
180,30 → 198,21
final Date previousEntryDate = previousEntryCal.getTime();
if (previousEntryDate.compareTo(date) >= 0)
throw new IllegalStateException("Previous date is after state to be created : " + previousEntryDate + " >= " + date);
if (!sameDayAllowed) {
final Calendar previousEntryDay = (Calendar) previousEntryCal.clone();
final Calendar newEntryDay = (Calendar) previousEntryCal.clone();
newEntryDay.clear();
newEntryDay.setTime(date);
TimeUtils.clearTime(previousEntryDay);
TimeUtils.clearTime(newEntryDay);
if (previousEntryDay.compareTo(newEntryDay) == 0)
throw new IllegalStateException("The state to be created would be in the same day as the previous : " + previousEntryDate + " ; " + date);
}
}
 
private final SQLRowValues createUpdateVals(final DBState fetchedState, final int userID, final Status newStatus, final Date date) {
checkDate(fetchedState, date, newStatus != Status.OPEN);
checkDate(fetchedState, date);
 
final SQLRowValues registerVals = new SQLRowValues(getRegisterTable());
registerVals.setPrimaryKey(fetchedState.getRegisterRow());
final SQLRowValues logVals = registerVals.putRowValues("ID_DERNIERE_ENTREE_JOURNAL");
logVals.put("ID_CAISSE", getPosID());
final SQLRowValues logVals = new SQLRowValues(getLogElement().getTable());
logVals.put("ID_CAISSE", registerVals);
logVals.put("DATE", date);
logVals.put("ID_USER", userID);
logVals.put("EVT", newStatus.name());
logVals.put("CREATOR", this.productInfo.getFullID());
logVals.put("CREATOR_VERSION", this.productInfo.getVersion());
fetchedState.fillHostValues(logVals);
return registerVals;
}
 
231,7 → 240,7
 
// actually close
final SQLRowValues registerVals = createUpdateVals(fetchedState, userID, Status.CLOSED, ourDate);
final SQLRowValues newLogEntry = (SQLRowValues) registerVals.getObject("ID_DERNIERE_ENTREE_JOURNAL");
final SQLRowValues newLogEntry = CollectionUtils.getSole(registerVals.getReferentRows(getLogElement().getTable()));
if (newLogEntry == null)
throw new IllegalStateException("Missing log entry in " + registerVals);
final SQLRowValues closureVals = registerVals.putRowValues("ID_DERNIERE_CLOTURE");
253,7 → 262,7
static SQLRowValues fillRow(final SQLRowValues closureVals, final List<ReceiptEntry> receiptEvents, final List<Ticket> receipts) {
BigDecimal totalTTC = BigDecimal.ZERO;
for (final Ticket t : receipts) {
totalTTC.add(BigDecimal.valueOf(t.getPaidTotal()).movePointLeft(2));
totalTTC = totalTTC.add(BigDecimal.valueOf(t.getPaidTotal()).movePointLeft(2));
}
closureVals.put("TOTAL_TTC", totalTTC);
if (!receiptEvents.isEmpty()) {
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/model/CheckIntegrity.java
19,11 → 19,13
import org.openconcerto.erp.core.sales.pos.model.RegisterLogEntry.ReceiptEntry;
import org.openconcerto.erp.core.sales.pos.model.RegisterLogEntry.RegisterEntry;
import org.openconcerto.erp.core.sales.pos.model.RegisterState.Status;
import org.openconcerto.sql.model.Order;
import org.openconcerto.sql.model.SQLRow;
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.TableRef;
import org.openconcerto.sql.model.Where;
import org.openconcerto.utils.CompareUtils;
import org.openconcerto.utils.Value;
30,6 → 32,7
 
import java.io.IOException;
import java.nio.file.Path;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.Date;
import java.util.Iterator;
45,10 → 48,12
final ComptaPropsConfiguration conf = posConf.createConnexion();
try {
for (final RegisterFiles files : RegisterFiles.scan(posConf.getRootDir())) {
checkRegisterFiles(conf, files);
final RegisterDB registerDB = new RegisterDB(conf.getDirectory(), conf.getProductInfo(), files.getPosID());
checkRegisterFiles(registerDB, files);
checkRegisterRow(registerDB, files);
}
System.out.println("\n\nAll done");
} catch (Exception e) {
} catch (Throwable e) {
e.printStackTrace();
} finally {
posConf.closeConnexion();
55,24 → 60,58
}
}
 
private static void checkRegisterFiles(final ComptaPropsConfiguration conf, final RegisterFiles files) throws IOException, JDOMException, ParseException {
final RegisterDB registerDB = new RegisterDB(conf.getDirectory(), conf.getProductInfo(), files.getPosID());
Value<RegisterLogEntry> lastEntry = Value.getNone();
private static void checkRegisterRow(final RegisterDB registerDB, final RegisterFiles files) throws IOException, JDOMException, ParseException, SQLException {
final RegisterState localRegisterState = files.getLastLog().getRegisterState();
final DBState dbState = registerDB.fetchRegisterState();
final RegisterState remoteRegisterState = dbState.getRegisterState();
if (!localRegisterState.equals(remoteRegisterState))
System.out.println("WARNING FS and DB state not equal (this may be fixed by launching the application) :\n" + localRegisterState + "\n" + remoteRegisterState);
 
final SQLTable logT = registerDB.getLogElement().getTable();
final SQLSelect sel = new SQLSelect();
sel.addSelect(logT.getKey());
setWhereAndOrder(sel, registerDB, logT);
final Number lastLogID = (Number) logT.getDBSystemRoot().getDataSource().executeScalar(sel.asString());
final SQLRowValues registerLastEntry = dbState.getLastEntry();
final Number registerLastEntryID = registerLastEntry == null ? null : registerLastEntry.getIDNumber();
if (!Objects.equals(registerLastEntryID, lastLogID))
throw new IllegalStateException("Last log entry referenced by the register " + registerLastEntryID + " isn't the last in the log table " + lastLogID);
 
final SQLTable closureT = registerDB.getClosureElement().getTable();
final SQLSelect selClosure = new SQLSelect();
selClosure.addSelect(closureT.getKey());
final TableRef entryRef = selClosure.addJoin("INNER", closureT.getField("ID_ENTREE_JOURNAL")).getJoinedTable();
setWhereAndOrder(selClosure, registerDB, entryRef);
final Number lastClosureID = (Number) logT.getDBSystemRoot().getDataSource().executeScalar(selClosure.asString());
final SQLRowValues registerLastClosure = dbState.getLastClosure();
final Number registerLastClosureID = registerLastClosure == null ? null : registerLastClosure.getIDNumber();
if (!Objects.equals(registerLastClosureID, lastClosureID))
throw new IllegalStateException("Last closure referenced by the register " + registerLastClosureID + " isn't the last in its table " + lastClosureID);
}
 
private static void setWhereAndOrder(final SQLSelect sel, final RegisterDB registerDB, final TableRef entryRef) {
sel.setWhere(new Where(entryRef.getField("ID_CAISSE"), "=", registerDB.getPosID()));
sel.addFieldOrder(entryRef.getField("DATE"), Order.desc());
sel.setLimit(1);
}
 
private static void checkRegisterFiles(final RegisterDB registerDB, final RegisterFiles files) throws IOException, JDOMException, ParseException {
Value<RegisterLog> lastLog = Value.getNone();
for (final Path logFile : files.findLogFiles()) {
System.out.println("Checking " + logFile);
final RegisterLog log = new RegisterLog(logFile).parse();
try {
checkOneLog(files, lastEntry, log, registerDB);
checkOneLog(files, lastLog, log, registerDB);
System.out.println("OK for " + logFile);
} catch (Exception e) {
// keep checking other files
e.printStackTrace();
}
lastEntry = Value.getSome(log.getLastEvent());
lastLog = Value.getSome(log);
}
}
 
private static void checkOneLog(final RegisterFiles files, final Value<RegisterLogEntry> previousEntry, final RegisterLog log, final RegisterDB registerDB)
private static void checkOneLog(final RegisterFiles files, final Value<RegisterLog> previousLog, final RegisterLog log, final RegisterDB registerDB)
throws IOException, JDOMException, ParseException {
if (log.getFirstRegisterEvent().getRegisterID() != files.getPosID())
throw new IllegalStateException("Opening register ID mismatch");
80,10 → 119,11
 
Date cal;
// this checks this log is chained to the previous
if (previousEntry.hasValue()) {
if (previousEntry.getValue().getType() != EventType.REGISTER_CLOSURE)
if (previousLog.hasValue()) {
final RegisterLogEntry lastEntry = previousLog.getValue().getLastEvent();
if (lastEntry.getType() != EventType.REGISTER_CLOSURE)
throw new IllegalStateException("Previous log isn't closed");
final RegisterEntry previousLogClosure = (RegisterEntry) previousEntry.getValue();
final RegisterEntry previousLogClosure = (RegisterEntry) lastEntry;
if (!Objects.equals(previousLogClosure.getLastReceiptHash(), log.getFirstRegisterEvent().getLastReceiptHash()))
throw new IllegalStateException("Register opening hash mismatch, chain broken");
if (log.getFirstRegisterEvent().getDate().compareTo(previousLogClosure.getDate()) < 0)
92,6 → 132,15
} else {
cal = null;
}
final Date expectedPreviousDate;
// getPreviousDate() was added in version 2
if (log.getVersion() < 2 || !previousLog.hasValue()) {
expectedPreviousDate = null;
} else {
expectedPreviousDate = previousLog.getValue().getFirstRegisterEvent().getDate();
}
if (!Objects.equals(expectedPreviousDate, log.getFirstRegisterEvent().getPreviousDate()))
throw new IllegalStateException("Previous opening date of this log (" + log.getFirstRegisterEvent() + ") doesn't match the previous log " + expectedPreviousDate);
 
final List<ReceiptEntry> receiptEvents = log.getReceiptEvents();
 
110,11 → 159,16
final List<Ticket> receipts = log.parseReceipts();
// this checks the closure
if (log.getRegisterState().getStatus() == Status.CLOSED) {
// parseReceipts() has already checked that lastReceiptHash matches the receipt
final String lastReceiptHash = receipts.isEmpty() ? null : log.getLastReceiptCreationEvent().getFileHash();
final ReceiptEntry lastReceiptCreationEvent = log.getLastReceiptCreationEvent();
assert receipts.isEmpty() == (lastReceiptCreationEvent == null);
// parseReceipts() has already checked that lastReceiptCreationEvent.getFileHash()
// matches the receipt
// if there's no receipt in this log, opening and closure should match
// the opening has already been checked above to match the previous log
final String lastReceiptHash = receipts.isEmpty() ? log.getFirstRegisterEvent().getLastReceiptHash() : lastReceiptCreationEvent.getFileHash();
final RegisterEntry lastRegisterEvent = log.getLastRegisterEvent();
if (!CompareUtils.equals(lastRegisterEvent.getLastReceiptHash(), lastReceiptHash))
throw new IllegalStateException("Closure hash mismatch, recorded " + lastRegisterEvent.getLastReceiptHash() + " but was " + lastReceiptHash);
throw new IllegalStateException("Closure receipt hash mismatch, recorded " + lastRegisterEvent.getLastReceiptHash() + " but was " + lastReceiptHash);
if (lastRegisterEvent.getRegisterID() != files.getPosID())
throw new IllegalStateException("Closure register ID mismatch");
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/model/Client.java
137,7 → 137,7
}
 
public void printCredit(TicketPrinter prt, int ticketWidth, BigDecimal amount, int paymentType, BigDecimal nouveauSolde) {
prt.clearBuffer();
prt.clearBuffer(this.getFullName() + " crédit");
List<TicketLine> headers = POSConfiguration.getInstance().getHeaderLines();
for (TicketLine line : headers) {
prt.addToBuffer(line);
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/model/Categorie.java
21,6 → 21,7
public class Categorie {
private static List<Categorie> topLevelCategories = new ArrayList<>();
private static List<Categorie> allCategories = new ArrayList<>();
private static List<Article> favoriteProducts = new ArrayList<>();
private String name;
// Sous catégories
private List<Categorie> l = new ArrayList<>();
27,6 → 28,7
// Articles dans cette categorie
private List<Article> articles = new ArrayList<>();
private Categorie parent;
private boolean isUnknown = false;
 
public Categorie(String string) {
this(string, false);
40,6 → 42,14
allCategories.add(this);
}
 
public void setUnknown() {
this.isUnknown = true;
}
 
public boolean isUnknown() {
return isUnknown;
}
 
@Override
public String toString() {
return name;
94,4 → 104,21
});
return result;
}
 
public static void setFavoriteProducts(List<Article> products) {
favoriteProducts = products;
}
 
public static List<Article> getFavoriteProducts() {
return favoriteProducts;
}
 
public static void toggleFavoriteState(Article product) {
if (favoriteProducts.contains(product)) {
favoriteProducts.remove(product);
} else {
favoriteProducts.add(product);
}
 
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/model/Ticket.java
21,6 → 21,7
import org.openconcerto.erp.core.finance.tax.model.TaxeCache;
import org.openconcerto.erp.core.sales.pos.POSConfiguration;
import org.openconcerto.erp.core.sales.pos.io.DefaultTicketPrinter;
import org.openconcerto.erp.core.sales.pos.io.Printable;
import org.openconcerto.erp.core.sales.pos.io.TicketPrinter;
import org.openconcerto.erp.core.sales.pos.model.RegisterFiles.HashMode;
import org.openconcerto.erp.core.sales.pos.ui.TicketCellRenderer;
49,6 → 50,8
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Locale;
58,7 → 61,7
import org.jdom2.Document;
import org.jdom2.Element;
 
public class Ticket {
public class Ticket implements Printable {
 
private static final XMLDateFormat DATE_FMT = new XMLDateFormat();
 
340,11 → 343,12
});
}
 
@Override
public void print(final TicketPrinter prt, final int ticketWidth) {
final int maxWidth = ticketWidth;
final int MAX_PRICE_WIDTH = 8;
final int MAX_QTE_WIDTH = 5;
prt.clearBuffer();
prt.clearBuffer("receipt " + this.getCode());
final List<TicketLine> headers = POSConfiguration.getInstance().getHeaderLines();
for (final TicketLine line : headers) {
prt.addToBuffer(line);
355,9 → 359,39
final SimpleDateFormat df = new SimpleDateFormat("EEEE d MMMM yyyy à HH:mm", Locale.FRENCH);
prt.addToBuffer(DefaultTicketPrinter.formatRight(maxWidth, "Le " + df.format(getCreationDate())));
prt.addToBuffer("");
List<Pair<Article, Integer>> itemsToPrint = new ArrayList<>(this.items);
Collections.sort(itemsToPrint, new Comparator<Pair<Article, Integer>>() {
 
@Override
public int compare(Pair<Article, Integer> o1, Pair<Article, Integer> o2) {
final Article p1 = o1.getFirst();
final Article p2 = o2.getFirst();
final Categorie c1 = p1.getCategorie();
final Categorie c2 = p2.getCategorie();
if (c1.equals(c2)) {
return p1.getName().compareTo(p2.getName());
}
// Unknown first
if (c1.isUnknown()) {
return -1;
}
if (c2.isUnknown()) {
return 1;
}
// Sort by name
return c1.getName().compareTo(c2.getName());
}
});
Categorie currentCategorie = null;
for (final Pair<Article, Integer> item : this.items) {
final Article article = item.getFirst();
if (currentCategorie == null || !currentCategorie.equals(article.getCategorie())) {
// Print category name, except for unknown
currentCategorie = article.getCategorie();
if (!currentCategorie.isUnknown()) {
prt.addToBuffer(currentCategorie.getName(), TicketPrinter.BOLD);
}
}
final Integer nb = item.getSecond();
final Float tauxFromId = TaxeCache.getCache().getTauxFromId(article.getIdTaxe());
final BigDecimal tauxTVA = new BigDecimal(tauxFromId).movePointLeft(2).add(BigDecimal.ONE);
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/model/RegisterState.java
15,6 → 15,7
 
import org.openconcerto.utils.CompareUtils;
 
import java.text.Format;
import java.util.Date;
 
import net.jcip.annotations.Immutable;
88,6 → 89,10
return this.date.compareTo(cal);
}
 
public final String formatDate(final Format f) {
return f.format(this.date);
}
 
@Override
public int hashCode() {
final int prime = 31;
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/io/TicketPrinter.java
32,6 → 32,6
 
public void addToBuffer(TicketLine line);
 
public void clearBuffer();
public void clearBuffer(String docName);
 
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/io/StringStandardPrinter.java
New file
0,0 → 1,86
/*
* 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.pos.io;
 
import org.openconcerto.utils.StringUtils;
import org.openconcerto.utils.XMLDateFormat;
 
import java.text.Format;
import java.util.Date;
import java.util.Locale;
 
import javax.print.Doc;
import javax.print.DocFlavor;
import javax.print.DocPrintJob;
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.SimpleDoc;
import javax.print.attribute.AttributeSet;
import javax.print.attribute.HashDocAttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.HashPrintServiceAttributeSet;
import javax.print.attribute.standard.DocumentName;
import javax.print.attribute.standard.JobName;
import javax.print.attribute.standard.PrinterName;
 
/**
* A printer using {@link DocFlavor.STRING}
*
* @author sylvain
*/
public class StringStandardPrinter extends DefaultTicketPrinter {
 
private static final Format DATE_FMT = new XMLDateFormat();
 
static JobName createJobName(final String name) {
return new JobName(name + ' ' + DATE_FMT.format(new Date()), Locale.getDefault());
}
 
private final String printerName;
 
public StringStandardPrinter(String printerName) {
if (StringUtils.isEmpty(printerName, true))
throw new IllegalArgumentException("Missing printer name");
this.printerName = printerName;
}
 
public final String getPrinterName() {
return this.printerName;
}
 
@Override
public void printBuffer() throws Exception {
final AttributeSet attrSet = new HashPrintServiceAttributeSet(new PrinterName(this.printerName, null));
final PrintService[] lookupPrintServices = PrintServiceLookup.lookupPrintServices(null, attrSet);
if (lookupPrintServices.length <= 0) {
throw new PrintException("Printer " + this.printerName + " not found");
}
final DocPrintJob job = lookupPrintServices[0].createPrintJob();
 
final int size = this.strings.size();
final StringBuilder sb = new StringBuilder(size * 50);
for (int i = 0; i < size; i++) {
sb.append(this.strings.get(i));
sb.append('\n');
}
 
final Doc doc = new SimpleDoc(sb.toString(), DocFlavor.STRING.TEXT_PLAIN, new HashDocAttributeSet(new DocumentName(getDocName(), Locale.getDefault())));
job.print(doc, new HashPrintRequestAttributeSet(createJobName(getDocName())));
}
 
@Override
public void openDrawer() throws Exception {
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/io/SwingPrinter.java
New file
0,0 → 1,58
/*
* 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.pos.io;
 
import org.openconcerto.erp.core.sales.pos.ui.TextAreaTicketPrinter;
import org.openconcerto.utils.StringUtils;
 
import javax.print.PrintException;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.AttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.HashPrintServiceAttributeSet;
import javax.print.attribute.standard.PrinterName;
import javax.swing.text.JTextComponent;
 
/**
* A printer using
* {@link JTextComponent#print(java.text.MessageFormat, java.text.MessageFormat, boolean, PrintService, javax.print.attribute.PrintRequestAttributeSet, boolean)}
*
* @author sylvain
*/
public class SwingPrinter extends TextAreaTicketPrinter {
 
private final String printerName;
 
public SwingPrinter(String printerName) {
if (StringUtils.isEmpty(printerName, true))
throw new IllegalArgumentException("Missing printer name");
this.printerName = printerName;
}
 
public final String getPrinterName() {
return this.printerName;
}
 
@Override
public void printBuffer() throws Exception {
super.printBuffer();
final AttributeSet attrSet = new HashPrintServiceAttributeSet(new PrinterName(this.printerName, null));
final PrintService[] lookupPrintServices = PrintServiceLookup.lookupPrintServices(null, attrSet);
if (lookupPrintServices.length <= 0) {
throw new PrintException("Printer " + this.printerName + " not found");
}
this.print(null, null, false, lookupPrintServices[0], new HashPrintRequestAttributeSet(StringStandardPrinter.createJobName(getDocName())), true);
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/io/DefaultTicketPrinter.java
19,6 → 19,7
import java.util.List;
 
public abstract class DefaultTicketPrinter implements TicketPrinter {
private String docName = "unknown doc";
protected List<String> strings = new ArrayList<String>();
protected List<Integer> modes = new ArrayList<Integer>();
 
36,11 → 37,16
}
 
@Override
public void clearBuffer() {
public void clearBuffer(final String docName) {
this.docName = docName;
this.strings.clear();
this.modes.clear();
}
 
public final String getDocName() {
return this.docName;
}
 
public static String formatLeft(int l, String string) {
if (string.length() > l) {
string = string.substring(0, l);
55,13 → 61,21
}
 
public static String formatRight(int l, String string) {
return format(l, string, false);
}
 
public static String formatCenter(int l, String string) {
return format(l, string, true);
}
 
private static String format(int l, String string, final boolean center) {
if (string.length() > l) {
string = string.substring(0, l);
return string.substring(0, l);
}
 
StringBuffer str = new StringBuffer(l);
 
final int stop = l - string.length();
final int stop = center ? (l - string.length()) / 2 : (l - string.length());
for (int i = 0; i < stop; i++) {
str.append(' ');
}
69,6 → 83,20
return str.toString();
}
 
public static String formatSides(int l, String s1, String s2) {
if (s1.length() + s2.length() > l) {
return s1.substring(0, l / 2) + s2.substring(0, l / 2);
}
final int spaceCount = l - (s1.length() + s2.length());
final StringBuilder sb = new StringBuilder(l);
sb.append(s1);
for (int i = 0; i < spaceCount; i++) {
sb.append(' ');
}
sb.append(s2);
return sb.toString();
}
 
public void addToBuffer(TicketLine line) {
final String style = line.getStyle();
final int mode;
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/pos/io/Printable.java
New file
0,0 → 1,18
/*
* 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.pos.io;
 
public interface Printable {
public void print(final TicketPrinter prt, final int ticketWidth);
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/order/element/ChiffrageCommandeClientSQLElement.java
37,7 → 37,10
*/
protected List<String> getComboFields() {
final List<String> l = new ArrayList<String>();
// remove id_commande_client for CIM
if (!getTable().getDBRoot().contains("ID_AFFAIRE")) {
l.add("ID_COMMANDE_CLIENT");
}
l.add("NOM");
return l;
}
50,6 → 53,8
@Override
protected void _initTableSource(SQLTableModelSource res) {
super._initTableSource(res);
res.getColumn(getTable().getField("QTE")).setRenderer(new DeviseTableCellRenderer());
 
res.getColumn(getTable().getField("PA_HT")).setRenderer(new DeviseTableCellRenderer());
res.getColumn(getTable().getField("MARGE")).setRenderer(new DeviseTableCellRenderer());
res.getColumn(getTable().getField("T_PA_HT")).setRenderer(new DeviseTableCellRenderer());
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/order/element/FacturationCommandeClientSQLElement.java
14,6 → 14,7
package org.openconcerto.erp.core.sales.order.element;
 
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
import org.openconcerto.erp.core.common.ui.DeviseTableCellRenderer;
import org.openconcerto.erp.core.sales.invoice.report.VenteFactureXmlSheet;
import org.openconcerto.erp.core.sales.order.ui.TypeFactureCommandeCellRenderer;
import org.openconcerto.erp.core.sales.order.ui.TypeFactureCommandeClient;
22,17 → 23,23
import org.openconcerto.sql.element.BaseSQLComponent;
import org.openconcerto.sql.element.SQLComponent;
import org.openconcerto.sql.element.UISQLComponent;
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.graph.Path;
import org.openconcerto.sql.view.EditFrame;
import org.openconcerto.sql.view.EditPanelListener;
import org.openconcerto.sql.view.list.BaseSQLTableModelColumn;
import org.openconcerto.sql.view.list.IListe;
import org.openconcerto.sql.view.list.RowAction;
import org.openconcerto.sql.view.list.SQLTableModelSource;
import org.openconcerto.utils.CollectionUtils;
import org.openconcerto.utils.DecimalUtils;
import org.openconcerto.utils.ExceptionHandler;
 
import java.awt.event.ActionEvent;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
214,7 → 221,26
@Override
protected void _initTableSource(SQLTableModelSource res) {
res.init();
res.getColumn(getTable().getField("POURCENT")).setRenderer(new DeviseTableCellRenderer());
res.getColumn(getTable().getField("TYPE_FACTURE")).setRenderer(new TypeFactureCommandeCellRenderer());
final BaseSQLTableModelColumn pourcentFact = new BaseSQLTableModelColumn("Montant facturé", BigDecimal.class) {
 
@Override
protected Object show_(SQLRowAccessor r) {
long ht = r.getForeign("ID_COMMANDE_CLIENT").getLong("T_TTC");
BigDecimal percent = r.getBigDecimal("POURCENT");
return percent.movePointLeft(2).multiply(new BigDecimal(ht).movePointLeft(2), DecimalUtils.HIGH_PRECISION);
}
 
@Override
public Set<FieldPath> getPaths() {
Path p = new Path(getTable());
Path p2 = p.add(p.getFirst().getField("ID_COMMANDE_CLIENT"));
return CollectionUtils.createSet(new FieldPath(p, "POURCENT"), new FieldPath(p2, "T_TTC"));
}
};
pourcentFact.setRenderer(new DeviseTableCellRenderer());
res.getColumns().add(pourcentFact);
super._initTableSource(res);
}
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/order/action/ListeDesCommandesClientAction.java
158,10 → 158,13
totalQte = totalQte.add(qte);
if (row.getBoolean("LIVRE_FORCED") || row.getBoolean("LIVRE")) {
totalQteL = totalQteL.add(qte);
} else {
totalQteL = totalQteL.add(row.getBigDecimal("QTE_LIVREE"));
} else if (row.getBigDecimal("QTE_LIVREE") != null) {
final BigDecimal qteLivree = row.getBigDecimal("QTE_LIVREE");
if (qteLivree != null) {
totalQteL = totalQteL.add(qteLivree);
}
}
}
if (totalQte.signum() != 0) {
return totalQteL.divide(totalQte, DecimalUtils.HIGH_PRECISION).movePointRight(2).setScale(2, RoundingMode.HALF_UP);
} else {
225,22 → 228,8
return null;
}
});
this.btnMngr.setAdditional(this.buttonModifier, new ITransformer<JButton, String>() {
 
@Override
public String transformChecked(JButton input) {
 
SQLRowAccessor row = getListe().fetchSelectedRow();
 
BigDecimal b = getAvancement(row);
 
if (row.getLong("T_HT") > 0 && b.signum() != 0) {
return "Vous ne pouvez pas modifier une commande facturée !";
}
return null;
}
});
}
};
 
final List<Tuple2<? extends SQLTableModelColumn, IListTotalPanel.Type>> fields = new ArrayList<Tuple2<? extends SQLTableModelColumn, IListTotalPanel.Type>>(2);
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/invoice/element/SaisieVenteFactureItemSQLElement.java
18,6 → 18,7
import org.openconcerto.erp.core.common.ui.AbstractVenteArticleItemTable;
import org.openconcerto.erp.core.common.ui.DeviseField;
import org.openconcerto.erp.preferences.DefaultNXProps;
import org.openconcerto.erp.rights.NXRights;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.element.BaseSQLComponent;
import org.openconcerto.sql.element.SQLComponent;
24,11 → 25,15
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLSelect;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.sqlobject.ElementComboBox;
import org.openconcerto.sql.users.rights.UserRights;
import org.openconcerto.sql.users.rights.UserRightsManager;
import org.openconcerto.sql.view.list.SQLTableModelSource;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.component.InteractionMode;
import org.openconcerto.utils.cc.ITransformer;
 
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
117,6 → 122,7
l.add("ECO_CONTRIBUTION");
l.add("T_ECO_CONTRIBUTION");
}
l.add("T_PA_HT");
l.add("T_PV_HT");
l.add("T_PV_TTC");
 
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/invoice/action/ListeDesFactureItemsAction.java
New file
0,0 → 1,75
/*
* 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.core.common.ui.IListFilterDatePanel;
import org.openconcerto.erp.core.common.ui.IListTotalPanel;
import org.openconcerto.erp.core.common.ui.ListeViewPanel;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.model.SQLField;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.view.IListFrame;
import org.openconcerto.sql.view.list.IListe;
import org.openconcerto.ui.DefaultGridBagConstraints;
 
import java.awt.GridBagConstraints;
import java.util.ArrayList;
import java.util.List;
 
import javax.swing.Action;
import javax.swing.JFrame;
 
public class ListeDesFactureItemsAction extends CreateFrameAbstractAction {
 
public ListeDesFactureItemsAction() {
super();
this.putValue(Action.NAME, "Liste des articles facturés");
}
 
public JFrame createFrame() {
final SQLElement element = Configuration.getInstance().getDirectory().getElement("SAISIE_VENTE_FACTURE_ELEMENT");
 
IListe liste = new IListe(element.getTableSource(true));
final ListeViewPanel listeAddPanel = new ListeViewPanel(element, liste);
listeAddPanel.getListe().getRequest().setWhere(new Where(element.getTable().getField("ID_SAISIE_VENTE_FACTURE"), ">", 1));
List<SQLField> l = new ArrayList<SQLField>();
l.add(element.getTable().getField("T_PA_HT"));
l.add(element.getTable().getField("T_PV_HT"));
l.add(element.getTable().getField("T_PV_TTC"));
IListTotalPanel total = new IListTotalPanel(listeAddPanel.getListe(), l);
GridBagConstraints c = new DefaultGridBagConstraints();
c.gridy = 2;
c.weightx = 0;
c.weighty = 0;
c.anchor = GridBagConstraints.EAST;
c.fill = GridBagConstraints.NONE;
listeAddPanel.add(total, c);
IListFrame frame = new IListFrame(listeAddPanel);
frame.setTextTitle("Liste des articles facturés");
frame.getPanel().getListe().setSQLEditable(false);
frame.getPanel().setAddVisible(false);
frame.getPanel().setSearchFullMode(true);
 
// Date panel
IListFilterDatePanel datePanel = new IListFilterDatePanel(frame.getPanel().getListe(), element.getTable().getTable("SAISIE_VENTE_FACTURE").getField("DATE"),
IListFilterDatePanel.getDefaultMap());
c.gridy++;
c.anchor = GridBagConstraints.CENTER;
frame.getPanel().add(datePanel, c);
 
return frame;
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/invoice/ui/EtatVentesPanel.java
25,11 → 25,13
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
 
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
41,6 → 43,7
private JDate du, au;
private JButton buttonGen = new JButton("Créer");
private JButton buttonClose = new JButton("Fermer");
JCheckBox boxTicket = new JCheckBox("Uniquement les ventes en caisse");
 
public EtatVentesPanel() {
super(new GridBagLayout());
59,6 → 62,16
final JPanel p = new JPanel();
p.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 1));
final DefaultComboBoxModel model = new DefaultComboBoxModel();
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
Date d1 = cal.getTime();
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
Date d2 = cal.getTime();
map.put("Aujourd'hui", Tuple2.create(d1, d2));
for (String s : map.keySet()) {
model.addElement(s);
}
100,7 → 113,14
 
c.gridy++;
c.gridx = 0;
c.weightx = 1;
c.gridwidth = GridBagConstraints.REMAINDER;
 
this.add(boxTicket, c);
 
c.gridy++;
c.gridx = 0;
 
JPanel panelButton = new JPanel();
panelButton.add(this.buttonGen);
panelButton.add(this.buttonClose);
147,7 → 167,7
if (e.getSource() == this.buttonGen) {
final Date start = this.du.getDate();
final Date stop = this.au.getDate();
final EtatVentesXmlSheet sheet = new EtatVentesXmlSheet(start, stop);
final EtatVentesXmlSheet sheet = new EtatVentesXmlSheet(start, stop, boxTicket.isSelected());
try {
// FIXME probleme de rendu avec le viewer
sheet.createDocumentAsynchronous().get();
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/invoice/component/SaisieVenteFactureSQLComponent.java
109,7 → 109,7
private AbstractArticleItemTable tableFacture;
private JLabel labelAffaire = new JLabel("Affaire");
private final JDate dateSaisie = new JDate(true);
private DeviseField textPortHT, textAvoirTTC, textRemiseHT, fieldTTC, textNetAPayer;
private DeviseField textPortHT, textAcompte, textAvoirTTC, textRemiseHT, fieldTTC, textNetAPayer;
private DeviseField totalTimbre, netPayer;
private JTextField tauxTimbre;
 
151,6 → 151,7
if (!rowCli.isForeignEmpty("ID_COMMERCIAL")) {
comboCommercial.setValue(rowCli.getForeignID("ID_COMMERCIAL"));
}
 
if (getMode() == SQLComponent.Mode.INSERTION || !isFilling()) {
SQLElement sqleltModeRegl = Configuration.getInstance().getDirectory().getElement("MODE_REGLEMENT");
int idModeRegl = rowCli.getInt("ID_MODE_REGLEMENT");
226,6 → 227,7
final ComptaPropsConfiguration comptaPropsConfiguration = ((ComptaPropsConfiguration) Configuration.getInstance());
 
this.textAvoirTTC = new DeviseField();
this.textAcompte = new DeviseField();
 
// Champ Module
c.gridx = 0;
268,7 → 270,7
@Override
public String getAutoRefreshNumber() {
if (getMode() == Mode.INSERTION) {
return NumerotationAutoSQLElement.getNextNumero(getElement().getClass(), dateSaisie.getDate());
return NumerotationAutoSQLElement.getNextNumero(getElement().getClass(), dateSaisie.getDate(), defaultNum);
} else {
return null;
}
826,6 → 828,7
this.add(this.panelOO, c);
 
this.addSQLObject(this.textAvoirTTC, "T_AVOIR_TTC");
this.addSQLObject(this.textAcompte, "T_ACOMPTE");
 
this.addRequiredSQLObject(dateSaisie, "DATE");
this.addRequiredSQLObject(this.textNumeroUnique, "NUMERO");
1140,6 → 1143,10
netAPayer += timbre;
}
}
Long acompte = this.textAcompte.getValue();
if (acompte != null) {
netAPayer -= acompte;
}
this.textNetAPayer.setValue(netAPayer);
this.textAvoirTTC.setValue(totalAvoirTTC);
}
1290,7 → 1297,7
} catch (InterruptedException e) {
e.printStackTrace();
}
String num = NumerotationAutoSQLElement.getNextNumero(getElement().getClass(), dateSaisie.getDate());
String num = NumerotationAutoSQLElement.getNextNumero(getElement().getClass(), dateSaisie.getDate(), defaultNum);
this.textNumeroUnique.setText(num);
validated = this.textNumeroUnique.checkValidation(false);
System.err.println("ATTEMPT " + attempt + " WITH NUMERO " + num + " validated : " + validated);
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/quote/element/DevisItemSQLElement.java
18,8 → 18,6
import org.openconcerto.erp.core.common.ui.AbstractVenteArticleItemTable;
import org.openconcerto.erp.core.common.ui.DeviseField;
import org.openconcerto.erp.preferences.DefaultNXProps;
import org.openconcerto.erp.utils.KDUtils;
import org.openconcerto.erp.utils.KDUtils.Folder;
import org.openconcerto.sql.element.SQLComponent;
import org.openconcerto.sql.element.UISQLComponent;
import org.openconcerto.sql.model.SQLRowAccessor;
28,11 → 26,8
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.utils.ExceptionHandler;
import org.openconcerto.utils.FileUtils;
 
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
 
52,7 → 47,6
return "ID_DEVIS";
}
 
 
protected List<String> getListFields() {
List<String> l = new ArrayList<String>();
l.add("ID_DEVIS");
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/quote/element/DevisSQLElement.java
26,8 → 26,7
import org.openconcerto.erp.core.sales.quote.ui.QuoteSQLComponent;
import org.openconcerto.erp.core.supplychain.stock.element.MouvementStockSQLElement;
import org.openconcerto.erp.model.MouseSheetXmlListeListener;
import org.openconcerto.erp.utils.KDUtils;
import org.openconcerto.erp.utils.KDUtils.Folder;
import org.openconcerto.erp.preferences.GestionCommercialeGlobalPreferencePanel;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.element.GlobalMapper;
import org.openconcerto.sql.element.SQLComponent;
45,6 → 44,7
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.model.graph.Path;
import org.openconcerto.sql.preferences.SQLPreferences;
import org.openconcerto.sql.request.ListSQLRequest;
import org.openconcerto.sql.users.UserManager;
import org.openconcerto.sql.users.rights.UserRightsManager;
63,6 → 63,7
import org.openconcerto.ui.light.ColumnsSpec;
import org.openconcerto.ui.light.CustomEditorProvider;
import org.openconcerto.ui.light.LightControler;
import org.openconcerto.ui.light.LightUIButtonUnmanaged;
import org.openconcerto.ui.light.LightUIComboBox;
import org.openconcerto.ui.light.LightUIElement;
import org.openconcerto.ui.light.LightUILine;
153,6 → 154,12
 
}
 
@Override
public Set<String> getReadOnlyFields() {
Set<String> s = new HashSet<String>();
s.add("T_ACOMPTE");
return s;
}
 
private List<RowAction> getDevisRowActions() {
 
164,6 → 171,65
 
rowsActions.add(factureAction);
 
SQLPreferences prefs = new SQLPreferences(getTable().getDBRoot());
if (prefs.getBoolean(GestionCommercialeGlobalPreferencePanel.ACOMPTE_DEVIS, false)) {
PredicateRowAction actionClient = new PredicateRowAction(new AbstractAction("Saisir un acompte") {
EditFrame edit;
 
public void actionPerformed(ActionEvent e) {
final SQLElement eltEncaisser = Configuration.getInstance().getDirectory()
.getElement(((ComptaPropsConfiguration) Configuration.getInstance()).getRootSociete().getTable("ENCAISSER_MONTANT"));
 
if (this.edit == null) {
this.edit = new EditFrame(eltEncaisser, EditMode.CREATION);
}
final SQLRowAccessor selRow = IListe.get(e).getSelectedRow();
SQLRowValues rowVals = new SQLRowValues(eltEncaisser.getTable());
rowVals.put("ACOMPTE", true);
rowVals.put("NOM", "Acompte devis " + selRow.getString("NUMERO"));
rowVals.put("ID_CLIENT", selRow.getForeignID("ID_CLIENT"));
rowVals.put("ID_DEVIS", selRow.getID());
SQLRowValues rowValsElt = new SQLRowValues(eltEncaisser.getTable().getTable("ENCAISSER_MONTANT_ELEMENT"));
rowValsElt.put("MONTANT_A_REGLER", selRow.getLong("T_TTC"));
rowValsElt.put("DATE", selRow.getObject("DATE"));
rowValsElt.put("ID_ENCAISSER_MONTANT", rowVals);
this.edit.getSQLComponent().select(rowVals);
this.edit.setVisible(true);
this.edit.addEditPanelListener(new EditPanelListener() {
 
@Override
public void modified() {
// TODO Auto-generated method stub
 
}
 
@Override
public void inserted(int id) {
// Put id devis and refresh devis.t_acompte
SQLRow rowE = eltEncaisser.getTable().getRow(id);
String up = "UPDATE " + selRow.getTable().getSQLName().quote() + " set \"T_ACOMPTE\"=(SELECT COALESCE(SUM(\"MONTANT\"),0) from " + rowE.getTable().getSQLName().quote()
+ " where \"ARCHIVE\"=0 and \"ID_DEVIS\"=" + selRow.getID() + ") where \"ID_DEVIS\"=" + selRow.getID();
eltEncaisser.getTable().getDBSystemRoot().getDataSource().execute(up);
}
 
@Override
public void deleted() {
// TODO Auto-generated method stub
 
}
 
@Override
public void cancelled() {
// TODO Auto-generated method stub
 
}
});
}
}, false);
actionClient.setPredicate(IListeEvent.getSingleSelectionPredicate());
rowsActions.add(actionClient);
}
 
PredicateRowAction actionClient = new PredicateRowAction(new AbstractAction("Détails client") {
EditFrame edit;
private SQLElement eltClient = Configuration.getInstance().getDirectory().getElement(((ComptaPropsConfiguration) Configuration.getInstance()).getRootSociete().getTable("CLIENT"));
537,6 → 603,10
}
l.add("T_HT");
l.add("T_TTC");
SQLPreferences prefs = SQLPreferences.getMemCached(getTable().getDBRoot());
if (prefs.getBoolean(GestionCommercialeGlobalPreferencePanel.ACOMPTE_DEVIS, false)) {
l.add("T_ACOMPTE");
}
l.add("INFOS");
if (getTable().contains("DUNNING_DATE")) {
l.add("DUNNING_DATE");
555,7 → 625,7
SQLRowAccessor rowAd;
if (!r.isForeignEmpty("ID_ADRESSE_LIVRAISON")) {
rowAd = r.getForeign("ID_ADRESSE_LIVRAISON");
} else if (!r.getForeign("ID_CLIENT").isForeignEmpty("ID_ADRESSE_L")) {
} else if (r.getForeign("ID_CLIENT").getObject("ID_ADRESSE_L") != null && !r.getForeign("ID_CLIENT").isForeignEmpty("ID_ADRESSE_L")) {
rowAd = r.getForeign("ID_CLIENT").getForeign("ID_ADRESSE_L");
} else {
rowAd = r.getForeign("ID_CLIENT").getForeign("ID_ADRESSE");
811,38 → 881,34
 
LightUILine toolbarLine = new LightUILine();
 
LightUIElement b1 = new LightUIElement("up");
b1.setType(LightUIElement.TYPE_BUTTON_UNMANAGED);
b1.setGridWidth(1);
LightUIButtonUnmanaged b1 = new LightUIButtonUnmanaged("up");
b1.setIcon("up.png");
panel.addControler(new ActivationOnSelectionControler(id, b1.getId()));
panel.addControler(new LightControler(LightControler.TYPE_UP, id, b1.getId()));
toolbarLine.addChild(b1);
 
final LightUIElement b2 = new LightUIElement("down");
b2.setType(LightUIElement.TYPE_BUTTON_UNMANAGED);
b2.setGridWidth(1);
final LightUIButtonUnmanaged b2 = new LightUIButtonUnmanaged("down");
b2.setIcon("down.png");
panel.addControler(new ActivationOnSelectionControler(id, b2.getId()));
panel.addControler(new LightControler(LightControler.TYPE_DOWN, id, b2.getId()));
toolbarLine.addChild(b2);
// Add
LightUIElement addButton = createButton("add", "Ajouter une ligne");
LightUIElement addButton = new LightUIButtonUnmanaged("add", "Ajouter une ligne");
panel.addControler(new LightControler(LightControler.TYPE_ADD_DEFAULT, id, addButton.getId()));
toolbarLine.addChild(addButton);
// Insert
LightUIElement insertButton = createButton("insert", "Insérer une ligne");
LightUIElement insertButton = new LightUIButtonUnmanaged("insert", "Insérer une ligne");
panel.addControler(new LightControler(LightControler.TYPE_INSERT_DEFAULT, id, insertButton.getId()));
toolbarLine.addChild(insertButton);
 
// Copy
LightUIElement copyButton = createButton("copy", "Dupliquer");
LightUIElement copyButton = new LightUIButtonUnmanaged("copy", "Dupliquer");
panel.addControler(new ActivationOnSelectionControler(id, copyButton.getId()));
panel.addControler(new LightControler(LightControler.TYPE_COPY, id, copyButton.getId()));
toolbarLine.addChild(copyButton);
 
// Remove
LightUIElement removeButton = createButton("remove", "Supprimer");
LightUIElement removeButton = new LightUIButtonUnmanaged("remove", "Supprimer");
panel.addControler(new ActivationOnSelectionControler(id, removeButton.getId()));
panel.addControler(new LightControler(LightControler.TYPE_REMOVE, id, removeButton.getId()));
toolbarLine.addChild(removeButton);
859,13 → 925,6
return panel;
}
 
LightUIElement createButton(String id, String label) {
final LightUIElement b1 = new LightUIElement(id);
b1.setType(LightUIElement.TYPE_BUTTON_UNMANAGED);
b1.setGridWidth(1);
b1.setLabel(label);
return b1;
}
});
return map;
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/quote/element/DevisLogMailSQLElement.java
New file
0,0 → 1,39
/*
* 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.quote.element;
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.element.SocieteJoinSQLElement;
import org.openconcerto.sql.element.JoinSQLElement;
import org.openconcerto.sql.model.DBRoot;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.utils.SQLCreateTable;
 
public class DevisLogMailSQLElement extends SocieteJoinSQLElement {
 
public static final String TABLENAME = "DEVIS_MAIL_LOG";
private static final String TO_OWNER_FIELDNAME = "ID_DEVIS";
 
private static final SQLCreateTable getCreateTable(final SQLTable devisT, final SQLTable logT) {
return JoinSQLElement.createBuilder(devisT, logT).setTableName(TABLENAME).setOwnerFK(TO_OWNER_FIELDNAME).getCreateTable();
}
 
public DevisLogMailSQLElement() {
this(ComptaPropsConfiguration.getInstanceCompta().getRootSociete());
}
 
public DevisLogMailSQLElement(final DBRoot root) {
super((SQLTable) root.getCheckedChild(TABLENAME).getJDBC(), TO_OWNER_FIELDNAME);
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/sales/quote/component/DevisSQLComponent.java
355,9 → 355,10
});
 
}
final SQLPreferences prefs = SQLPreferences.getMemCached(getTable().getDBRoot());
 
final ElementComboBox boxTarif = new ElementComboBox();
SQLPreferences prefs = SQLPreferences.getMemCached(getTable().getDBRoot());
 
if (prefs.getBoolean(GestionCommercialeGlobalPreferencePanel.ADDRESS_SPEC, true)) {
 
final SQLElement adrElement = getElement().getForeignElement("ID_ADRESSE");
594,6 → 595,24
this.textRemiseHT.setMinimumSize(new Dimension(150, 20));
this.textRemiseHT.setPreferredSize(new Dimension(150, 20));
 
if (prefs.getBoolean(GestionCommercialeGlobalPreferencePanel.ACOMPTE_DEVIS, false)) {
// Acompte
cRemise.gridy++;
cRemise.gridx = 0;
cRemise.weightx = 0;
cRemise.weighty = 0;
cRemise.gridwidth = 1;
JLabel compAcompte = new JLabel(getLabelFor("T_ACOMPTE"), SwingConstants.RIGHT);
panelRemise.add(compAcompte, cRemise);
cRemise.gridx++;
cRemise.gridwidth = GridBagConstraints.REMAINDER;
DeviseField fieldAcompte = new DeviseField();
fieldAcompte.setEnabled(false);
cRemise.weightx = 1;
panelRemise.add(fieldAcompte, cRemise);
this.addView(fieldAcompte, "T_ACOMPTE");
}
 
// cRemise.gridx = 1;
// cRemise.gridy++;
// cRemise.weightx = 0;
/trunk/OpenConcerto/src/org/openconcerto/erp/core/common/element/DepartementSQLElement.java
42,6 → 42,7
 
protected List<String> getComboFields() {
final List<String> l = new ArrayList<String>();
l.add("NUMERO");
l.add("NOM");
return l;
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/common/element/SocieteJoinSQLElement.java
New file
0,0 → 1,39
/*
* 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.common.element;
 
import org.openconcerto.erp.config.Gestion;
import org.openconcerto.sql.element.JoinSQLElement;
import org.openconcerto.sql.model.SQLTable;
 
public abstract class SocieteJoinSQLElement extends JoinSQLElement {
 
{
this.setL18nLocation(Gestion.class);
}
 
public SocieteJoinSQLElement(SQLTable table, final String... fieldsToOwner) {
super(table, fieldsToOwner);
}
 
@Override
protected String createCode() {
return createCodeFromPackage();
}
 
protected final String createCodeFromPackage() {
return SocieteSQLConfElement.createCodeFromPackage(SocieteSQLConfElement.getLastNonAbstractClass(this.getClass(), SocieteJoinSQLElement.class));
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/common/element/NumerotationAutoSQLElement.java
294,7 → 294,7
return getNextForMonth(clazz, d, rowNum);
} else {
final String numberLabel = getLabelNumberFor(clazz);
if (rowNum.getObject(numberLabel) == null) {
if (rowNum.getObject(numberLabel) == null || rowNum.getString(getLabelFormatFor(clazz)) == null || rowNum.getString(getLabelFormatFor(clazz)).trim().length() == 0) {
return "";
}
String format = rowNum.getString(getLabelFormatFor(clazz));
/trunk/OpenConcerto/src/org/openconcerto/erp/core/common/element/SocieteSQLConfElement.java
130,22 → 130,27
return createCodeFromPackage(getLastNonAbstractClass());
}
 
private final Class<? extends ComptaSQLConfElement> getLastNonAbstractClass() {
private final Class<? extends SocieteSQLConfElement> getLastNonAbstractClass() {
return getLastNonAbstractClass(this.getClass(), SocieteSQLConfElement.class);
}
 
static protected final <T extends SQLElement> Class<? extends T> getLastNonAbstractClass(final Class<? extends T> clazz, final Class<T> superClass) {
Class<?> prev = null;
Class<?> cl = this.getClass();
Class<?> cl = clazz;
// test loop
assert !Modifier.isAbstract(cl.getModifiers()) && ComptaSQLConfElement.class.isAssignableFrom(cl) && Modifier.isAbstract(ComptaSQLConfElement.class.getModifiers());
assert superClass.isAssignableFrom(cl);
if (Modifier.isAbstract(cl.getModifiers()))
throw new IllegalArgumentException("Class is abstract : " + cl);
if (!Modifier.isAbstract(superClass.getModifiers()))
throw new IllegalArgumentException("Superclass isn't abstract : " + superClass);
while (!Modifier.isAbstract(cl.getModifiers())) {
prev = cl;
cl = cl.getSuperclass();
}
assert ComptaSQLConfElement.class.isAssignableFrom(prev);
@SuppressWarnings("unchecked")
final Class<? extends ComptaSQLConfElement> res = (Class<? extends ComptaSQLConfElement>) prev;
return res;
return prev.asSubclass(superClass);
}
 
static protected String createCodeFromPackage(final Class<? extends ComptaSQLConfElement> cl) {
static protected String createCodeFromPackage(final Class<? extends SQLElement> cl) {
String canonicalName = cl.getName();
if (canonicalName.contains("erp.core") && canonicalName.contains(".element")) {
int i = canonicalName.indexOf("erp.core") + 9;
349,7 → 354,7
* Primary actions on the element (add/modify/remove)
*/
public List<TableAction> getPrimaryRowActions() {
final List<TableAction> actions = new ArrayList<TableAction>();
final List<TableAction> actions = new ArrayList<>(3);
actions.add(new TableAction(getAddAction()));
actions.add(new TableAction(getModifyAction()));
actions.add(new TableAction(getRemoveAction()));
360,8 → 365,7
* Secondary actions on the element (send by email, ..)
*/
public List<TableAction> getSecondaryRowActions() {
final List<TableAction> actions = new ArrayList<TableAction>(0);
return actions;
return new ArrayList<>(0);
}
 
public RowAction getAddAction() {
/trunk/OpenConcerto/src/org/openconcerto/erp/core/common/ui/PreviewFrame.java
13,31 → 13,106
package org.openconcerto.erp.core.common.ui;
 
import org.openconcerto.erp.generationDoc.A4;
import org.openconcerto.erp.generationDoc.AbstractSheetXml;
import org.openconcerto.erp.generationDoc.DefaultNXDocumentPrinter;
import org.openconcerto.erp.generationDoc.ODTPrinterNX;
import org.openconcerto.utils.ExceptionHandler;
 
import java.awt.Dimension;
import java.awt.GraphicsEnvironment;
import java.awt.print.Paper;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.util.Arrays;
import java.util.List;
 
import javax.print.PrintService;
import javax.print.attribute.Attribute;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.Size2DSyntax;
import javax.print.attribute.standard.Copies;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.MediaSizeName;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
 
import org.jopendocument.model.OpenDocument;
import org.jopendocument.panel.ODSViewerPanel;
import org.jopendocument.print.DefaultXMLDocumentPrinter;
import org.jopendocument.print.ODTPrinterXML;
 
public class PreviewFrame extends JFrame {
 
private PreviewFrame(OpenDocument doc, String title) {
super(title);
this.setContentPane(new ODSViewerPanel(doc, new DefaultXMLDocumentPrinter()));
this.setContentPane(new ODSViewerPanel(doc, createDocumentPrinter()));
init();
}
 
public PreviewFrame(String title, String url, String odspXml) {
this.setContentPane(new ODSViewerPanel(url, odspXml, new DefaultXMLDocumentPrinter(), true));
this.setContentPane(new ODSViewerPanel(url, odspXml, createDocumentPrinter(), true));
this.setTitle(title);
init();
}
 
public DefaultXMLDocumentPrinter createDocumentPrinter() {
return new DefaultXMLDocumentPrinter() {
public void print(List<OpenDocument> documents) {
 
final double POINTS_PER_INCH = 72.0;
// Printer configuration
final PrinterJob printJob = PrinterJob.getPrinterJob();
 
final HashPrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
// L'impression est forcée en A4, sur OpenSuse le format est en
// Letter par défaut alors que l'imprimante est en A4 dans le système
final MediaSizeName media = MediaSizeName.ISO_A4;
attributes.add(media);
Paper paper = new A4(0, 0);
 
final MediaPrintableArea printableArea = new MediaPrintableArea((float) (paper.getImageableX() / POINTS_PER_INCH), (float) (paper.getImageableY() / POINTS_PER_INCH),
(float) (paper.getImageableWidth() / POINTS_PER_INCH), (float) (paper.getImageableHeight() / POINTS_PER_INCH), Size2DSyntax.INCH);
attributes.add(printableArea);
attributes.add(new Copies(2));
// Print dialog
boolean okToPrint = printJob.printDialog(attributes);
final Attribute attribute = attributes.get(Copies.class);
if (attribute != null) {
final Copies attributeCopies = (Copies) attribute;
final int value = attributeCopies.getValue();
printJob.setCopies(value);
} else {
printJob.setCopies(1);
}
if (okToPrint) {
final Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
 
DefaultNXDocumentPrinter printer = new DefaultNXDocumentPrinter();
printer.print(documents, printJob);
 
} catch (Exception e) {
ExceptionHandler.handle("Print error", e);
}
 
}
});
t.setName("PreviewFrame Print Thread");
t.setDaemon(true);
t.start();
}
 
}
 
};
 
}
 
private void init() {
final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
this.setMaximizedBounds(ge.getMaximumWindowBounds());
/trunk/OpenConcerto/src/org/openconcerto/erp/core/common/ui/AbstractVenteArticleItemTable.java
316,6 → 316,11
list.add(tableElementDesc);
}
 
if (e.getTable().getFieldsName().contains("DELAI")) {
final SQLTableElement tableElementDelai = new SQLTableElement(e.getTable().getField("DELAI"));
list.add(tableElementDelai);
}
 
if (DefaultNXProps.getInstance().getBooleanValue(ARTICLE_SHOW_DEVISE, false)) {
// Code Douanier
final SQLTableElement tableElementCodeDouane = new SQLTableElement(e.getTable().getField("CODE_DOUANIER"));
833,7 → 838,7
defaultRowVals.put("ID_TAXE", TaxeCache.getCache().getFirstTaxe().getID());
defaultRowVals.put("CODE", "");
defaultRowVals.put("NOM", "");
final RowValuesTableModel model = new RowValuesTableModel(e, list, e.getTable().getField("NOM"), false, defaultRowVals);
final RowValuesTableModel model = new RowValuesTableModel(e, list, e.getTable().getField("ID_TAXE"), false, defaultRowVals);
setModel(model);
 
this.table = new RowValuesTable(model, getConfigurationFile());
911,6 → 916,8
@Override
public SQLSelect transformChecked(SQLSelect input) {
 
// FIXME utiliser le stock sélectionné sur la ligne et non le stock par défaut de
// l'article
final SQLTable tableStock = sqlTableArticle.getTable("STOCK");
input.andWhere(new Where(tableStock.getKey(), "=", sqlTableArticle.getField("ID_STOCK")));
input.setExcludeUndefined(false, tableStock);
/trunk/OpenConcerto/src/org/openconcerto/erp/core/common/ui/TotalPanel.java
573,7 → 573,9
}
}
}
rowValsPort.putRowValues("ID_ARTICLE").put("ID_COMPTE_PCE", rowDefaultCptPort.getID());
final SQLRowValues putRowValues = rowValsPort.putRowValues("ID_ARTICLE");
putRowValues.put("ID_COMPTE_PCE", rowDefaultCptPort.getID());
putRowValues.put("ID_COMPTE_PCE_ACHAT", rowDefaultCptPort.getID());
} else {
rowValsPort = null;
}
/trunk/OpenConcerto/src/org/openconcerto/erp/core/common/ui/AbstractAchatArticleItemTable.java.r23577
New file
0,0 → 1,1165
package ilm.erp.core.common.ui;
 
import ilm.erp.config.ComptaPropsConfiguration;
import ilm.erp.core.finance.accounting.model.CurrencyConverter;
import ilm.erp.core.finance.tax.model.TaxeCache;
import ilm.erp.core.sales.pos.io.BarcodeReader;
import ilm.erp.core.sales.pos.ui.BarcodeListener;
import ilm.erp.core.sales.product.element.ReferenceArticleSQLElement;
import ilm.erp.core.sales.product.element.UniteVenteArticleSQLElement;
import ilm.erp.core.sales.product.ui.CurrencyWithSymbolRenderer;
import ilm.erp.core.sales.product.ui.QteUnitRowValuesRenderer;
import ilm.erp.preferences.DefaultNXProps;
import ilm.erp.preferences.GestionArticleGlobalPreferencePanel;
import ilm.sql.Configuration;
import ilm.sql.element.SQLElement;
import ilm.sql.model.FieldPath;
import ilm.sql.model.SQLRow;
import ilm.sql.model.SQLRowAccessor;
import ilm.sql.model.SQLRowListRSH;
import ilm.sql.model.SQLRowValues;
import ilm.sql.model.SQLSelect;
import ilm.sql.model.SQLTable;
import ilm.sql.model.UndefinedRowValuesCache;
import ilm.sql.model.Where;
import ilm.sql.model.graph.Path;
import ilm.sql.preferences.SQLPreferences;
import ilm.sql.sqlobject.ITextArticleWithCompletionCellEditor;
import ilm.sql.sqlobject.ITextWithCompletion;
import ilm.sql.view.list.AutoCompletionManager;
import ilm.sql.view.list.CellDynamicModifier;
import ilm.sql.view.list.RowValuesTable;
import ilm.sql.view.list.RowValuesTableModel;
import ilm.sql.view.list.SQLTableElement;
import ilm.sql.view.list.ValidStateChecker;
import ilm.utils.DecimalUtils;
import ilm.utils.Tuple3;
import ilm.utils.i18n.TranslationManager;
 
import java.awt.event.ActionEvent;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
 
import javax.swing.AbstractAction;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableCellRenderer;
 
public abstract class AbstractAchatArticleItemTable extends AbstractArticleItemTable {
 
private AutoCompletionManager m;
private AutoCompletionManager m2, m3;
private AutoCompletionManager m4;
private final SQLTable tableArticle = getSQLElement().getTable().getTable("ARTICLE");
private SQLRowAccessor rowDevise;
private boolean supplierCode;
 
public AbstractAchatArticleItemTable() {
super();
}
 
@Override
protected void setModel(RowValuesTableModel model) {
super.setModel(model);
model.addTableModelListener(new TableModelListener() {
 
@Override
public void tableChanged(TableModelEvent e) {
 
calculTarifNomenclature();
 
}
});
}
 
protected void init() {
 
final SQLElement e = getSQLElement();
final SQLPreferences prefs = SQLPreferences.getMemCached(getSQLElement().getTable().getDBRoot());
final boolean selectArticle = prefs.getBoolean(GestionArticleGlobalPreferencePanel.USE_CREATED_ARTICLE, false);
final boolean createAuto = prefs.getBoolean(GestionArticleGlobalPreferencePanel.CREATE_ARTICLE_AUTO, true);
final boolean showEco = prefs.getBoolean(AbstractVenteArticleItemTable.SHOW_ECO_CONTRIBUTION_COLUMNS, false);
this.supplierCode = prefs.getBoolean(GestionArticleGlobalPreferencePanel.SUPPLIER_PRODUCT_CODE, false);
 
final List<SQLTableElement> list = new Vector<SQLTableElement>();
final SQLTableElement eNiveau = new SQLTableElement(e.getTable().getField("NIVEAU")) {
@Override
public void setValueFrom(SQLRowValues row, Object value) {
super.setValueFrom(row, value);
}
};
eNiveau.setRenderer(new NiveauTableCellRender());
eNiveau.setEditor(new NiveauTableCellEditor());
list.add(eNiveau);
list.add(new SQLTableElement(e.getTable().getField("ID_STYLE")));
 
SQLTableElement tableElementCodeFournisseur = null;
 
if (e.getTable().contains("ID_CODE_FOURNISSEUR") && supplierCode) {
tableElementCodeFournisseur = new SQLTableElement(e.getTable().getField("ID_CODE_FOURNISSEUR"), true, true, true);
list.add(tableElementCodeFournisseur);
}
 
SQLTableElement tableElementArticle = new SQLTableElement(e.getTable().getField("ID_ARTICLE"), true, true, true) {
@Override
public boolean isCellEditable(SQLRowValues vals, int rowIndex, int columnIndex) {
boolean b = super.isCellEditable(vals, rowIndex, columnIndex);
if (vals.getTable().contains("ID_COMMANDE_ELEMENT")) {
boolean noCmdElt = vals.getObject("ID_COMMANDE_ELEMENT") == null || vals.isForeignEmpty("ID_COMMANDE_ELEMENT");
return b && noCmdElt;
} else {
return b;
}
 
}
};
list.add(tableElementArticle);
 
if (e.getTable().getFieldsName().contains("ID_FAMILLE_ARTICLE")) {
final SQLTableElement tableFamille = new SQLTableElement(e.getTable().getField("ID_FAMILLE_ARTICLE"));
list.add(tableFamille);
}
 
if (e.getTable().getFieldsName().contains("ID_ECO_CONTRIBUTION")) {
this.tableElementEcoID = new SQLTableElement(e.getTable().getField("ID_ECO_CONTRIBUTION"));
list.add(this.tableElementEcoID);
}
 
if (e.getTable().getFieldsName().contains("INCOTERM")) {
final SQLTableElement tableElementInco = new SQLTableElement(e.getTable().getField("INCOTERM"));
tableElementInco.setEditable(false);
list.add(tableElementInco);
}
 
if (e.getTable().getFieldsName().contains("PREBILAN")) {
final SQLTableElement tableElementPre = new SQLTableElement(e.getTable().getField("PREBILAN"), BigDecimal.class);
tableElementPre.setRenderer(new DeviseTableCellRenderer());
list.add(tableElementPre);
}
 
// Code article
final SQLTableElement tableElementCode = new SQLTableElement(e.getTable().getField("CODE"), String.class,
new ITextArticleWithCompletionCellEditor(e.getTable().getTable("ARTICLE"), e.getTable().getTable("ARTICLE_FOURNISSEUR"))) {
@Override
public boolean isCellEditable(SQLRowValues vals, int rowIndex, int columnIndex) {
boolean b = super.isCellEditable(vals, rowIndex, columnIndex);
if (vals.getTable().contains("ID_COMMANDE_ELEMENT")) {
boolean noCmdElt = vals.getObject("ID_COMMANDE_ELEMENT") == null || vals.isForeignEmpty("ID_COMMANDE_ELEMENT");
return b && noCmdElt;
} else {
return b;
}
 
}
};
list.add(tableElementCode);
// Désignation de l'article
final SQLTableElement tableElementNom = new SQLTableElement(e.getTable().getField("NOM")) {
@Override
public boolean isCellEditable(SQLRowValues vals, int rowIndex, int columnIndex) {
boolean b = super.isCellEditable(vals, rowIndex, columnIndex);
if (vals.getTable().contains("ID_COMMANDE_ELEMENT")) {
boolean noCmdElt = vals.getObject("ID_COMMANDE_ELEMENT") == null || vals.isForeignEmpty("ID_COMMANDE_ELEMENT");
return b && noCmdElt;
} else {
return b;
}
 
}
};
list.add(tableElementNom);
 
SQLTableElement tableCmdElt = null;
if (e.getTable().contains("ID_COMMANDE_ELEMENT")) {
tableCmdElt = new SQLTableElement(e.getTable().getField("ID_COMMANDE_ELEMENT"));
list.add(tableCmdElt);
}
 
if (e.getTable().getFieldsName().contains("DESCRIPTIF")) {
final SQLTableElement tableElementDesc = new SQLTableElement(e.getTable().getField("DESCRIPTIF"));
list.add(tableElementDesc);
}
if (e.getTable().getFieldsName().contains("COLORIS")) {
final SQLTableElement tableElementColoris = new SQLTableElement(e.getTable().getField("COLORIS"));
list.add(tableElementColoris);
}
// Valeur des métriques
final SQLTableElement tableElement_ValeurMetrique2 = new SQLTableElement(e.getTable().getField("VALEUR_METRIQUE_2"), Float.class);
list.add(tableElement_ValeurMetrique2);
final SQLTableElement tableElement_ValeurMetrique3 = new SQLTableElement(e.getTable().getField("VALEUR_METRIQUE_3"), Float.class);
list.add(tableElement_ValeurMetrique3);
final SQLTableElement tableElement_ValeurMetrique1 = new SQLTableElement(e.getTable().getField("VALEUR_METRIQUE_1"), Float.class);
list.add(tableElement_ValeurMetrique1);
// Prix d'achat HT de la métrique 1
final SQLTableElement tableElement_PrixMetrique1_AchatHT = new SQLTableElement(e.getTable().getField("PRIX_METRIQUE_HA_1"), BigDecimal.class);
tableElement_PrixMetrique1_AchatHT.setRenderer(new CurrencyWithSymbolRenderer());
list.add(tableElement_PrixMetrique1_AchatHT);
 
if (e.getTable().getFieldsName().contains("ECO_CONTRIBUTION")) {
this.tableElementEco = new SQLTableElement(e.getTable().getField("ECO_CONTRIBUTION"));
list.add(this.tableElementEco);
}
 
final SQLTableElement tableElement_Devise = new SQLTableElement(e.getTable().getField("ID_DEVISE"));
tableElement_Devise.setEditable(false);
final SQLTableElement tableElement_PA_Devise = new SQLTableElement(e.getTable().getField("PA_DEVISE"), BigDecimal.class);
Path p = new Path(getSQLElement().getTable()).addForeignField("ID_DEVISE");
tableElement_PA_Devise.setRenderer(new CurrencyWithSymbolRenderer(new FieldPath(p, "CODE")));
if (DefaultNXProps.getInstance().getBooleanValue(AbstractVenteArticleItemTable.ARTICLE_SHOW_DEVISE, false)) {
// Devise
list.add(tableElement_Devise);
 
// Prix d'achat HT devise
list.add(tableElement_PA_Devise);
}
// Mode de vente
final SQLTableElement tableElement_ModeVente = new SQLTableElement(e.getTable().getField("ID_MODE_VENTE_ARTICLE"));
list.add(tableElement_ModeVente);
 
// Prix d'achat unitaire HT
this.ha = new SQLTableElement(e.getTable().getField("PA_HT"), BigDecimal.class);
this.ha.setRenderer(new CurrencyWithSymbolRenderer());
list.add(this.ha);
 
SQLTableElement qteU = new SQLTableElement(e.getTable().getField("QTE_UNITAIRE"), BigDecimal.class) {
@Override
public boolean isCellEditable(SQLRowValues vals, int rowIndex, int columnIndex) {
 
SQLRowAccessor row = vals.getForeign("ID_UNITE_VENTE");
if (row != null && !row.isUndefined() && row.getBoolean("A_LA_PIECE")) {
return false;
} else {
return super.isCellEditable(vals, rowIndex, columnIndex);
}
}
 
@Override
public TableCellRenderer getTableCellRenderer() {
return new QteUnitRowValuesRenderer();
}
 
protected Object getDefaultNullValue() {
return BigDecimal.ZERO;
}
};
list.add(qteU);
 
SQLTableElement uniteVente = new SQLTableElement(e.getTable().getField("ID_UNITE_VENTE"));
list.add(uniteVente);
 
// Quantité
final SQLTableElement qteElement = new SQLTableElement(e.getTable().getField("QTE"), Integer.class) {
protected Object getDefaultNullValue() {
return Integer.valueOf(0);
}
};
list.add(qteElement);
// TVA
this.tableElementTVA = new SQLTableElement(e.getTable().getField("ID_TAXE"));
list.add(this.tableElementTVA);
// Poids piece
SQLTableElement tableElementPoids = new SQLTableElement(e.getTable().getField("POIDS"), Float.class);
list.add(tableElementPoids);
 
// Poids total
this.tableElementPoidsTotal = new SQLTableElement(e.getTable().getField("T_POIDS"), Float.class);
list.add(this.tableElementPoidsTotal);
 
// Service
String val = DefaultNXProps.getInstance().getStringProperty("ArticleService");
Boolean b = Boolean.valueOf(val);
if (b != null && b.booleanValue()) {
this.service = new SQLTableElement(e.getTable().getField("SERVICE"), Boolean.class);
list.add(this.service);
}
 
if (DefaultNXProps.getInstance().getBooleanValue(AbstractVenteArticleItemTable.ARTICLE_SHOW_DEVISE, false)) {
// Prix d'achat HT devise
this.tableElementTotalDevise = new SQLTableElement(e.getTable().getField("PA_DEVISE_T"), BigDecimal.class);
this.tableElementTotalDevise.setRenderer(new CurrencyWithSymbolRenderer(new FieldPath(p, "CODE")));
list.add(tableElementTotalDevise);
}
 
SQLTableElement tableElementRemise = null;
if (e.getTable().contains("POURCENT_REMISE")) {
tableElementRemise = new SQLTableElement(e.getTable().getField("POURCENT_REMISE"));
list.add(tableElementRemise);
}
 
if (e.getTable().getFieldsName().contains("T_ECO_CONTRIBUTION")) {
this.tableElementEcoTotal = new SQLTableElement(e.getTable().getField("T_ECO_CONTRIBUTION"));
list.add(this.tableElementEcoTotal);
}
 
// Total HT
this.totalHT = new SQLTableElement(e.getTable().getField("T_PA_HT"), BigDecimal.class);
this.totalHT.setRenderer(new DeviseTableCellRenderer());
this.totalHT.setEditable(false);
if (e.getTable().contains("POURCENT_REMISE") && tableElementRemise != null) {
tableElementRemise.addModificationListener(this.totalHT);
}
list.add(this.totalHT);
this.totalHA = this.totalHT;
// Total TTC
this.tableElementTotalTTC = new SQLTableElement(e.getTable().getField("T_PA_TTC"), BigDecimal.class);
this.tableElementTotalTTC.setRenderer(new DeviseTableCellRenderer());
list.add(this.tableElementTotalTTC);
 
this.defaultRowVals = new SQLRowValues(UndefinedRowValuesCache.getInstance().getDefaultRowValues(e.getTable()));
this.defaultRowVals.put("ID_TAXE", TaxeCache.getCache().getFirstTaxe().getID());
this.defaultRowVals.put("CODE", "");
this.defaultRowVals.put("NOM", "");
this.defaultRowVals.put("QTE", 1);
this.defaultRowVals.put("QTE_UNITAIRE", BigDecimal.ONE);
this.defaultRowVals.put("ID_UNITE_VENTE", UniteVenteArticleSQLElement.A_LA_PIECE);
this.defaultRowVals.put("ID_MODE_VENTE_ARTICLE", ReferenceArticleSQLElement.A_LA_PIECE);
final RowValuesTableModel model = new RowValuesTableModel(e, list, e.getTable().getField("NOM"), false, this.defaultRowVals);
setModel(model);
 
this.table = new RowValuesTable(model, getConfigurationFile());
ToolTipManager.sharedInstance().unregisterComponent(this.table);
ToolTipManager.sharedInstance().unregisterComponent(this.table.getTableHeader());
 
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
handlePopup(e);
}
 
@Override
public void mousePressed(MouseEvent e) {
handlePopup(e);
}
 
public void handlePopup(MouseEvent e) {
final int rowindex = table.getSelectedRow();
if (rowindex < 0)
return;
if (e.isPopupTrigger() && e.getComponent() instanceof JTable) {
JPopupMenu popup = new JPopupMenu();
if (prefs.getBoolean(GestionArticleGlobalPreferencePanel.CAN_EXPAND_NOMENCLATURE_HA, true)) {
popup.add(new AbstractAction(TranslationManager.getInstance().getTranslationForItem("product.bom.expand")) {
 
@Override
public void actionPerformed(ActionEvent arg0) {
expandNomenclature(rowindex, m, EXPAND_TYPE.EXPAND);
}
});
popup.add(new AbstractAction(TranslationManager.getInstance().getTranslationForItem("product.bom.expose")) {
 
@Override
public void actionPerformed(ActionEvent arg0) {
expandNomenclature(rowindex, m, EXPAND_TYPE.VIEW_ONLY);
}
});
popup.add(new AbstractAction(TranslationManager.getInstance().getTranslationForItem("product.bom.flat")) {
 
@Override
public void actionPerformed(ActionEvent arg0) {
expandNomenclature(rowindex, m, EXPAND_TYPE.FLAT);
}
});
}
for (AbstractAction action : getAdditionnalMouseAction(rowindex)) {
popup.add(action);
}
 
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
});
 
// Autocompletion
List<String> completionFields = new ArrayList<String>();
if (e.getTable().getFieldsName().contains("INCOTERM")) {
completionFields.add("INCOTERM");
}
if (e.getTable().getFieldsName().contains("ID_ECO_CONTRIBUTION")) {
completionFields.add("ID_ECO_CONTRIBUTION");
}
completionFields.add("ID_UNITE_VENTE");
completionFields.add("PA_HT");
completionFields.add("PV_HT");
completionFields.add("POIDS");
completionFields.add("ID_TAXE");
completionFields.add("PRIX_METRIQUE_HA_1");
completionFields.add("PRIX_METRIQUE_HA_2");
completionFields.add("PRIX_METRIQUE_HA_3");
completionFields.add("VALEUR_METRIQUE_1");
completionFields.add("VALEUR_METRIQUE_2");
completionFields.add("VALEUR_METRIQUE_3");
completionFields.add("ID_MODE_VENTE_ARTICLE");
completionFields.add("PRIX_METRIQUE_VT_1");
completionFields.add("PRIX_METRIQUE_VT_2");
completionFields.add("PRIX_METRIQUE_VT_3");
completionFields.add("SERVICE");
completionFields.add("ID_DEVISE");
completionFields.add("PA_DEVISE");
if (e.getTable().getFieldsName().contains("COLORIS")) {
completionFields.add("COLORIS");
}
 
if (e.getTable().getFieldsName().contains("DESCRIPTIF")) {
completionFields.add("DESCRIPTIF");
}
if (e.getTable().getFieldsName().contains("ID_FAMILLE_ARTICLE")) {
completionFields.add("ID_FAMILLE_ARTICLE");
}
 
this.m = new AutoCompletionManager(tableElementCode, ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete().getField("ARTICLE.CODE"), this.table,
this.table.getRowValuesTableModel()) {
@Override
protected Object getValueFrom(SQLRow row, String field, SQLRowAccessor rowDest) {
Object res = tarifCompletion(row, field);
if (res == null) {
return super.getValueFrom(row, field, rowDest);
} else {
return res;
}
}
};
m.fill("NOM", "NOM");
m.fill("ID", "ID_ARTICLE");
for (String string : completionFields) {
m.fill(string, string);
}
final SQLTable sqlTableArticle = ((ComptaPropsConfiguration) Configuration.getInstance()).getRootSociete().getTable("ARTICLE");
final Where w = new Where(sqlTableArticle.getField("OBSOLETE"), "=", Boolean.FALSE);
m.setWhere(w);
 
this.m2 = new AutoCompletionManager(tableElementNom, ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete().getField("ARTICLE.NOM"), this.table,
this.table.getRowValuesTableModel()) {
@Override
protected Object getValueFrom(SQLRow row, String field, SQLRowAccessor rowDest) {
Object res = tarifCompletion(row, field);
if (res == null) {
return super.getValueFrom(row, field, rowDest);
} else {
return res;
}
}
};
m2.fill("CODE", "CODE");
m2.fill("ID", "ID_ARTICLE");
for (String string : completionFields) {
m2.fill(string, string);
}
m2.setWhere(w);
 
this.m3 = new AutoCompletionManager(tableElementArticle, ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete().getField("ARTICLE.NOM"), this.table,
this.table.getRowValuesTableModel(), ITextWithCompletion.MODE_CONTAINS, true, true, new ValidStateChecker()) {
@Override
protected Object getValueFrom(SQLRow row, String field, SQLRowAccessor rowDest) {
Object res = tarifCompletion(row, field);
if (res == null) {
return super.getValueFrom(row, field, rowDest);
} else {
return res;
}
}
};
m3.fill("CODE", "CODE");
m3.fill("NOM", "NOM");
for (String string : completionFields) {
m3.fill(string, string);
}
m3.setWhere(w);
 
if (e.getTable().contains("ID_CODE_FOURNISSEUR") && supplierCode) {
this.m4 = new AutoCompletionManager(tableElementCodeFournisseur, ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete().getField("ARTICLE.NOM"), this.table,
this.table.getRowValuesTableModel(), ITextWithCompletion.MODE_CONTAINS, true, true, new ValidStateChecker()) {
@Override
protected Object getValueFrom(SQLRow row, String field, SQLRowAccessor rowDest) {
Object res = tarifCompletion(row, field);
if (res == null) {
return super.getValueFrom(row, field, rowDest);
} else {
return res;
}
}
};
m4.fill("CODE", "CODE");
m4.fill("NOM", "NOM");
for (String string : completionFields) {
m4.fill(string, string);
}
}
 
tableElementCode.addModificationListener(tableElementArticle);
tableElementArticle.setModifier(new CellDynamicModifier() {
@Override
public Object computeValueFrom(SQLRowValues row, SQLTableElement source) {
try {
SQLRowAccessor foreign = row.getForeign("ID_ARTICLE");
if (foreign != null && !foreign.isUndefined() && foreign.getObject("CODE") != null && foreign.getString("CODE").equals(row.getString("CODE"))) {
return foreign.getID();
} else {
return tableArticle.getUndefinedID();
}
} catch (Exception e) {
return tableArticle.getUndefinedID();
}
}
});
 
// ECO Contribution
if (this.tableElementEco != null && this.tableElementEcoTotal != null && this.tableElementEcoID != null) {
qteElement.addModificationListener(this.tableElementEcoTotal);
this.tableElementEco.addModificationListener(this.tableElementEcoTotal);
this.tableElementEcoTotal.setModifier(new CellDynamicModifier() {
public Object computeValueFrom(final SQLRowValues row, SQLTableElement source) {
 
int qte = Integer.parseInt(row.getObject("QTE").toString());
BigDecimal f = (row.getObject("ECO_CONTRIBUTION") == null) ? BigDecimal.ZERO : (BigDecimal) row.getObject("ECO_CONTRIBUTION");
return f.multiply(new BigDecimal(qte));
}
 
});
this.tableElementEcoID.addModificationListener(this.tableElementEco);
this.tableElementEco.setModifier(new CellDynamicModifier() {
public Object computeValueFrom(final SQLRowValues row, SQLTableElement source) {
 
if (source.equals(tableElementEcoID)) {
return row.getForeign("ID_ECO_CONTRIBUTION").getBigDecimal("TAUX");
} else {
return row.getObject("ECO_CONTRIBUTION");
}
}
});
}
 
// Calcul automatique du total HT
qteElement.addModificationListener(this.totalHT);
qteU.addModificationListener(this.totalHT);
this.ha.addModificationListener(this.totalHT);
this.totalHT.setModifier(new CellDynamicModifier() {
public Object computeValueFrom(final SQLRowValues row, SQLTableElement source) {
 
int qte = Integer.parseInt(row.getObject("QTE").toString());
BigDecimal f = (row.getObject("PA_HT") == null) ? BigDecimal.ZERO : (BigDecimal) row.getObject("PA_HT");
BigDecimal b = (row.getObject("QTE_UNITAIRE") == null) ? BigDecimal.ONE : (BigDecimal) row.getObject("QTE_UNITAIRE");
BigDecimal r = b.multiply(f.multiply(BigDecimal.valueOf(qte)), DecimalUtils.HIGH_PRECISION).setScale(totalHT.getDecimalDigits(), BigDecimal.ROUND_HALF_UP);
 
if (row.getTable().contains("POURCENT_REMISE")) {
final Object o2 = row.getObject("POURCENT_REMISE");
 
BigDecimal lremise = (o2 == null) ? BigDecimal.ZERO : ((BigDecimal) o2);
if (lremise.compareTo(BigDecimal.ZERO) >= 0 && lremise.compareTo(BigDecimal.valueOf(100)) < 0) {
 
r = r.multiply(new BigDecimal(100).subtract(lremise).movePointLeft(2)).setScale(totalHT.getDecimalDigits(), BigDecimal.ROUND_HALF_UP);
}
}
 
return r;
}
 
});
if (DefaultNXProps.getInstance().getBooleanValue(AbstractVenteArticleItemTable.ARTICLE_SHOW_DEVISE, false)) {
 
if (tableElement_PA_Devise != null) {
tableElement_PA_Devise.addModificationListener(tableElement_PrixMetrique1_AchatHT);
}
 
if (tableElement_PA_Devise != null) {
tableElement_PrixMetrique1_AchatHT.addModificationListener(tableElement_PA_Devise);
 
tableElement_PA_Devise.setModifier(new CellDynamicModifier() {
public Object computeValueFrom(SQLRowValues row, SQLTableElement source) {
if (source != null && source.getField().getName().equals("PA_DEVISE")) {
return row.getObject("PA_DEVISE");
} else {
if (!row.isForeignEmpty("ID_DEVISE") && row.getForeign("ID_DEVISE") != null) {
String devCode = row.getForeign("ID_DEVISE").getString("CODE");
BigDecimal bigDecimal = (BigDecimal) row.getObject("PRIX_METRIQUE_HA_1");
 
CurrencyConverter c = new CurrencyConverter();
BigDecimal result = convert(bigDecimal, devCode, true);
if (result == null) {
JOptionPane.showMessageDialog(AbstractAchatArticleItemTable.this, "Unable to convert " + bigDecimal + " from " + c.getCompanyCurrencyCode() + " to " + devCode);
return BigDecimal.ZERO;
}
return result;
} else if (source != null && source.getField().getName().equalsIgnoreCase("PRIX_METRIQUE_HA_1")) {
return row.getObject("PRIX_METRIQUE_HA_1");
}
return row.getObject("PA_DEVISE");
}
}
 
});
}
 
qteElement.addModificationListener(this.tableElementTotalDevise);
qteU.addModificationListener(this.tableElementTotalDevise);
tableElement_PA_Devise.addModificationListener(this.tableElementTotalDevise);
if (e.getTable().contains("POURCENT_REMISE") && tableElementRemise != null) {
tableElementRemise.addModificationListener(this.tableElementTotalDevise);
}
this.tableElementTotalDevise.setModifier(new CellDynamicModifier() {
public Object computeValueFrom(final SQLRowValues row, SQLTableElement source) {
int qte = Integer.parseInt(row.getObject("QTE").toString());
BigDecimal f = (BigDecimal) row.getObject("PA_DEVISE");
BigDecimal b = (row.getObject("QTE_UNITAIRE") == null) ? BigDecimal.ONE : (BigDecimal) row.getObject("QTE_UNITAIRE");
BigDecimal r = b.multiply(f.multiply(BigDecimal.valueOf(qte)), DecimalUtils.HIGH_PRECISION).setScale(tableElementTotalDevise.getDecimalDigits(), BigDecimal.ROUND_HALF_UP);
 
if (row.getTable().contains("POURCENT_REMISE")) {
final Object o2 = row.getObject("POURCENT_REMISE");
BigDecimal lremise = (o2 == null) ? BigDecimal.ZERO : ((BigDecimal) o2);
if (lremise.compareTo(BigDecimal.ZERO) >= 0 && lremise.compareTo(BigDecimal.valueOf(100)) < 0) {
 
r = r.multiply(new BigDecimal(100).subtract(lremise).movePointLeft(2)).setScale(tableElementTotalDevise.getDecimalDigits(), BigDecimal.ROUND_HALF_UP);
}
}
return r;
}
 
});
}
// Calcul automatique du total TTC
qteElement.addModificationListener(this.tableElementTotalTTC);
qteU.addModificationListener(this.tableElementTotalTTC);
this.ha.addModificationListener(this.tableElementTotalTTC);
this.tableElementTVA.addModificationListener(this.tableElementTotalTTC);
this.tableElementTotalTTC.setModifier(new CellDynamicModifier() {
@Override
public Object computeValueFrom(SQLRowValues row, SQLTableElement source) {
int qte = Integer.parseInt(row.getObject("QTE").toString());
BigDecimal f = (BigDecimal) row.getObject("PA_HT");
int idTaux = Integer.parseInt(row.getObject("ID_TAXE").toString());
if (idTaux < 0) {
System.out.println(row);
}
Float resultTaux = TaxeCache.getCache().getTauxFromId(idTaux);
 
BigDecimal b = (row.getObject("QTE_UNITAIRE") == null) ? BigDecimal.ONE : (BigDecimal) row.getObject("QTE_UNITAIRE");
BigDecimal r = b.multiply(f.multiply(BigDecimal.valueOf(qte), DecimalUtils.HIGH_PRECISION), DecimalUtils.HIGH_PRECISION).setScale(tableElementTotalTTC.getDecimalDigits(),
BigDecimal.ROUND_HALF_UP);
float taux = (resultTaux == null) ? 0.0F : resultTaux.floatValue();
 
BigDecimal total = r.multiply(BigDecimal.ONE.add(new BigDecimal(taux / 100f))).setScale(tableElementTotalTTC.getDecimalDigits(), RoundingMode.HALF_UP);
return total;
}
 
});
 
this.table.readState();
 
// Mode Gestion article avancé
String valModeAvanceVt = DefaultNXProps.getInstance().getStringProperty("ArticleModeVenteAvance");
Boolean bModeAvance = Boolean.valueOf(valModeAvanceVt);
boolean view = !(bModeAvance != null && !bModeAvance.booleanValue());
setColumnVisible(model.getColumnForField("VALEUR_METRIQUE_1"), view);
setColumnVisible(model.getColumnForField("VALEUR_METRIQUE_2"), view);
setColumnVisible(model.getColumnForField("VALEUR_METRIQUE_3"), view);
setColumnVisible(model.getColumnForField("PRIX_METRIQUE_VT_1"), view);
setColumnVisible(model.getColumnForField("ID_MODE_VENTE_ARTICLE"), view);
setColumnVisible(model.getColumnForField("PA_HT"), view);
 
if (e.getTable().contains("ID_COMMANDE_ELEMENT")) {
setColumnVisible(model.getColumnForField("ID_COMMANDE_ELEMENT"), false);
}
 
// Gestion des unités de vente
final boolean gestionUV = prefs.getBoolean(GestionArticleGlobalPreferencePanel.UNITE_VENTE, true);
setColumnVisible(model.getColumnForField("QTE_UNITAIRE"), gestionUV);
setColumnVisible(model.getColumnForField("ID_UNITE_VENTE"), gestionUV);
 
setColumnVisible(model.getColumnForField("ID_STYLE"), DefaultNXProps.getInstance().getBooleanValue("ArticleShowStyle", true));
 
if (this.tableElementEco != null && this.tableElementEcoTotal != null && this.tableElementEcoID != null) {
setColumnVisible(model.getColumnForField("ID_ECO_CONTRIBUTION"), showEco);
setColumnVisible(model.getColumnForField("ECO_CONTRIBUTION"), showEco);
setColumnVisible(model.getColumnForField("T_ECO_CONTRIBUTION"), showEco);
}
 
setColumnVisible(model.getColumnForField("ID_ARTICLE"), selectArticle);
setColumnVisible(model.getColumnForField("CODE"), !selectArticle || (selectArticle && createAuto));
setColumnVisible(model.getColumnForField("NOM"), !selectArticle || (selectArticle && createAuto));
 
// Calcul automatique du poids unitaire
tableElement_ValeurMetrique1.addModificationListener(tableElementPoids);
tableElement_ValeurMetrique2.addModificationListener(tableElementPoids);
tableElement_ValeurMetrique3.addModificationListener(tableElementPoids);
tableElementPoids.setModifier(new CellDynamicModifier() {
public Object computeValueFrom(SQLRowValues row, SQLTableElement source) {
return new Float(ReferenceArticleSQLElement.getPoidsFromDetails(row));
}
 
});
// Calcul automatique du poids total
tableElementPoids.addModificationListener(this.tableElementPoidsTotal);
qteElement.addModificationListener(this.tableElementPoidsTotal);
qteU.addModificationListener(this.tableElementPoidsTotal);
this.tableElementPoidsTotal.setModifier(new CellDynamicModifier() {
public Object computeValueFrom(SQLRowValues row, SQLTableElement source) {
 
Number f = (row.getObject("POIDS") == null) ? 0 : (Number) row.getObject("POIDS");
int qte = Integer.parseInt(row.getObject("QTE").toString());
 
BigDecimal b = (row.getObject("QTE_UNITAIRE") == null) ? BigDecimal.ONE : (BigDecimal) row.getObject("QTE_UNITAIRE");
// FIXME convertir en float autrement pour éviter une valeur non transposable
// avec floatValue ou passer POIDS en bigDecimal
return b.multiply(new BigDecimal(f.floatValue() * qte)).floatValue();
}
 
});
 
tableElement_PrixMetrique1_AchatHT.setModifier(new CellDynamicModifier() {
public Object computeValueFrom(SQLRowValues row, SQLTableElement source) {
if (source != null && source.getField().getName().equals("PRIX_METRIQUE_HA_1")) {
return row.getObject("PRIX_METRIQUE_HA_1");
} else {
if (source != null && source.getField().getName().equals("PA_DEVISE")) {
if (!row.isForeignEmpty("ID_DEVISE") && row.getForeign("ID_DEVISE") != null) {
String devCode = row.getForeign("ID_DEVISE").getString("CODE");
BigDecimal bigDecimal = (BigDecimal) row.getObject("PA_DEVISE");
 
return convert(bigDecimal, devCode, false);
} else {
return row.getObject("PRIX_METRIQUE_HA_1");
}
}
return row.getObject("PRIX_METRIQUE_HA_1");
}
}
 
});
 
// Calcul automatique du prix d'achat unitaire HT
tableElement_ValeurMetrique1.addModificationListener(this.ha);
tableElement_ValeurMetrique2.addModificationListener(this.ha);
tableElement_ValeurMetrique3.addModificationListener(this.ha);
tableElement_PrixMetrique1_AchatHT.addModificationListener(this.ha);
this.ha.setModifier(new CellDynamicModifier() {
public Object computeValueFrom(SQLRowValues row, SQLTableElement source) {
 
if (row.isForeignEmpty("ID_MODE_VENTE_ARTICLE") || row.getInt("ID_MODE_VENTE_ARTICLE") == ReferenceArticleSQLElement.A_LA_PIECE) {
return row.getObject("PRIX_METRIQUE_HA_1");
} else {
 
final BigDecimal prixHAFromDetails = ReferenceArticleSQLElement.getPrixHAFromDetails(row);
return prixHAFromDetails.setScale(ha.getDecimalDigits(), RoundingMode.HALF_UP);
}
 
}
 
});
 
uniteVente.addModificationListener(qteU);
qteU.setModifier(new CellDynamicModifier() {
public Object computeValueFrom(SQLRowValues row, SQLTableElement source) {
SQLRowAccessor rowUnite = row.getForeign("ID_UNITE_VENTE");
if (rowUnite != null && !rowUnite.isUndefined() && rowUnite.getBoolean("A_LA_PIECE")) {
return BigDecimal.ONE;
} else {
return row.getObject("QTE_UNITAIRE");
}
}
 
});
// La devise est renseignée globalement dans la commande et est reportée automatiquement sur
// les lignes
setColumnVisible(model.getColumnIndexForElement(tableElement_Devise), false);
for (String string : visibilityMap.keySet()) {
setColumnVisible(model.getColumnForField(string), visibilityMap.get(string));
}
 
// Barcode reader
final BarcodeReader barcodeReader = ComptaPropsConfiguration.getInstanceCompta().getBarcodeReader();
if (barcodeReader != null) {
 
final BarcodeListener l = new BarcodeListener() {
 
@Override
public void keyReceived(KeyEvent ee) {
// TODO Auto-generated method stub
}
 
@Override
public void barcodeRead(String code) {
if (((JFrame) SwingUtilities.getRoot(getRowValuesTable())).isActive()) {
final SQLSelect selArticle = new SQLSelect();
final SQLTable tableArticle = getSQLElement().getForeignElement("ID_ARTICLE").getTable();
selArticle.addSelectStar(tableArticle);
Where w = new Where(tableArticle.getField("OBSOLETE"), "=", Boolean.FALSE);
w = w.and(new Where(tableArticle.getField("CODE_BARRE"), "=", code));
selArticle.setWhere(w);
List<SQLRow> l2 = SQLRowListRSH.execute(selArticle);
if (l2.size() > 0) {
System.err.println("ARTICLE " + l2.get(0).getString("NOM"));
Tuple3<Double, String, String> art = Tuple3.create(1.0D, l2.get(0).getString("CODE"), l2.get(0).getString("NOM"));
List<Tuple3<Double, String, String>> l = new ArrayList<Tuple3<Double, String, String>>();
l.add(art);
insertFromDrop(l, m);
} else {
System.err.println("ARTICLE NOT FOUND !");
}
}
 
}
};
getRowValuesTable().addHierarchyListener(new HierarchyListener() {
public void hierarchyChanged(HierarchyEvent e) {
if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0)
if (getRowValuesTable().isDisplayable()) {
barcodeReader.addBarcodeListener(l);
} else {
barcodeReader.removeBarcodeListener(l);
}