OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Compare Revisions

Regard whitespace Rev 155 → Rev 156

/trunk/OpenConcerto/src/META-INF/services/java.nio.file.spi.FileTypeDetector
New file
0,0 → 1,0
ilm.utils.mime.FreeDesktopMimeDetector
/trunk/OpenConcerto/src/org/jopenchart/DataModel1D.java
4,7 → 4,7
import java.util.List;
 
public class DataModel1D extends DataModel {
private final List<Number> l = new ArrayList<Number>();
private final List<Number> l = new ArrayList<>();
 
public DataModel1D() {
 
12,8 → 12,7
 
public DataModel1D(Number[] data) {
for (int i = 0; i < data.length; i++) {
Number number = data[i];
l.add(number);
l.add(data[i]);
}
}
 
21,15 → 20,15
this.addAll(list);
}
 
public void addAll(List<Number> data) {
public synchronized void addAll(List<Number> data) {
l.addAll(data);
}
 
public int getSize() {
public synchronized int getSize() {
return l.size();
}
 
public void setValueAt(int index, Number value) {
public synchronized void setValueAt(int index, Number value) {
ensureCapacity(index);
l.set(index, value);
}
40,37 → 39,34
}
}
 
public Number getValueAt(int index) {
public synchronized Number getValueAt(int index) {
ensureCapacity(index);
return l.get(index);
}
 
public Number getMaxValue() {
public synchronized Number getMaxValue() {
Number max = 0;
for (Number b : this.l) {
if (max == null) {
if (b != null && b.doubleValue() > max.doubleValue()) {
max = b;
} else if (b != null && b.doubleValue() > max.doubleValue()) {
max = b;
}
}
return max;
}
 
public Number getMinValue() {
public synchronized Number getMinValue() {
Number min = 0;
for (Number b : this.l) {
if (min == null) {
if (b != null && b.doubleValue() < min.doubleValue()) {
min = b;
} else if (b != null && b.doubleValue() < min.doubleValue()) {
min = b;
}
}
return min;
}
 
public void clear() {
for (int i = 0; i < this.getSize(); i++) {
public synchronized void clear() {
final int size = l.size();
for (int i = 0; i < size; i++) {
this.setValueAt(i, null);
}
}
/trunk/OpenConcerto/src/org/jopenchart/DataModel2D.java
7,10 → 7,10
public class DataModel2D extends DataModel {
 
private String[][] data;
private int rowCount;
private int colCount;
private List<String> rowLabels = new ArrayList<String>();
private List<String> colLabels = new ArrayList<String>();
private final int rowCount;
private final int colCount;
private List<String> rowLabels = new ArrayList<>();
private List<String> colLabels = new ArrayList<>();
 
public DataModel2D(int row, int col) {
this.rowCount = row;
27,24 → 27,24
this.rowLabels.add(String.valueOf((char) ('A' + i)));
}
for (int i = 0; i < col; i++) {
this.colLabels.add(String.valueOf(((1 + i))));
this.colLabels.add(String.valueOf(1 + i));
}
 
}
 
public String getValue(int row, int col) {
public synchronized String getValue(int row, int col) {
return data[row][col];
}
 
public void setValue(String value, int row, int col) {
public synchronized void setValue(String value, int row, int col) {
data[row][col] = value;
}
 
public String getColumnLabel(int col) {
public synchronized String getColumnLabel(int col) {
return this.colLabels.get(col);
}
 
public String getRowLabel(int row) {
public synchronized String getRowLabel(int row) {
return this.rowLabels.get(row);
}
 
/trunk/OpenConcerto/src/org/openconcerto/sql/view/search/TextSearchSpec.java
85,6 → 85,18
return res;
}
 
private final String format(final Format fmt, final Object cell) {
try {
return fmt.format(cell);
} catch (Exception e) {
throw new IllegalStateException("Couldn't format " + cell + '(' + getClass(cell) + ") with " + fmt, e);
}
}
 
static private String getClass(Object cell) {
return cell == null ? "<null>" : cell.getClass().getName();
}
 
private final Double getDouble() {
if (!this.parsedFilterD_tried) {
try {
131,7 → 143,7
// which is better achieved with contains)
// PS: the date format is useful for parsing since "> 25/12/2010" means
// "> 25/12/2010 00:00" which is understandable and concise.
if (isContains && containsOrEquals(fmt.format(cell)))
if (isContains && containsOrEquals(format(fmt, cell)))
return true;
// e.g. test if "01/01/2006" is before "25 déc. 2010"
else if (!isContains && test(getParsed(fmt), cell))
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/ListSQLLine.java
275,8 → 275,8
}
if (toRemove != null)
toRemove.remove(lastField.getName());
// attach updated values
if (vals != null && vals.getLong(lastField.getName()) == target.getIDNumber().longValue())
// attach updated values, foreign ID is always present but can be null
if (vals != null && target.getIDNumber().equals(vals.getForeignIDNumberValue(lastField.getName()).getValue()))
vals.deepCopy().put(lastField.getName(), target);
}
}
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/SQLTableModelLinesSourceOnline.java
49,7 → 49,7
assert SwingUtilities.isEventDispatchThread();
if (this.moveQ == null) {
this.moveQ = new MoveQueue(getModel());
this.moveQ.start();
getModel().startQueue(this.moveQ);
}
return this.moveQ;
}
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/MoveQueue.java
18,17 → 18,19
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.SQLSelect.LockStrength;
import org.openconcerto.sql.model.SQLSyntax;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.request.UpdateBuilder;
import org.openconcerto.sql.utils.ReOrder;
import org.openconcerto.sql.utils.SQLUtils;
import org.openconcerto.utils.DecimalUtils;
import org.openconcerto.utils.ExceptionUtils;
import org.openconcerto.utils.NumberUtils;
import org.openconcerto.utils.SleepingQueue;
 
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
131,20 → 133,13
// if only some rows are moved, update one by one (avoids refreshing the whole list)
// (getRowCount() is not thread-safe, so use getTotalRowCount())
if (rowCount < 5 && rowCount < (this.tableModel.getTotalRowCount() / 3)) {
final List<?> l;
if (after) {
// If we want to put X,Y after A in the list A,B,C
// we need to pass first Y : A,Y,B,C then X :
// A,X,Y,B,C
l = new ArrayList<Object>(srcRows);
Collections.reverse(l);
} else {
l = srcRows;
}
final SQLTable t = getTable();
final String orderName = t.getOrderField().getName();
final SQLRowValues vals = new SQLRowValues(t);
for (final Object src : l) {
vals.setOrder(destRow, after).update(getID(src, t).intValue());
final List<BigDecimal> orders = ReOrder.getFreeOrderValuesFor(rowCount, after, destRow).get0();
for (int i = 0; i < rowCount; i++) {
final Object src = srcRows.get(i);
vals.put(orderName, orders.get(i)).update(getID(src, t).intValue());
}
} else {
// update all rows at once and refresh the whole list
184,75 → 179,64
moveAtOnce(srcRows, srcRows.size(), after, destRow);
}
 
/**
* Move the passed rows just before or just after the destination row if needed.
*
* @param ids rows to order.
* @param after <code>true</code> if the rows should be placed after <code>destRow</code>,
* <code>false</code> otherwise.
* @param destRow <code>srcRows</code> will be placed relative to the order of this row.
* @param checkBefore if <code>true</code> the current DB order will be checked and if it
* matched the passed rows, no change will be made to the DB, <code>false</code> to
* always change the orders in the DB.
* @return if the DB was changed.
* @throws SQLException if an error occurs.
*/
static public boolean moveIDsAtOnce(final List<? extends Number> ids, final boolean after, final SQLRow destRow, final boolean checkBefore) throws SQLException {
final int size = ids.size();
if (checkBefore) {
final SQLTable table = destRow.getTable();
final SQLSelect sel = new SQLSelect(true);
sel.addSelect(table.getKey());
sel.addOrder(table);
sel.setWhere(new Where(table.getKey(), ids));
// needed since we might update them just after in moveAtOnce(), and it's safer to lock
// with the most restrictive mode first.
sel.setLockStrength(LockStrength.UPDATE);
final List<?> dbOrderedIDs = table.getDBSystemRoot().getDataSource().executeCol(sel.asString());
if (dbOrderedIDs.size() != size)
throw new IllegalStateException("Missing rows");
boolean orderOK = true;
for (int i = 0; i < size && orderOK; i++) {
final Number passedID = ids.get(i);
final Number dbID = (Number) dbOrderedIDs.get(i);
orderOK = NumberUtils.areNumericallyEqual(passedID, dbID);
}
if (orderOK)
return false;
}
moveAtOnce(ids, size, after, destRow);
return true;
}
 
static private void moveAtOnce(final List<?> srcRows, final int rowCount, final boolean after, final SQLRow destRow) throws SQLException {
if (rowCount == 0)
return;
final SQLTable t = destRow.getTable();
 
// ULP * 10 to give a little breathing room
final BigDecimal minDistance = t.getOrderULP().scaleByPowerOfTen(1);
assert minDistance.signum() > 0;
final BigDecimal places = BigDecimal.valueOf(rowCount + 1);
// the minimum room so that we can move all rows
final BigDecimal room = minDistance.multiply(places);
final List<BigDecimal> freeOrderValues = ReOrder.getFreeOrderValuesFor(rowCount, after, destRow).get0();
 
final BigDecimal destOrder = destRow.getOrder();
final SQLRow nextRow = destRow.getRow(true);
final BigDecimal inc;
final boolean destRowReordered;
if (nextRow == null) {
// if destRow is the last row, we can choose whatever increment we want
inc = ReOrder.DISTANCE;
// but we need to move destRow if we want to add before it
destRowReordered = false;
} else {
final BigDecimal nextOrder = nextRow.getOrder();
assert nextOrder.compareTo(destOrder) > 0;
final BigDecimal diff = nextOrder.subtract(destOrder);
assert diff.signum() > 0;
if (diff.compareTo(room) < 0) {
// if there's not enough room, reorder to squeeze rows upwards
// since we keep increasing count, we will eventually reorder all rows afterwards
int count = 100;
final int tableRowCount = t.getRowCount();
boolean reordered = false;
while (!reordered) {
// only push destRow upwards if we want to add before
reordered = ReOrder.create(t, destOrder, !after, count, destOrder.add(room)).exec();
if (!reordered && count > tableRowCount)
throw new IllegalStateException("Unable to reorder " + count + " rows in " + t);
count *= 10;
}
inc = minDistance;
destRowReordered = true;
} else {
// truncate
inc = DecimalUtils.round(diff.divide(places, DecimalUtils.HIGH_PRECISION), t.getOrderDecimalDigits(), RoundingMode.DOWN);
destRowReordered = false;
}
}
// i.e. inc > 0
assert inc.compareTo(minDistance) >= 0;
 
BigDecimal newOrder = destOrder;
// by definition if we want to add after, destOrder should remain unchanged
if (after) {
newOrder = newOrder.add(inc);
}
final List<List<String>> newOrdersAndIDs = new ArrayList<List<String>>(rowCount);
int i = 0;
final List<Number> ids = rowCount < 10 ? new ArrayList<Number>(rowCount) : null;
// we go from newOrder and up, so that the passed rows are in ascending order
for (final Object src : srcRows) {
final Number srcID = getID(src, t);
if (ids != null)
ids.add(srcID);
final BigDecimal newOrder = freeOrderValues.get(i++);
newOrdersAndIDs.add(Arrays.asList(srcID.toString(), newOrder.toPlainString()));
newOrder = newOrder.add(inc);
}
// move out before general request as most DB systems haven't got DEFERRABLE constraints
if (!after && !destRowReordered) {
final UpdateBuilder updateDestRow = new UpdateBuilder(t);
updateDestRow.setObject(t.getOrderField(), newOrder);
updateDestRow.setWhere(destRow.getWhere());
t.getDBSystemRoot().getDataSource().execute(updateDestRow.asString());
}
 
final SQLSyntax syntax = SQLSyntax.get(t);
final UpdateBuilder update = new UpdateBuilder(t);
261,6 → 245,12
update.setFromVirtualJoinField(t.getOrderField().getName(), constantTableAlias, "newOrder");
t.getDBSystemRoot().getDataSource().execute(update.asString());
 
t.fireTableModified(SQLRow.NONEXISTANT_ID, Collections.singletonList(t.getOrderField().getName()));
final List<String> fieldsChanged = Collections.singletonList(t.getOrderField().getName());
if (ids == null) {
t.fireTableModified(SQLRow.NONEXISTANT_ID, fieldsChanged);
} else {
for (final Number id : ids)
t.fireTableModified(id.intValue(), fieldsChanged);
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/RowValuesTableControlPanel.java
99,8 → 99,12
this.buttonInserer = new JButton(TM.tr("insertNewLine"));
this.buttonInserer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
RowValuesTableControlPanel.this.model.addNewRowAt(table.getSelectedRow());
int index = table.getSelectedRow();
if (index < 0 || index > table.getRowCount()) {
index = table.getRowCount();
}
RowValuesTableControlPanel.this.model.addNewRowAt(index);
}
});
this.buttonInserer.setEnabled(false);
c.gridx++;
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/UpdateQueue.java
140,7 → 140,7
this.put(new SetStateRunnable() {
@Override
public void run() {
getModel().getSearchQueue().start();
getModel().startSearchQueue();
}
});
}
244,7 → 244,8
}
// if the modified row isn't in the existing line, it might still affect it
// if it's a referent row insertion
if (!put && lastReferentField != null && r.exists()) {
if (!put && lastReferentField != null && r.exists() && !r.isForeignEmpty(lastReferentField)) {
// no NPE, even without an undefined ID since we tested isForeignEmpty()
final int foreignID = r.getInt(lastReferentField);
for (final SQLRowValues current : line.getRow().followPath(p.minusLast(), CreateMode.CREATE_NONE, false)) {
if (current.getID() == foreignID) {
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/IListe.java
370,7 → 370,7
 
public String getLine(final boolean created, final SQLRowValues row, final SQLField userF, final SQLField dateF) {
final Calendar date = dateF == null ? null : row.getDate(dateF.getName());
final SQLRowAccessor user = userF == null || row.isForeignEmpty(userF.getName()) ? null : row.getForeign(userF.getName());
final SQLRowAccessor user = userF == null || row.getObject(userF.getName()) == null || row.isForeignEmpty(userF.getName()) ? null : row.getForeign(userF.getName());
if (user == null && date == null)
return null;
 
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/TextTableCellEditorWithCompletion.java
17,6 → 17,8
import org.openconcerto.ui.TextAreaTableCellEditor;
import org.openconcerto.utils.checks.ValidState;
 
import java.awt.Component;
 
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
56,7 → 58,17
 
this.textWithCompl.hidePopup();
if (!getValidState().isValid()) {
JOptionPane.showMessageDialog(SwingUtilities.getRoot(this.getTextArea()), getValidState().getValidationText());
final Component root = SwingUtilities.getRoot(TextTableCellEditorWithCompletion.this.getTextArea());
final String validationText = getValidState().getValidationText();
// JOptionPane dans invokeLater pour éviter une boucle avec notre listener sur le focus
// de la table qui stoppe
// l'édition
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JOptionPane.showMessageDialog(root, validationText);
}
});
return false;
} else {
return super.stopCellEditing();
63,7 → 75,7
}
}
 
@Override
public void setLimitedSize(int nbChar) {
this.textWithCompl.setLimitedSize(nbChar);
}
73,5 → 85,3
}
 
}
 
 
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/SQLTextComboTableCellEditor.java
25,6 → 25,7
import org.openconcerto.ui.FrameUtil;
import org.openconcerto.ui.list.selection.BaseListStateModel;
import org.openconcerto.utils.cc.ITransformer;
import org.openconcerto.utils.convertor.NumberConvertor;
 
import java.awt.Color;
import java.awt.Component;
48,7 → 49,7
 
private Where w;
// Stock Value of Combo to fix problem with undefined
int val = 1;
Integer val = 1;
 
boolean addUndefined;
 
123,18 → 124,19
}
 
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
if (value != null) {
 
this.val = (Integer) value;
this.comboBox.setValue(this.val);
}
 
this.comboBox.grabFocus();
 
this.comboBox.addModelListener("wantedID", new PropertyChangeListener() {
@Override
public void propertyChange(final PropertyChangeEvent evt) {
SQLTextComboTableCellEditor.this.val = comboBox.getWantedID();
SQLTextComboTableCellEditor.this.val = NumberConvertor.convertExact((Number) evt.getNewValue(), Integer.class);
}
});
 
// Filtre sur une valeur specifique
if (this.fieldWhere != null && table instanceof RowValuesTable) {
RowValuesTable rowVals = (RowValuesTable) table;
160,7 → 162,7
}
 
public int getComboSelectedId() {
return SQLTextComboTableCellEditor.this.comboBox.getSelectedId();
return SQLTextComboTableCellEditor.this.comboBox.getWantedID();
}
 
private SQLField fieldWhere;
/trunk/OpenConcerto/src/org/openconcerto/sql/view/list/ITableModel.java
38,6 → 38,7
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
67,6 → 68,7
* addTableModelListener()) it dies and cannot be used again.
*
* @author Sylvain CUAZ
* @see #start()
*/
public class ITableModel extends AbstractTableModel {
public static enum SleepState {
169,6 → 171,8
private boolean cellsEditable, orderEditable;
private boolean debug;
 
@GuardedBy("this")
private UncaughtExceptionHandler uncaughtExnHandler = null;
private DyingQueueExceptionHandler dyingQueueHandler = null;
 
public ITableModel(SQLTableModelSource src) {
880,7 → 884,14
super.addTableModelListener(l);
}
 
// TODO no longer leak this in our constructor
public synchronized final void setUncaughtExceptionHandler(UncaughtExceptionHandler uncaughtExnHandler) {
this.uncaughtExnHandler = uncaughtExnHandler;
}
 
public synchronized final UncaughtExceptionHandler getUncaughtExceptionHandler() {
return this.uncaughtExnHandler;
}
 
public final void start() {
final RunningState state = this.updateQ.getRunningState();
if (state.compareTo(RunningState.RUNNING) > 0)
888,10 → 899,20
if (state == RunningState.NEW) {
print("starting");
this.getLinesSource().live();
this.updateQ.start();
this.startQueue(this.updateQ);
}
}
 
final void startSearchQueue() {
this.startQueue(this.getSearchQueue());
}
 
final void startQueue(final SleepingQueue q) {
q.start((thr) -> {
thr.setUncaughtExceptionHandler(getUncaughtExceptionHandler());
});
}
 
@Override
public void removeTableModelListener(TableModelListener l) {
assert SwingUtilities.isEventDispatchThread();
928,6 → 949,7
* {@link SleepingQueue#die()}, <code>null</code> to reset default behavior.
*/
public void setDyingQueueExceptionHandler(final DyingQueueExceptionHandler h) {
assert SwingUtilities.isEventDispatchThread();
this.dyingQueueHandler = h;
}
 
/trunk/OpenConcerto/src/org/openconcerto/sql/view/SQLMenuItemHelper.java
18,6 → 18,7
import org.openconcerto.utils.cc.IClosure;
 
import java.awt.event.ActionEvent;
import java.util.Objects;
 
import javax.swing.AbstractAction;
import javax.swing.Action;
149,15 → 150,15
return menuItemAction;
}
 
public static abstract class AbstractSQLMenuItemAction extends AbstractAction {
public static abstract class AbstractSQLMenuItemAction<E extends SQLElement> extends AbstractAction {
 
private final SQLElement elem;
private final E elem;
private JFrame frame;
private boolean cacheFrame;
 
public AbstractSQLMenuItemAction(SQLElement elem, String name) {
public AbstractSQLMenuItemAction(E elem, String name) {
super(name);
this.elem = elem;
this.elem = Objects.requireNonNull(elem, "SQLElement");
this.frame = null;
this.cacheFrame = true;
this.putValue(Action.ACTION_COMMAND_KEY, getClass().getName() + " with " + getElem().getCode());
188,7 → 189,7
 
protected abstract JFrame createFrame();
 
public final SQLElement getElem() {
public final E getElem() {
return this.elem;
}
 
198,7 → 199,7
}
}
 
static abstract class GenericSQLElementAction<F extends JFrame> extends AbstractSQLMenuItemAction {
static abstract class GenericSQLElementAction<F extends JFrame> extends AbstractSQLMenuItemAction<SQLElement> {
 
public GenericSQLElementAction(SQLElement elem, String name) {
super(elem, name);
/trunk/OpenConcerto/src/org/openconcerto/sql/PropsConfiguration.java
14,6 → 14,7
package org.openconcerto.sql;
 
import org.openconcerto.sql.element.SQLElementDirectory;
import org.openconcerto.sql.element.SQLElementNamesFromXML;
import org.openconcerto.sql.model.DBRoot;
import org.openconcerto.sql.model.DBStructureItem;
import org.openconcerto.sql.model.DBSystemRoot;
36,6 → 37,7
import org.openconcerto.utils.NetUtils;
import org.openconcerto.utils.ProductInfo;
import org.openconcerto.utils.RTInterruptedException;
import org.openconcerto.utils.ReflectUtils;
import org.openconcerto.utils.StreamUtils;
import org.openconcerto.utils.Tuple2;
import org.openconcerto.utils.Value;
372,6 → 374,13
return rootIsBase ? this.getRootName() : this.getSystemRootName();
}
 
private final String toClassName(final String rsrcName) {
if (rsrcName.charAt(0) == '/')
return rsrcName.substring(1).replace('/', '.');
else
return this.getResourceWD().getPackage().getName() + '.' + rsrcName.replace('/', '.');
}
 
/**
* Return the correct stream depending on file mode. If file mode is
* {@link FileMode#NORMAL_FILE} it will first check if a file named <code>name</code> exists,
383,7 → 392,7
public final InputStream getStream(final String name) {
final File f = getFile(name);
if (mustUseClassloader(f)) {
return this.getClass().getResourceAsStream(name);
return getResourceWD().getResourceAsStream(name);
} else
try {
return new FileInputStream(f);
392,6 → 401,11
}
}
 
// the "working directory" where relative names are resolved
protected Class<? extends PropsConfiguration> getResourceWD() {
return this.getClass();
}
 
private File getFile(final String name) {
return new File(name.startsWith("/") ? name.substring(1) : name);
}
403,7 → 417,7
public final String getResource(final String name) {
final File f = getFile(name);
if (mustUseClassloader(f)) {
return this.getClass().getResource(name).toExternalForm();
return this.getResourceWD().getResource(name).toExternalForm();
} else {
return f.getAbsolutePath();
}
967,7 → 981,8
return new SQLElementDirectory();
}
 
// items will be passed to #getStream(String)
// Use resource name to be able to use absolute (beginning with /) or relative path (to this
// class)
protected List<String> getMappings() {
return Arrays.asList("mapping", "mapping-" + this.getProperty("customer"));
}
977,7 → 992,7
if (mappings.size() == 0)
throw new IllegalStateException("empty mappings");
 
final SQLFieldTranslator trns = new SQLFieldTranslator(this.getRoot(), null, dir);
final SQLFieldTranslator trns = new SQLFieldTranslator(this.getRoot(), dir);
// perhaps listen to UserProps (as in TM)
return loadTranslations(trns, this.getRoot(), mappings);
}
995,20 → 1010,47
final ListIterator<Locale> listIterator = CollectionUtils.getListIterator(langs, true);
while (listIterator.hasNext()) {
final Locale lang = listIterator.next();
found |= loadTranslations(trns, PropsConfiguration.class.getResourceAsStream(cntrl.toBundleName("mapping", lang) + ".xml"), root);
final SQLElementNamesFromXML elemNames = new SQLElementNamesFromXML(lang);
found |= loadTranslations(trns, PropsConfiguration.class.getResourceAsStream(cntrl.toBundleName("mapping", lang) + ".xml"), root, elemNames);
for (final String m : mappings) {
found |= loadTranslations(trns, this.getStream(cntrl.toBundleName(m, lang) + ".xml"), root);
final String bundleName = cntrl.toBundleName(m, lang);
found |= loadTranslations(trns, this.getStream(bundleName + ".xml"), root, elemNames);
final Class<? extends TranslatorFiller> loadedClass = ReflectUtils.getSubclass(toClassName(bundleName), TranslatorFiller.class);
if (loadedClass != null) {
try {
ReflectUtils.createInstance(loadedClass, this).fill(trns);
} catch (Exception e) {
Log.get().log(Level.WARNING, "Couldn't use " + loadedClass, e);
}
}
}
}
}
return trns;
}
 
private final boolean loadTranslations(final SQLFieldTranslator trns, final InputStream in, final DBRoot root) {
@FunctionalInterface
static public interface TranslatorFiller {
void fill(final SQLFieldTranslator t);
}
 
static public abstract class AbstractTranslatorFiller implements TranslatorFiller {
private final PropsConfiguration conf;
 
public AbstractTranslatorFiller(final PropsConfiguration conf) {
this.conf = conf;
}
 
protected final PropsConfiguration getConf() {
return this.conf;
}
}
 
private final boolean loadTranslations(final SQLFieldTranslator trns, final InputStream in, final DBRoot root, final SQLElementNamesFromXML elemNames) {
final boolean res = in != null;
// do not force to have one mapping for each client and each locale
if (res)
trns.load(root, in);
trns.load(root, in, elemNames);
return res;
}
 
1294,11 → 1336,6
}
 
@Override
public final SQLFieldTranslator getTranslator() {
return this.getDirectory().getTranslator();
}
 
@Override
public final SQLElementDirectory getDirectory() {
return this.directory.get();
}
/trunk/OpenConcerto/src/org/openconcerto/sql/mapping_en.xml
1,6 → 1,7
<?xml version="1.0" encoding="UTF-8" ?>
<ROOT>
<TABLE name="USER_COMMON">
<translations>
<element refid="sql.user">
<name base="user" />
<FIELD name="NOM" label="Last Name" />
<FIELD name="PRENOM" label="First name" />
<FIELD name="PASSWORD" label="Password" />
12,17 → 13,21
<FIELD name="MAIL" label="E-Mail" />
<FIELD name="DISABLED" label="Account disabled" />
<FIELD name="TEL" label="Phone" titlelabel="Phone" />
</TABLE>
<TABLE name="RIGHT">
</element>
<element refid="sql.right">
<name base="right" />
<FIELD name="CODE" label="Code" />
<FIELD name="NOM" label="Name" titlelabel="Name of right" />
<FIELD name="DESCRIPTION" label="Description" titlelabel="Desc." />
</TABLE>
<TABLE name="USER_RIGHT">
</element>
<element refid="sql.user-right">
<name base="user right">
<variant refids="plural" value="users rights" />
</name>
<FIELD name="ID_USER_COMMON" label="User" />
<FIELD name="ID_RIGHT" label="Right" />
<FIELD name="OBJECT" label="Object" />
<FIELD name="user.right.parameters.editor" label="Object" />
<FIELD name="HAVE_RIGHT" label="Right granted" titlelabel="Granted" />
</TABLE>
</ROOT>
</element>
</translations>
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/LightAutoCompleteComboBox.java
File deleted
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/LightRowValuesTableOnline.java
40,8 → 40,12
import net.minidev.json.JSONObject;
 
public class LightRowValuesTableOnline extends LightRowValuesTable {
private final ITransformer<SQLSelect, SQLSelect> orginTransformer;
private ITransformer<SQLSelect, SQLSelect> orginTransformer;
 
public LightRowValuesTableOnline() {
// Serialization
}
 
public LightRowValuesTableOnline(final Configuration configuration, final Number userId, final String id, final ITableModel model) {
super(configuration, userId, id, model);
 
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/LightUISQLComboRequest.java
New file
0,0 → 1,50
/*
* 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.sql.ui.light;
 
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.request.ComboSQLRequest;
import org.openconcerto.sql.sqlobject.IComboSelectionItem;
import org.openconcerto.ui.light.LightUIComboBoxElement;
import org.openconcerto.ui.light.LightUIComboRequest;
 
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.regex.Pattern;
 
public class LightUISQLComboRequest implements LightUIComboRequest {
 
private final static Pattern QUERY_SPLIT_PATTERN = Pattern.compile("\\s+");
 
private final ComboSQLRequest request;
 
public LightUISQLComboRequest(ComboSQLRequest request) {
super();
this.request = request;
}
 
@Override
public List<LightUIComboBoxElement> getItems(String filter, Optional<LightUIComboBoxElement> selection) {
final Where where = selection.isPresent() ? new Where(this.request.getPrimaryTable().getKey(), "=", selection.get().getId()) : null;
final List<IComboSelectionItem> items = this.request.getComboItems(true, Arrays.asList(QUERY_SPLIT_PATTERN.split(filter)), Locale.getDefault(), where);
final List<LightUIComboBoxElement> res = new ArrayList<>(items.size());
for (final IComboSelectionItem item : items) {
res.add(new LightUIComboBoxElement(item.getId(), item.getLabel()));
}
return res;
}
}
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/GroupToLightUIConvertor.java
13,7 → 13,6
package org.openconcerto.sql.ui.light;
 
import org.openconcerto.sql.Log;
import org.openconcerto.sql.PropsConfiguration;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.model.FieldMapper;
25,6 → 24,7
import org.openconcerto.ui.group.Item;
import org.openconcerto.ui.group.LayoutHints;
import org.openconcerto.ui.light.CustomEditorProvider;
import org.openconcerto.ui.light.LightUIAutoCompleteComboBox;
import org.openconcerto.ui.light.LightUICheckBox;
import org.openconcerto.ui.light.LightUIDate;
import org.openconcerto.ui.light.LightUIElement;
32,8 → 32,9
import org.openconcerto.ui.light.LightUILabel;
import org.openconcerto.ui.light.LightUILine;
import org.openconcerto.ui.light.LightUIPanel;
import org.openconcerto.ui.light.LightUITextArea;
import org.openconcerto.ui.light.LightUITabbed;
import org.openconcerto.ui.light.LightUITextField;
import org.openconcerto.utils.Log;
import org.openconcerto.utils.i18n.TranslationManager;
 
import java.awt.Color;
78,8 → 79,10
 
final LightEditFrame editFrame = new LightEditFrame(this.configuration, group, defaultRow.asRowValues(), parentFrame, editMode);
final LightUIPanel framePanel = editFrame.getContentPanel();
append(sqlElement, framePanel, group);
 
Map<String, LightUITabbed> tabbedMap = new HashMap<>();
append(sqlElement, framePanel, group, tabbedMap);
 
String frameTitle = TranslationManager.getInstance().getTranslationForItem(group.getId());
if (frameTitle == null) {
frameTitle = group.getId();
91,11 → 94,12
return editFrame;
}
 
private void append(final SQLElement sqlElement, final LightUIPanel panel, final Item item) {
private void append(final SQLElement sqlElement, final LightUIPanel panel, final Item item, Map<String, LightUITabbed> tabbedMap) {
if (item instanceof Group) {
final Group gr = (Group) item;
int size = gr.getSize();
 
if (gr.getTabId() == null) {
final String groupTitle = TranslationManager.getInstance().getTranslationForItem(gr.getId());
final LightUIPanel childPanel = new LightUIPanel(gr.getId());
childPanel.setFillWidth(true);
120,7 → 124,7
}
 
for (int i = 0; i < size; i++) {
this.append(sqlElement, childPanel, gr.getItem(i));
this.append(sqlElement, childPanel, gr.getItem(i), tabbedMap);
}
 
final LightUILine line = new LightUILine();
127,6 → 131,36
line.addChild(childPanel);
panel.addChild(line);
} else {
String tabId = gr.getTabId();
LightUITabbed tabbed = tabbedMap.get(tabId);
if (tabbed == null) {
tabbed = new LightUITabbed(tabId) {
 
@Override
public void loadTab(String tabId) {
// TODO Auto-generated method stub
 
}
};
final LightUILine line = new LightUILine();
line.addChild(tabbed);
panel.addChild(line);
tabbedMap.put(tabId, tabbed);
}
// add the group in the tabbed
final LightUIPanel childPanel = new LightUIPanel(gr.getId());
childPanel.setFillWidth(true);
childPanel.setGridWidth(4);
String title = TranslationManager.getInstance().getTranslationForItem(gr.getId());
childPanel.setTitle(title);
for (int i = 0; i < size; i++) {
this.append(sqlElement, childPanel, gr.getItem(i), tabbedMap);
}
 
tabbed.addChild(childPanel);
 
}
} else {
final LayoutHints localHint = item.getLocalHint();
LightUILine currentLine = panel.getLastLine();
 
156,7 → 190,10
panel.addChild(currentLine);
}
 
final SQLField field = this.mapper.getSQLFieldForItem(item.getId());
SQLField field = this.mapper.getSQLFieldForItem(item.getId());
if (field == null) {
field = sqlElement.getTable().getFieldRaw(item.getId());
}
LightUILabel elementLabel = null;
 
String label = this.getLabelForItem(field, item);
191,19 → 228,13
if (field != null) {
Class<?> javaType = field.getType().getJavaType();
if (field.isKey()) {
elementEditor = new LightAutoCompleteComboBox(item.getId());
elementEditor = new LightUIAutoCompleteComboBox(item.getId());
elementEditor.setMinInputSize(20);
elementEditor.setValueType(LightUIElement.VALUE_TYPE_REF);
} else if (javaType.equals(String.class)) {
if (field.getType().getSize() > 1000) {
elementEditor = new LightUITextArea(item.getId());
elementEditor.setValue("");
elementEditor.setMinInputSize(10);
} else {
elementEditor = new LightUITextField(item.getId());
elementEditor.setValue("");
elementEditor.setMinInputSize(10);
}
elementEditor.setValueType(LightUIElement.VALUE_TYPE_STRING);
} else if (javaType.equals(Boolean.class)) {
elementEditor = new LightUICheckBox(item.getId(), "");
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/LightRowValuesTable.java
51,12 → 51,16
 
private int offset = 0;
 
private ITableModel model;
private transient ITableModel model;
 
private final ITransformer<SQLSelect, SQLSelect> orginTransformer;
private transient ITransformer<SQLSelect, SQLSelect> orginTransformer;
 
private List<TableModelListener> tableModelListeners = new ArrayList<TableModelListener>();
private transient List<TableModelListener> tableModelListeners = new ArrayList<TableModelListener>();
 
public LightRowValuesTable() {
// Serialization
}
 
public LightRowValuesTable(final Configuration configuration, final Number userId, final String id, final ITableModel model) {
super(id);
 
/trunk/OpenConcerto/src/org/openconcerto/sql/ui/light/LightEditFrame.java
27,7 → 27,6
import org.openconcerto.ui.group.Group;
import org.openconcerto.ui.group.Item;
import org.openconcerto.ui.light.CustomEditorProvider;
import org.openconcerto.ui.light.JSONToLightUIConvertor;
import org.openconcerto.ui.light.LightUICheckBox;
import org.openconcerto.ui.light.LightUIComboBox;
import org.openconcerto.ui.light.LightUIDate;
35,6 → 34,9
import org.openconcerto.ui.light.LightUIFrame;
import org.openconcerto.utils.io.JSONConverter;
 
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Timestamp;
52,6 → 54,10
 
private EditMode editMode = EditMode.READONLY;
 
public LightEditFrame() {
// Serialization
}
 
// Init from json constructor
public LightEditFrame(final JSONObject json) {
super(json);
176,18 → 182,20
}
}
 
final protected void putValueFromUserControl(final Configuration configuration, final SQLElement sqlElement, final SQLField sqlField, final LightUIElement uiElement,
protected final void putValueFromUserControl(final Configuration configuration, final SQLElement sqlElement, final SQLField sqlField, final LightUIElement uiElement,
final Map<String, CustomEditorProvider> customEditors) {
if (!uiElement.isNotSaved()) {
boolean useElementValue = true;
final Class<?> fieldType = sqlField.getType().getJavaType();
if (customEditors.containsKey(uiElement.getId())) {
final CustomEditorProvider customEditor = customEditors.get(uiElement.getId());
if (customEditor instanceof SavableCustomEditorProvider) {
((SavableCustomEditorProvider) customEditor).save(this.sqlRow, sqlField, uiElement);
} else {
throw new IllegalStateException(customEditor + " must implement SavableCustomEditorProvider for field " + sqlField.getFieldName() + " of tye " + fieldType);
useElementValue = false;
}
} else {
}
 
if (useElementValue) {
final String fieldName = sqlField.getFieldName();
if (sqlField.isKey()) {
if (!(uiElement instanceof LightUIComboBox)) {
297,13 → 305,17
final SQLTable sqlTable = this.sqlRow.getTable();
final Date now = new Date();
// FIXME only set those fields at insertion time
if (sqlTable.getCreationUserField() != null) {
if (this.sqlRow.getObject(sqlTable.getCreationUserField().getName()) == null || this.sqlRow.getObject(sqlTable.getCreationDateField().getName()) == null) {
setFieldValue(this.sqlRow, sqlTable.getCreationUserField(), false, userId);
setFieldValue(this.sqlRow, sqlTable.getCreationDateField(), false, now);
}
}
if (sqlTable.getModifUserField() != null) {
setFieldValue(this.sqlRow, sqlTable.getModifUserField(), false, userId);
setFieldValue(this.sqlRow, sqlTable.getModifDateField(), false, now);
}
}
 
static private boolean setFieldValue(final SQLRowValues vals, final SQLField f, final boolean remove, final Object val) {
if (f == null)
321,17 → 333,6
}
 
@Override
public JSONToLightUIConvertor getConvertor() {
return new JSONToLightUIConvertor() {
 
@Override
public LightUIElement convert(JSONObject json) {
return new LightEditFrame(json);
}
};
}
 
@Override
public LightUIElement clone() {
return new LightEditFrame(this);
}
362,4 → 363,33
this.editMode = EditMode.READONLY;
}
}
 
@Override
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
if (this.editMode.equals(EditMode.CREATION)) {
out.writeByte(0);
} else if (this.editMode.equals(EditMode.MODIFICATION)) {
out.writeByte(1);
} else if (this.editMode.equals(EditMode.READONLY)) {
out.writeByte(2);
} else {
throw new IllegalStateException("unknown mode " + this.editMode);
}
}
 
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
int mode = in.readByte();
if (mode == 0) {
this.editMode = EditMode.CREATION;
} else if (mode == 1) {
this.editMode = EditMode.MODIFICATION;
} else if (mode == 2) {
this.editMode = EditMode.READONLY;
} else {
throw new IllegalStateException("unknown mode " + mode);
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/sql/mapping_fr.xml
1,6 → 1,7
<?xml version="1.0" encoding="UTF-8" ?>
<ROOT>
<TABLE name="USER_COMMON">
<translations>
<element refid="sql.user">
<name base="utilisateur" nounClass="masculine" />
<FIELD name="NOM" label="Nom" titlelabel="Nom" />
<FIELD name="PRENOM" label="Prénom" titlelabel="Prénom" />
<FIELD name="PASSWORD" label="Mot de passe" titlelabel="Mot de passe" />
12,17 → 13,21
<FIELD name="MAIL" label="E-Mail" titlelabel="E-Mail" />
<FIELD name="DISABLED" label="Compte désactivé" />
<FIELD name="TEL" label="Téléphone" titlelabel="Téléphone" />
</TABLE>
<TABLE name="RIGHT">
</element>
<element refid="sql.right">
<name base="droit" nounClass="masculine" />
<FIELD name="CODE" label="Code" titlelabel="Code" />
<FIELD name="NOM" label="Nom" titlelabel="Nom du droit" />
<FIELD name="DESCRIPTION" label="Description" titlelabel="Desc." />
</TABLE>
<TABLE name="USER_RIGHT">
</element>
<element refid="sql.user-right">
<name base="droit utilisateur" nounClass="masculine">
<variant refids="plural" value="droits utilisateurs" />
</name>
<FIELD name="ID_USER_COMMON" label="Utilisateur" titlelabel="Utilis." />
<FIELD name="ID_RIGHT" label="Droit" />
<FIELD name="OBJECT" label="Objet" />
<FIELD name="user.right.parameters.editor" label="Objet" />
<FIELD name="HAVE_RIGHT" label="Droit accordé" titlelabel="Accordé" />
</TABLE>
</ROOT>
</element>
</translations>
/trunk/OpenConcerto/src/org/openconcerto/sql/mapping_es.xml
New file
0,0 → 1,14
<?xml version="1.0" encoding="UTF-8" ?>
<translations>
<element refid="sql.user">
<name base="usuario" nounClass="masculine" />
</element>
<element refid="sql.right">
<name base="derecho" nounClass="masculine" />
</element>
<element refid="sql.user-right">
<name base="derecho de usuario" nounClass="masculine">
<variant refids="plural" value="derechos de usuarios" />
</name>
</element>
</translations>
/trunk/OpenConcerto/src/org/openconcerto/sql/sqlobject/ITextArticleWithCompletionCellEditor.java
13,6 → 13,12
package org.openconcerto.sql.sqlobject;
 
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLSelect;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.utils.cc.ITransformer;
 
import java.awt.Component;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
23,12 → 29,6
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellEditor;
 
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLSelect;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.utils.cc.ITransformer;
 
public class ITextArticleWithCompletionCellEditor extends AbstractCellEditor implements TableCellEditor {
 
private final ITextArticleWithCompletion text;
37,6 → 37,7
public ITextArticleWithCompletionCellEditor(SQLTable tableArticle, SQLTable tableARticleFournisseur) {
this.text = new ITextArticleWithCompletion(tableArticle, tableARticleFournisseur);
this.text.setBorder(BorderFactory.createEmptyBorder());
this.text.getTextComp().setBorder(BorderFactory.createEmptyBorder());
}
 
private void initListener(final JTable t) {
/trunk/OpenConcerto/src/org/openconcerto/sql/Configuration.java
126,7 → 126,9
 
public abstract SQLFilter getFilter();
 
public abstract SQLFieldTranslator getTranslator();
public final SQLFieldTranslator getTranslator() {
return this.getDirectory().getTranslator();
}
 
public abstract SQLElementDirectory getDirectory();
 
207,15 → 209,13
}
 
/**
* Add the translator and directory of <code>o</code> to this.
* Add the directory of <code>o</code> to this.
*
* @param o the configuration to add.
* @return this.
* @see SQLFieldTranslator#putAll(SQLFieldTranslator)
* @see SQLElementDirectory#putAll(SQLElementDirectory)
*/
public Configuration add(Configuration o) {
this.getTranslator().putAll(o.getTranslator());
this.getDirectory().putAll(o.getDirectory());
return this;
}
/trunk/OpenConcerto/src/org/openconcerto/sql/request/SQLFieldTranslator.java
17,6 → 17,7
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.element.SQLElementDirectory;
import org.openconcerto.sql.element.SQLElementDirectory.DirectoryListener;
import org.openconcerto.sql.element.SQLElementNamesFromXML;
import org.openconcerto.sql.model.DBRoot;
import org.openconcerto.sql.model.SQLField;
import org.openconcerto.sql.model.SQLRow;
34,10 → 35,10
import org.openconcerto.utils.CollectionUtils;
import org.openconcerto.utils.StringUtils;
import org.openconcerto.utils.Tuple2;
import org.openconcerto.utils.i18n.Phrase;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
49,6 → 50,7
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.prefs.Preferences;
 
139,6 → 141,9
// { SQLTable -> { compCode, variant, item -> RowItemDesc }}
@GuardedBy("this")
private final Map<SQLTable, Map<List<String>, RowItemDesc>> translation;
// { element code -> { variant -> name }}
@GuardedBy("this")
private final Map<String, Map<String, Phrase>> elementNames;
private final SQLTable table;
private final SQLElementDirectory dir;
@GuardedBy("this")
146,6 → 151,7
 
{
this.translation = new HashMap<SQLTable, Map<List<String>, RowItemDesc>>();
this.elementNames = new HashMap<>();
this.unknownCodes = new HashSet<String>();
}
 
153,10 → 159,9
* Create a new instance.
*
* @param root the default root for tables.
* @param inputStream the XML, can be <code>null</code>.
* @param dir the directory where to look for tables not in <code>root</code>.
*/
public SQLFieldTranslator(DBRoot root, InputStream inputStream, SQLElementDirectory dir) {
public SQLFieldTranslator(DBRoot root, SQLElementDirectory dir) {
try {
this.table = getMetaTable(root);
} catch (SQLException e) {
180,8 → 185,6
}
}
});
if (inputStream != null)
this.load(root, inputStream);
fetchAndPut(this.table, null);
}
 
217,10 → 220,10
}
}
 
public void load(DBRoot b, File file) {
try {
load(b, new FileInputStream(file));
} catch (FileNotFoundException e) {
public void load(DBRoot b, File file, final SQLElementNamesFromXML elemNames) {
try (final InputStream ins = new FileInputStream(file)) {
this.load(b, ins, elemNames);
} catch (IOException e) {
e.printStackTrace();
}
}
229,14 → 232,8
return elem.getChildren();
}
 
/**
* Load more translations.
*
* @param b the default root for tables.
* @param inputStream the XML.
*/
public void load(DBRoot b, InputStream inputStream) {
this.load(b, CORE_VARIANT, inputStream);
public Tuple2<Set<SQLTable>, Set<String>> load(DBRoot b, InputStream inputStream, final SQLElementNamesFromXML elemNames) {
return this.load(b, CORE_VARIANT, inputStream, elemNames);
}
 
/**
245,9 → 242,10
* @param b the default root for tables.
* @param variant the variant to use.
* @param inputStream the XML.
* @param elemNames how to load element names.
* @return the loaded tables and the names not found (and thus not loaded).
*/
public Tuple2<Set<SQLTable>, Set<String>> load(DBRoot b, final String variant, InputStream inputStream) {
public Tuple2<Set<SQLTable>, Set<String>> load(DBRoot b, final String variant, InputStream inputStream, final SQLElementNamesFromXML elemNames) {
if (inputStream == null)
throw new NullPointerException("inputStream is null");
final Set<SQLTable> res = new HashSet<SQLTable>();
259,19 → 257,19
final String elemName = elem.getName().toLowerCase();
final DBRoot root;
final List<Element> tableElems;
if (elemName.equals("table")) {
if (elemName.equals("table") || elemName.equals("element")) {
root = b;
tableElems = Collections.singletonList(elem);
} else if (elemName.equals("root")) {
root = b.getDBSystemRoot().getRoot(elem.getAttributeValue("name"));
tableElems = getChildren(elem);
} else {
if (elemName.equals("root")) {
Log.get().warning("Ignoring deprecated <root> element, use element code to refer to tables outside the default root");
}
root = null;
tableElems = null;
}
if (tableElems != null) {
for (final Element tableElem : tableElems) {
final Tuple2<String, SQLTable> t = load(root, variant, tableElem, true);
final Tuple2<String, SQLTable> t = load(root, variant, tableElem, elemNames, true);
if (t.get1() == null) {
notFound.add(t.get0());
} else {
290,11 → 288,19
return Tuple2.create(res, notFound);
}
 
private Tuple2<String, SQLTable> load(DBRoot b, final String variant, final Element tableElem, final boolean lenient) {
private Tuple2<String, SQLTable> load(DBRoot b, final String variant, final Element tableElem, final SQLElementNamesFromXML elemNames, final boolean lenient) {
final String tableName = tableElem.getAttributeValue("name");
SQLTable table = this.dir == null || this.dir.getElement(tableName) == null ? b.getTable(tableName) : this.dir.getElement(tableName).getTable();
if (table == null && this.dir != null && this.dir.getElementForCode(tableName) != null)
table = this.dir.getElementForCode(tableName).getTable();
String elemCode = tableElem.getAttributeValue("refid");
SQLTable table = null;
// compatibility mode for files without element names
final boolean compatMode = tableElem.getName().toLowerCase().equals("table");
if (compatMode) {
table = this.dir == null || this.dir.getElement(tableName) == null ? b.getTable(tableName) : this.dir.getElement(tableName).getTable();
if (elemCode == null)
elemCode = tableName;
}
if (table == null && this.dir != null && this.dir.getElementForCode(elemCode) != null)
table = this.dir.getElementForCode(elemCode).getTable();
if (table != null) {
for (final Element elem : getChildren(tableElem)) {
final String elemName = elem.getName().toLowerCase();
307,6 → 313,15
}
}
}
try {
if (!compatMode) {
final Entry<String, Phrase> phrase = elemNames.createPhrase(tableElem);
if (phrase != null)
this.putElementName(this.dir.getElement(table), phrase.getValue(), variant);
}
} catch (IOException e) {
throw new IllegalStateException("Couldn't parse phrase for " + table, e);
}
} else if (lenient) {
// allow to supply the union all tables and ignore those that aren't in a given base
Log.get().config("Ignore loading of inexistent table " + tableName);
568,4 → 583,45
}
this.removeTranslation(elemTable, componentCode, DB_VARIANT, name);
}
 
// ** element names
 
public final Phrase putElementName(final Class<? extends SQLElement> elemCl, final Phrase phr) {
return this.putElementName(this.getDirectory().getElement(elemCl), phr);
}
 
public final Phrase putElementName(final SQLElement elem, final Phrase phr) {
return this.putElementName(elem, phr, CORE_VARIANT);
}
 
public synchronized final Phrase putElementName(final SQLElement elem, final Phrase phr, final String variant) {
return this.getElementNameMap(elem, true).put(variant, phr);
}
 
private synchronized final Map<String, Phrase> getElementNameMap(final SQLElement elem, final boolean create) {
Map<String, Phrase> elemMap = this.elementNames.get(elem.getCode());
if (elemMap == null && create) {
elemMap = new HashMap<>();
this.elementNames.put(elem.getCode(), elemMap);
}
return elemMap;
}
 
public final Phrase getElementName(final SQLElement elem) {
return this.getElementName(elem, elem.getMDPath());
}
 
public final Phrase getElementName(final SQLElement elem, final List<String> variantPath) {
for (final String variant : variantPath) {
final Phrase res = this.getElementName(elem, variant);
if (res != null)
return res;
}
return this.getElementName(elem, CORE_VARIANT);
}
 
private synchronized final Phrase getElementName(final SQLElement elem, final String variant) {
final Map<String, Phrase> map = this.getElementNameMap(elem, false);
return map == null ? null : map.get(variant);
}
}
/trunk/OpenConcerto/src/org/openconcerto/sql/element/SQLElementNamesMap.java
File deleted
/trunk/OpenConcerto/src/org/openconcerto/sql/element/SQLElementNames.java
File deleted
/trunk/OpenConcerto/src/org/openconcerto/sql/element/SQLElementDirectory.java
15,7 → 15,6
 
import org.openconcerto.sql.Log;
import org.openconcerto.sql.ShowAs;
import org.openconcerto.sql.TM;
import org.openconcerto.sql.model.DBRoot;
import org.openconcerto.sql.model.DBStructureItemNotFound;
import org.openconcerto.sql.model.SQLName;
25,12 → 24,7
import org.openconcerto.utils.CollectionUtils;
import org.openconcerto.utils.SetMap;
import org.openconcerto.utils.cc.ITransformer;
import org.openconcerto.utils.i18n.LocalizedInstances;
import org.openconcerto.utils.i18n.Phrase;
import org.openconcerto.utils.i18n.TranslationManager;
 
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
37,13 → 31,10
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
 
import org.jdom2.JDOMException;
 
import net.jcip.annotations.GuardedBy;
 
/**
53,29 → 44,6
*/
public final class SQLElementDirectory {
 
public static final String BASENAME = SQLElementNames.class.getSimpleName();
private static final LocalizedInstances<SQLElementNames> LOCALIZED_INSTANCES = new LocalizedInstances<SQLElementNames>(SQLElementNames.class, TranslationManager.getControl()) {
@Override
protected SQLElementNames createInstance(String bundleName, Locale candidate, Class<?> cl) throws IOException {
final InputStream ins = cl.getResourceAsStream('/' + getControl().toResourceName(bundleName, "xml"));
if (ins == null)
return null;
final SQLElementNamesFromXML res = new SQLElementNamesFromXML(candidate);
try {
res.load(ins);
} catch (JDOMException e) {
throw new IOException("Invalid XML", e);
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw new IOException(e);
} finally {
ins.close();
}
return res;
}
};
 
private final Map<SQLTable, SQLElement> elements;
private final SetMap<String, SQLTable> tableNames;
private final SetMap<String, SQLTable> byCode;
83,7 → 51,6
private final List<DirectoryListener> listeners;
 
private String phrasesPkgName;
private final Map<String, SQLElementNames> elementNames;
 
@GuardedBy("this")
private SQLFieldTranslator translator;
100,7 → 67,6
this.listeners = new ArrayList<DirectoryListener>();
 
this.phrasesPkgName = null;
this.elementNames = new HashMap<String, SQLElementNames>();
 
this.showAs = new ShowAs((DBRoot) null);
}
152,17 → 118,26
* @param element the element to add.
*/
public final void addSQLElement(final Class<? extends SQLElement> element) {
this.addSQLElement(element, null);
}
 
public final void addSQLElement(final Class<? extends SQLElement> element, final DBRoot root) {
final SQLElement newInstance;
try {
this.addSQLElement(element.getConstructor().newInstance());
if (root == null)
newInstance = element.getConstructor().newInstance();
else
newInstance = element.getConstructor(DBRoot.class).newInstance(root);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof DBStructureItemNotFound) {
Log.get().config("ignore inexistent tables: " + e.getCause().getLocalizedMessage());
return;
}
throw new IllegalArgumentException("ctor failed", e);
throw new IllegalArgumentException("Constructor failed", e);
} catch (Exception e) {
throw new IllegalArgumentException("no-arg ctor failed", e);
throw new IllegalArgumentException("Couldn't use constructor", e);
}
this.addSQLElement(newInstance);
}
 
/**
293,43 → 268,6
return this.phrasesPkgName;
}
 
protected synchronized final SQLElementNames getElementNames(final String pkgName, final Locale locale, final Class<?> cl) {
if (pkgName == null)
return null;
final char sep = ' ';
final String key = pkgName + sep + locale.toString();
assert pkgName.indexOf(sep) < 0 : "ambiguous key : " + key;
SQLElementNames res = this.elementNames.get(key);
if (res == null) {
final List<SQLElementNames> l = LOCALIZED_INSTANCES.createInstances(pkgName + "." + BASENAME, locale, cl).get1();
if (!l.isEmpty()) {
for (int i = 1; i < l.size(); i++) {
l.get(i - 1).setParent(l.get(i));
}
res = l.get(0);
}
this.elementNames.put(key, res);
}
return res;
}
 
/**
* Search a name for the passed instance and the {@link TM#getTranslationsLocale() current
* locale}. Search for {@link SQLElementNames} using {@link LocalizedInstances} and
* {@link SQLElementNamesFromXML} first in {@link SQLElement#getL18nPackageName()} then in
* {@link #getL18nPackageName()}. E.g. this could load SQLElementNames_en.class and
* SQLElementNames_en_UK.xml.
*
* @param elem the element.
* @return the name if found, <code>null</code> otherwise.
*/
public final Phrase getName(final SQLElement elem) {
final String elemBaseName = elem.getL18nPackageName();
final String pkgName = elemBaseName == null ? getL18nPackageName() : elemBaseName;
final SQLElementNames elementNames = getElementNames(pkgName, TM.getInstance().getTranslationsLocale(), elem.getL18nClass());
return elementNames == null ? null : elementNames.getName(elem);
}
 
public synchronized final void addListener(DirectoryListener dl) {
this.listeners.add(dl);
}
/trunk/OpenConcerto/src/org/openconcerto/sql/element/SharedSQLElement.java
13,6 → 13,7
package org.openconcerto.sql.element;
 
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.model.SQLTable;
 
/**
26,10 → 27,18
super(tableName);
}
 
public SharedSQLElement(final Configuration conf, String tableName, final String code) {
super(conf, tableName, null, code);
}
 
public SharedSQLElement(SQLTable table) {
super(table);
this(table, null);
}
 
public SharedSQLElement(final SQLTable table, final String code) {
super(table, null, code);
}
 
@Override
public final boolean isShared() {
return true;
/trunk/OpenConcerto/src/org/openconcerto/sql/element/SQLElementNamesFromXML.java
23,8 → 23,13
import java.io.IOException;
import java.io.InputStream;
import java.util.AbstractMap.SimpleEntry;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
import java.util.regex.Pattern;
 
import org.jdom2.Document;
50,27 → 55,61
*
*/
@ThreadSafe
public class SQLElementNamesFromXML extends SQLElementNamesMap.ByCode {
public class SQLElementNamesFromXML {
 
static public final Pattern SPLIT_PATTERN = Pattern.compile("\\s*,\\s*");
static private final Set<Object> SHORT_VARIANTS = Collections.singleton(Grammar.PLURAL);
 
private static final String ELEMENT_ELEM_NAME = "element";
private static final String NAME_ID_ATTR = "refid";
private static final String VARIANT_ATTR = "variant";
private static final String VARIANT_REFIDS_ATTR = "refids";
private static final String VARIANT_VALUE_ATTR = "value";
private static final String NAME_PLURAL_ATTR = "namePlural";
 
static private final String getNounClassAttrName(final boolean shortForm) {
return shortForm ? "nameClass" : "nounClass";
}
 
// <element nameClass="masculine" name="contact fournisseur">
// <name nounClass="masculine" base="droit utilisateur">
static final private void setNounClassAndBase(final Element elem, final Phrase phrase, final boolean shortForm) {
elem.setAttribute(getNounClassAttrName(shortForm), phrase.getNounClass().getName());
elem.setAttribute(shortForm ? "name" : "base", phrase.getBase());
}
 
private final Locale locale;
 
public SQLElementNamesFromXML(Locale locale) {
super(locale);
this.locale = locale;
}
 
public final void load(final InputStream ins) throws JDOMException, IOException {
final Grammar gr = Grammar.getInstance(getLocale());
public final Locale getLocale() {
return this.locale;
}
 
public final Map<String, Phrase> load(final InputStream ins) throws JDOMException, IOException {
final Document doc = new SAXBuilder().build(ins);
for (final Element elem : doc.getRootElement().getChildren("element"))
this.load(gr, elem);
return load(doc.getRootElement());
}
 
public final Map<String, Phrase> load(final Element root) throws IOException {
final Grammar gr = Grammar.getInstance(getLocale());
final Map<String, Phrase> res = new HashMap<>();
for (final Element elem : root.getChildren(ELEMENT_ELEM_NAME)) {
final Entry<String, Phrase> e = this.createPhrase(gr, elem);
if (e != null)
res.put(e.getKey(), e.getValue());
}
return res;
}
 
public final Entry<String, Phrase> createPhrase(final Element elem) throws IOException {
return this.createPhrase(Grammar.getInstance(getLocale()), elem);
}
 
private Entry<String, Phrase> createPhrase(final Grammar gr, final Element elem) throws IOException {
final String refid = elem.getAttributeValue("refid");
final String refid = elem.getAttributeValue(NAME_ID_ATTR);
if (refid == null)
throw new IOException("No refid attribute");
 
78,7 → 117,8
final boolean hasChild = nameElem != null;
final String nameAttr = elem.getAttributeValue("name");
if (!hasChild && nameAttr == null) {
Log.get().warning("No name for code : " + refid);
// perhaps elem is just used to change item names
Log.get().log(Level.FINER, "No name for code : {0}", refid);
return null;
}
if (hasChild && nameAttr != null) {
88,23 → 128,23
final String base = hasChild ? nameElem.getAttributeValue("base") : nameAttr;
if (base == null)
throw new IOException("No base for the name of " + refid);
final String nounClassName = hasChild ? nameElem.getAttributeValue("nounClass") : elem.getAttributeValue("nameClass");
final String nounClassName = (hasChild ? nameElem : elem).getAttributeValue(getNounClassAttrName(!hasChild));
final NounClass nounClass = nounClassName == null ? null : gr.getNounClass(nounClassName);
 
final Phrase res = new Phrase(gr, base, nounClass);
if (!hasChild) {
// most languages have at most 2 grammatical number
final String plural = elem.getAttributeValue("namePlural");
final String plural = elem.getAttributeValue(NAME_PLURAL_ATTR);
if (plural != null)
res.putVariant(Grammar.PLURAL, plural);
} else {
for (final Element variantElem : nameElem.getChildren("variant")) {
final String value = variantElem.getAttributeValue("value");
for (final Element variantElem : nameElem.getChildren(VARIANT_ATTR)) {
final String value = variantElem.getAttributeValue(VARIANT_VALUE_ATTR);
if (value == null) {
warning(refid, variantElem, "No value");
continue;
}
final String variantIDs = variantElem.getAttributeValue("refids");
final String variantIDs = variantElem.getAttributeValue(VARIANT_REFIDS_ATTR);
final String variantPattern = variantElem.getAttributeValue("idPattern");
if (variantIDs == null && variantPattern == null) {
warning(refid, variantElem, "No ID");
134,13 → 174,35
return new SimpleEntry<String, Phrase>(refid, res);
}
 
private void load(final Grammar gr, final Element elem) throws IOException {
final Entry<String, Phrase> entry = this.createPhrase(gr, elem);
if (entry != null)
this.put(entry.getKey(), entry.getValue());
}
 
private void warning(final String refid, final Element variantElem, final String msg) {
Log.get().warning(msg + " for variant of " + refid + " : " + JDOM2Utils.output(variantElem));
}
 
public final Element createElement(final String refID, final Phrase phrase) {
final Element elem = new Element(ELEMENT_ELEM_NAME);
elem.setAttribute(NAME_ID_ATTR, refID);
final Set<VariantKey> explicitVariants = phrase.getExplicitVariants();
final boolean shortForm = SHORT_VARIANTS.containsAll(explicitVariants);
final Element nameElem;
if (shortForm) {
nameElem = elem;
} else {
nameElem = new Element("name");
elem.addContent(nameElem);
}
setNounClassAndBase(nameElem, phrase, shortForm);
if (!shortForm) {
// <variant refids="plural" value="droits utilisateurs"
for (final VariantKey explicitVariant : explicitVariants) {
final Element variantElem = new Element(VARIANT_ATTR);
variantElem.setAttribute(VARIANT_REFIDS_ATTR, explicitVariant.getID());
variantElem.setAttribute(VARIANT_VALUE_ATTR, phrase.getVariant(explicitVariant));
nameElem.addContent(variantElem);
}
} else if (explicitVariants.contains(Grammar.PLURAL)) {
elem.setAttribute(NAME_PLURAL_ATTR, phrase.getVariant(Grammar.PLURAL));
}
return elem;
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/sql/element/SQLElement.java
159,8 → 159,8
}
final Phrase res = new Phrase(Grammar_fr.getInstance(), base, nounClass);
if (nounClass != null)
res.putVariant(Grammar.INDEFINITE_ARTICLE_SINGULAR, singular);
res.putVariant(Grammar.PLURAL, plural);
res.putVariantIfDifferent(Grammar.INDEFINITE_ARTICLE_SINGULAR, singular);
res.putVariantIfDifferent(Grammar.PLURAL, plural);
return res;
}
 
184,9 → 184,7
 
@GuardedBy("this")
private SQLElementDirectory directory;
private String l18nPkgName;
private Class<?> l18nClass;
private Phrase name;
private Phrase defaultName;
private final SQLTable primaryTable;
// used as a key in SQLElementDirectory so it should be immutable
private String code;
233,7 → 231,6
throw new DBStructureItemNotFound("table is null for " + this.getClass());
}
this.primaryTable = primaryTable;
this.setL18nPackageName(null);
this.setDefaultName(name);
this.code = code == null ? createCode() : code;
this.combo = null;
256,7 → 253,11
 
/**
* Should return the code for this element. This method is only called if the <code>code</code>
* parameter of the constructor is <code>null</code>.
* parameter of the constructor is <code>null</code>. This implementation returns a string
* containing the {@link Class#getName() full name} of the class and the {@link #getTable()
* table} name to handle a single class being used for multiple tables. NOTE: this method is
* also needed, since a subclass constructor cannot pass <code>this.getClass().getName()</code>
* as the code parameter to <code>super</code>.
*
* @return the default code for this element.
*/
598,7 → 599,10
 
// return Path from owner to owned
private final Set<Path> createPaths(final boolean wantedOwned) {
assert !(this instanceof JoinSQLElement) : "joins cannot have SQLElementLink : " + this;
// joins cannot have SQLElementLink
if (this instanceof JoinSQLElement)
return Collections.emptySet();
 
final SQLTable thisTable = this.getTable();
final Set<Link> allLinks = thisTable.getDBSystemRoot().getGraph().getAllLinks(getTable());
final Set<Path> res = new HashSet<Path>();
754,7 → 758,11
private synchronized void initRF() {
if (this.otherLinks != null)
return;
 
final Set<Path> otherPaths = this.createPaths(false);
if (otherPaths.isEmpty()) {
this.otherLinks = SQLElementLinks.empty();
} else {
final SetMap<LinkType, SQLElementLink> tmp = new SetMap<LinkType, SQLElementLink>();
for (final Path p : otherPaths) {
final SQLElement refElem = this.getElementLenient(p.getFirst());
770,6 → 778,7
}
this.otherLinks = new SQLElementLinks(tmp);
}
}
 
final void setDirectory(final SQLElementDirectory directory) {
// since this method should only be called at the end of SQLElementDirectory.addSQLElement()
812,36 → 821,7
return this.getTable().getBase().getGraph().getForeignTable(this.getTable().getField(foreignField));
}
 
public final synchronized String getL18nPackageName() {
return this.l18nPkgName;
}
 
public final synchronized Class<?> getL18nClass() {
return this.l18nClass;
}
 
public final void setL18nLocation(Class<?> clazz) {
this.setL18nLocation(clazz.getPackage().getName(), clazz);
}
 
public final void setL18nPackageName(String name) {
this.setL18nLocation(name, null);
}
 
/**
* Set the location for the localized name.
*
* @param name a package name, can be <code>null</code> :
* {@link SQLElementDirectory#getL18nPackageName()} will be used.
* @param ctxt the class loader to load the resource, <code>null</code> meaning this class.
* @see SQLElementDirectory#getName(SQLElement)
*/
public final synchronized void setL18nLocation(final String name, final Class<?> ctxt) {
this.l18nPkgName = name;
this.l18nClass = ctxt == null ? this.getClass() : ctxt;
}
 
/**
* Set the default name, used if no translations could be found.
*
* @param name the default name, if <code>null</code> the {@link #getTable() table} name will be
848,7 → 828,7
* used.
*/
public final synchronized void setDefaultName(Phrase name) {
this.name = name != null ? name : Phrase.getInvariant(getTable().getName());
this.defaultName = name != null ? name : Phrase.getInvariant(getTable().getName());
}
 
/**
857,7 → 837,7
* @return the default name, never <code>null</code>.
*/
public final synchronized Phrase getDefaultName() {
return this.name;
return this.defaultName;
}
 
/**
869,7 → 849,8
*/
public final Phrase getName() {
final SQLElementDirectory dir = this.getDirectory();
final Phrase res = dir == null ? null : dir.getName(this);
final SQLFieldTranslator trns = dir == null ? null : dir.getTranslator();
final Phrase res = trns == null ? null : trns.getElementName(this);
return res == null ? this.getDefaultName() : res;
}
 
/trunk/OpenConcerto/src/org/openconcerto/sql/element/ConfSQLElement.java
25,21 → 25,6
*/
public class ConfSQLElement extends SQLElement {
 
@Deprecated
public ConfSQLElement(String tableName, String singular, String plural) {
this(Configuration.getInstance(), tableName, singular, plural);
}
 
@Deprecated
public ConfSQLElement(Configuration conf, String tableName, String singular, String plural) {
this(conf.getRoot().findTable(tableName), singular, plural);
}
 
@Deprecated
public ConfSQLElement(SQLTable table, String singular, String plural) {
super(singular, plural, table);
}
 
public ConfSQLElement(String tableName) {
this(tableName, null);
}
48,22 → 33,30
this(conf, tableName, null);
}
 
public ConfSQLElement(SQLTable table) {
this(table, null);
}
 
public ConfSQLElement(String tableName, final Phrase name) {
this(Configuration.getInstance(), tableName, name);
}
 
public ConfSQLElement(Configuration conf, String tableName, final Phrase name) {
this(conf.getRoot().findTable(tableName), name);
this(conf, tableName, name, null);
}
 
public ConfSQLElement(Configuration conf, String tableName, final Phrase name, final String code) {
this(conf.getRoot().findTable(tableName), name, code);
}
 
public ConfSQLElement(final SQLTable table) {
this(table, null);
}
 
public ConfSQLElement(final SQLTable primaryTable, final Phrase name) {
super(primaryTable, name);
this(primaryTable, name, null);
}
 
public ConfSQLElement(final SQLTable primaryTable, final Phrase name, final String code) {
super(primaryTable, name, code);
}
 
@Override
protected List<String> getComboFields() {
return Collections.emptyList();
/trunk/OpenConcerto/src/org/openconcerto/sql/translation/SQLElementNames_en.xml
File deleted
/trunk/OpenConcerto/src/org/openconcerto/sql/translation/SQLElementNames_fr.xml
File deleted
/trunk/OpenConcerto/src/org/openconcerto/sql/translation/messages_es.properties
New file
0,0 → 1,199
init.error=Error de inicialización
add=Añadir
saveModifications=Guardar cambios
display=Ver
modify=Editar
delete=Limpiar
remove=Borrar
close=Cerrar
cancel=Cancelar
search=Buscar
open=Abrir
save=Guardar
backup=Hacer la copia de seguridad
export=Exportar
noSelection=Sin selección
duplicate=Duplicar
duplication=Duplicación
location=Ubicación
choose=Elige
toApply=Aplicar
 
all=Todo
toReverse=Revertir
 
contains=Contiene
contains.exactly=Contiene exactamente
isLessThan=Es menos de
isLessThanOrEqualTo=Es menor o igual a
isEqualTo=Es igual a
isExactlyEqualTo=Es exactamente igual a
isGreaterThan=Es más de
isGreaterThanOrEqualTo=Es más o igual a
isEmpty=Esta vacio
 
clone.newPlace=Nueva ubicación (opcional) :
 
saveError=Error al guardar
 
loginPanel.storePass=Almacenar contraseña
loginPanel.loginAction=Iniciar sesión
loginPanel.adminLogin=Administrador
loginPanel.loginLabel=Nombre de usuario
loginPanel.passLabel=Contraseña
loginPanel.companyLabel=Empresa
loginPanel.disabledUser=Cuenta de usuario deshabilitada
loginPanel.unknownUser=Usuario desconocido
loginPanel.multipleUser=Múltiples usuarios nombrados "{0}"
loginPanel.wrongPass=Contraseña incorrecta
 
noRightToAdd=No puedes agregar
noRightToModify=No puedes editar
noRightToDel=No puedes borrar
noRightToClone=No puedes duplicar
noRightToReorder=No puedes cambiar la orden
 
 
editPanel.keepOpen=No cerrar ventana
editPanel.readOnlySelection=This row is read only
editPanel.localPrivateSelection=This row is used by another item
editPanel.inexistentElement=this item doesn't exist
editPanel.cancelError=Error while canceling
editPanel.modifyError=Error while modifying
editPanel.addError=Error while adding
editPanel.deleteError=Error while deleting
editPanel.invalidContent=Input fields aren''t filled correctly.\n\nYou cannot save modifications :
editPanel.invalidContent.unknownReason= they aren''t valid
 
editAction.name=Crear {element__singularIndefiniteArticle}
editFrame.create=Crear {element__singularIndefiniteArticle}
editFrame.modify=Modificar {element__singularIndefiniteArticle}
editFrame.look=Detalles de {element__singularIndefiniteArticle}
 
listPanel.cloneToolTip=<html>Allow to duplicate a row.<br>Hold CTRL down to also duplicate the content<br>Hold Shift down to change the location.</html>
listPanel.cloneRows=listPanel.cloneRows=Do you want to clone {rec, select,\
true {\
{rowCount, plural,\
one {this row and its content ?}\
other {these # rows and their content ?}\
}}\
other {\
{rowCount, plural,\
one {this row ?}\
other {these # rows ?}\
}}\
}
listPanel.clone.collectingData=Collecting data for {0,plural,one{# row} other{# rows}}\u2026
listPanel.clone.storingData=Storing {0,plural,one{# row} other{# rows}}\u2026
listPanel.noSelectionOrSort=No selection or list sorted
listPanel.export=List export
listPanel.save=Save the list
listPanel.wholeList=the whole list
listPanel.selection=the selection
listPanel.duplicationError=Couldn''t duplicate {0}
 
listAction.name=Manage {element__pluralDefiniteArticle}
element.list=Lista de {element__plural}
 
ilist.setColumnsWidth=Ajustar ancho columnas
ilist.showAllColumns=Ver todas las columnas
ilist.lastCol=Cannot hide the last column
ilist.lockRows=Lock rows
ilist.unlockRows=Unlock rows
ilist.metadata={0,choice,0#Modified|1#Created}{1,choice,0#|1# by {2} {3}}{4,choice,0#|1#, {5,date,long} at {5,time,medium}}
 
sqlComp.stringValueTooLong=The value is {0, plural, one {# character too long} other {# characters too long}}
sqlComp.bdTooHigh=Number too high, {0, plural,\
one {it must have at most # digit before the decimal point ({1} after)}\
other {it must have at most # digits before the decimal point ({1} after)}}
sqlComp.invalidItem={0} is invalid{1,choice,0#|1# ({2})}
sqlComp.emptyItem={0} is empty
sqlComp.insertError=Error while inserting
sqlComp.insertCancelled=Insertion cancelled
sqlComp.selectError=Error while displaying {0}
sqlComp.updateError=Error while updating
sqlComp.updateCancelled=Update cancelled
sqlComp.updateCancelled.archived=The row was archived
sqlComp.updateCancelled.moreArchivedRows=The database was modified (there are more rows to be archived)
sqlComp.rowsToArchiveError=Error while searching data to archive {0}
sqlComp.archiveError=Error while archiving
sqlComp.archiveCancelled=Archive cancelled
sqlComp.saveDocError=Error while saving documentation of {0}
sqlComp.modifyDoc=Modify the documentation
sqlComp.deletedRow=The row is no longer in the database : {0}
 
sqlElement.archive.computingRows=Computing rows to archive\u2026
sqlElement.archiveError=Error while archiving {0} IDs {1}
sqlElement.confirmDelete=Confirm deletion
sqlElement.deleteNoRef=Do you want to delete {rowCount, plural, one {this row} other {these # rows}} ?
sqlElement.deleteRef.details= {descsSize, plural, =0 {} other\
{{rowCount, plural, one {This row is used} other {These rows are used}} by :\n\
{descs}}}\
{externsSize, plural, =0 {} other {{descsSize, plural, =0 {The} other {\n\nFurther the}} following links will be IRRETRIEVABLY cut : \n\
{externs}}}\n\n
sqlElement.deleteRef.details2=The following links will be IRRETRIEVABLY cut, they couldn\u2019t be 'unarchived' :\n\
{externs}\n\n
sqlElement.deleteRef=Do you{times, select, once {} other { REALLY}} want to delete {rowCount, plural, one {this row} other {these # rows}} and all linked ones ?
sqlElement.noLinesDeleted=No lines deleted.
sqlElement.noLinesDeletedTitle=Information
sqlElement.linksWillBeCut=- {elementName__indefiniteNumeral} {count, plural, one {will lose its} other {will lose their}} "{linkName}"
sqlElement.linkCantBeCut={rowDesc} cannot lose its field "{fieldLabel}"
 
sqlElement.deletePrivateNoRef={elementName__indefiniteNumeral} {elementNameCount, plural, one {is to be deleted} other {are to be deleted}}.
 
sqlElement.deletePrivateRef.details=The removal of {elementName__indefiniteNumeral} will cause :\n\
{descsSize, plural, =0 {} other {{descs}\n}}\
{externs}
sqlElement.deletePrivateRef.desc=- the removal of {elementName__indefiniteNumeral}
sqlElement.deletePrivateRef.linksWillBeCut=- the permanent deletion of the field "{linkName}" for {elementName__indefiniteNumeral}
 
sqlElement.modify.deletePrivate=\n\nModify {elementName__singularDemonstrative} and delete the informations listed above ?
 
user.passwordsDontMatch=Passwords don\u2019t match
user.passwordsDontMatch.short=Passwords don\u2019t match
 
infoPanel.rights=Rights enabled
infoPanel.appName=Application name
infoPanel.noAppName=unknown
infoPanel.version=Application version
infoPanel.noVersion=unknown
infoPanel.secureLink=Secure link
infoPanel.dbURL=Database URL
infoPanel.dirs=Folders
infoPanel.logs=Logs
infoPanel.docs=Documents
infoPanel.dataDir=Data
infoPanel.prefsDir=Preferences
infoPanel.cacheDir=Cache
 
infoPanel.softwareTitle=Software
infoPanel.systemTitle=System information
infoPanel.refresh=Click to refresh
 
backupPanel.backup=Backup
backupPanel.createFolderError=Couldn't create destination folder. Backup canceled !
backupPanel.folderRightsError=Insufficient rights on destination folder. Backup canceled !
backupPanel.errorsOnLastBackup=Errors occurred on last backup. Please contact IT.
backupPanel.lastBackup=Last backup {date, date, long} at {date, time, short}\non {destination}
backupPanel.differentDisks=Please backup on different disks !
backupPanel.progress=Backup progress
backupPanel.inProgress=Backup in progress
backupPanel.closingIn=Closing in {0}s
backupPanel.endFail=Backup ended with errors !
backupPanel.endSuccess=Backup ended successfully
backupPanel.failed=Backup failed
 
rights=Rights
rightsPanel.defaultRights=Default rights
rights.allTables=All tables
 
combo.list=List {element__pluralDefiniteArticle}
 
joinComp.usedBy=Cannot delete selection, it is used by "{0}"
 
browserCol.content=Content of {element__pluralDefiniteArticle}
 
addNewLine=Añadir nueva línea
insertNewLine=Insertar línea
duplicateLine=Duplicar líneas seleccionadas
deleteLine=Eliminar líneas seleccionadas
/trunk/OpenConcerto/src/org/openconcerto/sql/translation/messages_fr.properties
69,8 → 69,18
editFrame.look=Détail {element__de__singularIndefiniteArticle}
 
listPanel.cloneToolTip=<html>Permet de dupliquer une ligne.<br>Maintenir CTRL enfoncé pour dupliquer également le contenu<br>Maintenir Maj. enfoncé pour changer d'emplacement.</html>
listPanel.cloneRows=Voulez-vous cloner {rowCount, plural, one {cette ligne{rec, select, true { et son contenu} other {}}}\
other {ces # lignes{rec, select, true { et leurs contenus} other {}}}} ?
listPanel.cloneRows=Voulez-vous cloner {rec, select,\
true {\
{rowCount, plural,\
one {cette ligne et son contenu ?}\
other {ces # lignes et leurs contenus ?}\
}}\
other {\
{rowCount, plural,\
one {cette ligne ?}\
other {ces # lignes ?}\
}}\
}
listPanel.noSelectionOrSort=Pas de sélection ou liste triée
listPanel.export=Export de la liste
listPanel.save=Sauver la liste
88,8 → 98,10
ilist.unlockRows=Déverrouiller les lignes
ilist.metadata={0,choice,0#Modifiée|1#Créée}{1,choice,0#|1# par {2} {3}}{4,choice,0#|1# le {5,date,long} à {5,time,medium}}
 
sqlComp.stringValueTooLong=La valeur fait {0} caractère{0,choice,1#|1<s} de trop
sqlComp.bdTooHigh=Nombre trop grand, il doit faire moins de {0} chiffre{0,choice,1#|1<s} avant la virgule ({1} après)
sqlComp.stringValueTooLong=La valeur fait {0, plural, one {# caractère de trop} other {# caractères de trop}}
sqlComp.bdTooHigh=Nombre trop grand, {0, plural,\
one {il doit faire moins d\u2019un chiffre avant la virgule ({1} après)}\
other {il doit faire moins de # chiffres avant la virgule ({1} après)}}
sqlComp.invalidItem={0} n''est pas valide{1,choice,0#|1# ({2})}
sqlComp.emptyItem={0} est vide
sqlComp.insertError=Impossible d''insérer
/trunk/OpenConcerto/src/org/openconcerto/sql/translation/messages_pl.properties
New file
0,0 → 1,198
init.error=Initialization error
add=Add
saveModifications=Save modifications
display=Display
modify=Modify
delete=Delete
remove=Remove
close=Close
cancel=Cancel
search=Search
open=Open
save=Save
backup=Backup
export=Export
noSelection=No selection
duplicate=Duplicate
duplication=Duplication
location=Location
choose=Choose
toApply=Apply
 
all=All
toReverse=Reverse
 
contains=Contains
contains.exactly=Contains exactly
isLessThan=Is less than
isLessThanOrEqualTo=Is less than or equal to
isEqualTo=Is equal to
isExactlyEqualTo=Is exactly equal to
isGreaterThan=Is greater than
isGreaterThanOrEqualTo=Is greater than or equal to
isEmpty=Is empty
 
clone.newPlace=New location (optional) :
 
saveError=Error while saving
 
loginPanel.storePass=Store password
loginPanel.loginAction=Log in
loginPanel.adminLogin=Administrator
loginPanel.loginLabel=Login
loginPanel.passLabel=Password
loginPanel.companyLabel=Company
loginPanel.disabledUser=Disabled user account
loginPanel.unknownUser=Unknown user
loginPanel.multipleUser=Multiple users named "{0}"
loginPanel.wrongPass=Wrong password
 
noRightToAdd=You''re not allowed to add
noRightToModify=You''re not allowed to modify
noRightToDel=You''re not allowed to delete
noRightToClone=You''re not allowed to duplicate
noRightToReorder=You''re not allowed to change order
 
editPanel.keepOpen=don''t close the window
editPanel.readOnlySelection=This row is read only
editPanel.localPrivateSelection=This row is used by another item
editPanel.inexistentElement=this item doesn't exist
editPanel.cancelError=Error while canceling
editPanel.modifyError=Error while modifying
editPanel.addError=Error while adding
editPanel.deleteError=Error while deleting
editPanel.invalidContent=Input fields aren''t filled correctly.\n\nYou cannot save modifications :
editPanel.invalidContent.unknownReason= they aren''t valid
 
editAction.name=Create {element__singularIndefiniteArticle}
editFrame.create=Create {element__singularIndefiniteArticle}
editFrame.modify=Modify {element__singularIndefiniteArticle}
editFrame.look=Details of {element__singularIndefiniteArticle}
 
listPanel.cloneToolTip=<html>Allow to duplicate a row.<br>Hold CTRL down to also duplicate the content<br>Hold Shift down to change the location.</html>
listPanel.cloneRows=Do you want to clone {rec, select,\
true {\
{rowCount, plural,\
one {this row and its content ?}\
other {these # rows and their content ?}\
}}\
other {\
{rowCount, plural,\
one {this row ?}\
other {these # rows ?}\
}}\
}
listPanel.clone.collectingData=Collecting data for {0,plural,one{# row} other{# rows}}\u2026
listPanel.clone.storingData=Storing {0,plural,one{# row} other{# rows}}\u2026
listPanel.noSelectionOrSort=No selection or list sorted
listPanel.export=List export
listPanel.save=Save the list
listPanel.wholeList=the whole list
listPanel.selection=the selection
listPanel.duplicationError=Couldn''t duplicate {0}
 
listAction.name=Manage {element__pluralDefiniteArticle}
element.list=List of {element__plural}
 
ilist.setColumnsWidth=Adjust columns widths
ilist.showAllColumns=Show all columns
ilist.lastCol=Cannot hide the last column
ilist.lockRows=Lock rows
ilist.unlockRows=Unlock rows
ilist.metadata={0,choice,0#Modified|1#Created}{1,choice,0#|1# by {2} {3}}{4,choice,0#|1#, {5,date,long} at {5,time,medium}}
 
sqlComp.stringValueTooLong=The value is {0, plural, one {# character too long} other {# characters too long}}
sqlComp.bdTooHigh=Number too high, {0, plural,\
one {it must have at most # digit before the decimal point ({1} after)}\
other {it must have at most # digits before the decimal point ({1} after)}}
sqlComp.invalidItem={0} is invalid{1,choice,0#|1# ({2})}
sqlComp.emptyItem={0} is empty
sqlComp.insertError=Error while inserting
sqlComp.insertCancelled=Insertion cancelled
sqlComp.selectError=Error while displaying {0}
sqlComp.updateError=Error while updating
sqlComp.updateCancelled=Update cancelled
sqlComp.updateCancelled.archived=The row was archived
sqlComp.updateCancelled.moreArchivedRows=The database was modified (there are more rows to be archived)
sqlComp.rowsToArchiveError=Error while searching data to archive {0}
sqlComp.archiveError=Error while archiving
sqlComp.archiveCancelled=Archive cancelled
sqlComp.saveDocError=Error while saving documentation of {0}
sqlComp.modifyDoc=Modify the documentation
sqlComp.deletedRow=The row is no longer in the database : {0}
 
sqlElement.archive.computingRows=Computing rows to archive\u2026
sqlElement.archiveError=Error while archiving {0} IDs {1}
sqlElement.confirmDelete=Confirm deletion
sqlElement.deleteNoRef=Do you want to delete {rowCount, plural, one {this row} other {these # rows}} ?
sqlElement.deleteRef.details= {descsSize, plural, =0 {} other\
{{rowCount, plural, one {This row is used} other {These rows are used}} by :\n\
{descs}}}\
{externsSize, plural, =0 {} other {{descsSize, plural, =0 {The} other {\n\nFurther the}} following links will be IRRETRIEVABLY cut : \n\
{externs}}}\n\n
sqlElement.deleteRef.details2=The following links will be IRRETRIEVABLY cut, they couldn\u2019t be 'unarchived' :\n\
{externs}\n\n
sqlElement.deleteRef=Do you{times, select, once {} other { REALLY}} want to delete {rowCount, plural, one {this row} other {these # rows}} and all linked ones ?
sqlElement.noLinesDeleted=No lines deleted.
sqlElement.noLinesDeletedTitle=Information
sqlElement.linksWillBeCut=- {elementName__indefiniteNumeral} {count, plural, one {will lose its} other {will lose their}} "{linkName}"
sqlElement.linkCantBeCut={rowDesc} cannot lose its field "{fieldLabel}"
 
sqlElement.deletePrivateNoRef={elementName__indefiniteNumeral} {elementNameCount, plural, one {is to be deleted} other {are to be deleted}}.
 
sqlElement.deletePrivateRef.details=The removal of {elementName__indefiniteNumeral} will cause :\n\
{descsSize, plural, =0 {} other {{descs}\n}}\
{externs}
sqlElement.deletePrivateRef.desc=- the removal of {elementName__indefiniteNumeral}
sqlElement.deletePrivateRef.linksWillBeCut=- the permanent deletion of the field "{linkName}" for {elementName__indefiniteNumeral}
 
sqlElement.modify.deletePrivate=\n\nModify {elementName__singularDemonstrative} and delete the informations listed above ?
 
user.passwordsDontMatch=Passwords don\u2019t match
user.passwordsDontMatch.short=Passwords don\u2019t match
 
infoPanel.rights=Rights enabled
infoPanel.appName=Application name
infoPanel.noAppName=unknown
infoPanel.version=Application version
infoPanel.noVersion=unknown
infoPanel.secureLink=Secure link
infoPanel.dbURL=Database URL
infoPanel.dirs=Folders
infoPanel.logs=Logs
infoPanel.docs=Documents
infoPanel.dataDir=Data
infoPanel.prefsDir=Preferences
infoPanel.cacheDir=Cache
 
infoPanel.softwareTitle=Software
infoPanel.systemTitle=System information
infoPanel.refresh=Click to refresh
 
backupPanel.backup=Backup
backupPanel.createFolderError=Couldn't create destination folder. Backup canceled !
backupPanel.folderRightsError=Insufficient rights on destination folder. Backup canceled !
backupPanel.errorsOnLastBackup=Errors occurred on last backup. Please contact IT.
backupPanel.lastBackup=Last backup {date, date, long} at {date, time, short}\non {destination}
backupPanel.differentDisks=Please backup on different disks !
backupPanel.progress=Backup progress
backupPanel.inProgress=Backup in progress
backupPanel.closingIn=Closing in {0}s
backupPanel.endFail=Backup ended with errors !
backupPanel.endSuccess=Backup ended successfully
backupPanel.failed=Backup failed
 
rights=Rights
rightsPanel.defaultRights=Default rights
rights.allTables=All tables
 
combo.list=List {element__pluralDefiniteArticle}
 
joinComp.usedBy=Cannot delete selection, it is used by "{0}"
 
browserCol.content=Content of {element__pluralDefiniteArticle}
 
addNewLine=Add a new line
insertNewLine=Insert a line
duplicateLine=Duplicate selected lines
deleteLine=Remove selected lines
/trunk/OpenConcerto/src/org/openconcerto/sql/translation/messages_en.properties
69,7 → 69,18
editFrame.look=Details of {element__singularIndefiniteArticle}
 
listPanel.cloneToolTip=<html>Allow to duplicate a row.<br>Hold CTRL down to also duplicate the content<br>Hold Shift down to change the location.</html>
listPanel.cloneRows=Do you want to clone {rowCount, plural, one {this row{rec, select, true { and its content} other {}}} other {these # rows{rec, select, true { and their contents} other {}}}} ?
listPanel.cloneRows=Do you want to clone {rec, select,\
true {\
{rowCount, plural,\
one {this row and its content ?}\
other {these # rows and their content ?}\
}}\
other {\
{rowCount, plural,\
one {this row ?}\
other {these # rows ?}\
}}\
}
listPanel.noSelectionOrSort=No selection or list sorted
listPanel.export=List export
listPanel.save=Save the list
87,8 → 98,10
ilist.unlockRows=Unlock rows
ilist.metadata={0,choice,0#Modified|1#Created}{1,choice,0#|1# by {2} {3}}{4,choice,0#|1#, {5,date,long} at {5,time,medium}}
 
sqlComp.stringValueTooLong=The value is {0} character{0,choice,1#|1<s} too long
sqlComp.bdTooHigh=Number too high, it must have at most {0} digit{0,choice,1#|1<s} before the decimal point ({1} after)
sqlComp.stringValueTooLong=The value is {0, plural, one {# character too long} other {# characters too long}}
sqlComp.bdTooHigh=Number too high, {0, plural,\
one {it must have at most # digit before the decimal point ({1} after)}\
other {it must have at most # digits before the decimal point ({1} after)}}
sqlComp.invalidItem={0} is invalid{1,choice,0#|1# ({2})}
sqlComp.emptyItem={0} is empty
sqlComp.insertError=Error while inserting
/trunk/OpenConcerto/src/org/openconcerto/sql/utils/ReOrder.java
13,11 → 13,13
package org.openconcerto.sql.utils;
 
import org.openconcerto.sql.Log;
import org.openconcerto.sql.model.ConnectionHandlerNoSetup;
import org.openconcerto.sql.model.FieldRef;
import org.openconcerto.sql.model.SQLBase;
import org.openconcerto.sql.model.SQLDataSource;
import org.openconcerto.sql.model.SQLField;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLSelect;
import org.openconcerto.sql.model.SQLSyntax;
import org.openconcerto.sql.model.SQLSystem;
24,6 → 26,9
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.model.Where;
import org.openconcerto.sql.request.UpdateBuilder;
import org.openconcerto.utils.DecimalUtils;
import org.openconcerto.utils.Tuple2;
import org.openconcerto.utils.Tuple2.List2;
import org.openconcerto.utils.convertor.NumberConvertor;
 
import java.math.BigDecimal;
30,9 → 35,13
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
 
import net.jcip.annotations.GuardedBy;
 
/**
* Reorder some or all rows of a table.
*
40,6 → 49,161
*/
public abstract class ReOrder {
 
@GuardedBy("this")
private static boolean AUTO_FIX_NULLS = false;
 
public static synchronized void setAutoFixNulls(boolean b) {
AUTO_FIX_NULLS = b;
}
 
public static synchronized boolean isAutoFixNulls() {
return AUTO_FIX_NULLS;
}
 
public static BigDecimal makeRoom(final SQLTable t, final BigDecimal roomNeeded, final boolean after, final BigDecimal destOrder) throws SQLException {
return makeRoom(t, roomNeeded, after, destOrder, 100);
}
 
/**
* Make sure that there's no rows with order in the passed range. This method accomplishes this
* by re-ordering an increasing number of rows. This method only changes orders greater than or
* equal to <code>destOrder</code> and the first row re-ordered (<code>destOrder</code> if
* <code>!after</code> the next one otherwise) always has <code>destOrder + roomNeeded</code> as
* order :
*
* <pre>
* "row foo" 1.0
* "row bar" 2.0
* "row baz" 3.0
* "row qux" 4.0
* If <code>roomNeeded</code> is 2 after order 2.0, then the new values will be :
* "row foo" 1.0
* "row bar" 2.0
* "row baz" 4.0
* "row qux" 5.0
* If on the other hand, one wants the room before 2.0, then :
* "row foo" 1.0
* "row bar" 4.0
* "row baz" 5.0
* "row qux" 6.0
* </pre>
*
* @param t the table.
* @param roomNeeded the size of the requested free range, e.g 10.
* @param after <code>true</code> if the free range should begin after <code>destOrder</code>,
* <code>false</code> if it should end before <code>destOrder</code>.
* @param destOrder the start or end of the range.
* @param initialCount the initial size of the range to re-order if there's no room.
* @return the smallest possibly used order <code>>=</code> destOrder.
* @throws SQLException if an error occurs.
*/
public static BigDecimal makeRoom(final SQLTable t, final BigDecimal roomNeeded, final boolean after, final BigDecimal destOrder, final int initialCount) throws SQLException {
if (roomNeeded.signum() <= 0)
throw new IllegalArgumentException("Negative roomNeeded");
if (initialCount < 1)
throw new IllegalArgumentException("Initial count too small");
final BigDecimal newFirst = destOrder.add(roomNeeded);
// reorder to squeeze rows upwards
// since we keep increasing count, we will eventually reorder all rows afterwards
// NOTE since we only go in one direction (from destOrder and upwards), there shouldn't be
// any DB deadlocks
int count = Math.max(initialCount, roomNeeded.intValue() + 1);
final int tableRowCount = t.getRowCount();
boolean reordered = false;
while (!reordered) {
// only push destRow upwards if we want to add before
reordered = ReOrder.create(t, destOrder, !after, count, newFirst).exec();
if (!reordered && count > tableRowCount)
throw new IllegalStateException("Unable to reorder " + count + " rows in " + t);
count *= 10;
}
return after ? destOrder : newFirst;
}
 
/**
* Get a number of free order values after/before the passed row,
* {@link #makeRoom(SQLTable, BigDecimal, boolean, BigDecimal, int) making room} if needed.
*
* @param rowCount the number of order values needed.
* @param after <code>true</code> if the free values should begin after <code>r</code>,
* <code>false</code> if they should end before <code>r</code>.
* @param r the row that is before or after the returned orders.
* @return a list of <code>rowCount</code> free orders and the new order for the passed row
* (only changed if there was not enough free values).
* @throws SQLException if an error occurs.
*/
public static Tuple2<List<BigDecimal>, BigDecimal> getFreeOrderValuesFor(final int rowCount, final boolean after, final SQLRow r) throws SQLException {
return getFreeOrderValuesFor(rowCount, after, r, isAutoFixNulls());
}
 
public static Tuple2<List<BigDecimal>, BigDecimal> getFreeOrderValuesFor(final int rowCount, final boolean after, final SQLRow r, final boolean autoFixNulls) throws SQLException {
if (rowCount == 0)
return Tuple2.<List<BigDecimal>, BigDecimal> create(Collections.<BigDecimal> emptyList(), null);
// both rows are locked FOR UPDATE, so there shouldn't be any row that can get between them
// in this transaction, as the only way to do that is to call fetchThisAndSequentialRow()
List2<SQLRow> seqRows = r.fetchThisAndSequentialRow(after);
if (seqRows == null)
throw new IllegalStateException("Couldn't find " + r);
assert seqRows.get0().equals(r) : "fetchThisAndSequentialRow() failed";
if (seqRows.get0().getOrder() == null) {
if (autoFixNulls)
Log.get().log(Level.WARNING, "Re-order table with null orders : " + r);
else
throw new IllegalStateException("Row with null order : " + r);
if (!ReOrder.create(r.getTable()).exec())
throw new IllegalStateException("Couldn't re-order table with null orders : " + r.getTable());
seqRows = r.fetchThisAndSequentialRow(after);
if (seqRows == null || seqRows.get0().getOrder() == null)
throw new IllegalStateException("Re-order table with null orders failed : " + seqRows);
}
final BigDecimal destOrder = seqRows.get0().getOrder();
if (destOrder.compareTo(ReOrder.MIN_ORDER) < 0)
throw new IllegalStateException(seqRows.get0() + " has invalid order : " + destOrder);
BigDecimal newRowOrder = destOrder;
final SQLRow otherRow = seqRows.get1();
final BigDecimal inc;
BigDecimal newOrder;
if (after && otherRow == null) {
// dernière ligne de la table
inc = ReOrder.DISTANCE;
newOrder = destOrder.add(inc);
} else {
final BigDecimal otherOrder;
if (otherRow != null) {
otherOrder = otherRow.getOrder();
} else {
// première ligne
otherOrder = ReOrder.MIN_ORDER;
}
if (otherOrder.compareTo(ReOrder.MIN_ORDER) < 0)
throw new IllegalStateException(otherRow + " has invalid order : " + otherOrder);
 
// ULP * 10 to give a little breathing room
final BigDecimal minDistance = r.getTable().getOrderULP().scaleByPowerOfTen(1);
final BigDecimal places = BigDecimal.valueOf(rowCount + 1);
// the minimum room to fit rowCount
final BigDecimal roomNeeded = minDistance.multiply(places);
final BigDecimal roomAvailable = otherOrder.subtract(destOrder).abs();
 
if (roomAvailable.compareTo(roomNeeded) < 0) {
newRowOrder = makeRoom(r.getTable(), roomNeeded, after, destOrder);
inc = minDistance;
newOrder = after ? destOrder.add(inc) : destOrder;
} else {
inc = roomAvailable.divide(places, DecimalUtils.HIGH_PRECISION);
newOrder = (after ? destOrder : otherOrder).add(inc);
}
}
assert inc.signum() > 0;
final List<BigDecimal> orders = new ArrayList<>(rowCount);
for (int i = 0; i < rowCount; i++) {
orders.add(DecimalUtils.round(newOrder, r.getTable().getOrderDecimalDigits()));
newOrder = newOrder.add(inc);
}
assert after && newRowOrder.compareTo(orders.get(0)) < 0 || !after && orders.get(rowCount - 1).compareTo(newRowOrder) < 0;
return Tuple2.create(orders, newRowOrder);
}
 
// must be zero so that we can work on negative numbers without breaking the unique constraint
public static final BigDecimal MIN_ORDER = BigDecimal.ZERO;
// preferred distance
123,15 → 287,16
 
// MAYBE return affected IDs
public final boolean exec() throws SQLException {
final UpdateBuilder updateUndef = new UpdateBuilder(this.t).setObject(this.t.getOrderField(), MIN_ORDER);
updateUndef.setWhere(new Where(this.t.getKey(), "=", this.t.getUndefinedID()));
return (Boolean) SQLUtils.executeAtomic(this.t.getBase().getDataSource(), new ConnectionHandlerNoSetup<Object, SQLException>() {
final SQLTable t = this.t;
return SQLUtils.executeAtomic(this.t.getBase().getDataSource(), new ConnectionHandlerNoSetup<Boolean, SQLException>() {
@Override
public Object handle(SQLDataSource ds) throws SQLException, SQLException {
public Boolean handle(SQLDataSource ds) throws SQLException, SQLException {
final Connection conn = ds.getConnection();
final Statement stmt = conn.createStatement();
if (isAll()) {
// reorder all, undef must be at 0
if (isAll() && t.getUndefinedIDNumber() != null) {
final UpdateBuilder updateUndef = new UpdateBuilder(t).setObject(t.getOrderField(), MIN_ORDER);
updateUndef.setWhere(new Where(t.getKey(), "=", t.getUndefinedID()));
stmt.execute(updateUndef.asString());
}
stmt.execute("SELECT " + ReOrder.this.spec.getInc());
138,13 → 303,13
final BigDecimal inc = NumberConvertor.toBigDecimal((Number) SQLDataSource.SCALAR_HANDLER.handle(stmt.getResultSet()));
// needed since the cast in getInc() rounds so if the real increment is 0.006 it
// might get rounded to 0.01 and thus the last rows will overlap non moved rows
if (inc.compareTo(ReOrder.this.t.getOrderULP().scaleByPowerOfTen(1)) < 0)
if (inc.compareTo(t.getOrderULP().scaleByPowerOfTen(1)) < 0)
return false;
for (final String s : getSQL(conn, inc)) {
stmt.execute(s);
}
// MAYBE fire only changed IDs
ReOrder.this.t.fireTableModified(-1, Collections.singletonList(ReOrder.this.t.getOrderField().getName()));
t.fireTableModified(SQLRow.NONEXISTANT_ID, Collections.singletonList(t.getOrderField().getName()));
return true;
}
});
174,7 → 339,7
if (first.compareTo(MIN_ORDER) <= 0) {
this.firstToReorder = MIN_ORDER;
this.firstToReorderInclusive = false;
// make some room before the first non MIN_ORDER row so that another on can came
// make some room before the first non MIN_ORDER row so that another one can came
// before it
this.first = MIN_ORDER.add(DISTANCE).max(newFirst);
// try to keep asked value
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLField.java
391,7 → 391,7
* @see #getFieldGroup()
*/
public boolean isForeignKey() {
final FieldGroup fieldGroup = getFieldGroup();
final FieldGroup fieldGroup = getContainingFieldGroup();
return fieldGroup.getKeyType() == Type.FOREIGN_KEY && fieldGroup.getSingleField() != null;
}
 
401,10 → 401,23
* @return the group of this field.
* @see SQLTable#getFieldGroups()
*/
public FieldGroup getFieldGroup() {
public FieldGroup getContainingFieldGroup() {
return this.getTable().getFieldGroups().get(this.getName());
}
 
/**
* The group consisting of this single field.
*
* @return the group consisting of this single field.
* @throws IllegalStateException if this field is part of a multi-field group.
*/
public FieldGroup getFieldGroup() throws IllegalStateException {
final FieldGroup fg = this.getTable().getFieldGroups().get(this.getName());
if (fg.getSingleField() == null)
throw new IllegalStateException(this + " is part of a group with others : " + fg);
return fg;
}
 
public final SQLTable getForeignTable() {
return this.getDBSystemRoot().getGraph().getForeignTable(this);
}
/trunk/OpenConcerto/src/org/openconcerto/sql/model/OrderComparator.java
15,6 → 15,7
 
import org.openconcerto.utils.CompareUtils;
 
import java.math.BigDecimal;
import java.util.Comparator;
 
/**
24,11 → 25,14
*/
public class OrderComparator implements Comparator<SQLRowAccessor> {
 
public static final Comparator<BigDecimal> BD_NULLS_FIRST = Comparator.nullsFirst(Comparator.naturalOrder());
public static final Comparator<BigDecimal> BD_NULLS_LAST = Comparator.nullsLast(Comparator.naturalOrder());
 
/**
* Order rows by {@link SQLTable#getOrderField()}.
*/
public static final OrderComparator INSTANCE = new OrderComparator(false);
private static final OrderComparator INSTANCE_FALLBACK_TO_PK = new OrderComparator(true);
public static final OrderComparator INSTANCE = new OrderComparator(false, BD_NULLS_LAST);
private static final OrderComparator INSTANCE_FALLBACK_TO_PK = new OrderComparator(true, BD_NULLS_LAST);
 
/**
* Order rows by {@link SQLTable#getOrderField()}, or if the table is not
41,11 → 45,12
}
 
private final boolean fallbackToPK;
private final Comparator<BigDecimal> bdComparator;
 
// singleton
private OrderComparator(boolean fallbackToPK) {
public OrderComparator(final boolean fallbackToPK, final Comparator<BigDecimal> bdComparator) {
super();
this.fallbackToPK = fallbackToPK;
this.bdComparator = bdComparator;
}
 
@Override
57,8 → 62,11
final SQLTable t = r1.getTable();
if (!t.equals(r2.getTable()))
throw new IllegalArgumentException(r1 + " and " + r2 + " are not of the same table");
if (t.isOrdered()) {
return r1.getOrder().compareTo(r2.getOrder());
final SQLField orderField = t.getTable().getOrderField();
if (orderField != null) {
final BigDecimal order1 = r1.getObjectAs(orderField.getName(), true, BigDecimal.class);
final BigDecimal order2 = r2.getObjectAs(orderField.getName(), true, BigDecimal.class);
return this.bdComparator.compare(order1, order2);
} else if (this.fallbackToPK) {
if (!t.isRowable())
throw new IllegalArgumentException(t + " neither ordered nor rowable");
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLRowValues.java
1218,25 → 1218,21
* @return this.
*/
public SQLRowValues setOrder(SQLRow r, boolean after) {
return this.setOrder(r, after, ReOrder.DISTANCE.movePointRight(2).intValue(), 0);
setOrder(Collections.singletonList(this), r, after);
return this;
}
 
private SQLRowValues setOrder(SQLRow r, boolean after, int nbToReOrder, int nbReOrdered) {
final BigDecimal freeOrder = r.getOrder(after);
final String orderName = this.getTable().getOrderField().getName();
if (freeOrder != null)
return this.put(orderName, freeOrder);
else if (nbReOrdered > r.getTable().getRowCount()) {
throw new IllegalStateException("cannot reorder " + r.getTable().getSQLName());
} else {
// make room
public static void setOrder(final List<SQLRowValues> values, final SQLRow r, boolean after) {
final int valuesCount = values.size();
final List<BigDecimal> orders;
try {
ReOrder.create(this.getTable(), r.getOrder().intValue() - (nbToReOrder / 2), nbToReOrder).exec();
orders = ReOrder.getFreeOrderValuesFor(valuesCount, after, r).get0();
} catch (SQLException e) {
throw ExceptionUtils.createExn(IllegalStateException.class, "reorder failed for " + this.getTable() + " at " + r.getOrder(), e);
throw ExceptionUtils.createExn(IllegalStateException.class, "reorder failed for " + r.getTable() + " at " + r.getOrder(), e);
}
r.fetchValues();
return this.setOrder(r, after, nbToReOrder * 10, nbToReOrder);
final String orderName = r.getTable().getOrderField().getName();
for (int i = 0; i < valuesCount; i++) {
values.get(i).put(orderName, orders.get(i));
}
}
 
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLRowAccessor.java
402,9 → 402,13
}
 
public final <T> T getObjectAs(String field, Class<T> clazz) {
return this.getObjectAs(field, false, clazz);
}
 
public final <T> T getObjectAs(final String field, final boolean mustBePresent, final Class<T> clazz) {
T res = null;
try {
res = clazz.cast(this.getObject(field));
res = clazz.cast(this.getObject(field, mustBePresent));
} catch (ClassCastException e) {
throw new IllegalArgumentException("Impossible d'accéder au champ " + field + " de la ligne " + this + " en tant que " + clazz.getSimpleName(), e);
}
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLSyntaxPG.java
107,7 → 107,9
this.typeNames.addAll(java.sql.Date.class, "date");
this.typeNames.addAll(java.sql.Time.class, "time", "time without time zone");
this.typeNames.addAll(Blob.class, "bytea");
this.typeNames.addAll(Clob.class, "varchar", "char", "character varying", "character", "text");
// even though PG treats all Character Types equally, unbounded varchar is not standard, so
// prefer "text" which is supported by all systems
this.typeNames.addAll(Clob.class, "text", "varchar", "char", "character varying", "character");
this.typeNames.addAll(String.class, "varchar", "char", "character varying", "character", "text");
}
 
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLSyntax.java
710,8 → 710,9
sqlType = type + "(" + size + ")";
} else {
Log.get().warning("Unbounded varchar for " + f.getSQLName());
if (this.getSystem() == SQLSystem.MYSQL)
throw new IllegalStateException("MySQL doesn't support unbounded varchar and might truncate data if reducing size of " + f.getSQLName());
// if (this.getSystem() == SQLSystem.MYSQL)
// throw new IllegalStateException("MySQL doesn't support unbounded varchar and
// might truncate data if reducing size of " + f.getSQLName());
// don't specify size
sqlType = type;
}
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLTable.java
872,11 → 872,38
*
* @return the key, <code>null</code> for a simple field.
*/
public final SQLKey getKey() {
public final SQLKey getRawKey() {
return this.key;
}
 
/**
* The key for this group.
*
* @return the key, never <code>null</code>.
* @throws IllegalStateException for a simple field.
*/
public final SQLKey getKey() throws IllegalStateException {
if (this.key == null)
throw new IllegalStateException("Not a key : " + this);
return this.key;
}
 
/**
* The foreign link for this group.
*
* @return the foreign link, never <code>null</code>.
* @throws IllegalStateException for a simple field or a primary key.
*/
public final Link getForeignLink() throws IllegalStateException {
if (this.key != null) {
final Link foreignLink = this.key.getForeignLink();
if (foreignLink != null)
return foreignLink;
}
throw new IllegalStateException("Not a foreign key : " + this);
}
 
/**
* The one and only field of this group.
*
* @return the only field of this group, only <code>null</code> if this group is a
/trunk/OpenConcerto/src/org/openconcerto/sql/model/SQLRow.java
23,12 → 23,10
import org.openconcerto.sql.model.graph.Link;
import org.openconcerto.sql.model.graph.Link.Direction;
import org.openconcerto.sql.model.graph.Path;
import org.openconcerto.sql.utils.ReOrder;
import org.openconcerto.utils.DecimalUtils;
import org.openconcerto.utils.ListMap;
import org.openconcerto.utils.SetMap;
import org.openconcerto.utils.Tuple2.List2;
 
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
298,10 → 296,26
this.fetchValues(true);
}
 
/**
* Fetch up-to-date values from the DB.
*
* @param useCache <code>true</code> to use the {@link SQLDataSource#isCacheEnabled() cache}.
* @return this.
*/
public final SQLRow fetchValues(final boolean useCache) {
return this.fetchValues(useCache, useCache);
}
 
/**
* Return a new instance with up-to-date values.
*
* @param useCache <code>true</code> to use the {@link SQLDataSource#isCacheEnabled() cache}.
* @return a new instance.
*/
public final SQLRow fetchNew(final boolean useCache) {
return new SQLRow(this.getTable(), this.getIDNumber()).fetchValues(useCache);
}
 
@SuppressWarnings("unchecked")
SQLRow fetchValues(final boolean readCache, final boolean writeCache) {
final IResultSetHandler handler = new IResultSetHandler(SQLDataSource.MAP_HANDLER, readCache, writeCache) {
397,14 → 411,44
return this.getValues().get(field);
}
 
public final SQLRow getRow(boolean after) {
/**
* Fetch from the DB this row and the next/previous one. ATTN the rows are locked
* {@link LockStrength#UPDATE for update}, but if this method is not called from within a
* transaction, they will immediately be obsolete.
*
* @param after <code>true</code> to return the next row, <code>false</code> to return the
* previous.
* @return {@link List2#get0() this row} and the next/previous one with only
* {@link SQLTable#getOrderField()} and {@link SQLTable#getArchiveField()} fetched,
* <code>null</code> if this row doesn't exist, the {@link List2#get1() next/previous
* row} is <code>null</code> if this is the last/first row of the table or has
* <code>null</code> order.
* @throws IllegalStateException if this is the {@link #isUndefined() undefined} row.
*/
public final List2<SQLRow> fetchThisAndSequentialRow(boolean after) throws IllegalStateException {
if (this.isUndefined())
throw new IllegalStateException("Cannot order against the undefined");
final SQLTable t = this.getTable();
final BigDecimal destOrder = this.getOrder();
final int diff = (!after) ? -1 : 1;
 
// this is one statement (subquery included) and thus atomic : the inner FOR UPDATE ensures
// that the ORDER doesn't change by the time the outer query is executed
// SELECT * FROM "test"."BATIMENT"
// WHERE "ORDRE" >= (SELECT "ORDRE" FROM "test"."BATIMENT" WHERE "ID" = 3 FOR UPDATE)
// ORDER BY "ORDRE"
// LIMIT 2
// FOR UPDATE;
 
final SQLSelect selOrder = new SQLSelect();
// OK to order against an archived
selOrder.setArchivedPolicy(SQLSelect.BOTH);
selOrder.addSelect(t.getOrderField());
selOrder.setWhere(this.getWhere());
selOrder.setLockStrength(LockStrength.UPDATE);
 
final SQLSelect sel = new SQLSelect();
// undefined must not move
sel.setExcludeUndefined(true);
// don't ignore undefined or the caller might want to use its order
sel.setExcludeUndefined(false);
// unique index prend aussi en compte les archivés
sel.setArchivedPolicy(SQLSelect.BOTH);
sel.addSelect(t.getKey());
411,50 → 455,22
sel.addSelect(t.getOrderField());
if (t.isArchivable())
sel.addSelect(t.getArchiveField());
sel.setWhere(new Where(t.getOrderField(), diff < 0 ? "<" : ">", destOrder));
final Where orderWhere = Where.createRaw(t.getOrderField().getFieldRef() + (diff < 0 ? "<=" : ">=") + "(" + selOrder + ")", t.getOrderField());
// this.getWhere() needed when ORDER is null
sel.setWhere(orderWhere.or(this.getWhere()));
sel.addFieldOrder(t.getOrderField(), diff < 0 ? Order.desc() : Order.asc());
sel.setLimit(1);
sel.setLimit(2);
sel.setLockStrength(LockStrength.UPDATE);
 
final SQLDataSource ds = t.getBase().getDataSource();
@SuppressWarnings("unchecked")
final Map<String, Object> otherMap = ds.execute1(sel.asString());
if (otherMap != null) {
return new SQLRow(t, otherMap);
} else {
final List<SQLRow> rows = SQLRowListRSH.execute(sel);
assert rows.size() <= 2;
if (rows.isEmpty()) {
return null;
}
}
 
/**
* The free order just after or before this row.
*
* @param after whether to look before or after this row.
* @return a free order, or <code>null</code> if there's no room left.
*/
public final BigDecimal getOrder(boolean after) {
final BigDecimal destOrder = this.getOrder();
final SQLRow otherRow = this.getRow(after);
final BigDecimal otherOrder;
if (otherRow != null) {
otherOrder = otherRow.getOrder();
} else if (after) {
// dernière ligne de la table
otherOrder = destOrder.add(ReOrder.DISTANCE);
} else {
// première ligne
otherOrder = ReOrder.MIN_ORDER;
assert rows.get(0).equals(this);
return new List2<>(rows.get(0), rows.size() == 1 ? null : rows.get(1));
}
 
final int decDigits = this.getTable().getOrderDecimalDigits();
final BigDecimal least = BigDecimal.ONE.scaleByPowerOfTen(-decDigits);
final BigDecimal distance = destOrder.subtract(otherOrder).abs();
if (distance.compareTo(least) <= 0)
return null;
else {
final BigDecimal mean = destOrder.add(otherOrder).divide(BigDecimal.valueOf(2));
return DecimalUtils.round(mean, decDigits);
}
}
 
@Override
public SQLRow getForeign(String fieldName) {
/trunk/OpenConcerto/src/org/openconcerto/sql/users/CompanyAccessSQLElement.java
File deleted
/trunk/OpenConcerto/src/org/openconcerto/sql/users/rights/RightSQLElement.java
13,20 → 13,18
package org.openconcerto.sql.users.rights;
 
import org.openconcerto.sql.TM;
import org.openconcerto.sql.element.ConfSQLElement;
import org.openconcerto.sql.element.SQLComponent;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.element.UISQLComponent;
import org.openconcerto.sql.model.DBRoot;
import org.openconcerto.sql.utils.SQLCreateTable;
import org.openconcerto.ui.component.ITextArea;
import org.openconcerto.utils.ListMap;
import org.openconcerto.utils.i18n.I18nUtils;
 
import java.util.Arrays;
import java.util.List;
 
public class RightSQLElement extends ConfSQLElement {
public class RightSQLElement extends SQLElement {
 
public static final String TABLE_NAME = "RIGHT";
 
38,9 → 36,8
return res;
}
 
public RightSQLElement() {
super(TABLE_NAME);
this.setL18nPackageName(I18nUtils.getPackageName(TM.class));
public RightSQLElement(final DBRoot root) {
super(root.findTable(TABLE_NAME), null, "sql.right");
}
 
@Override
/trunk/OpenConcerto/src/org/openconcerto/sql/users/rights/UserRightsManager.java
289,7 → 289,7
};
this.javaRights = new JavaRights();
this.table = t;
this.toUserLink = t.getFieldGroups().get("ID_USER_COMMON").getKey().getForeignLink();
this.toUserLink = t.getField("ID_USER_COMMON").getFieldGroup().getForeignLink();
defaultRegister();
this.userRights = new HashMap<Integer, UserRights>();
this.exec = Executors.newSingleThreadExecutor(new ThreadFactory(this.getClass().getSimpleName() + " executor for " + t.getSQLName(), true).setPriority(Thread.MIN_PRIORITY));
/trunk/OpenConcerto/src/org/openconcerto/sql/users/rights/UserRightSQLElement.java
14,14 → 14,13
package org.openconcerto.sql.users.rights;
 
import static java.util.Arrays.asList;
import org.openconcerto.sql.TM;
import org.openconcerto.sql.element.ConfSQLElement;
 
import org.openconcerto.sql.element.GlobalMapper;
import org.openconcerto.sql.element.SQLComponent;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.model.DBRoot;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.utils.SQLCreateTable;
import org.openconcerto.utils.i18n.I18nUtils;
 
import java.util.ArrayList;
import java.util.Collections;
28,7 → 27,7
import java.util.List;
import java.util.Set;
 
public class UserRightSQLElement extends ConfSQLElement {
public class UserRightSQLElement extends SQLElement {
public static final String TABLE_NAME = "USER_RIGHT";
 
static public List<SQLCreateTable> getCreateTables(final SQLTable userT) {
56,9 → 55,8
return res;
}
 
public UserRightSQLElement() {
super(TABLE_NAME);
this.setL18nPackageName(I18nUtils.getPackageName(TM.class));
public UserRightSQLElement(final DBRoot r) {
super(r.findTable(TABLE_NAME), null, "sql.user-right");
final UserRightGroup group = new UserRightGroup();
GlobalMapper.getInstance().map(UserRightSQLComponent.ID, group);
setDefaultGroup(group);
/trunk/OpenConcerto/src/org/openconcerto/sql/users/UserCommonSQLElement.java
16,7 → 16,6
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.TM;
import org.openconcerto.sql.element.BaseSQLComponent;
import org.openconcerto.sql.element.ConfSQLElement;
import org.openconcerto.sql.element.SQLComponent;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.model.DBRoot;
47,7 → 46,6
import org.openconcerto.utils.ListMap;
import org.openconcerto.utils.cc.ITransformer;
import org.openconcerto.utils.checks.ValidState;
import org.openconcerto.utils.i18n.I18nUtils;
import org.openconcerto.utils.text.SimpleDocumentListener;
 
import java.awt.Component;
75,7 → 73,7
import javax.swing.table.DefaultTableCellRenderer;
 
// FIXME Login user unique ?
public class UserCommonSQLElement extends ConfSQLElement {
public class UserCommonSQLElement extends SQLElement {
 
/**
* Set this system property to "true" if this should generate old style passwords.
82,19 → 80,15
*/
public static final String LEGACY_PASSWORDS = "org.openconcerto.sql.legacyPasswords";
 
{
this.setL18nPackageName(I18nUtils.getPackageName(TM.class));
}
 
private final boolean familyNameFirst;
 
public UserCommonSQLElement() {
super("USER_COMMON");
this.familyNameFirst = false;
public UserCommonSQLElement(final DBRoot root) {
this(root, false);
}
 
public UserCommonSQLElement(final DBRoot root, final boolean familyNameFirst) {
super(root.findTable("USER_COMMON"));
// allow subclass to keep same code
super(root.findTable("USER_COMMON"), null, "sql.user");
this.familyNameFirst = familyNameFirst;
}
 
/trunk/OpenConcerto/src/org/openconcerto/utils/i18n/MessageArgs.java
13,15 → 13,15
package org.openconcerto.utils.i18n;
 
import java.util.HashMap;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeSet;
 
import com.ibm.icu.text.MessageFormat;
 
import net.jcip.annotations.ThreadSafe;
 
import com.ibm.icu.text.MessageFormat;
 
/**
* {@link MessageFormat} can take numbered or named arguments, this class unifies both. This class
* is thread safe if the array or map isn't modified.
33,6 → 33,16
return m instanceof LinkedHashMap;
}
 
static private final MessageArgs EMPTY = new MessageArgs(new Object[0]);
 
public final static MessageArgs getEmpty() {
return EMPTY;
}
 
public final static MessageArgs create(final String key, final Object value) {
return new MessageArgs(Collections.singletonMap(key, value));
}
 
private final boolean mapPrimary;
private Object[] array;
private Map<String, ?> map;
82,12 → 92,16
protected synchronized Map<String, ?> getMap() {
if (this.map == null) {
final int stop = this.array.length;
final Map<String, Object> res = new HashMap<String, Object>(stop);
if (stop == 0) {
this.map = Collections.emptyMap();
} else {
final Map<String, Object> res = new LinkedHashMap<>(stop);
for (int i = 0; i < stop; i++) {
res.put(String.valueOf(i), this.array[i]);
}
this.map = res;
this.map = Collections.unmodifiableMap(res);
}
}
return this.map;
}
 
/trunk/OpenConcerto/src/org/openconcerto/utils/i18n/Grammar_fr.java
84,11 → 84,11
} else if (key.equals(DEMONSTRATIVE_PLURAL)) {
res = "ces " + getPlural(noun);
} else if (key.equals(INDEFINITE_NUMERAL)) {
res = "{0, plural, =0 {auc" + getVariant(noun, INDEFINITE_ARTICLE_SINGULAR) + "} one {# " + getSingular(noun) + "} other {# " + getPlural(noun) + "}}";
res = "{0, plural, =0 {auc" + noun.getVariant(INDEFINITE_ARTICLE_SINGULAR) + "} one {# " + getSingular(noun) + "} other {# " + getPlural(noun) + "}}";
} else if (key.equals(DEFINITE_NUMERAL)) {
res = "{0, plural, =0 {auc" + getVariant(noun, INDEFINITE_ARTICLE_SINGULAR) + "} one {" + getVariant(noun, DEFINITE_ARTICLE_SINGULAR) + "} other {les # " + getPlural(noun) + "}}";
res = "{0, plural, =0 {auc" + noun.getVariant(INDEFINITE_ARTICLE_SINGULAR) + "} one {" + noun.getVariant(DEFINITE_ARTICLE_SINGULAR) + "} other {les # " + getPlural(noun) + "}}";
} else if (key.equals(DEMONSTRATIVE_NUMERAL)) {
res = "{0, plural, =0 {auc" + getVariant(noun, INDEFINITE_ARTICLE_SINGULAR) + "} one {" + getVariant(noun, DEMONSTRATIVE_SINGULAR) + "} other {ces # " + getPlural(noun) + "}}";
res = "{0, plural, =0 {auc" + noun.getVariant(INDEFINITE_ARTICLE_SINGULAR) + "} one {" + noun.getVariant(DEMONSTRATIVE_SINGULAR) + "} other {ces # " + getPlural(noun) + "}}";
} else if (key.equals(DEFINITE_ORDINAL) || key.equals(INDEFINITE_ORDINAL)) {
final boolean estFéminin = noun.getNounClass() == NounClass.FEMININE;
final String article = key.equals(DEFINITE_ORDINAL) ? (estFéminin ? "la " : "le ") : "";
/trunk/OpenConcerto/src/org/openconcerto/utils/i18n/Grammar_es.java
New file
0,0 → 1,123
/*
* 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.utils.i18n;
 
import java.util.Arrays;
import java.util.Collection;
import java.util.Locale;
 
import net.jcip.annotations.Immutable;
 
@Immutable
public class Grammar_es extends Grammar {
 
static private final Grammar_es INSTANCE = new Grammar_es();
 
public static Grammar_es getInstance() {
return INSTANCE;
}
 
private Grammar_es() {
this(Locale.forLanguageTag("es"));
}
 
protected Grammar_es(final Locale l) {
super(l);
}
 
@Override
protected Collection<? extends VariantKey> createVariantKeys() {
return Arrays.asList(SINGULAR, PLURAL, INDEFINITE_ARTICLE_SINGULAR, INDEFINITE_ARTICLE_PLURAL, DEFINITE_ARTICLE_SINGULAR, DEFINITE_ARTICLE_PLURAL, DEMONSTRATIVE_SINGULAR, DEMONSTRATIVE_PLURAL,
INDEFINITE_NUMERAL, DEFINITE_NUMERAL, DEMONSTRATIVE_NUMERAL, INDEFINITE_ORDINAL, DEFINITE_ORDINAL);
}
 
@Override
protected Collection<? extends NounClass> createNounClasses() {
return Arrays.asList(NounClass.FEMININE, NounClass.MASCULINE);
}
 
public final Phrase createPhrase(final String singular) {
return this.createPhrase(singular, null);
}
 
public final Phrase createPhrase(final String singular, final String plural) {
final Phrase res = new Phrase(this, singular, null);
if (plural != null)
res.putVariant(PLURAL, plural);
return res;
}
 
@Override
public String getVariant(Phrase noun, VariantKey key) {
final String res;
if (key.equals(SINGULAR)) {
res = noun.getBase();
} else if (key.equals(INDEFINITE_ARTICLE_SINGULAR)) {
res = (noun.getNounClass() == NounClass.FEMININE ? "una " : "un ") + getSingular(noun);
} else if (key.equals(DEFINITE_ARTICLE_SINGULAR)) {
res = getDefiniteArticle(noun) + getSingular(noun);
} else if (key.equals(DEMONSTRATIVE_SINGULAR)) {
res = (noun.getNounClass() == NounClass.FEMININE ? "esta " : "este ") + getSingular(noun);
} else if (key.equals(PLURAL)) {
res = getPlural(noun.getBase());
} else if (key.equals(INDEFINITE_ARTICLE_PLURAL)) {
res = (noun.getNounClass() == NounClass.FEMININE ? "unas " : "unos ") + getPlural(noun);
} else if (key.equals(DEFINITE_ARTICLE_PLURAL)) {
res = (noun.getNounClass() == NounClass.FEMININE ? "las " : "los ") + getPlural(noun);
} else if (key.equals(DEMONSTRATIVE_PLURAL)) {
res = (noun.getNounClass() == NounClass.FEMININE ? "estas " : "estos ") + getPlural(noun);
} else if (key.equals(INDEFINITE_NUMERAL)) {
res = "{0, plural, =0 {" + getZero(noun) + "} one {# " + getSingular(noun) + "} other {# " + getPlural(noun) + "}}";
} else if (key.equals(DEFINITE_NUMERAL)) {
res = "{0, plural, =0 {" + getZero(noun) + "} one {" + getVariant(noun, DEFINITE_ARTICLE_SINGULAR) + "} other {" + (noun.getNounClass() == NounClass.FEMININE ? "las " : "los ") + " # "
+ getPlural(noun) + "}}";
} else if (key.equals(DEMONSTRATIVE_NUMERAL)) {
res = "{0, plural, =0 {" + getZero(noun) + "} one {" + getVariant(noun, DEMONSTRATIVE_SINGULAR) + "} other {" + (noun.getNounClass() == NounClass.FEMININE ? "estas " : "estos ") + " # "
+ getPlural(noun) + "}}";
} else if (key.equals(DEFINITE_ORDINAL) || key.equals(INDEFINITE_ORDINAL)) {
final boolean estFéminin = noun.getNounClass() == NounClass.FEMININE;
final String article = key.equals(DEFINITE_ORDINAL) ? (estFéminin ? "la " : "el ") : "";
res = article + "{0, ordinal, %digits-ordinal" + (estFéminin ? "-feminine" : "") + "} " + getSingular(noun);
} else {
res = null;
}
 
return res;
}
 
protected String getZero(Phrase noun) {
return (noun.getNounClass() == NounClass.MASCULINE ? "ningún " : "ninguna ") + noun.getBase();
}
 
protected String getDefiniteArticle(Phrase noun) {
if (noun.getNounClass() == NounClass.MASCULINE || noun.getBase().startsWith("a") || noun.getBase().startsWith("ha"))
return "el ";
else
return "la ";
}
 
protected String getSingular(Phrase noun) {
final String res = noun.getVariant(SINGULAR);
return res == null ? noun.getBase() : res;
}
 
protected String getPlural(Phrase noun) {
final String res = noun.getVariant(PLURAL);
return res == null ? getPlural(noun.getBase()) : res;
}
 
protected String getPlural(String noun) {
return noun + 's';
}
}
/trunk/OpenConcerto/src/org/openconcerto/utils/i18n/LocalizedInstances.java
14,6 → 14,7
package org.openconcerto.utils.i18n;
 
import org.openconcerto.utils.Log;
import org.openconcerto.utils.ReflectUtils;
import org.openconcerto.utils.Tuple2;
import org.openconcerto.utils.Value;
 
88,19 → 89,20
// test emptiness to not mix languages
for (Locale targetLocale = locale; targetLocale != null && l.isEmpty(); targetLocale = this.cntrl.getFallbackLocale(baseName, targetLocale)) {
localeRes = targetLocale;
// e.g. "fr_FR", "fr"
for (final Locale candidate : this.cntrl.getCandidateLocales(baseName, targetLocale)) {
// e.g. org.acme.MyClass_fr
final String bundleName = this.cntrl.toBundleName(baseName, candidate);
 
// code first
final Class<?> loadedClass = loadClass(bundleName, cl);
if (loadedClass != null && this.clazz.isAssignableFrom(loadedClass)) {
final Class<? extends T> subclazz = loadedClass.asSubclass(this.clazz);
final Class<? extends T> subclazz = ReflectUtils.getSubclass(bundleName, this.clazz, cl.getClassLoader());
if (subclazz != null) {
try {
final Value<? extends T> instance = this.getInstance(subclazz);
if (instance.hasValue())
l.add(instance.getValue());
else
Log.get().warning(loadedClass + " exists but the constructor wasn't found");
Log.get().warning(subclazz + " exists but the constructor wasn't found");
} catch (Exception e) {
Log.get().log(Level.WARNING, "Couldn't create an instance using " + subclazz, e);
}
118,14 → 120,6
return Tuple2.create(localeRes, l);
}
 
private final Class<?> loadClass(final String name, final Class<?> cl) {
try {
return Class.forName(name, true, cl.getClassLoader());
} catch (ClassNotFoundException e) {
return null;
}
}
 
/**
* The no-arg static method to use.
*
/trunk/OpenConcerto/src/org/openconcerto/utils/i18n/translation/messages_en.properties
7,7 → 7,7
 
memory=memory
megabytes={0} MB
processors={0} processor{0,choice,1#|1<s}
processors={0, plural, one { # processor } other { # processors } }
os=Operating system
javaVersion=Version <b>{0}</b> of {1}
javaHome=installation directory
/trunk/OpenConcerto/src/org/openconcerto/utils/i18n/translation/messages_fr.properties
7,7 → 7,7
 
memory=mémoire
megabytes={0} Mo
processors={0} processor{0,choice,1#|1<s}
processors={0, plural, one { # processeur } other { # processeurs } }
os=Système d''exploitation
javaVersion=Version <b>{0}</b> de {1}
javaHome=dossier d'installation
/trunk/OpenConcerto/src/org/openconcerto/utils/i18n/translation/messages_pl.properties
New file
0,0 → 1,29
true_key=prawdziwe
false_key=fa\u0142szywy
yes_key=tak
no_key=Nie
 
linkOpenError=Error while opening {0}
 
memory=pami\u0119ci
megabytes={0} MB
processors={0, plural, one { # procesora } other { # procesorów } }
os=Operating system
javaVersion=Version <b>{0}</b> of {1}
javaHome=installation directory
no.laf=No look and feel
 
user=u\u017Cytkownika
home.dir=home directory
cwd=current directory
 
network=Network
hardwareAddress=adres sprz\u0119towy
interfaceFullName=full name
interfaceState=state
interfaceStateUp=up
interfaceStateDown=down
 
cut=Wytnij
copy=Kopi\u0119
paste=Wklej
/trunk/OpenConcerto/src/org/openconcerto/utils/i18n/TM.java
21,6 → 21,7
import java.beans.Introspector;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
28,6 → 29,7
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Objects;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
49,9 → 51,37
public class TM {
 
static public enum MissingMode {
EXCEPTION, NULL, STRING
EXCEPTION {
@Override
protected String returnMissing(TM tm, String key) throws MissingResourceException {
throw new MissingResourceException("Missing translation", tm.getBaseName(), key);
}
},
NULL {
@Override
protected String returnMissing(TM tm, String key) {
return null;
}
},
STRING {
@Override
protected String returnMissing(TM tm, String key) {
return '!' + key + '!';
}
};
 
protected abstract String returnMissing(final TM tm, final String key) throws MissingResourceException;
 
// method to avoid array allocation and Arrays.toString()
protected final String returnResult(final TM tm, final String res, final String key) throws MissingResourceException {
return res == null ? this.returnMissing(tm, key) : res;
}
 
protected final String returnResult(final TM tm, final String res, final String... keys) throws MissingResourceException {
return res == null ? this.returnMissing(tm, Arrays.toString(keys)) : res;
}
}
 
static public final String NOUN_CLASS_PROP = "nounClass";
static {
assert NOUN_CLASS_PROP.equals(Introspector.decapitalize(NounClass.class.getSimpleName()));
178,21 → 208,40
}
 
public final String translate(final MissingMode mode, final String key, final Object... args) throws MissingResourceException {
return translate(mode, key, new MessageArgs(args));
return translate(mode, key, args.length == 0 ? MessageArgs.getEmpty() : new MessageArgs(args));
}
 
public final String translateFirst(final MissingMode mode, final String... keys) throws MissingResourceException {
return translateFirst(mode, MessageArgs.getEmpty(), keys);
}
 
/**
* Return the first non-<code>null</code> result.
*
* @param mode what to do if all keys are <code>null</code>.
* @param args the arguments.
* @param keys the keys to search for.
* @return the first non-<code>null</code> result.
* @throws MissingResourceException if {@link MissingMode#EXCEPTION} and all keys are
* <code>null</code>.
*/
public final String translateFirst(final MissingMode mode, final MessageArgs args, final String... keys) throws MissingResourceException {
String res = null;
for (int i = 0; i < keys.length && res == null; i++) {
final String key = keys[i];
if (key != null)
res = this.translate(MissingMode.NULL, key, args);
}
return mode.returnResult(this, res, keys);
}
 
private final String translate(final MissingMode mode, final String key, MessageArgs args) throws MissingResourceException {
Objects.requireNonNull(mode, "Null mode");
Objects.requireNonNull(key, "Null key");
Objects.requireNonNull(args, "Null arguments");
final String res = this.translations.translate(key, args);
if (res == null) {
if (mode == MissingMode.STRING)
return '!' + key + '!';
else if (mode == MissingMode.NULL)
return null;
else
throw new MissingResourceException("Missing translation", this.getBaseName(), key);
return mode.returnResult(this, res, key);
}
return res;
}
 
protected MessageArgs replaceMap(final MessageArgs args, final String msg) {
final MessageArgs res;
/trunk/OpenConcerto/src/org/openconcerto/utils/i18n/Grammar_pl.java
New file
0,0 → 1,55
/*
* 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.utils.i18n;
 
import java.util.Arrays;
import java.util.Collection;
import java.util.Locale;
 
import net.jcip.annotations.Immutable;
 
@Immutable
public class Grammar_pl extends Grammar {
 
static private final Grammar_pl INSTANCE = new Grammar_pl();
 
public static Grammar_pl getInstance() {
return INSTANCE;
}
 
private Grammar_pl() {
this(Locale.forLanguageTag("pl"));
}
 
protected Grammar_pl(final Locale l) {
super(l);
}
 
@Override
protected Collection<? extends VariantKey> createVariantKeys() {
return Arrays.asList(SINGULAR, PLURAL, INDEFINITE_ARTICLE_SINGULAR, INDEFINITE_ARTICLE_PLURAL, DEFINITE_ARTICLE_SINGULAR, DEFINITE_ARTICLE_PLURAL, DEMONSTRATIVE_SINGULAR, DEMONSTRATIVE_PLURAL,
INDEFINITE_NUMERAL, DEFINITE_NUMERAL, DEMONSTRATIVE_NUMERAL, INDEFINITE_ORDINAL, DEFINITE_ORDINAL);
}
 
@Override
protected Collection<? extends NounClass> createNounClasses() {
return Arrays.asList(NounClass.FEMININE, NounClass.MASCULINE, NounClass.NEUTER);
}
 
@Override
public String getVariant(Phrase noun, VariantKey key) {
// TODO
return noun.getBase();
}
}
/trunk/OpenConcerto/src/org/openconcerto/utils/i18n/Phrase.java
18,17 → 18,18
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
 
import com.ibm.icu.text.MessageFormat;
import com.ibm.icu.text.MessagePattern;
 
import net.jcip.annotations.GuardedBy;
import net.jcip.annotations.ThreadSafe;
 
import com.ibm.icu.text.MessageFormat;
import com.ibm.icu.text.MessagePattern;
 
/**
* A phrase and its declension. E.g. "light bulb or electrical outlet" and
* "light bulbs or electrical outlets".
* A phrase and its declension. E.g. "light bulb or electrical outlet" and "light bulbs or
* electrical outlets".
*
* @author Sylvain
* @see <a href="Wikipedia">http://en.wikipedia.org/wiki/Declension</a>
46,7 → 47,7
@GuardedBy("this")
private final Map<Object, String> variants;
@GuardedBy("this")
private final Set<Object> explicitVariants;
private final Set<VariantKey> explicitVariants;
 
public Phrase(Grammar grammar, String base, NounClass nounClass) {
super();
61,7 → 62,7
} else {
this.variants = new HashMap<Object, String>();
this.variants.put(null, this.getBase());
this.explicitVariants = new HashSet<Object>();
this.explicitVariants = new HashSet<>();
}
}
 
88,6 → 89,22
return this.putVariant(key, variant, true);
}
 
/**
* Put a variant only if needed, i.e. if {@link #getVariant(VariantKey)} doesn't already return
* <code>variant</code>. This is useful to keep {@link #getExplicitVariants()} to a minimum.
*
* @param key which variant, e.g. plural.
* @param variant the value, e.g. feet.
* @return <code>true</code> if the variant was put.
*/
public final synchronized boolean putVariantIfDifferent(final VariantKey key, final String variant) {
final boolean diff = !variant.equals(this.getVariant(key));
if (diff) {
this.putVariant(key, variant);
}
return diff;
}
 
private final synchronized String putVariant(final VariantKey key, final String variant, final boolean explicit) {
final String res = this.variants.put(key, variant);
if (explicit) {
99,6 → 116,16
}
 
/**
* The variants that have been explicitly set by {@link #putVariant(VariantKey, String)}, as
* opposed to variants computed automatically by the {@link #getGrammar() grammar}.
*
* @return all explicit variants.
*/
public synchronized Set<VariantKey> getExplicitVariants() {
return this.explicitVariants == null ? null : new HashSet<>(this.explicitVariants);
}
 
/**
* Get a variant. If the asked variant wasn't put by {@link #putVariant(VariantKey, String)},
* the {@link #getGrammar() grammar} is {@link Grammar#getVariant(Phrase, VariantKey) used}.
*
140,6 → 167,31
}
 
@Override
public synchronized int hashCode() {
return Objects.hash(this.base, this.explicitVariants, this.grammar, this.nounClass);
}
 
@Override
public synchronized boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final Phrase o = (Phrase) obj;
final boolean fast = Objects.equals(this.base, o.base) && Objects.equals(this.explicitVariants, o.explicitVariants) && Objects.equals(this.grammar, o.grammar)
&& Objects.equals(this.nounClass, o.nounClass);
if (!fast || this.variants == null)
return fast;
for (final VariantKey e : this.explicitVariants) {
if (!Objects.equals(this.variants.get(e), o.variants.get(e)))
return false;
}
return true;
}
 
@Override
public String toString() {
final String cl = this.getNounClass() == null ? " " : " (" + this.getNounClass().getName() + ") ";
final String gr = this.getGrammar() == null ? "" : " with " + this.getGrammar();
/trunk/OpenConcerto/src/org/openconcerto/utils/mime/MimeType.java
New file
0,0 → 1,205
/*
* 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.
*/
/*
* Copyright 2007-2009 Medsea Business Solutions S.L.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.openconcerto.utils.mime;
 
import java.io.Serializable;
import java.util.regex.Pattern;
 
/**
* This class represents a simple MimeType object. A mime type is made up of two parts
* <code>&lt;media type&gt;/&lt;sub type&gt;</code>. The media type can be something like
* <code>application</code> or <code>text</code> and the the sub type can be something like
* <code>xml</code> or <code>plain</code>.
*
* Both the media type and sub type can also be the wild card <code>*</code> such as
* <code>*&#47;*</code> and <code>text&#47;*</code>. Note, if the media type is the wild card then
* the sub type must also be a wild card.
*
* @author Steven McArdle
*
*/
public class MimeType implements Serializable {
 
private static final long serialVersionUID = -1324243127744494894L;
 
private static final Pattern mimeSplitter = Pattern.compile("[/;]++");
 
protected String mediaType = "*";
protected String subType = "*";
 
// This is a estimate of how specific this mime type is
private int specificity = 1;
 
/**
* Construct a MimeType from another MimeType instance
*
* @param mimeType
*/
public MimeType(final MimeType mimeType) {
this.mediaType = mimeType.mediaType;
this.subType = mimeType.subType;
this.specificity = mimeType.specificity;
}
 
/**
* Construct a mime type from a String such as <code>text/plain</code>. It tries to ensure that
* the mime type pattern passed in is correctly formatted.
*
* @param mimeType
* @throws IllegalArgumentException
*/
public MimeType(final String mimeType) throws IllegalArgumentException {
if (mimeType == null || mimeType.trim().length() == 0) {
throw new IllegalArgumentException("Invalid MimeType [" + mimeType + "]");
}
String[] parts = mimeSplitter.split(mimeType.trim());
 
if (parts.length > 0) {
// Treat as the mediaType
mediaType = getValidMediaType(parts[0]);
}
if (parts.length > 1) {
subType = getValidSubType(parts[1]);
}
}
 
/**
* Get the media type part of the mime type.
*
* @return media type
*/
public String getMediaType() {
return mediaType;
}
 
/**
* Get the sub type of the mime type
*
* @return sub type
*/
public String getSubType() {
return subType;
}
 
/**
* See if this MimeType is the same as the passed in mime type string
*
* @param mimeType as a String
* @return true if the MimeType passed in has the same media and sub types, else returns false.
*/
private boolean match(final String mimeType) {
return toString().equals(mimeType);
}
 
/**
* Get the hashCode of this MimeType. The hashCode is calculate as (31 * mediaType.hashCode()) +
* subType.hashCode()
*
* @return calculated hashCode
* @see Object#hashCode()
*/
public int hashCode() {
return (31 * mediaType.hashCode()) + subType.hashCode();
}
 
/**
* Overrides the equals method of <code>java.lang.Object</code>. This is able to compare against
* another MimeType instance or a string representation of a mime type.
*
* @return true if the types match else false.
* @see Object#equals(Object o)
*/
public boolean equals(Object o) {
if (o instanceof MimeType) {
if (this.mediaType.equals(((MimeType) o).mediaType) && this.subType.equals(((MimeType) o).subType)) {
return true;
}
} else if (o instanceof String) {
return match((String) o);
}
return false;
}
 
/**
* Overrides the toString method of <code>java.lang.Object</code>.
*
* @return String representation i.e. <code>&lt;media type&gt;/&lt;sub type&gt;.
* @see Object#toString()
*/
public String toString() {
return mediaType + "/" + subType;
}
 
/**
* This indicates how specific the mime types is i.e. how good a match the mime type is when
* returned from the getMimeTypes(...) calls.
* <p>
* This is calculated by the number of times this MimeType would be returned if the Collection
* was not normalised. The higher the count the more MimeDetectors have matched this type. As
* this can be a false positive for types such as application/octect-stream and text/plain where
* they would be returned by multiple MimeDetector(s). These types are referred to as root mime
* types where ALL mime types derive from application/octet-stream and all text/* types derive
* from text/plan so in these cases we set the specificity to 0 no matter how many times they
* match. This ensures they are regarded as the least specific in the returned Collection.
* </p>
*
* @return how specific this MimeType is according to the rest of the MimeTypes in a Collection.
*/
public int getSpecificity() {
return specificity;
}
 
/*
* Set the value of the specificity. The higher the value the more specific a MimeType is.
*/
void setSpecificity(final int specificity) {
this.specificity = specificity;
}
 
/*
* Check the media type at least looks valid. TODO: Enforce more rigorous checking of valid
* media types.
*/
private String getValidMediaType(final String mediaType) {
if (mediaType == null || mediaType.trim().length() == 0) {
return "*";
}
return mediaType;
}
 
/*
* Check the sub type at least looks valid. TODO: Enforce more rigorous checking of valid sub
* types.
*/
private String getValidSubType(final String subType) {
if (subType == null || subType.trim().length() == 0 || "*".equals(mediaType)) {
// If the mediaType is a wild card then the sub type must also be a wild card
return "*";
}
return subType;
}
}
/trunk/OpenConcerto/src/org/openconcerto/utils/mime/mime.cache
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/OpenConcerto/src/org/openconcerto/utils/mime/mime.cache
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/OpenConcerto/src/org/openconcerto/utils/mime/FreeDesktopMimeDetector.java
New file
0,0 → 1,772
/*
* 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.utils.mime;
 
/*
* Copyright 2007-2009 Medsea Business Solutions S.L.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
 
import org.openconcerto.utils.CollectionUtils;
import org.openconcerto.utils.Log;
import org.openconcerto.utils.OSFamily;
import org.openconcerto.utils.StreamUtils;
 
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.spi.FileTypeDetector;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.logging.Level;
import java.util.regex.Pattern;
 
/**
* <p>
* The Opendesktop shared mime database contains glob rules and magic number lookup information to
* enable applications to detect the mime types of files.
* </p>
* <p>
* This class uses the mime.cache file which is one of the files created by the update-mime-database
* application. This file is a memory mapped file that enables the database to be updated and copied
* without interrupting applications.
* </p>
* <p>
* This implementation follows the memory mapped spec so it is not required to restart an
* application using this mime detector should the underlying mime.cache database change.
* </p>
* <p>
* For a complete description of the information contained in this file please see:
* http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html
* </p>
* <p>
* This class also follows, where possible, the RECOMENDED order of detection as detailed in this
* spec. Thanks go to Mathias Clasen at Red Hat for pointing me to the original xdgmime
* implementation http://svn.gnome.org/viewvc/glib/trunk/
* gio/xdgmime/xdgmimecache.c?revision=7784&view=markup
* </p>
* More up to date : https://github.com/GNOME/beagle/blob/master/beagle/glue/xdgmime/xdgmimecache.c
*
* @author Steven McArdle
* @see <a
* href="http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html">Shared
* MIME-Info</a>
*/
@SuppressWarnings({ "unqualified-field-access" })
public class FreeDesktopMimeDetector extends FileTypeDetector {
 
public static enum Mode {
/**
* <a href=
* "http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html#idm140625828606432"
* >Recommended checking order</a>
*/
RECOMMENDED, DATA_ONLY, NAME_ONLY
}
 
public static final String DEFAULT_CACHE = "freeDesktop.mime.cache";
public static final String DEFAULT_MODE = "freeDesktop.mime.mode";
 
static private Mode getDefaultMode() {
final String m = System.getProperty(DEFAULT_MODE);
if (m != null) {
try {
return Mode.valueOf(m.toUpperCase());
} catch (Exception e) {
Log.get().log(Level.CONFIG, "Ignoring invalid mode : " + m, e);
}
}
return Mode.RECOMMENDED;
}
 
private static File mimeCacheFile = OSFamily.getInstance() == OSFamily.Windows ? null : new File("/usr/share/mime/mime.cache");
 
static private boolean canReadFile(final File f, final String msg) {
if (f == null)
return false;
final boolean res = f.isFile() && f.canRead();
if (!res)
Log.get().config(msg + f);
return res;
}
 
static private Object getDefaultCache() {
final String m = System.getProperty(DEFAULT_CACHE);
final File f = m != null ? new File(m) : null;
if (canReadFile(f, "Ignoring invalid passed file : ")) {
return f;
} else if (canReadFile(mimeCacheFile, "Ignoring invalid system file : ")) {
return mimeCacheFile;
} else {
final URL res = FreeDesktopMimeDetector.class.getResource("mime.cache");
if (res == null)
throw new IllegalStateException("No mime.cache found for " + FreeDesktopMimeDetector.class);
return res;
}
}
 
private final ByteBuffer content;
private final Mode mode;
 
public FreeDesktopMimeDetector() throws IOException {
this(getDefaultCache(), getDefaultMode());
}
 
public FreeDesktopMimeDetector(final File mimeCacheFile, final Mode mode) throws IOException {
this((Object) mimeCacheFile, mode);
}
 
public FreeDesktopMimeDetector(final InputStream is, final Mode mode) throws IOException {
this((Object) is, mode);
}
 
// InputStream will be closed
private FreeDesktopMimeDetector(final Object cache, final Mode mode) throws IOException {
if (cache instanceof File || cache instanceof FileInputStream) {
// Map the mime.cache file as a memory mapped file
try (final FileInputStream is = cache instanceof FileInputStream ? (FileInputStream) cache : new FileInputStream((File) cache); final FileChannel rCh = is.getChannel();) {
content = rCh.map(FileChannel.MapMode.READ_ONLY, 0, rCh.size());
}
} else {
final ByteArrayOutputStream out = new ByteArrayOutputStream(250 * 1024);
try (final InputStream is = cache instanceof URL ? ((URL) cache).openStream() : (InputStream) cache) {
StreamUtils.copy(is, out);
}
content = ByteBuffer.wrap(out.toByteArray());
}
this.mode = mode;
}
 
@Override
public String probeContentType(Path path) throws IOException {
final Collection<String> col;
switch (this.mode) {
case RECOMMENDED:
col = this.getMimeTypesFile(path.toFile());
break;
case DATA_ONLY:
try (final InputStream is = new BufferedInputStream(new FileInputStream(path.toFile()))) {
col = this.getMimeTypesInputStream(is);
}
break;
case NAME_ONLY:
col = this.getMimeTypesFileName(path.getFileName().toString());
break;
default:
throw new IllegalStateException("Unknown mode : " + this.mode);
}
return CollectionUtils.getFirst(col);
}
 
/**
* This method resolves mime types closely in accordance with the RECOMENDED order of detection
* detailed in the Opendesktop shared mime database specification
* http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html See
* the Recommended checking order.
*
* @param fileName the name to inspect.
* @return a collection of MIME types.
*/
public Collection<String> getMimeTypesFileName(String fileName) {
Collection<WeightedMimeType> mimeTypes = new ArrayList<WeightedMimeType>();
// Lookup the globbing methods first
lookupMimeTypesForGlobFileName(fileName, mimeTypes);
 
return normalizeWeightedMimeList(mimeTypes);
}
 
/**
* This method resolves mime types closely in accordance with the RECOMENDED order of detection
* detailed in the Opendesktop shared mime database specification
* http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html See
* the Recommended checking order.
*
* @param file the file to inspect.
* @return a collection of MIME types.
* @throws IOException if the file couldn't be read.
*/
public Collection<String> getMimeTypesFile(File file) throws IOException {
Collection<String> mimeTypes = getMimeTypesFileName(file.getName());
if (!file.exists()) {
return mimeTypes;
}
try (final InputStream is = new BufferedInputStream(new FileInputStream(file))) {
return _getMimeTypes(mimeTypes, is);
}
}
 
/**
* This method is unable to perform glob matching as no name is available. This means that it
* does not follow the recommended order of detection defined in the shared mime database spec
* http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html
*
* @param in the stream to inspect.s
* @return a collection of MIME types.
* @throws IOException if the stream couldn't be read.
*/
public Collection<String> getMimeTypesInputStream(InputStream in) throws IOException {
return lookupMimeTypesForMagicData(in);
}
 
/**
* This method is unable to perform glob matching as no name is available. This means that it
* does not follow the recommended order of detection defined in the shared mime database spec
* http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html
*
* @param data the data to inspect.
* @return a collection of MIME types.
*/
public Collection<String> getMimeTypesByteArray(byte[] data) {
return lookupMagicData(data);
}
 
@Override
public String toString() {
return this.getClass().getSimpleName() + " using the mime.cache file version [" + getMajorVersion() + "." + getMinorVersion() + "].";
}
 
public String dump() {
return "{MAJOR_VERSION=" + getMajorVersion() + " MINOR_VERSION=" + getMinorVersion() + " ALIAS_LIST_OFFSET=" + getAliasListOffset() + " PARENT_LIST_OFFSET=" + getParentListOffset()
+ " LITERAL_LIST_OFFSET=" + getLiteralListOffset() + " REVERSE_SUFFIX_TREE_OFFSET=" + getReverseSuffixTreeOffset() + " GLOB_LIST_OFFSET=" + getGlobListOffset() + " MAGIC_LIST_OFFSET="
+ getMagicListOffset() + " NAMESPACE_LIST_OFFSET=" + getNameSpaceListOffset() + " ICONS_LIST_OFFSET=" + getIconListOffset() + " GENERIC_ICONS_LIST_OFFSET="
+ getGenericIconListOffset() + "}";
}
 
private Collection<String> lookupMimeTypesForMagicData(InputStream in) throws IOException {
int offset = 0;
int len = getMaxExtents();
byte[] data = new byte[len];
// Mark the input stream
in.mark(len);
 
try {
// Since an InputStream might return only some data (not all
// requested), we have to read in a loop until
// either EOF is reached or the desired number of bytes have been
// read.
int restBytesToRead = len;
while (restBytesToRead > 0) {
int bytesRead = in.read(data, offset, restBytesToRead);
if (bytesRead < 0)
break; // EOF
 
offset += bytesRead;
restBytesToRead -= bytesRead;
}
} finally {
// Reset the input stream to where it was marked.
in.reset();
}
return lookupMagicData(data);
}
 
private Collection<String> lookupMagicData(byte[] data) {
 
Collection<String> mimeTypes = new ArrayList<String>();
 
int listOffset = getMagicListOffset();
int numEntries = content.getInt(listOffset);
int offset = content.getInt(listOffset + 8);
 
for (int i = 0; i < numEntries; i++) {
final int matchOffset = offset + (16 * i);
final String mimeType = compareToMagicData(matchOffset, data);
if (mimeType != null) {
mimeTypes.add(mimeType);
} else {
final String nonMatch = getMimeType(content.getInt(matchOffset + 4));
mimeTypes.remove(nonMatch);
}
}
 
return mimeTypes;
}
 
private String compareToMagicData(int offset, byte[] data) {
// TODO
// int priority = content.getInt(offset);
int mimeOffset = content.getInt(offset + 4);
int numMatches = content.getInt(offset + 8);
int matchletOffset = content.getInt(offset + 12);
 
for (int i = 0; i < numMatches; i++) {
if (matchletMagicCompare(matchletOffset + (i * 32), data)) {
return getMimeType(mimeOffset);
}
}
return null;
}
 
private boolean matchletMagicCompare(int offset, byte[] data) {
int n_children = content.getInt(offset + 24);
int child_offset = content.getInt(offset + 28);
 
if (magic_matchlet_compare_to_data(offset, data)) {
if (n_children == 0)
return true;
 
for (int i = 0; i < n_children; i++) {
if (matchletMagicCompare(child_offset + 32 * i, data))
return true;
}
}
 
return false;
}
 
private boolean magic_matchlet_compare_to_data(int offset, byte[] data) {
int rangeStart = content.getInt(offset);
int rangeLength = content.getInt(offset + 4);
int dataLength = content.getInt(offset + 12);
int dataOffset = content.getInt(offset + 16);
int maskOffset = content.getInt(offset + 20);
 
for (int i = rangeStart; i <= rangeStart + rangeLength; i++) {
boolean validMatch = true;
if (i + dataLength > data.length) {
return false;
}
if (maskOffset != 0) {
for (int j = 0; j < dataLength; j++) {
if ((content.get(dataOffset + j) & content.get(maskOffset + j)) != (data[j + i] & content.get(maskOffset + j))) {
validMatch = false;
break;
}
}
} else {
for (int j = 0; j < dataLength; j++) {
if (content.get(dataOffset + j) != data[j + i]) {
validMatch = false;
break;
}
}
}
 
if (validMatch) {
return true;
}
}
return false;
}
 
private void lookupGlobLiteral(String fileName, Collection<WeightedMimeType> mimeTypes) {
int listOffset = getLiteralListOffset();
int numEntries = content.getInt(listOffset);
 
int min = 0;
int max = numEntries - 1;
while (max >= min) {
int mid = (min + max) / 2;
String literal = getString(content.getInt((listOffset + 4) + (12 * mid)));
int cmp = literal.compareTo(fileName);
if (cmp < 0) {
min = mid + 1;
} else if (cmp > 0) {
max = mid - 1;
} else {
String mimeType = getMimeType(content.getInt((listOffset + 4) + (12 * mid) + 4));
int weight = content.getInt((listOffset + 4) + (12 * mid) + 8);
mimeTypes.add(new WeightedMimeType(mimeType, literal, weight));
return;
}
}
}
 
private void lookupGlobFileNameMatch(String fileName, Collection<WeightedMimeType> mimeTypes) {
final int listOffset = getGlobListOffset();
final int numEntries = content.getInt(listOffset);
final int entriesOffset = listOffset + 4;
 
for (int i = 0; i < numEntries; i++) {
final int entryOffset = entriesOffset + 12 * 1;
final int offset = content.getInt(entryOffset);
final int mimeTypeOffset = content.getInt(entryOffset + 4);
final int weightNFlags = content.getInt(entryOffset + 8);
final int weight = weightNFlags & 0xFF;
final boolean cs = (weightNFlags & 0x100) != 0;
 
final Pattern pattern = Pattern.compile(getString(offset, true), !cs ? (Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) : 0);
if (pattern.matcher(fileName).matches()) {
final String mimeType = getMimeType(mimeTypeOffset);
final String globPattern = getString(offset, false);
mimeTypes.add(new WeightedMimeType(mimeType, globPattern, weight));
}
}
}
 
private Collection<String> normalizeWeightedMimeList(Collection<WeightedMimeType> weightedMimeTypes) {
if (weightedMimeTypes.isEmpty())
return Collections.emptySet();
Collection<WeightedMimeType> mimeTypes = new LinkedHashSet<WeightedMimeType>();
 
// Sort the weightedMimeTypes
Collections.sort((List<WeightedMimeType>) weightedMimeTypes, new Comparator<WeightedMimeType>() {
public int compare(WeightedMimeType obj1, WeightedMimeType obj2) {
return obj1.weight - obj2.weight;
}
});
 
// Keep only globs with the biggest weight. They are in weight order at
// this point
int weight = 0;
int patternLen = 0;
for (final WeightedMimeType mw : weightedMimeTypes) {
if (weight < mw.weight) {
weight = mw.weight;
}
if (weight >= mw.weight) {
if (mw.pattern.length() > patternLen) {
patternLen = mw.pattern.length();
}
mimeTypes.add(mw);
}
}
 
// Now keep only the longest patterns
for (final WeightedMimeType mw : weightedMimeTypes) {
if (mw.pattern.length() < patternLen) {
mimeTypes.remove(mw);
}
}
 
// Could possibly have multiple mimeTypes here with the same weight and
// pattern length. Can even have multiple entries for the same type so
// lets remove
// any duplicates by copying entries to a HashSet that can only have a
// single instance
// of each type
Collection<String> _mimeTypes = new HashSet<String>();
for (final WeightedMimeType mw : mimeTypes) {
_mimeTypes.add(mw.toString());
}
return _mimeTypes;
}
 
private void lookupMimeTypesForGlobFileName(String fileName, Collection<WeightedMimeType> mimeTypes) {
if (fileName == null) {
return;
}
 
lookupGlobLiteral(fileName, mimeTypes);
if (!mimeTypes.isEmpty()) {
return;
}
 
int len = fileName.length();
lookupGlobSuffix(fileName, false, len, mimeTypes);
if (mimeTypes.isEmpty()) {
lookupGlobSuffix(fileName, true, len, mimeTypes);
}
 
if (mimeTypes.isEmpty()) {
lookupGlobFileNameMatch(fileName, mimeTypes);
}
}
 
private void lookupGlobSuffix(String fileName, boolean ignoreCase, int len, Collection<WeightedMimeType> mimeTypes) {
int listOffset = getReverseSuffixTreeOffset();
int numEntries = content.getInt(listOffset);
int offset = content.getInt(listOffset + 4);
 
lookupGlobNodeSuffix(fileName, numEntries, offset, ignoreCase, len, mimeTypes, new StringBuffer());
}
 
private void lookupGlobNodeSuffix(final String fileName, final int numEntries, final int offset, final boolean ignoreCase, int len, Collection<WeightedMimeType> mimeTypes, StringBuffer pattern) {
final char character = ignoreCase ? fileName.toLowerCase().charAt(len - 1) : fileName.charAt(len - 1);
 
if (character == 0) {
return;
}
 
int min = 0;
int max = numEntries - 1;
while (max >= min && len >= 0) {
int mid = (min + max) / 2;
 
char matchChar = (char) content.getInt(offset + (12 * mid));
if (ignoreCase)
matchChar = Character.toLowerCase(matchChar);
if (matchChar < character) {
min = mid + 1;
} else if (matchChar > character) {
max = mid - 1;
} else {
len--;
// first leaf nodes (matchChar==0) then tree nodes
final int numChildren = content.getInt(offset + (12 * mid) + 4);
final int firstChildOffset = content.getInt(offset + (12 * mid) + 8);
if (len > 0) {
pattern.append(matchChar);
lookupGlobNodeSuffix(fileName, numChildren, firstChildOffset, ignoreCase, len, mimeTypes, pattern);
}
// if the name did not match a longer pattern, try to match this one
if (mimeTypes.isEmpty()) {
for (int i = 0; i < numChildren; i++) {
final int childOffset = firstChildOffset + (12 * i);
if (content.getInt(childOffset) != 0) {
// not a leaf node anymore
break;
}
 
final int mimeOffset = content.getInt(childOffset + 4);
final int weightNFlags = content.getInt(childOffset + 8);
final int weight = weightNFlags & 0xFF;
final boolean cs = (weightNFlags & 0x100) != 0;
 
if (!(cs && ignoreCase))
mimeTypes.add(new WeightedMimeType(getMimeType(mimeOffset), pattern.toString(), weight));
}
}
return;
}
}
}
 
static class WeightedMimeType extends MimeType {
 
private static final long serialVersionUID = 1L;
String pattern;
int weight;
 
WeightedMimeType(String mimeType, String pattern, int weight) {
super(mimeType);
this.pattern = pattern;
this.weight = weight;
}
}
 
private int getMaxExtents() {
return content.getInt(getMagicListOffset() + 4);
}
 
private String aliasLookup(String alias) {
int aliasListOffset = getAliasListOffset();
int min = 0;
int max = content.getInt(aliasListOffset) - 1;
 
while (max >= min) {
int mid = (min + max) / 2;
// content.position((aliasListOffset + 4) + (mid * 8));
 
int aliasOffset = content.getInt((aliasListOffset + 4) + (mid * 8));
int mimeOffset = content.getInt((aliasListOffset + 4) + (mid * 8) + 4);
 
int cmp = getMimeType(aliasOffset).compareTo(alias);
if (cmp < 0) {
min = mid + 1;
} else if (cmp > 0) {
max = mid - 1;
} else {
return getMimeType(mimeOffset);
}
}
return null;
}
 
private String unaliasMimeType(String mimeType) {
String lookup = aliasLookup(mimeType);
return lookup == null ? mimeType : lookup;
}
 
private boolean isMimeTypeSubclass(String mimeType, String subClass) {
String umimeType = unaliasMimeType(mimeType);
String usubClass = unaliasMimeType(subClass);
MimeType _mimeType = new MimeType(umimeType);
MimeType _subClass = new MimeType(usubClass);
 
if (umimeType.compareTo(usubClass) == 0) {
return true;
}
 
if (isSuperType(usubClass) && (_mimeType.getMediaType().equals(_subClass.getMediaType()))) {
return true;
}
 
// Handle special cases text/plain and application/octet-stream
if (usubClass.equals("text/plain") && _mimeType.getMediaType().equals("text")) {
return true;
}
 
if (usubClass.equals("application/octet-stream")) {
return true;
}
int parentListOffset = getParentListOffset();
int numParents = content.getInt(parentListOffset);
int min = 0;
int max = numParents - 1;
while (max >= min) {
int med = (min + max) / 2;
int offset = content.getInt((parentListOffset + 4) + (8 * med));
String parentMime = getMimeType(offset);
int cmp = parentMime.compareTo(umimeType);
if (cmp < 0) {
min = med + 1;
} else if (cmp > 0) {
max = med - 1;
} else {
offset = content.getInt((parentListOffset + 4) + (8 * med) + 4);
int _numParents = content.getInt(offset);
for (int i = 0; i < _numParents; i++) {
int parentOffset = content.getInt((offset + 4) + (4 * i));
if (isMimeTypeSubclass(getMimeType(parentOffset), usubClass)) {
return true;
}
}
break;
}
}
return false;
}
 
private boolean isSuperType(String mimeType) {
return mimeType.endsWith("/*");
}
 
private int getGenericIconListOffset() {
return content.getInt(36);
}
 
private int getIconListOffset() {
return content.getInt(32);
}
 
private int getNameSpaceListOffset() {
return content.getInt(28);
}
 
private int getMagicListOffset() {
return content.getInt(24);
}
 
private int getGlobListOffset() {
return content.getInt(20);
}
 
private int getReverseSuffixTreeOffset() {
return content.getInt(16);
}
 
private int getLiteralListOffset() {
return content.getInt(12);
}
 
private int getParentListOffset() {
return content.getInt(8);
}
 
private int getAliasListOffset() {
return content.getInt(4);
}
 
private short getMinorVersion() {
return content.getShort(2);
}
 
private short getMajorVersion() {
return content.getShort(0);
}
 
private String getMimeType(int offset) {
return getString(offset);
}
 
private String getString(int offset) {
return getString(offset, false);
}
 
private String getString(int offset, boolean regularExpression) {
int position = content.position();
content.position(offset);
StringBuffer buf = new StringBuffer();
char c = 0;
while ((c = (char) content.get()) != 0) {
if (regularExpression) {
switch (c) {
case '.':
buf.append("\\");
break;
case '*':
case '+':
case '?':
buf.append(".");
}
}
buf.append(c);
}
// Reset position
content.position(position);
 
if (regularExpression) {
buf.insert(0, '^');
buf.append('$');
}
return buf.toString();
}
 
private Collection<String> _getMimeTypes(Collection<String> mimeTypes, final InputStream in) throws IOException {
if (mimeTypes.isEmpty() || mimeTypes.size() > 1) {
Collection<String> _mimeTypes = getMimeTypesInputStream(in);
 
if (!_mimeTypes.isEmpty()) {
if (!mimeTypes.isEmpty()) {
// more than one glob matched
 
// Check for same mime type
for (final String mimeType : mimeTypes) {
if (_mimeTypes.contains(mimeType)) {
// mimeTypes = new ArrayList();
mimeTypes.add(mimeType);
// return mimeTypes;
}
// Check for mime type subtype
for (final String _mimeType : _mimeTypes) {
if (isMimeTypeSubclass(mimeType, _mimeType)) {
// mimeTypes = new ArrayList();
mimeTypes.add(mimeType);
// return mimeTypes;
}
}
}
} else {
// No globs matched but we have magic matches
return _mimeTypes;
}
}
}
 
return mimeTypes;
 
}
}
/trunk/OpenConcerto/src/org/openconcerto/utils/mime/File.java
New file
0,0 → 1,35
/*
* 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.utils.mime;
 
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
 
public class File {
public static void main(String[] args) throws IOException {
if (args.length == 0) {
System.out.println(File.class.getName() + " file...");
System.out.println("Allow to find the MIME type of files");
System.out.println("The '" + FreeDesktopMimeDetector.DEFAULT_MODE + "' property can be set to " + Arrays.asList(FreeDesktopMimeDetector.Mode.values()));
System.out.println("\tthe default is the first one, see http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html#idm140625828606432");
System.exit(1);
}
for (final String f : args) {
final Path p = Paths.get(f);
System.out.println(f + '\t' + new FreeDesktopMimeDetector().probeContentType(p));
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/utils/mime/FileMagicMimeDetector.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.utils.mime;
 
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.spi.FileTypeDetector;
 
/**
* <p>
* The <a
* href="http://standards.freedesktop.org/shared-mime-info-spec/shared-mime-info-spec-latest.html"
* >freedesktop Shared MIME-Info</a> only contains basic magic support. In particular it misses
* indirect offset and calculations that <a href="http://www.darwinsys.com/file">file</a> supports.
* For example these features are needed for <a
* href="https://github.com/file/file/blob/master/magic/Magdir/msooxml">MS OOXML</a>.
* </p>
*
* @see <a href="https://github.com/file/file/blob/master/doc/magic.man">Magic Format</a>
*/
public class FileMagicMimeDetector extends FileTypeDetector {
 
@Override
public String probeContentType(Path path) throws IOException {
throw new UnsupportedOperationException();
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/utils/StreamUtils.java
13,11 → 13,9
package org.openconcerto.utils;
 
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
24,6 → 22,9
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.logging.Level;
 
public class StreamUtils {
 
48,6 → 49,7
* @throws IOException if an error occurs while reading or writing.
*/
public static void copy(InputStream in, OutputStream out) throws IOException {
// TODO use in.transferTo(out) in Java 9
copy(in, out, 512 * 1024);
}
 
56,6 → 58,8
}
 
public static long copy(InputStream in, OutputStream out, final int bufferSize, final long length) throws IOException {
if (bufferSize < 1)
throw new IllegalArgumentException("Buffer size too small : " + bufferSize);
final byte[] buffer = new byte[bufferSize];
long totalCount = 0;
final boolean copyAll = length < 0;
62,10 → 66,14
while (copyAll || totalCount < length) {
final long toRead = copyAll ? buffer.length : Math.min(length - totalCount, buffer.length);
// since buffer.length is an int
assert 0 <= toRead && toRead <= Integer.MAX_VALUE;
assert 0 < toRead && toRead <= Integer.MAX_VALUE;
final int count = in.read(buffer, 0, (int) toRead);
if (count == -1)
if (count <= 0) {
// like Files.copy(InputStream, OutputStream), stop if reading 0 bytes
if (count == 0)
Log.get().log(Level.WARNING, "", new IllegalStateException("read() returned 0 for " + in));
break;
}
totalCount += count;
out.write(buffer, 0, count);
}
75,14 → 83,8
}
 
public static void copy(InputStream ins, File out) throws IOException {
// buffered since read() in copy(InputStream, OutputStream) may return 1 byte at a time
final OutputStream ous = new BufferedOutputStream(new FileOutputStream(out));
try {
copy(ins, ous);
} finally {
ous.close();
Files.copy(ins, out.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
}
 
/**
* Read until the end of the stream is reached. NOTE : since this method didn't create the
/trunk/OpenConcerto/src/org/openconcerto/utils/ExceptionUtils.java
81,7 → 81,7
}
 
static public String getStackTrace(Throwable cause) {
final StringWriter res = new StringWriter(128);
final StringWriter res = new StringWriter(8192);
final PrintWriter pw = new PrintWriter(res);
try {
cause.printStackTrace(pw);
/trunk/OpenConcerto/src/org/openconcerto/utils/TableSorter.java
37,6 → 37,8
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
45,6 → 47,8
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
 
import net.jcip.annotations.Immutable;
 
/**
* TableSorter is a decorator for TableModels; adding sorting functionality to a supplied
* TableModel. TableSorter does not store or copy the data in its TableModel; instead it maintains a
51,16 → 55,18
* map from the row indexes of the view to the row indexes of the model. As requests are made of the
* sorter (like getValueAt(row, col)) they are passed to the underlying model after the row numbers
* have been translated via the internal mapping array. This way, the TableSorter appears to hold
* another copy of the table with the rows in a different order. <p/>TableSorter registers itself as
* a listener to the underlying model, just as the JTable itself would. Events recieved from the
* model are examined, sometimes manipulated (typically widened), and then passed on to the
* TableSorter's listeners (typically the JTable). If a change to the model has invalidated the
* order of TableSorter's rows, a note of this is made and the sorter will resort the rows the next
* time a value is requested. <p/>When the tableHeader property is set, either by using the
* setTableHeader() method or the two argument constructor, the table header may be used as a
* complete UI for TableSorter. The default renderer of the tableHeader is decorated with a renderer
* that indicates the sorting status of each column. In addition, a mouse listener is installed with
* the following behavior:
* another copy of the table with the rows in a different order.
* <p/>
* TableSorter registers itself as a listener to the underlying model, just as the JTable itself
* would. Events recieved from the model are examined, sometimes manipulated (typically widened),
* and then passed on to the TableSorter's listeners (typically the JTable). If a change to the
* model has invalidated the order of TableSorter's rows, a note of this is made and the sorter will
* resort the rows the next time a value is requested.
* <p/>
* When the tableHeader property is set, either by using the setTableHeader() method or the two
* argument constructor, the table header may be used as a complete UI for TableSorter. The default
* renderer of the tableHeader is decorated with a renderer that indicates the sorting status of
* each column. In addition, a mouse listener is installed with the following behavior:
* <ul>
* <li>Mouse-click: Clears the sorting status of all other columns and advances the sorting status
* of that column through three values: {NOT_SORTED, ASCENDING, DESCENDING} (then back to NOT_SORTED
72,8 → 78,9
* column do not cancel the statuses of columns that are already sorting - giving a way to initiate
* a compound sort.
* </ul>
* <p/>This is a long overdue rewrite of a class of the same name that first appeared in the swing
* table demos in 1997.
* <p/>
* This is a long overdue rewrite of a class of the same name that first appeared in the swing table
* demos in 1997.
*
* @author Philip Milne
* @author Brendon McLean
92,11 → 99,13
private static Directive EMPTY_DIRECTIVE = new Directive(-1, NOT_SORTED);
 
public static final Comparator COMPARABLE_COMAPRATOR = new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return ((Comparable) o1).compareTo(o2);
}
};
public static final Comparator LEXICAL_COMPARATOR = new Comparator() {
public static final Comparator<Object> LEXICAL_COMPARATOR = new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
return o1.toString().compareTo(o2.toString());
}
108,8 → 117,8
private JTableHeader tableHeader;
private MouseListener mouseListener;
private TableModelListener tableModelListener;
private Map columnComparators = new HashMap();
private List sortingColumns = new ArrayList();
private Map<Class<?>, Comparator<?>> columnComparators = new HashMap<>();
private final List<Directive> sortingColumns = new ArrayList<>();
 
private boolean enabled;
private boolean sorting;
144,6 → 153,9
}
 
public void setTableModel(TableModel tableModel) {
if (!SwingUtilities.isEventDispatchThread()) {
throw new IllegalStateException("must be called from EDT");
}
if (this.tableModel != null) {
this.tableModel.removeTableModelListener(tableModelListener);
}
188,6 → 200,9
}
 
public void setTableHeader(JTableHeader tableHeader) {
if (!SwingUtilities.isEventDispatchThread()) {
throw new IllegalStateException("must be called from EDT");
}
if (this.tableHeader != null) {
this.tableHeader.removeMouseListener(mouseListener);
TableCellRenderer defaultRenderer = this.tableHeader.getDefaultRenderer();
207,9 → 222,22
return sortingColumns.size() != 0;
}
 
public final List<Directive> getSortingColumns() {
return Collections.unmodifiableList(this.sortingColumns);
}
 
public void setSortingColumns(List<Directive> sortingColumns) {
if (!SwingUtilities.isEventDispatchThread()) {
throw new IllegalStateException("must be called from EDT");
}
this.sortingColumns.clear();
this.sortingColumns.addAll(sortingColumns);
sortingStatusChanged();
}
 
private Directive getDirective(int column) {
for (int i = 0; i < sortingColumns.size(); i++) {
Directive directive = (Directive) sortingColumns.get(i);
Directive directive = sortingColumns.get(i);
if (directive.column == column) {
return directive;
}
234,6 → 262,9
}
 
private synchronized void sortingStatusChanged() {
if (!SwingUtilities.isEventDispatchThread()) {
throw new IllegalStateException("must be called from EDT");
}
this.sortingStatusChanged(true);
}
 
271,7 → 302,7
sortingStatusChanged(fire);
}
 
public void setColumnComparator(Class type, Comparator comparator) {
public void setColumnComparator(Class<?> type, Comparator<?> comparator) {
if (comparator == null) {
columnComparators.remove(type);
} else {
280,8 → 311,8
}
 
protected Comparator getComparator(int column) {
Class columnType = tableModel.getColumnClass(column);
Comparator comparator = (Comparator) columnComparators.get(columnType);
Class<?> columnType = tableModel.getColumnClass(column);
Comparator<?> comparator = columnComparators.get(columnType);
if (comparator != null) {
return comparator;
}
292,6 → 323,9
}
 
private Row[] getViewToModel() {
if (!SwingUtilities.isEventDispatchThread()) {
throw new IllegalStateException("must be called from EDT");
}
if (viewToModel == null) {
int tableModelRowCount = tableModel.getRowCount();
viewToModel = new Row[tableModelRowCount];
318,6 → 352,9
}
 
private int[] getModelToView() {
if (!SwingUtilities.isEventDispatchThread()) {
throw new IllegalStateException("must be called from EDT");
}
if (modelToView == null) {
int n = getViewToModel().length;
modelToView = new int[n];
334,31 → 371,50
 
// TableModel interface methods
 
@Override
public int getRowCount() {
if (!SwingUtilities.isEventDispatchThread()) {
throw new IllegalStateException("must be called from EDT");
}
return (tableModel == null) ? 0 : tableModel.getRowCount();
}
 
@Override
public int getColumnCount() {
if (!SwingUtilities.isEventDispatchThread()) {
throw new IllegalStateException("must be called from EDT");
}
return (tableModel == null) ? 0 : tableModel.getColumnCount();
}
 
@Override
public String getColumnName(int column) {
return tableModel.getColumnName(column);
}
 
public Class getColumnClass(int column) {
@Override
public Class<?> getColumnClass(int column) {
return tableModel.getColumnClass(column);
}
 
@Override
public boolean isCellEditable(int row, int column) {
return tableModel.isCellEditable(modelIndex(row), column);
}
 
@Override
public Object getValueAt(int row, int column) {
if (!SwingUtilities.isEventDispatchThread()) {
throw new IllegalStateException("must be called from EDT");
}
return tableModel.getValueAt(modelIndex(row), column);
}
 
@Override
public void setValueAt(Object aValue, int row, int column) {
if (!SwingUtilities.isEventDispatchThread()) {
throw new IllegalStateException("must be called from EDT");
}
tableModel.setValueAt(aValue, modelIndex(row), column);
}
 
376,7 → 432,7
 
// Helper classes
 
private class Row implements Comparable {
private class Row implements Comparable<Row> {
private int modelIndex;
 
public Row(int index) {
383,12 → 439,13
this.modelIndex = index;
}
 
public int compareTo(Object o) {
@Override
public int compareTo(Row o) {
int row1 = modelIndex;
int row2 = ((Row) o).modelIndex;
int row2 = o.modelIndex;
 
for (Iterator it = sortingColumns.iterator(); it.hasNext();) {
Directive directive = (Directive) it.next();
for (Iterator<Directive> it = sortingColumns.iterator(); it.hasNext();) {
Directive directive = it.next();
int column = directive.column;
Object o1 = tableModel.getValueAt(row1, column);
Object o2 = tableModel.getValueAt(row2, column);
413,6 → 470,7
}
 
private class TableModelHandler implements TableModelListener {
@Override
public void tableChanged(TableModelEvent e) {
// If we're not sorting by anything, just pass the event along.
if (!isSorting()) {
487,6 → 545,7
}
 
private class MouseHandler extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
JTableHeader h = (JTableHeader) e.getSource();
TableColumnModel columnModel = h.getColumnModel();
523,6 → 582,7
this.priority = priority;
}
 
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
Color color = c == null ? Color.GRAY : c.getBackground();
// In a compound sort, make each succesive triangle 20%
556,10 → 616,12
g.translate(-x, -y);
}
 
@Override
public int getIconWidth() {
return size;
}
 
@Override
public int getIconHeight() {
return size;
}
572,11 → 634,12
this.tableCellRenderer = tableCellRenderer;
}
 
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component c = tableCellRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (c instanceof JLabel) {
JLabel l = (JLabel) c;
l.setHorizontalTextPosition(JLabel.LEFT);
l.setHorizontalTextPosition(SwingConstants.LEFT);
int modelColumn = table.convertColumnIndexToModel(column);
l.setIcon(getHeaderRendererIcon(modelColumn, l.getFont().getSize()));
}
584,13 → 647,27
}
}
 
private static class Directive {
private int column;
private int direction;
@Immutable
public static class Directive {
private final int column;
private final int direction;
 
public Directive(int column, int direction) {
this.column = column;
this.direction = direction;
}
 
public final int getColumn() {
return this.column;
}
 
public final int getDirection() {
return this.direction;
}
 
@Override
public String toString() {
return this.getClass().getSimpleName() + " " + this.getDirection() + " on column " + this.getColumn();
}
}
}
/trunk/OpenConcerto/src/org/openconcerto/utils/ExceptionHandler.java
25,6 → 25,7
import java.awt.Desktop.Action;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GraphicsEnvironment;
47,8 → 48,10
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
66,7 → 69,6
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.text.JTextComponent;
 
/**
* Allow to display an exception both on the GUI and on the console.
81,6 → 83,9
private static boolean showProbably = false;
private static IFactory<String> softwareInfos = null;
private static ThrowableHandler tHandler = null;
private static boolean safeToExit = false;
private static final CompletableFuture<Boolean> FALSE_FUTURE = CompletableFuture.completedFuture(Boolean.FALSE);
private static final CompletableFuture<Boolean> TRUE_FUTURE = CompletableFuture.completedFuture(Boolean.TRUE);
 
public static void setThrowableHandler(ThrowableHandler handler) {
tHandler = handler;
90,11 → 95,19
forumURL = url;
}
 
public synchronized static void setShowProbably(boolean showProbably) {
public static void setSafeToExit(boolean b) {
safeToExit = b;
}
 
public static void setSubmitErrorAutoEnabled(boolean b) {
submitErrorAuto = b;
}
 
public static synchronized void setShowProbably(boolean showProbably) {
ExceptionHandler.showProbably = showProbably;
}
 
public synchronized static boolean isShowProbably() {
public static synchronized boolean isShowProbably() {
return ExceptionHandler.showProbably;
}
 
120,21 → 133,25
* @param comp the modal parent of the error window.
* @param msg the message to display.
* @param originalExn the cause, can be <code>null</code>.
* @return an exception.
* @return a future completed when the error is handled (e.g. the user clicked on the dialog),
* <code>false</code> if the error couldn't be displayed to the user.
*/
static public ExceptionHandler handle(Component comp, String msg, Throwable originalExn) {
static public Future<Boolean> handle(Component comp, String msg, Throwable originalExn) {
final Future<Boolean> res;
if (tHandler != null && tHandler.handle(msg, originalExn)) {
return new ExceptionHandler(msg, originalExn);
res = TRUE_FUTURE;
} else {
res = new ExceptionHandler(comp, msg, originalExn, false).display();
}
return new ExceptionHandler(comp, msg, originalExn, false);
 
assert res != null;
return res;
}
 
static public RuntimeException handle(String msg, Throwable originalExn) {
static public Future<Boolean> handle(String msg, Throwable originalExn) {
return handle(null, msg, originalExn);
}
 
static public RuntimeException handle(String msg) {
static public Future<Boolean> handle(String msg) {
return handle(msg, null);
}
 
147,7 → 164,9
* @return an exception.
*/
static public RuntimeException die(String msg, Throwable originalExn) {
return new ExceptionHandler(null, msg, originalExn);
final ExceptionHandler res = new ExceptionHandler(null, msg, originalExn);
res.display();
return res;
}
 
static public RuntimeException die(String msg) {
160,27 → 179,31
 
// the comp on which to display the popup, may be null
private final Component comp;
private final Future<?> future;
private final boolean quit;
protected static AtomicInteger openedWindows = new AtomicInteger(0);
private static boolean forceUI;
private static boolean submitErrorAuto = false;
 
public static void setForceUI(boolean forceUI) {
ExceptionHandler.forceUI = forceUI;
}
 
private Future<?> display(final boolean error) {
private Future<Boolean> display() {
final boolean error = this.quit;
final String msg = this.getMessage();
// write out the message as soon as possible
getLogger().log(error ? Level.SEVERE : Level.INFO, null, this);
// then show it to the user
if (!GraphicsEnvironment.isHeadless() || forceUI) {
if (openedWindows.get() > 3) {
return FALSE_FUTURE;
}
final FutureTask<Boolean> run = new FutureTask<>(() -> {
return showMsgHardened(msg, error);
});
if (SwingUtilities.isEventDispatchThread()) {
showMsgHardened(msg, error);
run.run();
} else {
final FutureTask<?> run = new FutureTask<Object>(new Runnable() {
public void run() {
showMsgHardened(msg, error);
}
}, null);
if (error) {
try {
SwingUtilities.invokeAndWait(run);
191,19 → 214,16
} else {
SwingUtilities.invokeLater(run);
}
}
return run;
}
return TRUE_FUTURE;
}
return null;
}
 
public final Future<?> getDialogFuture() {
return this.future;
}
 
protected final void showMsgHardened(final String msg, final boolean error) {
protected final Boolean showMsgHardened(final String msg, final boolean error) {
try {
showMsg(msg, error);
return Boolean.TRUE;
} catch (Throwable e) {
// sometimes the VM cannot display the dialog, in that case don't crash the EDT as the
// message has already been logged. Further if this class is used in
217,6 → 237,7
// nothing
}
}
return Boolean.FALSE;
}
 
protected final void showMsg(final String msg, final boolean quit) {
320,62 → 341,6
}
}));
 
final javax.swing.Action submitAction = new AbstractAction("Soumettre l'erreur") {
@Override
public void actionPerformed(ActionEvent e) {
submitError(p, textArea);
}
 
private void submitError(final JPanel p, final JTextComponent textArea) {
final Charset cs = StringUtils.UTF8;
try {
ProductInfo productInfo = ProductInfo.getInstance();
 
String name = "", version = "";
if (productInfo != null) {
name = productInfo.getName();
version = productInfo.getProperty(ProductInfo.VERSION, version);
}
 
final Map<Info, String> systemInfos = SystemInfo.get(false);
final String os = systemInfos.remove(Info.OS);
final String java = systemInfos.toString();
final String encodedData = "java=" + PercentEncoder.encode(java, cs) + "&os=" + PercentEncoder.encode(os, cs) + "&software=" + PercentEncoder.encode(name + version, cs) + "&stack="
+ PercentEncoder.encode(computeSoftwareInformations() + "\n\n" + textArea.getText(), cs);
final String request = "http://bugreport.ilm-informatique.fr:5000/bugreport";
final URL url = new URL(request);
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("charset", cs.name());
final byte[] bytes = encodedData.getBytes(cs);
connection.setRequestProperty("Content-Length", String.valueOf(bytes.length));
 
final OutputStream outputStream = connection.getOutputStream();
outputStream.write(bytes);
outputStream.flush();
 
// Get the response
final StringBuilder answer = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
answer.append(line);
}
outputStream.close();
reader.close();
connection.disconnect();
 
JOptionPane.showMessageDialog(p, "Merci d'avoir envoyé le rapport d'erreur au service technique.\nIl sera analysé prochainement.");
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
 
btnPanel.add(new JButton(submitAction));
 
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.EAST;
p.add(btnPanel, c);
400,9 → 365,10
message = msg + "\n\n" + message;
}
message += "\n";
message +=
 
getTrace();
message += getTrace();
if (submitErrorAuto) {
submitError(message);
}
textArea.setText(message);
textArea.setEditable(false);
 
420,9 → 386,22
c.fill = GridBagConstraints.NONE;
c.weighty = 0;
c.insets = new Insets(2, 4, 2, 4);
JPanel closePanel = new JPanel();
closePanel.setLayout(new FlowLayout());
if (safeToExit) {
closePanel.add(new JButton(new AbstractAction("Quitter") {
 
@Override
public void actionPerformed(ActionEvent e) {
System.exit(2);
}
}));
}
final JButton buttonClose = new JButton("Fermer");
p.add(buttonClose, c);
closePanel.add(buttonClose);
 
p.add(closePanel, c);
 
final Window window = this.comp == null ? null : SwingUtilities.getWindowAncestor(this.comp);
final JDialog f;
if (window instanceof Frame) {
432,7 → 411,7
}
f.setContentPane(p);
f.pack();
f.setSize(580, 680);
f.setSize(780, 580);
f.setMinimumSize(new Dimension(380, 380));
f.setLocationRelativeTo(this.comp);
final ActionListener al = new ActionListener() {
439,12 → 418,12
 
@Override
public void actionPerformed(ActionEvent e) {
openedWindows.decrementAndGet();
if (quit) {
System.exit(1);
} else {
f.dispose();
}
 
}
};
buttonClose.addActionListener(al);
453,10 → 432,13
@Override
public void windowClosing(WindowEvent e) {
al.actionPerformed(null);
 
}
});
openedWindows.incrementAndGet();
 
f.setVisible(true);
 
}
 
private String getTrace() {
485,17 → 467,70
private ExceptionHandler(Component comp, String msg, Throwable cause, boolean quit) {
super(msg, cause);
this.comp = comp;
this.future = this.display(quit);
this.quit = quit;
}
 
public ExceptionHandler(String msg, Throwable cause) {
super(msg, cause);
this.comp = null;
this.future = null;
private void submitError(String error) {
final Charset cs = StringUtils.UTF8;
try {
ProductInfo productInfo = ProductInfo.getInstance();
 
String name = "", version = "";
if (productInfo != null) {
name = productInfo.getName();
version = productInfo.getProperty(ProductInfo.VERSION, version);
}
 
final Map<Info, String> systemInfos = SystemInfo.get(false);
final String os = systemInfos.remove(Info.OS);
final String java = systemInfos.toString();
final String encodedData = "java=" + PercentEncoder.encode(java, cs) + "&os=" + PercentEncoder.encode(os, cs) + "&software=" + PercentEncoder.encode(name + version, cs) + "&stack="
+ PercentEncoder.encode(computeSoftwareInformations() + "\n\n" + error, cs);
Thread t = new Thread(new Runnable() {
 
@Override
public void run() {
final String request = "http://bugreport.ilm-informatique.fr:5000/bugreport";
try {
System.err.println("ExceptionHandler.submitError");
final URL url = new URL(request);
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("charset", cs.name());
final byte[] bytes = encodedData.getBytes(cs);
connection.setRequestProperty("Content-Length", String.valueOf(bytes.length));
 
final OutputStream outputStream = connection.getOutputStream();
outputStream.write(bytes);
outputStream.flush();
 
// Get the response
final StringBuilder answer = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
answer.append(line);
}
outputStream.close();
reader.close();
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.start();
 
} catch (Exception ex) {
ex.printStackTrace();
}
}
 
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
ExceptionHandler.handle("Fichier de configuration corrompu\n\nmulti\nline", new IllegalStateException("Id manquant"));
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/utils/FileUtils.java
38,6 → 38,7
import java.net.URL;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.CopyOption;
import java.nio.file.DirectoryStream;
import java.nio.file.DirectoryStream.Filter;
97,6 → 98,9
}
 
public static void openFile(File f) throws IOException {
if (!f.exists()) {
throw new FileNotFoundException(f.getAbsolutePath() + " not found");
}
if (Desktop.isDesktopSupported()) {
Desktop d = Desktop.getDesktop();
if (d.isSupported(Desktop.Action.OPEN)) {
616,6 → 620,10
return readUTF8(new FileInputStream(f));
}
 
public static final String readUTF8(Path p) throws IOException {
return new String(Files.readAllBytes(p), StandardCharsets.UTF_8);
}
 
public static final String readUTF8(InputStream ins) throws IOException {
return read(ins, StringUtils.UTF8);
}
900,6 → 908,9
* @throws IOException if the file can't be opened.
*/
public static final void open(File f, String[] executables) throws IOException {
if (!f.exists()) {
throw new FileNotFoundException(f.getAbsolutePath() + " not found");
}
try {
openNative(f);
} catch (IOException exn) {
/trunk/OpenConcerto/src/org/openconcerto/utils/CompareUtils.java
312,4 → 312,12
}
return null;
}
 
static public final <T extends Comparable<? super T>> T min(final T o1, final T o2) {
return o1.compareTo(o2) < 0 ? o1 : o2;
}
 
static public final <T extends Comparable<? super T>> T max(final T o1, final T o2) {
return o1.compareTo(o2) < 0 ? o2 : o1;
}
}
/trunk/OpenConcerto/src/org/openconcerto/utils/SleepingQueue.java
18,6 → 18,7
 
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.Collection;
import java.util.Deque;
import java.util.concurrent.Callable;
227,6 → 228,13
}
 
public final void start() {
this.start(null);
}
 
public final void start(final IClosure<Thread> customizeThread) {
customizeThread(this.tasksQueue);
if (customizeThread != null)
customizeThread.executeChecked(this.tasksQueue);
synchronized (this) {
this.tasksQueue.start();
this.setState(RunningState.RUNNING);
338,14 → 346,25
}
 
/**
* An exception was thrown by a task. This implementation merely
* {@link Exception#printStackTrace()}.
* An exception was thrown by a task. This implementation uses
* {@link Thread#getUncaughtExceptionHandler()} or
* {@link Thread#getDefaultUncaughtExceptionHandler()} if available, otherwise falls back to
* just {@link Exception#printStackTrace()}. To set the handler, {@link #start(IClosure)} can be
* used.
*
* @param exn the exception thrown.
*/
protected void exceptionThrown(final ExecutionException exn) {
final Thread thr = this.tasksQueue;
UncaughtExceptionHandler h = thr.getUncaughtExceptionHandler();
if (h == null)
h = Thread.getDefaultUncaughtExceptionHandler();
if (h != null) {
h.uncaughtException(thr, exn);
} else {
exn.printStackTrace();
}
}
 
/**
* Cancel all queued tasks and the current task.
617,7 → 636,6
private final class SingleThreadedExecutor extends DropperQueue<FutureTask<?>> {
private SingleThreadedExecutor() {
super(SleepingQueue.this.name + System.currentTimeMillis());
customizeThread(this);
}
 
@Override
/trunk/OpenConcerto/src/org/openconcerto/utils/ProcessStreams.java
19,6 → 19,7
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.ProcessBuilder.Redirect;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
35,6 → 36,10
static public enum Action {
/**
* Redirect process streams to ours.
*
* @deprecated use {@link ProcessStreams#redirect(ProcessBuilder)} (or
* {@link Redirect#INHERIT} directly) as it makes sure that
* {@link Process#waitFor()} only returns once all streams are flushed.
*/
REDIRECT,
/**
52,6 → 57,10
DO_NOTHING
}
 
static public final ProcessBuilder redirect(final ProcessBuilder pb) throws IOException {
return pb.redirectErrorStream(true).redirectOutput(Redirect.INHERIT);
}
 
static public final Process handle(final Process p, final Action action) throws IOException {
if (action == Action.CLOSE) {
p.getInputStream().close();
/trunk/OpenConcerto/src/org/openconcerto/utils/ReflectUtils.java
13,6 → 13,7
package org.openconcerto.utils;
 
import java.beans.Expression;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.GenericArrayType;
29,7 → 30,10
public final class ReflectUtils {
 
/**
* Find a constructor with compatible parameters.
* Find a constructor with compatible parameters. NOTE: This follow a simpler algorithm than the
* one in the JLS (<a href=
* "https://docs.oracle.com/javase/specs/jls/se11/html/jls-15.html#jls-15.12.2.5">15.12.2.5.
* Choosing the Most Specific Method</a>).
*
* @param cls the class to find a constructor for, not <code>null</code>.
* @param parameterTypes types of parameters the constructor must accept.
58,6 → 62,35
}
}
 
@SuppressWarnings("unchecked")
static public final <T> T createInstance(final Class<T> clazz, Object... args) throws Exception {
// too difficult to order superclasses and all implemented interfaces of args in order to
// find the most specific constructor
return (T) new Expression(clazz, "new", args).getValue();
}
 
/**
* Return the class with the passed name if it is a subclass of <code>clazz</code>.
*
* @param name the name of the class, not <code>null</code>.
* @param clazz the superclass, not <code>null</code>.
* @return the requested class, <code>null</code> if {@link ClassNotFoundException not found} or
* not a {@link Class#asSubclass(Class) subclass} of <code>clazz</code>.
*/
static public final <T> Class<? extends T> getSubclass(final String name, final Class<T> clazz) {
return getSubclass(name, clazz, clazz.getClassLoader());
}
 
static public final <T> Class<? extends T> getSubclass(final String name, final Class<T> clazz, final ClassLoader cl) {
final Class<?> res;
try {
res = Class.forName(name, true, cl);
} catch (ClassNotFoundException e) {
return null;
}
return clazz.isAssignableFrom(res) ? res.asSubclass(clazz) : null;
}
 
static private Map<Type, Type> resolveTypes(Class<?> c, Class<?> raw) {
final Map<Type, Type> res = new HashMap<Type, Type>();
if (!raw.isAssignableFrom(c))
/trunk/OpenConcerto/src/org/openconcerto/utils/ntp/SNTPClient.java
New file
0,0 → 1,116
/*
* 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.utils.ntp;
 
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
 
public class SNTPClient {
 
protected final DatagramSocket socket;
 
/**
* The SNTP time is referenced to 01/01/1900-00:00. On the other hand, Unix systems and Java
* reference time to 01/01/1970-00:00. This means that convertion is necessary.
*/
private static final long SECS_1900_1970 = 2208988800L;
 
/**
* Constructor.
*
* @param timeout the response timeout (in milliseconds).
* @throws IllegalArgumentException if the timeout is invalid.
* @throws SocketException if an error occurs while creating the socket.
*/
public SNTPClient() throws SocketException {
this.socket = new DatagramSocket();
// 10s timeout
socket.setSoTimeout(10000);
}
 
/**
* Retrieves the network time offset from an SNTP server.
*
* @param host the server host address (IP or DNS).
* @param port the server port.
* @return the network time offset (in milliseconds).
*
* @throws IOException if an error occurs while contacting the server.
*/
public long getOffsetInMillis(final String host, final int port) throws IOException {
final InetAddress addr = InetAddress.getByName(host);
// Send
final Message smessage = new Message();
smessage.setTransmitTimestamp(toTimestamp(System.currentTimeMillis()));
final ByteArrayOutputStream output = new ByteArrayOutputStream();
smessage.encodeMessage(output);
final byte[] data = output.toByteArray();
output.close();
 
DatagramPacket rpacket = new DatagramPacket(data, data.length, addr, port);
socket.send(rpacket);
 
// Receive
final DatagramPacket packet = new DatagramPacket(new byte[Message.MAXIMUM_LENGTH], Message.MAXIMUM_LENGTH);
socket.receive(packet);
final long destinationTime = System.currentTimeMillis();
final Message rmessage = Message.decodeMessage(new ByteArrayInputStream(packet.getData()));
final long originalTime = fromTimestamp(rmessage.getOriginateTimestamp());
final long receiveTime = fromTimestamp(rmessage.getReceiveTimestamp());
final long transmitTime = fromTimestamp(rmessage.getTransmitTimestamp());
return ((receiveTime - originalTime) + (transmitTime - destinationTime)) / 2;
 
}
 
public void close() {
socket.close();
}
 
/**
* Converts Java time to an SNTP timestamp.
*
* @param time the Java time (in milliseconds).
* @return the SNTP timestamp.
*/
private static Timestamp toTimestamp(final long time) {
final double temp = ((double) time) / 1000D;
final long integer = (long) Math.floor(temp);
final long fraction = (long) ((temp - (double) integer) * 0x100000000L);
return new Timestamp(integer + SECS_1900_1970, fraction);
}
 
/**
* Converts an SNTP timestamp to Java time.
*
* @param timestamp the timestamp.
* @return the Java time (in milliseconds).
*/
private static final long fromTimestamp(final Timestamp timestamp) {
long time = (timestamp.getInteger() - SECS_1900_1970) * 1000L;
time += (timestamp.getFraction() * 1000L) / 0x100000000L;
return time;
}
 
public static void main(String[] args) throws IOException {
final SNTPClient client = new SNTPClient();
final long offset = client.getOffsetInMillis("fr.pool.ntp.org", 123);
client.close();
System.out.println(offset);
}
}
/trunk/OpenConcerto/src/org/openconcerto/utils/ntp/Timestamp.java
New file
0,0 → 1,36
/*
* 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.utils.ntp;
 
public final class Timestamp {
 
public static final Timestamp ZERO = new Timestamp(0, 0);
 
private final long integer;
private final long fraction;
 
public Timestamp(final long integer, final long fraction) {
this.integer = integer;
this.fraction = fraction;
}
 
public long getInteger() {
return integer;
}
 
public long getFraction() {
return fraction;
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/utils/ntp/Message.java
New file
0,0 → 1,448
/*
* 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.utils.ntp;
 
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
 
public final class Message {
 
/** Maximum message length (in bytes), without authentication */
public static final int MAXIMUM_LENGTH = 384;
 
/** Leap Indicator. */
private byte byLeapIndicator;
 
/** Version Number. */
private byte byVersionNumber = 0x04;
 
/** Client mode. */
private byte byMode = 0x03;
 
/** Stratum. */
private byte byStratum;
 
/** Poll Interval. */
private byte byPollInterval;
 
/** Precision. */
private byte byPrecision;
 
/** Rood Delay. */
private double dRootDelay;
 
/** Root Dispersion. */
private double dRootDispersion;
 
/** Reference Identifier. */
private byte[] sReferenceIdentifier = "LOCL".getBytes();
 
/** Reference Timestamp. */
private Timestamp tReferenceTimestamp = Timestamp.ZERO;
 
/** Originate Timestamp. */
private Timestamp tOriginateTimestamp = Timestamp.ZERO;
 
/** Receive Timestamp. */
private Timestamp tReceiveTimestamp = Timestamp.ZERO;
 
/** Transmit Timestamp. */
private Timestamp tTransmitTimestamp = Timestamp.ZERO;
 
/**
* Returns the Leap Indicator.
*
* @return the Leap Indicator.
*/
public byte getLeapIndicator() {
return byLeapIndicator;
}
 
/**
* Sets the Leap Indicator.
*
* @param byLeapIndicator the Leap Indicator.
*/
public void setLeapIndicator(final byte byLeapIndicator) {
this.byLeapIndicator = byLeapIndicator;
}
 
/**
* Returns the Version Number.
*
* @return the Version Number.
*/
public byte getVersionNumber() {
return byVersionNumber;
}
 
/**
* Sets the Version Number.
*
* @param byVersionNumber the Version Number.
*/
public void setVersionNumber(final byte byVersionNumber) {
this.byVersionNumber = byVersionNumber;
}
 
/**
* Returns the Mode.
*
* @return the Mode.
*/
public byte getMode() {
return byMode;
}
 
/**
* Sets the Mode.
*
* @param byMode the Mode.
*/
public void setMode(final byte byMode) {
this.byMode = byMode;
}
 
/**
* Returns the Stratum.
*
* @return the Stratum.
*/
public byte getStratum() {
return byStratum;
}
 
/**
* Sets the Stratum.
*
* @param byStratum the Stratum.
*/
public void setStratum(final byte byStratum) {
this.byStratum = byStratum;
}
 
/**
* Returns the Poll Interval.
*
* @return the Poll Interval.
*/
public byte getPollInterval() {
return byPollInterval;
}
 
/**
* Sets the Poll Interval.
*
* @param byPollInterval the Poll Interval.
*/
public void setPollInterval(final byte byPollInterval) {
this.byPollInterval = byPollInterval;
}
 
/**
* Returns the Precision.
*
* @return the Precision.
*/
public byte getPrecision() {
return byPrecision;
}
 
/**
* Sets the Precision.
*
* @param byPrecision the Precision.
*/
public void setPrecision(final byte byPrecision) {
this.byPrecision = byPrecision;
}
 
/**
* Returns the Root Delay.
*
* @return the Root Delay.
*/
public double getRootDelay() {
return dRootDelay;
}
 
/**
* Sets the Root Delay.
*
* @param dRootDelay the Root Delay.
*/
public void setRootDelay(final double dRootDelay) {
this.dRootDelay = dRootDelay;
}
 
/**
* Returns the Root Dispersion.
*
* @return the Root Dispersion.
*/
public double getRootDispersion() {
return dRootDispersion;
}
 
/**
* Sets the Root Dispersion.
*
* @param dRootDispersion the Root Dispersion.
*/
public void setRootDispersion(final double dRootDispersion) {
this.dRootDispersion = dRootDispersion;
}
 
/**
* Returns the Reference Identifier.
*
* @return the Reference Identifier.
*/
public byte[] getReferenceIdentifier() {
return sReferenceIdentifier;
}
 
/**
* Sets the Reference Identifier.
*
* @param sReferenceIdentifier the Reference Identifier.
*/
public void setReferenceIdentifier(final byte[] sReferenceIdentifier) {
this.sReferenceIdentifier = sReferenceIdentifier;
}
 
/**
* Returns the Reference Timestamp.
*
* @return the Reference Timestamp.
*/
public Timestamp getReferenceTimestamp() {
return tReferenceTimestamp;
}
 
/**
* Sets the Reference Timestamp.
*
* @param tReferenceTimestamp the Reference Timestamp.
*/
public void setReferenceTimestamp(final Timestamp tReferenceTimestamp) {
this.tReferenceTimestamp = tReferenceTimestamp;
}
 
/**
* Returns the Originate Timestamp.
*
* @return the Originate Timestamp.
*/
public Timestamp getOriginateTimestamp() {
return tOriginateTimestamp;
}
 
/**
* Sets the Originate Timestamp.
*
* @param tOriginateTimestamp the Originate Timestamp.
*/
public void setOriginateTimestamp(final Timestamp tOriginateTimestamp) {
this.tOriginateTimestamp = tOriginateTimestamp;
}
 
/**
* Returns the Receive Timestamp.
*
* @return the Receive Timestamp.
*/
public Timestamp getReceiveTimestamp() {
return tReceiveTimestamp;
}
 
/**
* Sets the Receive Timestamp.
*
* @param tReceiveTimestamp the Receive Timestamp.
*/
public void setReceiveTimestamp(final Timestamp tReceiveTimestamp) {
this.tReceiveTimestamp = tReceiveTimestamp;
}
 
/**
* Returns the Transmit Timestamp.
*
* @return the Transmit Timestamp.
*/
public Timestamp getTransmitTimestamp() {
return tTransmitTimestamp;
}
 
/**
* Sets the Transmit Timestamp.
*
* @param tTransmitTimestamp the Transmit Timestamp.
*/
public void setTransmitTimestamp(final Timestamp tTransmitTimestamp) {
this.tTransmitTimestamp = tTransmitTimestamp;
}
 
/**
* Encodes an SNTP message to a byte stream.
*
* @param output the byte stream.
*/
public void encodeMessage(final OutputStream output) throws IOException {
byte flags = (byte) (this.getLeapIndicator() << 6);
flags += (byte) (this.getVersionNumber() << 3);
flags += this.getMode();
output.write(flags);
output.write(this.getStratum());
output.write(this.getPollInterval());
output.write(this.getPrecision());
encodeFixedPoint(this.getRootDelay(), output);
encodeFixedPoint(this.getRootDispersion(), output);
encodeBitstring(this.getReferenceIdentifier(), output);
encodeTimestamp(this.getReferenceTimestamp(), output);
encodeTimestamp(this.getOriginateTimestamp(), output);
encodeTimestamp(this.getReceiveTimestamp(), output);
encodeTimestamp(this.getTransmitTimestamp(), output);
}
 
/**
* Decodes an SNTP message from a byte stream.
*
* @param input the byte stream.
* @return the message.
*/
public static Message decodeMessage(final InputStream input) throws IOException {
final Message message = new Message();
final byte flags = (byte) input.read();
message.setLeapIndicator((byte) (flags >> 6));
message.setVersionNumber((byte) ((flags >> 3) & 0x07));
message.setMode((byte) (flags & 0x07));
message.setStratum((byte) input.read());
message.setPollInterval((byte) input.read());
message.setPrecision((byte) input.read());
message.setRootDelay(decodeFixedPoint(input));
message.setRootDispersion(decodeFixedPoint(input));
message.setReferenceIdentifier(decodeBitstring(input));
message.setReferenceTimestamp(decodeTimestamp(input));
message.setOriginateTimestamp(decodeTimestamp(input));
message.setReceiveTimestamp(decodeTimestamp(input));
message.setTransmitTimestamp(decodeTimestamp(input));
 
return message;
}
 
/**
* Encodes a 32 bit number to a byte stream.
*
* @param number the number to encode.
* @param output the byte stream.
* @throws IOException if an error occurs while writting to the stream.
*/
private static void encode32(final long number, final OutputStream output) throws IOException {
for (int i = 3; i >= 0; i--) {
output.write((int) ((number >> (8 * i)) & 0xFF));
}
}
 
/**
* Decodes a 32 bit number from a byte stream.
*
* @param input the byte stream.
* @return the decoded number.
* @throws IOException if an error occurs while reading from the stream.
*/
private static long decode32(final InputStream input) throws IOException {
long number = 0;
for (int i = 0; i < 4; i++) {
number = (number << 8) + input.read();
}
return number;
}
 
/**
* Encodes a 32-bit bitstring to a byte stream.
*
* @param bitstring the bitstring to encode.
* @param output the byte stream.
* @throws IOException if an error occurs while writting to the stream.
*/
private static void encodeBitstring(final byte[] bitstring, final OutputStream output) throws IOException {
final byte[] temp = { 0, 0, 0, 0 };
System.arraycopy(bitstring, 0, temp, 0, bitstring.length);
output.write(temp);
}
 
/**
* Decodes a 32-bit bitstring from a byte stream.
*
* @param input the byte stream.
* @return the decoded string.
* @throws IOException if an error occurs while reading from the stream.
*/
private static byte[] decodeBitstring(final InputStream input) throws IOException {
final byte[] bitstring = new byte[4];
input.read(bitstring, 0, 4);
 
return bitstring;
}
 
/**
* Encodes a 32 bit fixed-point number to a byte stream.
*
* @param number the fixed-point number to encode.
* @param output the byte stream.
* @throws IOException if an error occurs while writting to the stream.
*/
private static void encodeFixedPoint(final double number, final OutputStream output) throws IOException {
encode32((long) (number * 0x10000L), output);
}
 
/**
* Decodes a 32 bit fixed-point number from a byte stream. The binary point is between bits 15
* and 16.
*
* @param input the byte stream.
* @return the decoded fixed-point number.
* @throws IOException if an error occurs while reading from the stream.
*/
private static double decodeFixedPoint(final InputStream input) throws IOException {
return ((double) decode32(input)) / 0x10000L;
}
 
/**
* Encodes a timestamp to a byte stream.
*
* @param timestamp the timestamp to encode.
* @param output the byte stream.
* @throws IOException if an error occurs while writting to the stream.
*/
private static void encodeTimestamp(final Timestamp timestamp, final OutputStream output) throws IOException {
encode32(timestamp.getInteger(), output);
encode32(timestamp.getFraction(), output);
}
 
/**
* Decodes a timestamp from a byte stream.
*
* @param input the byte stream.
* @return the decoded timestamp.
* @throws IOException if an error occurs while reading from the stream.
*/
private static Timestamp decodeTimestamp(final InputStream input) throws IOException {
final long integer = decode32(input);
final long fraction = decode32(input);
return new Timestamp(integer, fraction);
}
}
/trunk/OpenConcerto/src/org/openconcerto/task/element/CompanyAccessSQLElement.java
New file
0,0 → 1,49
/*
* 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.task.element;
 
import org.openconcerto.sql.element.ConfSQLElement;
 
import java.util.ArrayList;
import java.util.List;
 
public class CompanyAccessSQLElement extends ConfSQLElement {
 
public CompanyAccessSQLElement() {
super("ACCES_SOCIETE");
 
}
 
@Override
protected List<String> getListFields() {
final List<String> l = new ArrayList<String>();
l.add("ID_USER_COMMON");
l.add("ID_SOCIETE_COMMON");
return l;
}
 
@Override
protected List<String> getComboFields() {
final List<String> l = new ArrayList<String>();
l.add("ID_USER_COMMON");
l.add("ID_SOCIETE_COMMON");
return l;
}
 
@Override
protected String createCode() {
return "common.company-access";
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/task/element/TaskSQLElementBase.java
15,8 → 15,6
 
import org.openconcerto.sql.element.ConfSQLElement;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.task.TM;
import org.openconcerto.utils.i18n.I18nUtils;
 
/**
* @author Sylvain CUAZ
23,10 → 21,6
*/
public abstract class TaskSQLElementBase extends ConfSQLElement {
 
{
this.setL18nPackageName(I18nUtils.getPackageName(TM.class));
}
 
public TaskSQLElementBase(final String tableName) {
super(tableName);
}
/trunk/OpenConcerto/src/org/openconcerto/task/translation/SQLElementNames_en.xml
1,4 → 1,8
<translations>
<element refid="common.company-access">
<FIELD name="USER_COMMON" label="User" />
<FIELD name="ID_SOCIETE_COMMON" label="Allowed company access" />
</element>
<element refid="TACHE_COMMON" name="task" />
<element refid="TACHE_RIGHTS" name="right for tasks" namePlural="rights for tasks" />
</translations>
/trunk/OpenConcerto/src/org/openconcerto/task/translation/SQLElementNames_es.xml
New file
0,0 → 1,8
<translations>
<element refid="common.company-access">
<FIELD name="USER_COMMON" label="Usario" />
<FIELD name="ID_SOCIETE_COMMON" label="Acceso a la sociedad" />
</element>
<element refid="TACHE_COMMON" name="tarea" />
<element refid="TACHE_RIGHTS" name="derechos para tareas" namePlural="derechos para tareas" />
</translations>
/trunk/OpenConcerto/src/org/openconcerto/task/translation/SQLElementNames_fr.xml
1,4 → 1,8
<translations>
<element refid="common.company-access">
<FIELD name="USER_COMMON" label="Utilisateur" />
<FIELD name="ID_SOCIETE_COMMON" label="Accés à la société" />
</element>
<element refid="TACHE_COMMON" nameClass="feminine" name="tâche" />
<element refid="TACHE_RIGHTS" nameClass="masculine" name="droit pour les tâches" namePlural="droits pour les tâches" />
</translations>
/trunk/OpenConcerto/src/org/openconcerto/task/translation/SQLElementNames_pl.xml
New file
0,0 → 1,8
<translations>
<element refid="common.company-access">
<FIELD name="USER_COMMON" label="User" />
<FIELD name="ID_SOCIETE_COMMON" label="Ustawienia dostępu" />
</element>
<element refid="TACHE_COMMON" name="task" />
<element refid="TACHE_RIGHTS" name="right for tasks" namePlural="rights for tasks" />
</translations>
/trunk/OpenConcerto/src/org/openconcerto/task/translation/messages_es.properties
New file
0,0 → 1,20
summary=Summary :
todoBefore=Para hacer antes de {date, date, medium} en {date, time, short} por {user}
todoBefore.col=Hacer antes
ok=OK
cancel=Cancelar
taskToDo=Descripción de la tarea
assignedTo=Asignado a
created=Created
completed=Completado
deleteForbidden=Solo puedes eliminar tareas que creaste
assignedBy=Asignado por {user}\nEn {date, date, medium} por {date, time, short}
delete=Borrar
deleteSelectedTasks=Borrar {count, plural, =0 {selected tasks} one {the selected task} other {the # selected tasks}}
addTask=Nueva tarea
hideHistory= Ocultar historial
showDetails=Mostrar detalles
details=Detalles
markDone=Marca hecha
moveOneDay=Mover por un día
showTaskAssignedTo=Mostrar tarea asignada a ...
/trunk/OpenConcerto/src/org/openconcerto/task/TodoListModel.java
152,7 → 152,7
for (TodoListElement elt : rowsDeleted) {
int index = this.elements.indexOf(elt);
if (index >= 0) {
removeRow(index);
elements.remove(index);
}
}
 
/trunk/OpenConcerto/src/org/openconcerto/task/config/ComptaBasePropsConfiguration.java
23,10 → 23,12
import org.openconcerto.sql.model.SQLField;
import org.openconcerto.sql.model.SQLFilter;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.users.CompanyAccessSQLElement;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.users.UserCommonSQLElement;
import org.openconcerto.sql.users.rights.RightSQLElement;
import org.openconcerto.sql.users.rights.UserRightSQLElement;
import org.openconcerto.task.TM;
import org.openconcerto.task.element.CompanyAccessSQLElement;
import org.openconcerto.task.element.TaskRightSQLElement;
import org.openconcerto.task.element.TaskSQLElement;
import org.openconcerto.utils.BaseDirs;
33,6 → 35,8
import org.openconcerto.utils.DesktopEnvironment;
import org.openconcerto.utils.LogUtils;
import org.openconcerto.utils.ProductInfo;
import org.openconcerto.utils.i18n.Grammar_fr;
import org.openconcerto.utils.i18n.NounClass;
 
import java.io.File;
import java.io.FileNotFoundException;
39,8 → 43,10
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
 
public abstract class ComptaBasePropsConfiguration extends PropsConfiguration {
125,13 → 131,21
}
 
@Override
protected List<String> getMappings() {
final List<String> res = new ArrayList<>(super.getMappings());
final String pkg = "/" + TM.class.getPackage().getName().replace('.', '/');
res.add(pkg + "/translation/SQLElementNames");
return res;
}
 
@Override
protected SQLElementDirectory createDirectory() {
final SQLElementDirectory dir = super.createDirectory();
 
// TACHE_COMMON points to SOCIETE but we never display it we don't need the full element
dir.addSQLElement(new ConfSQLElement("SOCIETE_COMMON", "une société", "sociétés"));
dir.addSQLElement(new ConfSQLElement("EXERCICE_COMMON", "un exercice", "exercices"));
dir.addSQLElement(new ConfSQLElement("ADRESSE_COMMON", "une adresse", "adresses"));
dir.addSQLElement(new ConfSQLElement("SOCIETE_COMMON", Grammar_fr.getInstance().createPhrase(NounClass.FEMININE, "société")));
dir.addSQLElement(new ConfSQLElement("EXERCICE_COMMON", Grammar_fr.getInstance().createPhrase(NounClass.MASCULINE, "exercice")));
dir.addSQLElement(new ConfSQLElement("ADRESSE_COMMON", Grammar_fr.getInstance().createPhrase(NounClass.FEMININE, "adresse")));
 
dir.addSQLElement(new TaskRightSQLElement());
dir.addSQLElement(new TaskSQLElement());
138,8 → 152,8
 
dir.addSQLElement(new UserCommonSQLElement(getRoot(), false));
dir.addSQLElement(new CompanyAccessSQLElement());
dir.addSQLElement(UserRightSQLElement.class);
dir.addSQLElement(RightSQLElement.class);
dir.addSQLElement(new UserRightSQLElement(getRoot()));
dir.addSQLElement(new RightSQLElement(getRoot()));
 
return dir;
}
164,8 → 178,15
 
protected final void setRowSociete(int id) {
this.idSociete = id;
this.rowSociete = getSystemRoot().findTable("SOCIETE_COMMON").getValidRow(this.getSocieteID());
final SQLTable tableSociete = getSystemRoot().findTable("SOCIETE_COMMON");
final SQLRow row = tableSociete.getRow(id);
if (row == null) {
throw new IllegalArgumentException("no row for id " + id + " in " + tableSociete);
} else if (!row.isValid()) {
throw new IllegalArgumentException("invalid row : " + row);
}
this.rowSociete = row;
}
 
public final SQLBase getSQLBaseSociete() {
return this.getRootSociete().getBase();
/trunk/OpenConcerto/src/org/openconcerto/task/ui/UserRightPanelDetail.java
179,14 → 179,15
private void swapOnDoubleClick(final JList list, MouseEvent e, String field) {
if (e.getClickCount() == 2) {
int index = list.locationToIndex(e.getPoint());
if (index >= 0) {
ListModel dlm = list.getModel();
Object item = dlm.getElementAt(index);
list.ensureIndexIsVisible(index);
User toUser = (User) item;
swapState(selectedUser, toUser, field);
 
}
}
}
 
protected void swapState(User user, User toUser, String field) {
final SQLSelect sel = new SQLSelect();
/trunk/OpenConcerto/src/org/openconcerto/erp/model/MouseSheetXmlListeListener.java
26,6 → 26,7
import org.openconcerto.sql.view.list.RowAction;
import org.openconcerto.ui.EmailComposer;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.ListMap;
 
import java.awt.event.ActionEvent;
import java.io.File;
33,6 → 34,7
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
 
import javax.swing.AbstractAction;
import javax.swing.Action;
111,15 → 113,18
}
 
protected void sendMail(final AbstractSheetXml sheet, final boolean readOnly) {
List<AbstractSheetXml> l = new ArrayList<AbstractSheetXml>(1);
List<AbstractSheetXml> l = new ArrayList<>(1);
l.add(sheet);
sendMail(l, readOnly);
}
 
protected void sendMail(final List<AbstractSheetXml> sheets, final boolean readOnly) {
final Thread t = new Thread() {
@Override
public void run() {
ListMap<String, File> mailFilesMap = new ListMap<>();
for (AbstractSheetXml sheet : sheets) {
String mail = "";
 
for (AbstractSheetXml sheet : sheets) {
final SQLRow row = sheet.getSQLRow();
Set<SQLField> setContact = null;
SQLTable tableContact = Configuration.getInstance().getRoot().findTable("CONTACT");
134,7 → 139,7
mail = row.getForeignRow(field.getName()).getString("EMAIL");
}
}
 
String nomClient = "";
if (setClient != null && (mail == null || mail.trim().length() == 0)) {
for (SQLField field : setClient) {
SQLRow rowCli = row.getForeignRow(field.getName());
141,9 → 146,18
if (mail == null || mail.trim().length() == 0) {
mail = rowCli.getString("MAIL");
}
nomClient = rowCli.getString("NOM");
}
}
 
if (mail.trim().length() == 0) {
mail = nomClient;
}
 
String table = row.getTable().getName();
if (table.equalsIgnoreCase("COMMANDE") || table.equalsIgnoreCase("DEMANDE_PRIX") || table.equalsIgnoreCase("FACTURE_FOURNISSEUR")) {
mail = "";
}
if (mail == null || mail.trim().length() == 0) {
SQLTable tableF = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete().getTable("FOURNISSEUR");
Set<SQLField> setF = null;
195,20 → 209,21
}
}
}
try {
if (readOnly) {
mailFilesMap.add(mail, sheet.getOrCreatePDFDocumentFile(true).getAbsoluteFile());
} else {
mailFilesMap.add(mail, sheet.getOrCreateDocumentFile().getAbsoluteFile());
 
}
final String adresseMail = mail;
} catch (Exception e) {
ExceptionHandler.handle("Impossible de charger le document PDF", e);
}
}
 
final String subject = sheets.get(0).getReference();
for (final String mailDest : mailFilesMap.keySet()) {
 
if (readOnly) {
final Thread t = new Thread() {
@Override
public void run() {
final List<File> files = new ArrayList<File>();
try {
for (AbstractSheetXml sheet : sheets) {
files.add(sheet.getOrCreatePDFDocumentFile(true).getAbsoluteFile());
}
final List<File> files = mailFilesMap.get(mailDest);
 
SwingUtilities.invokeLater(new Runnable() {
 
215,31 → 230,27
@Override
public void run() {
try {
EmailComposer.getInstance().compose(adresseMail, subject + (subject.trim().length() == 0 ? "" : ", ") + files.get(0).getName(),
getMailObject(sheets.get(0).getSQLRow()), files.toArray(new File[files.size()]));
String subject = sheets.get(0).getReference();
if (subject.isEmpty()) {
final StringJoiner joiner = new StringJoiner(", ");
for (File f : files) {
joiner.add(f.getName());
}
subject = joiner.toString();
}
final String message = getMailObject(sheets.get(0).getSQLRow());
EmailComposer.getInstance().compose(mailDest, subject, message, files.toArray(new File[files.size()]));
} catch (Exception e) {
ExceptionHandler.handle("Impossible de charger le document PDF dans l'email!", e);
ExceptionHandler.handle("Impossible d'envoyer le courriel!", e);
}
}
});
} catch (Exception e) {
ExceptionHandler.handle("Impossible de charger le document PDF", e);
}
 
}
 
};
t.start();
} else {
try {
final List<File> files = new ArrayList<File>();
for (AbstractSheetXml sheet : sheets) {
files.add(sheet.getGeneratedFile().getAbsoluteFile());
}
EmailComposer.getInstance().compose(adresseMail, subject + (subject.trim().length() == 0 ? "" : ", ") + sheets.get(0).getGeneratedFile().getName(),
getMailObject(sheets.get(0).getSQLRow()), files.toArray(new File[files.size()]));
} catch (Exception exn) {
ExceptionHandler.handle(null, "Impossible de créer le courriel", exn);
}
}
 
}
 
365,7 → 376,7
 
@Override
public boolean enabledFor(List<SQLRowValues> selection) {
return selection != null && selection.size() > 0;
return selection != null && !selection.isEmpty();
}
 
});
/trunk/OpenConcerto/src/org/openconcerto/erp/model/FichePayeModel.java
72,7 → 72,7
private SQLJavaEditor javaEdit = new SQLJavaEditor(VariablePayeSQLElement.getMapTree());
 
// liste des variable de paye à calculer
private BigDecimal salBrut, salBrutBase, salBrutCotis, salBrutTaxable, cotPat, cotSal, taxCmPat, taxCmSal, netImp, netAPayer, csg, csgSansAbattement, cice, allegmentCotisation, avantage,
private BigDecimal salBrut, salBrutBase, salBrutCotis, salBrutTaxable, cotPat, cotSal, taxCmPat, taxCmSal, netImp, pas, netAPayer, csg, csgSansAbattement, cice, allegmentCotisation, avantage,
reduction;
 
private Map<Integer, String> mapField;
154,14 → 154,22
return csgSansAbattement;
}
 
public BigDecimal getPas() {
return pas;
}
 
public BigDecimal getNetAPayerTotal() {
return netAPayer.add(this.salBrut);
}
 
public BigDecimal getNetImpTotal() {
return netImp.add(this.salBrut);
return netImp.add(this.salBrutTaxable);
}
 
public BigDecimal getNetAvantPas() {
return getNetAPayerTotal().subtract(this.pas);
}
 
public BigDecimal getSalBrut() {
return salBrut;
}
206,6 → 214,7
this.taxCmPat = BigDecimal.ZERO;
this.taxCmSal = BigDecimal.ZERO;
this.netAPayer = BigDecimal.ZERO;
this.pas = BigDecimal.ZERO;
this.netImp = BigDecimal.ZERO;
this.csg = BigDecimal.ZERO;
this.csgSansAbattement = BigDecimal.ZERO;
757,6 → 766,7
rowValsFiche.put("SAL_BRUT_TAXABLE", this.salBrutTaxable);
rowValsFiche.put("NET_IMP", getNetImpTotal());
rowValsFiche.put("NET_A_PAYER", getNetAPayerTotal());
rowValsFiche.put("NET_AVANT_PAS", getNetAvantPas());
rowValsFiche.put("COT_SAL", this.cotSal);
rowValsFiche.put("COT_PAT", this.cotPat);
rowValsFiche.put("TAXE_CM_PAT", this.taxCmPat);
763,6 → 773,8
rowValsFiche.put("TAXE_CM_SAL", this.taxCmSal);
rowValsFiche.put("CSG", getCsgTotal());
rowValsFiche.put("HEURE_TRAV", getHeureTrav());
rowValsFiche.put("TOTAL_PAS", getPas());
 
if (this.cice == null) {
if (salBrut.signum() > 0
&& salBrut.compareTo(new BigDecimal(getSmicHoraire(tableFichePaye.getDBRoot())).multiply(getHeureTrav()).multiply(new BigDecimal(2.5), DecimalUtils.HIGH_PRECISION)) <= 0) {
954,6 → 966,9
if (rowSource.getBoolean("IMPOSABLE")) {
this.netImp = this.netImp.subtract(montant);
}
if (rowSource.getBoolean("PAS")) {
this.pas = this.pas.subtract(montant);
}
 
} // Gain
else {
964,7 → 979,10
if (rowSource.getBoolean("IMPOSABLE")) {
this.netImp = this.netImp.add(montant);
}
if (rowSource.getBoolean("PAS")) {
this.pas = this.pas.add(montant);
}
}
 
// Mis a jour du salaire net
// updateValueFiche();
975,7 → 993,10
if (rowSource.getBoolean("IMPOSABLE")) {
this.netImp = this.netImp.subtract(ded);
}
if (rowSource.getBoolean("PAS")) {
this.pas = this.pas.subtract(ded);
}
}
BigDecimal add = rowVals.getBigDecimal("MONTANT_SAL_AJ");
if (add != null) {
this.netAPayer = this.netAPayer.add(add);
982,10 → 1003,13
if (rowSource.getBoolean("IMPOSABLE")) {
this.netImp = this.netImp.add(add);
}
if (rowSource.getBoolean("IMPOSABLE")) {
this.pas = this.pas.add(add);
}
}
}
}
}
 
private void loadElementNet(SQLRow rowSource, SQLRow row) {
SQLRowValues rowVals = new SQLRowValues(tableFichePayeElt);
1057,7 → 1081,12
 
// CICE
int codeTP = rowSource.getForeignID("ID_CODE_CAISSE_TYPE_RUBRIQUE");
if (codeTP == 298) {
String codeStringTP = "";
if (rowSource.getForeign("ID_CODE_CAISSE_TYPE_RUBRIQUE") != null && !rowSource.isForeignEmpty("ID_CODE_CAISSE_TYPE_RUBRIQUE")) {
codeStringTP = rowSource.getForeign("ID_CODE_CAISSE_TYPE_RUBRIQUE").getString("CODE");
}
 
if (codeTP == 298 || codeStringTP.equals("400")) {
this.cice = rowVals.getBigDecimal("NB_BASE");
}
 
1064,6 → 1093,7
// Mis a jour des cotisations
// updateValueFiche();
}
 
}
 
private void loadElementCotisation(final SQLRow rowSource, SQLRow row) {
1127,6 → 1157,7
return;
}
 
try {
Object baseOb = this.javaEdit.checkFormule(rowSource.getString("NB_BASE"), "BASE");
Object tauxSalOb = this.javaEdit.checkFormule(rowSource.getString("TAUX_SAL"), "SAL");
Object tauxPatOb = this.javaEdit.checkFormule(rowSource.getString("TAUX_PAT"), "PAT");
1144,7 → 1175,6
rowVals.put("MONTANT_SAL_DED", montantDed);
 
boolean b = isEltImprimable(rowSource, rowVals);
// System.err.println("Impression --- > " + b);
rowVals.put("IMPRESSION", Boolean.valueOf(b));
 
if (rowSource.getBoolean("REDUCTION_GVT_COM")) {
1157,7 → 1187,10
}
 
this.vectRubrique.add(rowVals);
} catch (NumberFormatException e) {
JOptionPane.showMessageDialog(null, "Une des formules de la rubrique de commentaire " + rowSource.getString("CODE") + " -- " + rowSource.getString("NOM") + " n'est pas correcte!");
}
}
 
private void calculValue() {
 
1165,9 → 1198,6
 
resetValueFiche();
 
/*
* this.threadUpdate = new Thread("Update Fiche Paye") { public void run() {
*/
Vector<SQLRowValues> vectTmp = new Vector<SQLRowValues>(this.vectRubrique);
 
this.vectRubrique = new Vector<SQLRowValues>();
1180,8 → 1210,6
 
if (source.trim().length() != 0) {
 
// System.err.println("Source != null");
 
if (this.mapTableSource.get(source) != null) {
SQLRow rowSource = this.mapTableSource.get(source).getRow(idSource);
 
1205,9 → 1233,6
System.err.println(this.vectRubrique.size() + " elements ADDed ");
updateValueFiche();
fireTableDataChanged();
/*
* } }; this.threadUpdate.start();
*/
 
System.err.println("End calculValue At " + new Date());
}
/trunk/OpenConcerto/src/org/openconcerto/erp/rights/UserRightGroupComptaSQLElement.java
13,9 → 13,9
package org.openconcerto.erp.rights;
 
import org.openconcerto.sql.element.GlobalMapper;
import org.openconcerto.sql.element.SQLComponent;
import org.openconcerto.sql.element.SQLElement;
import org.openconcerto.sql.model.DBRoot;
import org.openconcerto.sql.users.rights.UserRightSQLComponent;
import org.openconcerto.sql.users.rights.UserRightSQLElement;
 
23,8 → 23,8
 
public class UserRightGroupComptaSQLElement extends UserRightSQLElement {
 
public UserRightGroupComptaSQLElement() {
super();
public UserRightGroupComptaSQLElement(final DBRoot r) {
super(r);
// ((Group)GlobalMapper.getInstance().get(UserRightSQLComponent.ID)).
}
 
/trunk/OpenConcerto/src/org/openconcerto/erp/utils/translation/messages_pl.properties
7,4 → 7,7
apply.associated.pricelist.to.customer=Zastosuj cennik klienta
invoice.address.same.main.address=Adres faktury same jak g\u0142ówny adres
delivery.address.same.main.address=Adres dostawy same jak g\u0142ówny adres
additional.address=Dodatkowy adres
additional.address=Dodatkowy adres
 
createMenuItem.name={elem__singular}
listMenuItem.name=List of {elem__plural}
/trunk/OpenConcerto/src/org/openconcerto/erp/utils/translation/messages_en.properties
12,6 → 12,8
delivery.address.same.main.address=Delivery address same as main address
additional.address=Additional address
 
register.missing.title=Configuration error
register.missing=The register n° {0} doesn\u2019t exist in the database.\n\nPlease create it or modify this host's configuration.
register.moved.title=Different host
register.moved=<html>It seems that this register has been moved.\
You can ignore this message if for instance :\
24,7 → 26,36
register.moved.ignore=Ignore
register.moved.quit=Quit
 
register.notReconciled.title=Incoherence of the opening state of the register
register.notReconciled.outsideMeddling=The files and/or data base were modified outside of this software.
register.notReconciled.resumeFailed=The opening or closure was interrupted, the process was resumed but it failed.
register.notReconciled.unknown=The opening of the register on this host and in the database was incoherent. \
The state couldn\u2019t be reconciled.
# local open
register.notReconciled.open.datesMismatch=The register was opened at different dates on this host ({localDate,date} at {localDate,time}) \
and in the database ({remoteDate,date} at {remoteDate,time}).
register.notReconciled.localOpen_remoteClosed=The register is opened on this host ({localDate,date} at {localDate,time}) \
but closed in the database ({remoteDate,date} at {remoteDate,time}).
register.notReconciled.localOpen_remoteMissing=The register is opened on this host ({localDate,date} at {localDate,time}) \
but was never opened in the database.
# remote open
register.notReconciled.localMissing_remoteReopen=The register was opened multiple times in the database \
(the last time {remoteDate,date} at {remoteDate,time}), but never on this host.
register.notReconciled.localOpenFailed_remoteOpen=The register was open in the database ({remoteDate,date} at {remoteDate,time}) \
and the opening on this host failed.
register.notReconciled.localClosed_remoteCloseFailed=The register was closed on this host ({localDate,date} at {localDate,time}) \
and the closure in the database failed.
register.notReconciled.localClosed_remoteOpen.datesMismatch=The register is closed on this host ({localDate,date} at {localDate,time}) \
but open in the database ({remoteDate,date} at {remoteDate,time}). The opening and closure dates don\u2019t match.
# both closed
register.notReconciled.localMissing_remoteClosed=The register is closed in the database ({remoteDate,date} at {remoteDate,time}) \
but was never used on this host.
register.notReconciled.closed.datesMismatch=The register is closed on this host ({localDate,date} at {localDate,time}) \
and in the database ({remoteDate,date} at {remoteDate,time}), but with different dates.
register.notReconciled.localClosed_remoteMissing=The register is closed on this host ({localDate,date} at {localDate,time}) \
but the database is empty.
 
 
sddMessage.generation.noneNeeded=No invoice needs {msgElem__singularIndefiniteArticle}.
sddMessage.generation.noneIgnored=The generated {msgElem__singular} includes {invoiceElem__definiteNumeral}.
sddMessage.generation.someIgnored={invoiceElemCount, plural, =0 {All invoices needing {msgElem__singularIndefiniteArticle} were ignored :}\
33,3 → 64,47
sddMessage.generation.someIgnored.duplicateMandate={duplicateCount, plural, =1 {one because its mandate was shared with another invoice}\
other {# because their mandates were shared with other invoices}}. You must generate again {msgElem__singularIndefiniteArticle}.
sddMessage.generation.someIgnored.missingInfo={missingInfoCount, plural, =1 {one because some information was missing} other {# because some information was missing}}
 
sales.shipment.allShipments=All shipments
sales.shipment.nonInvoicedShipments=Non invoiced shipments
sales.shipment.invoicedShipments=Invoiced shipments
sales.shipment.listTotal=Total of the shipments in the list
 
dateFilter.none=No filter
dateFilter.currentYear=Current year
dateFilter.previousYear=Previous year
dateFilter.currentMonth=Current month
dateFilter.previousMonth=Previous month
dateFilter.currentWeek=Current week
dateFilter.previousWeek=Previous week
dateFilter.currentFiscalYear=Current fiscal year
dateFilter.custom=Custom
dateFilter.range=Range
dateFilter.from=From
dateFilter.to=To
 
TotalPanel.global=Global
TotalPanel.margin=Margin
TotalPanel.purchaseTotal.taxExcluded=Purchase total excl tax
TotalPanel.service.taxExcluded=Service included excl tax
TotalPanel.total.taxExcluded=Total excl tax
TotalPanel.total.taxIncluded=Total incl tax
TotalPanel.total.VAT=VAT total
TotalPanel.currencyTotal=Currency total
TotalPanel.ecoTax=Dont Eco-Contrib.
TotalPanel.estimatedBudget=Estimated budget
TotalPanel.selection=Selection
 
deliveryForm.applyClientRates=Apply client rates?
deliveryForm.cannotAdd.existingNumber=Cannot add, form number already exists.
deliveryForm.cannotCreate.notInStock=Cannot create the form, the following articles are out of stock :
deliveryForm.numberRefreshed=The number has been refreshed to {0}
deliveryForm.shipAll=Ship all
 
createMenuItem.name={elem__singular}
listMenuItem.name=List of {elem__plural}
 
PanelOOSQLComponent.createSubscription=Create subscription
PanelOOSQLComponent.missingField=Cannot add a combo to choose templates because the field ID_MODELE is missing in the table {0}
PanelOOSQLComponent.print=Print
PanelOOSQLComponent.view=View
/trunk/OpenConcerto/src/org/openconcerto/erp/utils/translation/messages_es.properties
New file
0,0 → 1,78
add=Ajouter
modify.or.delete=Modifier/Supprimer
address=Adresse
address.type.invoice=Facturation
address.type.delivery=Livraison
address.type.external=Mandataire
address.type.other=Autre
product.bom.expand.warning=Attention en éclatant la nomenclature le prix total sera calculé à partir du prix des composants!
product.bom.flatexpand.warning=Attention en applatissant la nomenclature le kit sera remplacé par ses composants!
apply.associated.pricelist.to.customer=Appliquer les tarifs associés au client
invoice.address.same.main.address=Adresse de facturation identique à la principale
delivery.address.same.main.address=Adresse de livraison identique à l\u2019adresse principale
additional.address=Adresses supplémentaires
 
register.moved.title=Hôte différent
register.moved=<html>Il semble que cette caisse ait été déplacée.\
Vous pouvez ignorer ce message si par exemple :\
<ul>\
<li>la session utilisateur a été renommé,</li>\
<li>l\u2019ordinateur a été renommé,</li>\
<li>la caisse a été déplacé vers un nouvel ordinateur.</li>\
</ul><p>Si ce n\u2019est pas le cas, merci de vérifier qu\u2019il n\u2019y ait pas plusieurs installations configurées avec le même numéro de caisse (n° {0}).\
<p>Voulez-vous ignorer message et continuer ou alors quitter l\u2019application ?</html>
register.moved.ignore=Ignorer
register.moved.quit=Quitter
 
sddMessage.generation.noneNeeded=Aucune facture ne nécessite {msgElem__de__singular}.
sddMessage.generation.noneIgnored={msgElem__singularDefiniteArticle} généré inclut {invoiceElem__definiteNumeral}.
sddMessage.generation.someIgnored={invoiceElemCount, plural, =0 {Toutes les factures nécessitant {msgElem__singularIndefiniteArticle} ont été ignorées :}\
other {{msgElem__singularDefiniteArticle} généré inclut {invoiceElem__indefiniteNumeral}, d\u2019autres ont été ignorées :}}
sddMessage.generation.someIgnored.future={futureCount, plural, =1 {une car sa date d\u2019échéance est trop éloignée} other {# car leurs dates d\u2019échéance sont trop éloignées}}
sddMessage.generation.someIgnored.duplicateMandate={duplicateCount, plural, =1 {une car son mandat est partagé avec une autre facture}\
other {# car leurs mandats sont partagés avec d\u2019autres factures}}. Vous devez générer à nouveau {msgElem__singularIndefiniteArticle}.
sddMessage.generation.someIgnored.missingInfo={missingInfoCount, plural, =1 {une car il manquait des informations} other {# car il manquait des informations}}
 
sales.shipment.allShipments=Todas las salidas
sales.shipment.nonInvoicedShipments=Salidas no facturadas
sales.shipment.invoicedShipments=Salidas facturas
sales.shipment.listTotal=Total salidas de la lista
 
dateFilter.none=Sin filtrar
dateFilter.currentYear=Año corriente
dateFilter.previousYear=Año anterior
dateFilter.currentMonth=Mes corriente
dateFilter.previousMonth=Mes anterior
dateFilter.currentWeek=Semana corriente
dateFilter.previousWeek=Semana anterior
dateFilter.currentFiscalYear=Ejercicio corriente
dateFilter.custom=Personalizado
dateFilter.range=Periodo
dateFilter.from=Del
dateFilter.to=Al
 
TotalPanel.global=Global
TotalPanel.margin=Margen
TotalPanel.purchaseTotal.taxExcluded=Total compra bruto
TotalPanel.service.taxExcluded=Service HT inclus
TotalPanel.total.taxExcluded=Total bruto
TotalPanel.total.taxIncluded=Total TTC
TotalPanel.total.VAT=Total TVA
TotalPanel.currencyTotal=Total Devise
TotalPanel.ecoTax=Dont Eco-Contrib.
TotalPanel.estimatedBudget=Budget prévisionnel
TotalPanel.selection=Selección
 
deliveryForm.applyClientRates=Appliquer les tarifs associés au client?
deliveryForm.cannotAdd.existingNumber=Impossible d\u2019ajouter, numéro de bon existant.
deliveryForm.cannotCreate.notInStock=Impossible de créer le BL, Les articles suivants ne sont pas en stock :
deliveryForm.numberRefreshed=Le numéro a été actualisé en {0}
deliveryForm.shipAll=Entregar todo
 
createMenuItem.name={elem__singular}
listMenuItem.name=Lista de {elem__plural}
 
PanelOOSQLComponent.createSubscription=Create subscription
PanelOOSQLComponent.missingField=Cannot add a combo to choose templates because the field ID_MODELE is missing in the table {0}
PanelOOSQLComponent.print=Imprimir
PanelOOSQLComponent.view=Visualizar
/trunk/OpenConcerto/src/org/openconcerto/erp/utils/translation/messages_fr.properties
9,9 → 9,11
product.bom.flatexpand.warning=Attention en applatissant la nomenclature le kit sera remplacé par ses composants!
apply.associated.pricelist.to.customer=Appliquer les tarifs associés au client
invoice.address.same.main.address=Adresse de facturation identique à la principale
delivery.address.same.main.address=Adresse de livraison identique à l'adresse principale
delivery.address.same.main.address=Adresse de livraison identique à l\u2019adresse principale
additional.address=Adresses supplémentaires
 
register.missing.title=Erreur de configuration
register.missing=La caisse n° {0} n\u2019existe pas dans la base de données.\n\nMerci de la créer ou de corriger le paramétrage de ce poste.
register.moved.title=Hôte différent
register.moved=<html>Il semble que cette caisse ait été déplacée.\
Vous pouvez ignorer ce message si par exemple :\
19,16 → 21,94
<li>la session utilisateur a été renommé,</li>\
<li>l\u2019ordinateur a été renommé,</li>\
<li>la caisse a été déplacé vers un nouvel ordinateur.</li>\
</ul><p>Si ce n'est pas le cas, merci de vérifier qu'il n'y ait pas plusieurs installations configurées avec le même numéro de caisse (n° {0}).\
</ul><p>Si ce n\u2019est pas le cas, merci de vérifier qu\u2019il n\u2019y ait pas plusieurs installations configurées avec le même numéro de caisse (n° {0}).\
<p>Voulez-vous ignorer message et continuer ou alors quitter l\u2019application ?</html>
register.moved.ignore=Ignorer
register.moved.quit=Quitter
 
register.notReconciled.title=Incohérence d\u2019ouverture de la caisse
register.notReconciled.outsideMeddling=Les fichiers et/ou la base de données ont été modifiés en dehors de ce logiciel.
register.notReconciled.resumeFailed=L\u2019ouverture ou la clôture avait été interrompue, elle a repris sans succès.
register.notReconciled.unknown=L\u2019ouverture de la caisse sur ce poste et dans la base de donnée était incohérente. \
L\u2019état n\u2019a pas pu être réconcilié.
# local open
register.notReconciled.open.datesMismatch=La caisse est ouverte à des dates différentes sur ce poste (le {localDate,date} à {localDate,time}) \
et dans la base de donnée (le {remoteDate,date} à {remoteDate,time}).
register.notReconciled.localOpen_remoteClosed=La caisse est ouverte sur ce poste (le {localDate,date} à {localDate,time}) \
mais fermée dans la base de donnée (le {remoteDate,date} à {remoteDate,time}).
register.notReconciled.localOpen_remoteMissing=La caisse est ouverte sur ce poste (le {localDate,date} à {localDate,time}) \
mais n\u2019a jamais été ouverte dans la base de donnée.
# remote open
register.notReconciled.localMissing_remoteReopen=La caisse a été ouverte plusieurs fois dans la base de donnée \
(la dernière fois le {remoteDate,date} à {remoteDate,time}), mais jamais sur ce poste.
register.notReconciled.localOpenFailed_remoteOpen=La caisse avait été ouverte dans la base de donnée (le {remoteDate,date} à {remoteDate,time}) \
et l\u2019ouverture sur ce poste a échouée.
register.notReconciled.localClosed_remoteCloseFailed=La caisse avait été fermée sur ce poste (le {localDate,date} à {localDate,time}) \
et la clôture dans la base de donnée a échouée.
register.notReconciled.localClosed_remoteOpen.datesMismatch=La caisse est fermée sur ce poste (le {localDate,date} à {localDate,time}) \
mais ouverte dans la base de donnée (le {remoteDate,date} à {remoteDate,time}). Les dates d\u2019ouverture et de clôture précédentes ne concordent pas.
# both closed
register.notReconciled.localMissing_remoteClosed=La caisse est fermée dans la base de donnée (le {remoteDate,date} à {remoteDate,time}), \
mais n\u2019a jamais été utilisée sur ce poste.
register.notReconciled.closed.datesMismatch=La caisse est fermée sur ce poste (le {localDate,date} à {localDate,time}) \
et dans la base de donnée (le {remoteDate,date} à {remoteDate,time}), mais les dates ne concordent pas.
register.notReconciled.localClosed_remoteMissing=La caisse est fermée sur ce poste (le {localDate,date} à {localDate,time}) \
mais la base de donnée est vide.
 
 
sddMessage.generation.noneNeeded=Aucune facture ne nécessite {msgElem__de__singular}.
sddMessage.generation.noneIgnored={msgElem__singularDefiniteArticle} généré inclut {invoiceElem__definiteNumeral}.
sddMessage.generation.someIgnored={invoiceElemCount, plural, =0 {Toutes les factures nécessitant {msgElem__singularIndefiniteArticle} ont été ignorées :}\
other {{msgElem__singularDefiniteArticle} généré inclut {invoiceElem__indefiniteNumeral}, d'autres ont été ignorées :}}
other {{msgElem__singularDefiniteArticle} généré inclut {invoiceElem__indefiniteNumeral}, d\u2019autres ont été ignorées :}}
sddMessage.generation.someIgnored.future={futureCount, plural, =1 {une car sa date d\u2019échéance est trop éloignée} other {# car leurs dates d\u2019échéance sont trop éloignées}}
sddMessage.generation.someIgnored.duplicateMandate={duplicateCount, plural, =1 {une car son mandat est partagé avec une autre facture}\
other {# car leurs mandats sont partagés avec d\u2019autres factures}}. Vous devez générer à nouveau {msgElem__singularIndefiniteArticle}.
sddMessage.generation.someIgnored.missingInfo={missingInfoCount, plural, =1 {une car il manquait des informations} other {# car il manquait des informations}}
 
sales.shipment.allShipments=Toutes les livraisons
sales.shipment.nonInvoicedShipments=Livraisons non facturées
sales.shipment.invoicedShipments=Livraisons facturées
sales.shipment.listTotal=Total des livraisons de la liste
 
dateFilter.none=Sans filtrage
dateFilter.currentYear=Année courante
dateFilter.previousYear=Année précédente
dateFilter.currentMonth=Mois courant
dateFilter.previousMonth=Mois précédent
dateFilter.currentWeek=Semaine courante
dateFilter.previousWeek=Semaine précédente
dateFilter.currentFiscalYear=Exercice courant
dateFilter.custom=Personnalisée
dateFilter.range=Période
dateFilter.from=Du
dateFilter.to=Au
 
TotalPanel.global=Global
TotalPanel.margin=Marge
TotalPanel.purchaseTotal.taxExcluded=Total achat HT
TotalPanel.service.taxExcluded=Service HT inclus
TotalPanel.total.taxExcluded=Total HT
TotalPanel.total.taxIncluded=Total TTC
TotalPanel.total.VAT=Total TVA
TotalPanel.currencyTotal=Total Devise
TotalPanel.ecoTax=Dont Eco-Contrib.
TotalPanel.estimatedBudget=Budget prévisionnel
TotalPanel.selection=Sélection
 
deliveryForm.applyClientRates=Appliquer les tarifs associés au client?
deliveryForm.cannotAdd.existingNumber=Impossible d\u2019ajouter, numéro de bon existant.
deliveryForm.cannotCreate.notInStock=Impossible de créer le BL, Les articles suivants ne sont pas en stock :
deliveryForm.numberRefreshed=Le numéro a été actualisé en {0}
deliveryForm.shipAll=Tout livrer
 
createMenuItem.name={elem__singular}
listMenuItem.name=Liste {elem__pluralIndefiniteArticle}
 
PanelOOSQLComponent.createSubscription=Créer l\u2019abonnement associé
PanelOOSQLComponent.missingField=Impossible d\u2019ajouter la combo pour le choix des modèles car le champ ID_MODELE n\u2019est pas présent dans la table {0}
PanelOOSQLComponent.print=Imprimer
PanelOOSQLComponent.view=Visualiser
 
 
accounting.editing.piece.label=Nom de la pièce comptable
 
/trunk/OpenConcerto/src/org/openconcerto/erp/utils/ConvertDevise.java
23,20 → 23,15
/**
* Convertit un prix ht en ttc
*
* @param ht
* la valeur hors taxe à convertir
* @param taxe
* taux de la tva à appliquer (ex : 7, 20)
* @param scale
* précision à appliquer sur le ttc retourné
* @param ht la valeur hors taxe à convertir
* @param taxe taux de la tva à appliquer (ex : 7, 20)
* @param scale précision à appliquer sur le ttc retourné
* @return le ttc avec la précision scale
*/
public static final BigDecimal getTtcFromHt(BigDecimal ht, BigDecimal taxe,
int scale) {
public static final BigDecimal getTtcFromHt(BigDecimal ht, BigDecimal taxe, int scale) {
 
BigDecimal tauxB = taxe.movePointLeft(2).add(BigDecimal.ONE);
BigDecimal result = ht.multiply(tauxB, DecimalUtils.HIGH_PRECISION)
.setScale(scale, RoundingMode.HALF_UP);
BigDecimal result = ht.multiply(tauxB, DecimalUtils.HIGH_PRECISION).setScale(scale, RoundingMode.HALF_UP);
return result;
 
}
44,23 → 39,18
/**
* Convertit un prix ttc en ht
*
* @param tts
* la valeur tts à convertir
* @param taxe
* taux de la tva à appliquer (ex : 7, 20)
* @param scale
* précision à appliquer sur le ht retourné
* @param tts la valeur tts à convertir
* @param taxe taux de la tva à appliquer (ex : 7, 20)
* @param scale précision à appliquer sur le ht retourné
* @return le ht avec la précision scale
*/
public static final BigDecimal getHtFromTtc(BigDecimal ttc,
BigDecimal taxe, int scale) {
public static final BigDecimal getHtFromTtc(BigDecimal ttc, BigDecimal taxe, int scale) {
if (taxe.signum() == 0) {
return ttc.setScale(scale, RoundingMode.HALF_UP);
}
 
BigDecimal tauxB = taxe.movePointLeft(2).add(BigDecimal.ONE);
BigDecimal result = ttc.divide(tauxB, DecimalUtils.HIGH_PRECISION).setScale(
scale, RoundingMode.HALF_UP);
BigDecimal result = ttc.divide(tauxB, DecimalUtils.HIGH_PRECISION).setScale(scale, RoundingMode.HALF_UP);
return result;
 
}
67,8 → 57,7
 
public static void main(String[] args) {
 
BigDecimal ttcFromHt = getTtcFromHt(BigDecimal.ONE, new BigDecimal(20),
6);
BigDecimal ttcFromHt = getTtcFromHt(BigDecimal.ONE, new BigDecimal(20), 6);
System.err.println(ttcFromHt);
System.err.println(getHtFromTtc(ttcFromHt, new BigDecimal(20), 6));
 
/trunk/OpenConcerto/src/org/openconcerto/erp/utils/HeadlessGestion.java
32,30 → 32,29
try {
this.comptaPropsConfiguration.getUserManager().setCurrentUserID(userId);
this.comptaPropsConfiguration.setUpSocieteDataBaseConnexion(companyId);
// finish filling the configuration before going any further, otherwise the
// SQLElementDirectory is not coherent
this.comptaPropsConfiguration.getModuleManager().init();
} catch (Exception e) {
e.printStackTrace();
throw new IllegalStateException("Unable to configure connection for userId: " + userId + " companyId: " + companyId);
 
throw new IllegalStateException("Unable to configure connection for userId: " + userId + " companyId: " + companyId, e);
}
return this;
}
 
public HeadlessGestion setupGlobalState(int userId, int companyId) {
setupGlobalState(userId, companyId);
// setUpSocieteDataBaseConnexion() called by setup() needs the directory and elements need
// Configuration.getInstance()
setGlobalState();
setup(userId, companyId);
return this;
}
 
public HeadlessGestion setGlobalState() {
System.setProperty("java.awt.headless", "true");
 
TranslationManager.getInstance().addTranslationStreamFromClass(MainFrame.class);
TranslationManager.getInstance().setLocale(Locale.getDefault());
// TODO remove
Configuration.setInstance(this.comptaPropsConfiguration);
 
System.out.println("HeadlessOpenConcerto ready");
System.out.println(
"Connected to " + this.comptaPropsConfiguration.getServerIp() + " on " + this.comptaPropsConfiguration.getSystemRootName() + "/" + this.comptaPropsConfiguration.getSocieteBaseName());
return this;
}
 
/trunk/OpenConcerto/src/org/openconcerto/erp/graph/GraphArticleMargePanel.java
42,11 → 42,7
sel.addSelect(tableVFElement.getField("QTE"), "SUM");
 
@SuppressWarnings("unchecked")
final List<Object[]> rowsArticle = (List<Object[]>) Configuration
.getInstance()
.getBase()
.getDataSource()
.execute(
final List<Object[]> rowsArticle = (List<Object[]>) Configuration.getInstance().getBase().getDataSource().execute(
sel.asString() + " GROUP BY \"SAISIE_VENTE_FACTURE_ELEMENT\".\"" + field + "\"" + ",\"SAISIE_VENTE_FACTURE_ELEMENT\".\"PA_HT\"" + ",\"SAISIE_VENTE_FACTURE_ELEMENT\".\"PV_HT\"",
new ArrayListHandler());
 
/trunk/OpenConcerto/src/org/openconcerto/erp/importer/DataImporter.java
20,6 → 20,7
import org.openconcerto.sql.model.SQLBase;
import org.openconcerto.sql.model.SQLField;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLRowValuesCluster.StoreMode;
import org.openconcerto.sql.model.SQLRowValuesListFetcher;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.sql.users.UserManager;
116,10 → 117,10
 
public void commit() throws SQLException {
for (SQLRowValues row : this.valuesToInsert) {
row.insert();
row.getGraph().store(StoreMode.INSERT, false);
}
for (SQLRowValues row : this.valuesToUpdate) {
row.update();
row.getGraph().store(StoreMode.COMMIT, false);
}
doAfterImport();
}
/trunk/OpenConcerto/src/org/openconcerto/erp/preferences/GestionCommercialeGlobalPreferencePanel.java
40,6 → 40,7
public static String CREATE_ECR_CHQ = "CreateEcritureCheque";
public static String CHIFFRAGE_COMMANDE_CLIENT = "ChiffrageCmdClient";
public static String IMPUT_ECART = "ImputEcart";
public static String FRAIS_DOCUMENT = "GestionFraisDocuments";
 
public GestionCommercialeGlobalPreferencePanel() {
super("Gestion des pièces commerciales", null);
88,6 → 89,10
ecoColumns.setDefaultValue(Boolean.FALSE);
this.addView(ecoColumns);
 
PrefView<Boolean> fraisDoc = new PrefView<Boolean>(PrefType.BOOLEAN_TYPE, "Gérer des frais sur la création des documents clients", FRAIS_DOCUMENT);
fraisDoc.setDefaultValue(Boolean.FALSE);
this.addView(fraisDoc);
 
PrefView<Boolean> ecoTotal = new PrefView<Boolean>(PrefType.BOOLEAN_TYPE, "Afficher le total de l'éco-contribution", AbstractArticleItemTable.SHOW_TOTAL_ECO_CONTRIBUTION);
ecoTotal.setDefaultValue(Boolean.FALSE);
this.addView(ecoTotal);
/trunk/OpenConcerto/src/org/openconcerto/erp/preferences/SocietePreferencePanel.java
19,13 → 19,21
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.preferences.DefaultPreferencePanel;
import org.openconcerto.utils.checks.ValidListener;
import org.openconcerto.utils.checks.ValidObject;
import org.openconcerto.utils.checks.ValidState;
 
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
 
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
 
public class SocietePreferencePanel extends DefaultPreferencePanel {
 
private SQLComponent sc;
private boolean valid = true;
private String validText = "";
 
public SocietePreferencePanel() {
this.setLayout(new GridBagLayout());
40,7 → 48,15
this.sc.uiInit();
this.sc.select(((ComptaPropsConfiguration) Configuration.getInstance()).getSocieteID());
this.add(this.sc, c);
this.sc.addValidListener(new ValidListener() {
 
@Override
public void validChange(ValidObject src, ValidState newValue) {
valid = newValue.isValid();
validText = newValue.getValidationText();
}
});
}
 
public String getTitleName() {
return "Société";
47,10 → 63,27
}
 
public void storeValues() {
if (valid) {
this.sc.update();
} else {
final String t;
if (this.validText == null) {
t = "valeurs non valides";
} else {
t = this.validText;
}
SwingUtilities.invokeLater(new Runnable() {
 
public void restoreToDefaults() {
@Override
public void run() {
JOptionPane.showMessageDialog(SocietePreferencePanel.this, t);
}
});
 
}
}
 
public void restoreToDefaults() {
// nothing
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/preferences/GestionArticleGlobalPreferencePanel.java
17,6 → 17,7
package org.openconcerto.erp.preferences;
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.core.common.ui.AbstractVenteArticleItemTable;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.preferences.SQLPreferences;
import org.openconcerto.ui.preferences.JavaPrefPreferencePanel;
35,6 → 36,7
public static String SHOW_PRODUCT_BAR_CODE = "ShowProductBarCode";
public static String ITEM_PACKAGING = "ItemPackaging";
public static String FILTER_BY_FAMILY = "FilterByFamily";
public static String STOCK_MULTI_DEPOT = "MultiDepot";
public static String CAN_EXPAND_NOMENCLATURE_VT = "CanExpandNomenclature";
public static String CAN_EXPAND_NOMENCLATURE_HA = "CanExpandNomenclaturePurchase";
 
46,6 → 48,10
@Override
protected void addViews() {
 
PrefView<Boolean> viewShowDevise = new PrefView<Boolean>(PrefType.BOOLEAN_TYPE, "Gérer plusieurs devises", AbstractVenteArticleItemTable.ARTICLE_SHOW_DEVISE);
viewShowDevise.setDefaultValue(Boolean.FALSE);
this.addView(viewShowDevise);
 
PrefView<Boolean> viewExpandNom = new PrefView<Boolean>(PrefType.BOOLEAN_TYPE, "Permettre d'applatir, d'exposer, d'éclater les articles dans les pièces commerciales de vente",
CAN_EXPAND_NOMENCLATURE_VT);
viewExpandNom.setDefaultValue(Boolean.TRUE);
72,6 → 78,10
view.setDefaultValue(Boolean.TRUE);
this.addView(view);
 
PrefView<Boolean> viewMultiStock = new PrefView<Boolean>(PrefType.BOOLEAN_TYPE, "Activer la gestion multidépôt", STOCK_MULTI_DEPOT);
viewMultiStock.setDefaultValue(Boolean.FALSE);
this.addView(viewMultiStock);
 
PrefView<Boolean> view2 = new PrefView<Boolean>(PrefType.BOOLEAN_TYPE, "Gérer différentes unités de vente", UNITE_VENTE);
view2.setDefaultValue(Boolean.TRUE);
this.addView(view2);
/trunk/OpenConcerto/src/org/openconcerto/erp/preferences/TemplatePreferencePanel.java
13,11 → 13,11
package org.openconcerto.erp.preferences;
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.erp.generationDoc.AbstractLocalTemplateProvider;
import org.openconcerto.erp.generationDoc.DefaultLocalTemplateProvider;
import org.openconcerto.erp.generationDoc.TemplateManager;
import org.openconcerto.erp.generationDoc.TemplateProvider;
import org.openconcerto.sql.users.UserManager;
import org.openconcerto.sql.users.rights.UserRightsManager;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.preferences.DefaultPreferencePanel;
48,7 → 48,6
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
57,7 → 56,6
public class TemplatePreferencePanel extends DefaultPreferencePanel {
 
private JTextField textTemplate;
private JFileChooser fileChooser = null;
 
private JButton bModify;
private JButton bUndo;
71,18 → 69,36
/*******************************************************************************************
* Emplacement
******************************************************************************************/
if (!ComptaPropsConfiguration.getInstanceCompta().isOnCloud()) {
this.add(new JLabel("Modèles des documents"), cPanel);
cPanel.gridx++;
cPanel.weightx = 1;
this.textTemplate = new JTextField();
this.add(this.textTemplate, cPanel);
 
this.textTemplate.setEditable(false);
final JButton buttonTemplate = new JButton("...");
cPanel.gridx++;
cPanel.weightx = 0;
cPanel.fill = GridBagConstraints.NONE;
this.add(buttonTemplate, cPanel);
buttonTemplate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fileChooser.setCurrentDirectory(new File(TemplatePreferencePanel.this.textTemplate.getText()));
if (fileChooser.showDialog(TemplatePreferencePanel.this, "Sélectionner") == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
if (selectedFile.exists()) {
TemplatePreferencePanel.this.textTemplate.setForeground(UIManager.getColor("TextField.foreground"));
} else {
TemplatePreferencePanel.this.textTemplate.setForeground(Color.RED);
}
TemplatePreferencePanel.this.textTemplate.setText(selectedFile.getPath());
}
 
}
});
}
final JPanel templates = createTemplateList();
templates.setOpaque(false);
cPanel.gridy++;
93,13 → 109,6
cPanel.gridx = 0;
this.add(templates, cPanel);
 
buttonTemplate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
directoryChoose("template");
}
});
this.textTemplate.setEditable(false);
 
setValues();
}
 
118,7 → 127,11
bUndo.setOpaque(false);
c.gridx++;
p.add(bUndo, c);
if (ComptaPropsConfiguration.getInstanceCompta().isOnCloud()) {
bSync = new JButton("Synchroniser vers le cloud");
} else {
bSync = new JButton("Synchroniser");
}
bSync.setEnabled(false);
bSync.setOpaque(false);
if (!UserRightsManager.getCurrentUserRights().haveRight("SYNC_TEMPLATE")) {
175,10 → 188,18
if (provider instanceof AbstractLocalTemplateProvider) {
final String templateId = dm.getTemplateId(row);
File f = ((AbstractLocalTemplateProvider) provider).getFileTemplate(templateId, null, null);
String path = "invalid path";
if (f != null) {
try {
path = f.getCanonicalPath();
} catch (IOException e) {
path = f.getAbsolutePath();
}
}
if (f == null || !f.exists()) {
tableCellRendererComponent.setBackground(Color.ORANGE);
if (f != null) {
setToolTipText(f.getAbsolutePath() + " not found");
setToolTipText(path + " not found");
} else {
setToolTipText("no file for template " + templateId);
}
188,7 → 209,7
} else {
tableCellRendererComponent.setBackground(table.getBackground());
}
setToolTipText(f.getAbsolutePath());
setToolTipText(path);
}
}
return tableCellRendererComponent;
256,7 → 277,7
}
 
public void storeValues() {
 
if (this.textTemplate != null) {
final File z = new File(".");
final File f = new File(this.textTemplate.getText());
try {
272,6 → 293,7
 
TemplateNXProps.getInstance().store();
}
}
 
public void restoreToDefaults() {
 
282,6 → 304,7
}
 
private void setValues() {
if (this.textTemplate != null) {
try {
final File f = new File(TemplateNXProps.getInstance().getStringProperty("LocationTemplate"));
if (f.exists()) {
295,33 → 318,8
e.printStackTrace();
}
}
 
private void directoryChoose(final String type) {
 
if (this.fileChooser == null) {
this.fileChooser = new JFileChooser();
this.fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
}
this.fileChooser.setCurrentDirectory(new File(TemplatePreferencePanel.this.textTemplate.getText()));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
 
if (TemplatePreferencePanel.this.fileChooser.showDialog(TemplatePreferencePanel.this, "Sélectionner") == JFileChooser.APPROVE_OPTION) {
 
if (type.equalsIgnoreCase("template")) {
File selectedFile = TemplatePreferencePanel.this.fileChooser.getSelectedFile();
if (selectedFile.exists()) {
TemplatePreferencePanel.this.textTemplate.setForeground(UIManager.getColor("TextField.foreground"));
} else {
TemplatePreferencePanel.this.textTemplate.setForeground(Color.RED);
}
TemplatePreferencePanel.this.textTemplate.setText(selectedFile.getPath());
}
}
}
});
}
 
public void modifyTemplate(final TemplateTableModel dm, final JTable table) {
int row = table.getSelectedRow();
dm.unsync(row);
/trunk/OpenConcerto/src/org/openconcerto/erp/preferences/logo_paypal_106x29.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
/trunk/OpenConcerto/src/org/openconcerto/erp/preferences/logo_paypal_106x29.png
New file
Property changes:
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/OpenConcerto/src/org/openconcerto/erp/preferences/PayPalPreferencePanel.java
New file
0,0 → 1,280
/*
* 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.preferences;
 
import org.openconcerto.erp.config.ComptaPropsConfiguration;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.preferences.SQLPreferences;
import org.openconcerto.ui.DefaultGridBagConstraints;
import org.openconcerto.ui.JLabelBold;
import org.openconcerto.ui.preferences.JavaPrefPreferencePanel;
import org.openconcerto.ui.preferences.PrefView;
import org.openconcerto.utils.Base64;
import org.openconcerto.utils.JImage;
import org.openconcerto.utils.PrefType;
 
import java.awt.Desktop;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.StringJoiner;
 
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
 
public class PayPalPreferencePanel extends JavaPrefPreferencePanel {
 
public static final String PAYPAL_INVOICE = "paypal.invoice";
public static final String PAYPAL_CLIENTID = "paypal.clientid";
public static final String PAYPAL_SECRET = "paypal.secret";
public static final String PAYPAL_INVOICE_X = "paypal.invoice.x";
public static final String PAYPAL_INVOICE_Y = "paypal.invoice.y";
 
// Usage :
// SQLPreferences prefs = SQLPreferences.getMemCached(comptaConf.getRootSociete());
// prefs.getBoolean(PayPalPreferencePanel.PAYPAL_INVOICE, false));
 
public PayPalPreferencePanel() {
super("Paypal", null);
 
setPrefs(new SQLPreferences(((ComptaPropsConfiguration) Configuration.getInstance()).getRootSociete()));
this.removeAll();
 
this.setLayout(new GridBagLayout());
GridBagConstraints c = new DefaultGridBagConstraints();
// Logo
c.gridwidth = 3;
c.weightx = 1;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.WEST;
final JImage img = new JImage(PayPalPreferencePanel.class.getResource("logo_paypal_106x29.png"));
try {
img.setHyperLink(new URI("https://www.paypal.fr"));
} catch (URISyntaxException e2) {
// No hyperlink
}
this.add(img, c);
c.gridy++;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 3;
this.add(new JLabel("Intégration du lien de paiement PayPal dans les factures PDF"), c);
c.gridy++;
this.add(new JLabel("Cette fonctionnalité nécessite la création d'un compte professionnel (gratuit)."), c);
// Account creation
final JButton b = new JButton("Créer votre compte maintenant");
b.addActionListener(new ActionListener() {
 
@Override
public void actionPerformed(ActionEvent e) {
if (Desktop.isDesktopSupported()) {
final String url = "https://www.paypal.com/fr/merchantsignup/create";
try {
Desktop.getDesktop().browse(new URI(url));
} catch (IOException | URISyntaxException e1) {
JOptionPane.showMessageDialog(PayPalPreferencePanel.this, url, "Erreur d'ouverture du navigateur", JOptionPane.WARNING_MESSAGE);
}
}
 
}
});
c.gridy++;
c.fill = GridBagConstraints.NONE;
this.add(b, c);
 
c.gridy++;
this.add(new JLabel(" "), c);
c.gridy++;
this.add(new JLabelBold("Paramètres de l'API"), c);
c.gridy++;
this.add(new JLabel("à créer depuis https://developer.paypal.com"), c);
 
// Client ID
c.gridx = 0;
c.gridy++;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 1;
c.weightx = 0;
this.add(new JLabel("Client ID", SwingConstants.RIGHT), c);
c.gridwidth = 2;
c.gridx++;
c.weightx = 1;
PrefView<String> clientIdPrefView = new PrefView<>(PrefType.STRING_TYPE, "Client ID", PAYPAL_CLIENTID);
this.addView(clientIdPrefView);
this.add(clientIdPrefView.getVW().getComp(), c);
 
// Secret
c.gridx = 0;
c.gridy++;
c.fill = GridBagConstraints.HORIZONTAL;
c.gridwidth = 1;
c.weightx = 0;
this.add(new JLabel("Secret", SwingConstants.RIGHT), c);
c.gridwidth = 2;
c.gridx++;
c.weightx = 1;
PrefView<String> secretPrefView = new PrefView<>(PrefType.STRING_TYPE, "Secret", PAYPAL_SECRET);
this.addView(secretPrefView);
this.add(secretPrefView.getVW().getComp(), c);
 
// Enable
c.gridx = 0;
c.gridy++;
c.fill = GridBagConstraints.NONE;
c.gridwidth = 3;
c.weightx = 0;
c.anchor = GridBagConstraints.EAST;
final JButton bVerify = new JButton("Vérifier les paramètres");
this.add(bVerify, c);
// Enable
c.gridx = 1;
c.gridy++;
c.fill = GridBagConstraints.NONE;
c.gridwidth = 1;
c.weightx = 0;
c.anchor = GridBagConstraints.EAST;
PrefView<Boolean> enabledPrefView = new PrefView<>(PrefType.BOOLEAN_TYPE, "intégration", PAYPAL_INVOICE);
this.addView(enabledPrefView);
final JComponent comp = enabledPrefView.getVW().getComp();
((JCheckBox) comp).setText("intégrer le lien de paiement dans les factures PDF");
this.add(comp, c);
 
// Position
c.gridy++;
c.fill = GridBagConstraints.HORIZONTAL;
this.add(new JLabel(" "), c);
c.gridy++;
c.gridx = 0;
c.gridwidth = 3;
this.add(new JLabelBold("Position du logo sur le PDF"), c);
 
c.gridx = 0;
c.gridy++;
c.gridwidth = 1;
c.weightx = 0;
this.add(new JLabel("X (0 - 440)", SwingConstants.RIGHT), c);
c.gridx++;
PrefView<Integer> xPrefView = new PrefView<>(PrefType.INT_TYPE, "X", PAYPAL_INVOICE_X);
xPrefView.setDefaultValue(10);
this.addView(xPrefView);
this.add(xPrefView.getVW().getComp(), c);
 
c.gridx = 0;
c.gridy++;
c.gridwidth = 1;
c.weightx = 0;
this.add(new JLabel("Y (0 - 780)", SwingConstants.RIGHT), c);
c.gridx++;
PrefView<Integer> yPrefView = new PrefView<>(PrefType.INT_TYPE, "Y", PAYPAL_INVOICE_Y);
yPrefView.setDefaultValue(10);
this.addView(yPrefView);
this.add(yPrefView.getVW().getComp(), c);
c.gridy++;
c.weighty = 1;
JPanel spacer = new JPanel();
this.add(spacer, c);
 
bVerify.addActionListener(new ActionListener() {
 
@Override
public void actionPerformed(ActionEvent e) {
boolean ok = false;
try {
ok = sendAuth(clientIdPrefView.getVW().getValue(), secretPrefView.getVW().getValue());
} catch (IOException e1) {
e1.printStackTrace();
}
if (ok) {
JOptionPane.showMessageDialog(PayPalPreferencePanel.this, "Paramètres OK", "API Paypal", JOptionPane.INFORMATION_MESSAGE);
} else {
JOptionPane.showMessageDialog(PayPalPreferencePanel.this, "Paramètres incorrects", "API Paypal", JOptionPane.ERROR_MESSAGE);
}
}
});
 
}
 
@Override
protected void addViews() {
// Nothing to do here, panel is built in the constructor
}
 
public static void main(String[] args) throws IOException {
String id = "Abb2mKqK0TSU6Jgf71CJjFx0u5x6_NmEzHduuvsCXjYCfYxRg9GZ7B6ptx3pijriuq9Apx9Jp-VTFveF";
String s = "ENR1EyKreAlPbLRI0ofm2NbW6nyk8W5cJUZ7mvaBMgoQ6gB6VBivZpQW6B96toCtLZ3ClCUVutN-Gal2";
sendAuth(id, s + "");
}
 
static boolean sendAuth(String clientId, String secret) throws IOException {
final URL url = new URL("https://api.paypal.com/v1/oauth2/token");
final URLConnection con = url.openConnection();
final HttpURLConnection http = (HttpURLConnection) con;
http.setRequestMethod("POST");
http.setDoOutput(true);
http.setDefaultUseCaches(false);
String authString = clientId + ":" + secret;
String authStringEnc = Base64.encodeBytes(authString.getBytes(), Base64.DONT_BREAK_LINES);
con.setRequestProperty("Authorization", "Basic " + authStringEnc);
 
// x-www-form-urlencoded
final Map<String, String> arguments = new HashMap<>();
arguments.put("grant_type", "client_credentials");
final StringJoiner sj = new StringJoiner("&");
for (Map.Entry<String, String> entry : arguments.entrySet()) {
sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "=" + URLEncoder.encode(entry.getValue(), "UTF-8"));
}
byte[] out = sj.toString().getBytes(StandardCharsets.UTF_8);
int length = out.length;
http.setFixedLengthStreamingMode(length);
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
http.connect();
try (OutputStream os = http.getOutputStream()) {
os.write(out);
}
if (http.getResponseCode() == 401) {
return false;
}
 
InputStream is = http.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
 
int numCharsRead;
char[] charArray = new char[1024];
StringBuilder sb = new StringBuilder();
while ((numCharsRead = isr.read(charArray)) > 0) {
sb.append(charArray, 0, numCharsRead);
}
String result = sb.toString();
return result.contains("access_token");
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/erp/config/SQLElementNames_fr.xml
File deleted
/trunk/OpenConcerto/src/org/openconcerto/erp/config/SQLElementNames_pl.xml
File deleted
/trunk/OpenConcerto/src/org/openconcerto/erp/config/SQLElementNames_en.xml
File deleted
/trunk/OpenConcerto/src/org/openconcerto/erp/config/InstallationPanel.java
19,6 → 19,7
import org.openconcerto.erp.core.sales.quote.element.EtatDevisSQLElement;
import org.openconcerto.erp.modules.ModuleManager;
import org.openconcerto.erp.modules.ModuleReference;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.changer.convert.AddFK;
import org.openconcerto.sql.changer.convert.ChangeIDToInt;
import org.openconcerto.sql.changer.correct.CorrectOrder;
138,6 → 139,20
System.setProperty(SQLSchema.NOAUTO_CREATE_METADATA, "false");
final ComptaPropsConfiguration conf = ComptaPropsConfiguration.create(true);
 
final DBSystemRoot systemRoot = conf.getSystemRoot();
if (systemRoot.getChild(conf.getRootNameValue().getValue()) == null) {
conf.destroy();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
up.setEnabled(true);
bar.setValue(bar.getMaximum());
JOptionPane.showMessageDialog(InstallationPanel.this, "Votre base de données n'est pas initialisée");
}
});
return;
}
 
updateDatabase(conf);
 
conf.destroy();
198,7 → 213,6
 
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
try {
if (finderPanel.getServerConfig().createUserIfNeeded(login.getText(), mdp.getText())) {
JOptionPane.showMessageDialog(InstallationPanel.this, "L'utilisateur openconcerto a été correctement ajouté.");
206,7 → 220,6
JOptionPane.showMessageDialog(InstallationPanel.this, "L'utilisateur openconcerto existe déjà dans la base.");
}
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
JOptionPane.showMessageDialog(InstallationPanel.this, "Une erreur est survenue pendant la connexion au serveur, vérifiez vos paramètres de connexion.");
}
882,11 → 895,14
for (final SQLTable t : root.getTables()) {
final AlterTable alter = new AlterTable(t);
for (final SQLField f : t.getFields()) {
if (f.getType().getType() == Types.VARCHAR && f.getType().getSize() == Integer.MAX_VALUE) {
// on PG, CLOB are text and the JDBC driver returns Types.VARCHAR, not CLOB. So test
// if the type name contains "char", since we only want unbounded varchar, not
// text/clob.
if (f.getType().getType() == Types.VARCHAR && f.getType().getSize() == Integer.MAX_VALUE && f.getTypeDecl().contains("char")) {
 
UpdateBuilder build = new UpdateBuilder(t);
build.set(f.getName(), "''");
build.setWhere(new Where(f, "=", (Object) null));
build.setObject(f.getName(), "");
build.setWhere(Where.isNull(f));
builds.add(build);
 
final String fName = f.getName();
1241,7 → 1257,190
checkDepartementExists(root, "Aisne", "Laon", "Picardie", "02");
 
if (root.contains("TARIF_AGENCE")) {
SQLTable tableCmdFA = root.getTable("COMMANDE");
if (!tableCmdFA.contains("INCOTERM")) {
AlterTable t = new AlterTable(tableCmdFA);
t.addVarCharColumn("INCOTERM", 256);
tableCmdFA.getBase().getDataSource().execute(t.asString());
tableCmdFA.getSchema().updateVersion();
tableCmdFA.fetchFields();
}
 
SQLTable tableArticleA = root.getTable("ARTICLE");
if (!tableArticleA.contains("CLOSED_KIT")) {
AlterTable t = new AlterTable(tableArticleA);
t.addBooleanColumn("CLOSED_KIT", Boolean.FALSE, true);
tableArticleA.getBase().getDataSource().execute(t.asString());
tableArticleA.getSchema().updateVersion();
tableArticleA.fetchFields();
}
 
if (!tableArticleA.contains("CLOSED_KIT_DESC")) {
AlterTable t = new AlterTable(tableArticleA);
t.addVarCharColumn("CLOSED_KIT_DESC", 4096);
tableArticleA.getBase().getDataSource().execute(t.asString());
tableArticleA.getSchema().updateVersion();
tableArticleA.fetchFields();
}
 
SQLTable tableCmdFEltA = root.getTable("COMMANDE_ELEMENT");
if (!tableCmdFEltA.contains("INCOTERM")) {
AlterTable t = new AlterTable(tableCmdFEltA);
t.addVarCharColumn("INCOTERM", 256);
tableCmdFEltA.getBase().getDataSource().execute(t.asString());
tableCmdFEltA.getSchema().updateVersion();
tableCmdFEltA.fetchFields();
}
 
if (root.getTable("VILLE") == null) {
 
// INSERT INTO "OpenConcerto49"."VILLE" ("CODE_POSTAL","NOM") SELECT
// "CODE_POSTAL",
// "VILLE" FROM "OpenConcerto49"."ADRESSE" a WHERE a."ARCHIVE"=0
final SQLCreateTable createTableVille = new SQLCreateTable(root, "VILLE");
createTableVille.addVarCharColumn("NOM", 2048);
createTableVille.addVarCharColumn("CODE_POSTAL", 2048);
createTableVille.addLongColumn("X_LAMBERT", 0L, true);
createTableVille.addLongColumn("Y_LAMBERT", 0L, true);
createTableVille.addLongColumn("POPULATION", 0L, true);
try {
root.getBase().getDataSource().execute(createTableVille.asString());
insertUndef(createTableVille);
root.refetchTable("VILLE");
root.getSchema().updateVersion();
} catch (SQLException ex2) {
throw new IllegalStateException("Erreur lors de la création de la table " + "VILLE", ex2);
}
}
 
if (root.getTable("ARTICLE_PRIX_MIN_VENTE") == null) {
final SQLCreateTable createTablePrixMin = new SQLCreateTable(root, "ARTICLE_PRIX_MIN_VENTE");
createTablePrixMin.addForeignColumn("ARTICLE");
createTablePrixMin.addIntegerColumn("QTE", 1);
createTablePrixMin.addDecimalColumn("PRIX", 16, 8, BigDecimal.ZERO, true);
createTablePrixMin.addDateAndTimeColumn("DATE");
try {
root.getBase().getDataSource().execute(createTablePrixMin.asString());
insertUndef(createTablePrixMin);
root.refetchTable("ARTICLE_PRIX_MIN_VENTE");
root.getSchema().updateVersion();
} catch (SQLException ex2) {
throw new IllegalStateException("Erreur lors de la création de la table " + "ARTICLE_PRIX_MIN_VENTE", ex2);
}
}
 
{
final SQLTable tableTarifAgence = root.getTable("TARIF_AGENCE");
AlterTable tTarifAgence = new AlterTable(tableTarifAgence);
boolean updateTarifAgence = false;
 
if (!tableTarifAgence.contains("PRC_AGENCE")) {
updateTarifAgence = true;
tTarifAgence.addDecimalColumn("PRC_AGENCE", 16, 8, BigDecimal.ZERO, true);
}
if (!tableTarifAgence.contains("CLOSED_KIT")) {
updateTarifAgence = true;
tTarifAgence.addBooleanColumn("CLOSED_KIT", false, true);
}
if (!tableTarifAgence.contains("PRIX_MIN_VENTE")) {
updateTarifAgence = true;
tTarifAgence.addDecimalColumn("PRIX_MIN_VENTE", 16, 8, BigDecimal.ZERO, true);
}
 
if (updateTarifAgence) {
tableTarifAgence.getBase().getDataSource().execute(tTarifAgence.asString());
tableTarifAgence.getSchema().updateVersion();
tableTarifAgence.fetchFields();
}
}
{
final SQLTable tableClient = root.getTable("CLIENT");
AlterTable tClient = new AlterTable(tableClient);
boolean updateClient = false;
 
if (!tableClient.contains("ALG_REGISTRE")) {
updateClient = true;
tClient.addVarCharColumn("ALG_REGISTRE", 512);
}
if (!tableClient.contains("ALG_MATRICULE")) {
updateClient = true;
tClient.addVarCharColumn("ALG_MATRICULE", 512);
}
if (!tableClient.contains("ALG_ARTICLE")) {
updateClient = true;
tClient.addVarCharColumn("ALG_ARTICLE", 512);
}
 
if (updateClient) {
tableClient.getBase().getDataSource().execute(tClient.asString());
tableClient.getSchema().updateVersion();
tableClient.fetchFields();
}
}
final SQLTable tableMvtStock = root.getTable("MOUVEMENT_STOCK");
 
if (!tableMvtStock.contains("PRICE")) {
AlterTable tMvt = new AlterTable(tableMvtStock);
tMvt.addDecimalColumn("PRICE", 16, 6, BigDecimal.ZERO, true);
tableMvtStock.getBase().getDataSource().execute(tMvt.asString());
tableMvtStock.getSchema().updateVersion();
tableMvtStock.fetchFields();
}
 
final SQLTable tableArticle = root.getTable("ARTICLE");
 
if (!tableArticle.contains("AUTO_PRIX_MIN_VENTE_NOMENCLATURE")) {
AlterTable tArt = new AlterTable(tableArticle);
tArt.addBooleanColumn("AUTO_PRIX_MIN_VENTE_NOMENCLATURE", false, true);
tableMvtStock.getBase().getDataSource().execute(tArt.asString());
tableMvtStock.getSchema().updateVersion();
tableMvtStock.fetchFields();
}
SQLTable tableContact = root.getTable("CONTACT");
if (!tableContact.contains("TYPE")) {
AlterTable t = new AlterTable(tableContact);
t.addVarCharColumn("TYPE", 256);
t.addVarCharColumn("SERVICE", 256);
t.addVarCharColumn("PAYS", 256);
t.addForeignColumn("ID_ADRESSE", root.getTable("ADRESSE"));
tableContact.getBase().getDataSource().execute(t.asString());
tableContact.getSchema().updateVersion();
tableContact.fetchFields();
}
 
if (!root.contains("PERSONNEL_AFHYMAT")) {
final SQLCreateTable createTablePers = new SQLCreateTable(root, "PERSONNEL_AFHYMAT");
createTablePers.addVarCharColumn("NOM", 256);
createTablePers.addVarCharColumn("PRENOM", 256);
createTablePers.addVarCharColumn("FONCTION", 256);
 
try {
root.getBase().getDataSource().execute(createTablePers.asString());
insertUndef(createTablePers);
root.refetchTable("PERSONNEL_AFHYMAT");
root.getSchema().updateVersion();
} catch (SQLException ex) {
throw new IllegalStateException("Erreur lors de la création de la table " + "PERSONNEL_AFHYMAT", ex);
}
 
final SQLCreateTable createTable = new SQLCreateTable(root, "PERSONNEL_AFHYMAT_COUT");
for (int i = 1; i <= 12; i++) {
createTable.addDecimalColumn("SAL_MONTH_" + i, 16, 2, BigDecimal.ZERO, false);
createTable.addDecimalColumn("COM_MONTH_" + i, 16, 2, BigDecimal.ZERO, false);
}
createTable.addIntegerColumn("ANNEE", 0);
createTable.addForeignColumn("ID_PERSONNEL_AFHYMAT", root.getTable("PERSONNEL_AFHYMAT"));
 
try {
root.getBase().getDataSource().execute(createTable.asString());
insertUndef(createTable);
root.refetchTable("PERSONNEL_AFHYMAT_COUT");
root.getSchema().updateVersion();
} catch (SQLException ex) {
throw new IllegalStateException("Erreur lors de la création de la table " + "PERSONNEL_AFHYMAT_COUT", ex);
}
}
 
List<String> tablesUiLocked = Arrays.asList("BON_DE_LIVRAISON", "COMMANDE_CLIENT", "SAISIE_VENTE_FACTURE", "AVOIR_CLIENT", "COMMANDE", "BON_RECEPTION", "FACTURE_FOURNISSEUR");
for (String tableName : tablesUiLocked) {
final SQLTable table = root.getTable(tableName);
1277,7 → 1476,6
}
 
if (!root.getTable("ARTICLE").contains("TRANSPORT")) {
final SQLTable tableArticle = root.getTable("ARTICLE");
AlterTable alterArticle = new AlterTable(tableArticle);
alterArticle.addBooleanColumn("TRANSPORT", false, false);
tableArticle.getBase().getDataSource().execute(alterArticle.asString());
1307,7 → 1505,6
 
{
if (root.getName().endsWith("54")) {
final SQLTable tableArticle = root.getTable("ARTICLE");
AlterTable tArt = new AlterTable(tableArticle);
if (!tableArticle.contains("LABEL_DOUANE")) {
tArt.addVarCharColumn("LABEL_DOUANE", 512);
2165,6 → 2362,7
root.getDBSystemRoot().getDataSource().execute(createTable.asString());
insertUndef(createTable);
tableDevis.getSchema().updateVersion();
root.refetchTable("DEVISE_HISTORIQUE");
} catch (SQLException ex) {
throw new IllegalStateException("Erreur lors de la création de la table TASK", ex);
}
3360,7 → 3558,7
patchFieldElt1Dot3(table, root);
}
 
private void updateSocieteSchema(final DBRoot root) throws IOException, Exception {
private void updateSocieteSchema(final Configuration conf, final DBRoot root) throws IOException, Exception {
final DBSystemRoot sysRoot = root.getDBSystemRoot();
final SQLDataSource ds = sysRoot.getDataSource();
System.out.println("InstallationPanel.InstallationPanel() UPDATE COMMERCIAL " + root);
3464,7 → 3662,7
final List<ChangeTable<?>> changes = new ArrayList<ChangeTable<?>>();
 
final ModuleManager instance = new ModuleManager();
instance.setRoot(root);
instance.setup(root, conf);
final Collection<ModuleReference> refs = instance.getModulesInstalledRemotely();
final Set<String> allUsedTable = new HashSet<String>();
for (ModuleReference ref : refs) {
3473,6 → 3671,10
}
System.out.println("Tables created by modules:" + allUsedTable);
 
final Set<String> notMigrated = instance.migrateOldTransientDirs();
if (!notMigrated.isEmpty())
System.out.println("Couldn't migrate old backed up/failed modules: " + notMigrated);
 
final List<String> alterRequests = ChangeTable.cat(changes, root.getName());
try {
for (final String req : alterRequests) {
3956,24 → 4158,27
}
 
public void updateDatabase(final ComptaPropsConfiguration conf) {
 
try {
final SQLDataSource ds = conf.getSystemRoot().getDataSource();
System.err.println("SystemRoot:" + conf.getSystemRoot());
System.err.println("Root:" + conf.getRoot());
final DBSystemRoot systemRoot = conf.getSystemRoot();
System.err.println("SystemRoot:" + systemRoot);
final DBRoot rootCommon = conf.getRoot();
System.err.println("Root:" + rootCommon);
 
final SQLDataSource ds = systemRoot.getDataSource();
// FixUnbounded varchar
fixUnboundedVarchar(conf.getRoot());
fixUnboundedVarchar(rootCommon);
 
// FIXME DROP CONSTRAINT UNIQUE ORDRE ON
// CONTACT_FOURNISSEUR
 
checkCompteDefault(conf.getRoot());
checkCompteDefault(rootCommon);
 
updateSocieteTable(conf.getRoot());
updateVille(conf.getRoot().getTable("ADRESSE"));
updateSocieteTable(rootCommon);
updateVille(rootCommon.getTable("ADRESSE"));
 
// Champ user 1.4.1
final SQLTable tableUser = conf.getRoot().getTable("USER_COMMON");
final SQLTable tableUser = rootCommon.getTable("USER_COMMON");
if (tableUser != null) {
final AlterTable alter = new AlterTable(tableUser);
boolean alterUser = false;
3988,32 → 4193,32
 
if (alterUser) {
final String req = alter.asString();
conf.getRoot().getDBSystemRoot().getDataSource().execute(req);
conf.getRoot().refetchTable(tableUser.getName());
conf.getRoot().getSchema().updateVersion();
rootCommon.getDBSystemRoot().getDataSource().execute(req);
rootCommon.refetchTable(tableUser.getName());
rootCommon.getSchema().updateVersion();
}
}
 
// Champ Paye
final SQLTable tableCaisse = conf.getRoot().getTable("CAISSE_COTISATION");
final SQLTable tableCaisse = rootCommon.getTable("CAISSE_COTISATION");
if (!tableCaisse.contains("NUMERO_COMPTE_PCE")) {
final AlterTable alter = new AlterTable(tableCaisse);
alter.addVarCharColumn("NUMERO_COMPTE_PCE", 128);
alter.addVarCharColumn("NUMERO_COMPTE_PCE_CHARGES", 128);
final String req = alter.asString();
conf.getRoot().getDBSystemRoot().getDataSource().execute(req);
conf.getRoot().refetchTable(tableCaisse.getName());
conf.getRoot().getSchema().updateVersion();
rootCommon.getDBSystemRoot().getDataSource().execute(req);
rootCommon.refetchTable(tableCaisse.getName());
rootCommon.getSchema().updateVersion();
}
 
final SQLTable tableRC = conf.getRoot().getTable("RUBRIQUE_COTISATION");
final SQLTable tableRC = rootCommon.getTable("RUBRIQUE_COTISATION");
if (!tableRC.contains("PART_CSG_SANS_ABATTEMENT")) {
final AlterTable alter = new AlterTable(tableRC);
alter.addBooleanColumn("PART_CSG_SANS_ABATTEMENT", Boolean.FALSE, false);
final String req = alter.asString();
conf.getRoot().getDBSystemRoot().getDataSource().execute(req);
conf.getRoot().refetchTable(tableRC.getName());
conf.getRoot().getSchema().updateVersion();
rootCommon.getDBSystemRoot().getDataSource().execute(req);
rootCommon.refetchTable(tableRC.getName());
rootCommon.getSchema().updateVersion();
}
 
// Paye simplifiee
4020,14 → 4225,14
List<SQLRow> rowRubriqueReduGvt = new ArrayList<>();
{
 
final SQLTable tableRCom = conf.getRoot().getTable("RUBRIQUE_COMM");
final SQLTable tableRCom = rootCommon.getTable("RUBRIQUE_COMM");
if (!tableRCom.contains("REDUCTION_GVT_COM")) {
final AlterTable alter = new AlterTable(tableRCom);
alter.addBooleanColumn("REDUCTION_GVT_COM", Boolean.FALSE, false);
final String req = alter.asString();
conf.getRoot().getDBSystemRoot().getDataSource().execute(req);
conf.getRoot().refetchTable(tableRCom.getName());
conf.getRoot().getSchema().updateVersion();
rootCommon.getDBSystemRoot().getDataSource().execute(req);
rootCommon.refetchTable(tableRCom.getName());
rootCommon.getSchema().updateVersion();
 
SQLRowValues rowValsCommChom = new SQLRowValues(tableRCom);
rowValsCommChom.put("TAUX_SAL", "1.45;");
4066,13 → 4271,13
rowRubriqueReduGvt.add(rowValsCommCSG.commit());
 
SQLSelect sel = new SQLSelect();
sel.addSelect(conf.getRoot().getTable("PROFIL_PAYE").getKey());
sel.addSelect(rootCommon.getTable("PROFIL_PAYE").getKey());
List<SQLRow> rowsProfil = SQLRowListRSH.execute(sel);
int pos = 70;
for (SQLRow rowRub : rowRubriqueReduGvt) {
for (SQLRow rowProfil : rowsProfil) {
 
SQLRowValues rowValsRubGvt = new SQLRowValues(conf.getRoot().getTable("PROFIL_PAYE_ELEMENT"));
SQLRowValues rowValsRubGvt = new SQLRowValues(rootCommon.getTable("PROFIL_PAYE_ELEMENT"));
rowValsRubGvt.put("ID_PROFIL_PAYE", rowProfil.getID());
rowValsRubGvt.put("POSITION", pos);
rowValsRubGvt.put("IDSOURCE", rowRub.getID());
4084,14 → 4289,14
}
}
 
final SQLTable tableRB = conf.getRoot().getTable("RUBRIQUE_BRUT");
final SQLTable tableRB = rootCommon.getTable("RUBRIQUE_BRUT");
if (!tableRB.contains("AVANTAGE_NATURE")) {
final AlterTable alter = new AlterTable(tableRB);
alter.addBooleanColumn("AVANTAGE_NATURE", Boolean.FALSE, false);
final String req = alter.asString();
conf.getRoot().getDBSystemRoot().getDataSource().execute(req);
conf.getRoot().refetchTable(tableRB.getName());
conf.getRoot().getSchema().updateVersion();
rootCommon.getDBSystemRoot().getDataSource().execute(req);
rootCommon.refetchTable(tableRB.getName());
rootCommon.getSchema().updateVersion();
}
 
if (!tableRC.contains("LIGNE_PAYE_SIMPLIFIEE")) {
4100,9 → 4305,9
alter.addBooleanColumn("ALLEGEMENT_COTISATION", Boolean.FALSE, false);
alter.addVarCharColumn("LIGNE_PAYE_SIMPLIFIEE", 256);
final String req = alter.asString();
conf.getRoot().getDBSystemRoot().getDataSource().execute(req);
conf.getRoot().refetchTable(tableRC.getName());
conf.getRoot().getSchema().updateVersion();
rootCommon.getDBSystemRoot().getDataSource().execute(req);
rootCommon.refetchTable(tableRC.getName());
rootCommon.getSchema().updateVersion();
Map<String, String> liaison = new HashMap<String, String>();
liaison.put("COTCSA", LignePayeSimplifiee.SANTE_SECURITE.getId());
liaison.put("COTMALADIE", LignePayeSimplifiee.SANTE_SECURITE.getId());
4125,20 → 4330,20
liaison.put("COTCSGDED", LignePayeSimplifiee.CSG_NON_IMP.getId());
liaison.put("COTFILLON", LignePayeSimplifiee.ALLEGEMENT_COTISATIONS.getId());
liaison.put("COTFNGS", LignePayeSimplifiee.ASSURANCE_CHOMAGE_CHOMAGE.getId());
liaison.put("COTCADRET1", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_TA.getId());
liaison.put("COTCADRET2", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_TB.getId());
liaison.put("COTCADRET1", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_T1.getId());
liaison.put("COTCADRET2", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_T2.getId());
 
liaison.put("COT_CADRE_RET_C_A", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_TA.getId());
liaison.put("COT_CADRE_RET_C_B", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_TB.getId());
liaison.put("COT_CADRE_RET_C_C", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_TC.getId());
liaison.put("COT_CADRE_RET_C_A", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_T1.getId());
liaison.put("COT_CADRE_RET_C_B", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_T2.getId());
liaison.put("COT_CADRE_RET_C_C", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_T2.getId());
liaison.put("COTAPEC", LignePayeSimplifiee.ASSURANCE_CHOMAGE_APEC.getId());
liaison.put("COTAPECFORF", LignePayeSimplifiee.ASSURANCE_CHOMAGE_APEC.getId());
liaison.put("COTCET", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_TA.getId());
liaison.put("COTCET", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_T1.getId());
 
liaison.put("COTPREVCADRETA", LignePayeSimplifiee.SANTE_COMPLEMENAIRE_DECES.getId());
liaison.put("COTGMP", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_GMP.getId());
liaison.put("COTGMP", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_GMP_2019_REMOVE.getId());
liaison.put("COTCRDSIMP", LignePayeSimplifiee.CSG_IMP.getId());
liaison.put("COTGMP2", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_GMP.getId());
liaison.put("COTGMP2", LignePayeSimplifiee.RETRAITE_COMPLEMENTAIRE_GMP_2019_REMOVE.getId());
liaison.put("TAXEAPPR", LignePayeSimplifiee.AUTRES_CONTRIBUTIONS.getId());
liaison.put("CDA", LignePayeSimplifiee.AUTRES_CONTRIBUTIONS.getId());
 
4151,9 → 4356,9
liaison.put("COT_PENIBLE", LignePayeSimplifiee.AUTRES_CONTRIBUTIONS.getId());
 
SQLSelect sel = new SQLSelect();
sel.addSelect(conf.getRoot().findTable("RUBRIQUE_COTISATION").getField("CODE"));
sel.addSelect(conf.getRoot().findTable("RUBRIQUE_COTISATION").getField("NOM"));
sel.addSelect(conf.getRoot().findTable("RUBRIQUE_COTISATION").getKey());
sel.addSelect(rootCommon.findTable("RUBRIQUE_COTISATION").getField("CODE"));
sel.addSelect(rootCommon.findTable("RUBRIQUE_COTISATION").getField("NOM"));
sel.addSelect(rootCommon.findTable("RUBRIQUE_COTISATION").getKey());
List<SQLRow> rubCotis = SQLRowListRSH.execute(sel);
 
for (SQLRow sqlRow : rubCotis) {
4168,14 → 4373,15
}
}
 
final SQLTable tableRnet = conf.getRoot().getTable("RUBRIQUE_NET");
final SQLTable tableRnet = rootCommon.getTable("RUBRIQUE_NET");
 
if (!tableRnet.contains("NUMERO_COMPTE_PCE_CHARGES")) {
final AlterTable alter = new AlterTable(tableRnet);
alter.addVarCharColumn("NUMERO_COMPTE_PCE_CHARGES", 128);
final String req = alter.asString();
conf.getRoot().getDBSystemRoot().getDataSource().execute(req);
conf.getRoot().refetchTable(tableRnet.getName());
conf.getRoot().getSchema().updateVersion();
rootCommon.getDBSystemRoot().getDataSource().execute(req);
rootCommon.refetchTable(tableRnet.getName());
rootCommon.getSchema().updateVersion();
}
 
if (!tableRC.contains("PART_PAT_IMPOSABLE")) {
4182,9 → 4388,9
final AlterTable alter = new AlterTable(tableRC);
alter.addBooleanColumn("PART_PAT_IMPOSABLE", Boolean.FALSE, false);
final String req = alter.asString();
conf.getRoot().getDBSystemRoot().getDataSource().execute(req);
conf.getRoot().refetchTable(tableRC.getName());
conf.getRoot().getSchema().updateVersion();
rootCommon.getDBSystemRoot().getDataSource().execute(req);
rootCommon.refetchTable(tableRC.getName());
rootCommon.getSchema().updateVersion();
}
 
if (!tableRC.contains("REDUCTION_FILLON")) {
4191,21 → 4397,21
final AlterTable alter = new AlterTable(tableRC);
alter.addBooleanColumn("REDUCTION_FILLON", Boolean.FALSE, false);
final String req = alter.asString();
conf.getRoot().getDBSystemRoot().getDataSource().execute(req);
conf.getRoot().refetchTable(tableRC.getName());
conf.getRoot().getSchema().updateVersion();
rootCommon.getDBSystemRoot().getDataSource().execute(req);
rootCommon.refetchTable(tableRC.getName());
rootCommon.getSchema().updateVersion();
}
 
// Vérification des droits existants
checkRights(conf.getRoot());
checkRights(rootCommon);
 
if (!conf.getRoot().contains("DEVISE")) {
if (!rootCommon.contains("DEVISE")) {
System.out.println("InstallationPanel.InstallationPanel() ADD DEVISE");
try {
SQLUtils.executeAtomic(ds, new SQLUtils.SQLFactory<Object>() {
@Override
public Object create() throws SQLException {
final SQLCreateTable createDevise = new SQLCreateTable(conf.getRoot(), "DEVISE");
final SQLCreateTable createDevise = new SQLCreateTable(rootCommon, "DEVISE");
createDevise.addVarCharColumn("CODE", 128);
createDevise.addVarCharColumn("NOM", 128);
createDevise.addVarCharColumn("LIBELLE", 128);
4214,7 → 4420,7
createDevise.addDecimalColumn("TAUX_COMMERCIAL", 16, 8, BigDecimal.ONE, false);
ds.execute(createDevise.asString());
insertUndef(createDevise);
conf.getRoot().getSchema().updateVersion();
rootCommon.getSchema().updateVersion();
return null;
}
});
4221,8 → 4427,8
} catch (Exception ex) {
throw new IllegalStateException("Erreur lors de la création de la table DEVISE", ex);
}
} else if (!conf.getRoot().getTable("DEVISE").contains("TAUX_COMMERCIAL")) {
final SQLTable tDevise = conf.getRoot().getTable("DEVISE");
} else if (!rootCommon.getTable("DEVISE").contains("TAUX_COMMERCIAL")) {
final SQLTable tDevise = rootCommon.getTable("DEVISE");
final AlterTable alterDevise = new AlterTable(tDevise);
alterDevise.addDecimalColumn("TAUX_COMMERCIAL", 16, 8, BigDecimal.ONE, false);
ds.execute(alterDevise.asString());
4229,13 → 4435,14
tDevise.getSchema().updateVersion();
}
 
if (!conf.getRoot().contains("TYPE_MODELE")) {
if (!rootCommon.contains("TYPE_MODELE")) {
System.out.println("InstallationPanel.InstallationPanel() ADD TYPE_MODELE");
try {
SQLUtils.executeAtomic(ds, new SQLUtils.SQLFactory<Object>() {
 
@Override
public Object create() throws SQLException {
final SQLCreateTable createTypeModele = new SQLCreateTable(conf.getRoot(), "TYPE_MODELE");
final SQLCreateTable createTypeModele = new SQLCreateTable(rootCommon, "TYPE_MODELE");
createTypeModele.addVarCharColumn("NOM", 128);
createTypeModele.addVarCharColumn("TABLE", 128);
createTypeModele.addVarCharColumn("DEFAULT_MODELE", 128);
4243,9 → 4450,9
 
insertUndef(createTypeModele);
 
conf.getRoot().getSchema().updateVersion();
rootCommon.getSchema().updateVersion();
 
conf.getRoot().refetch();
rootCommon.refetch();
 
return null;
}
4255,7 → 4462,7
// ('FR', 'Français', 1.000), ('EN',
// 'Anglais', 2.000)
final List<String> values = new ArrayList<String>();
final SQLBase base = conf.getRoot().getBase();
final SQLBase base = rootCommon.getBase();
 
for (int i = 0; i < type.length; i += 3) {
final int order = values.size() + 1;
4262,8 → 4469,8
values.add("(" + base.quoteString(type[i]) + ", " + base.quoteString(type[i + 1]) + ", " + base.quoteString(type[i + 2]) + ", " + order + ")");
}
final String valuesStr = CollectionUtils.join(values, ", ");
final String insertVals = "INSERT INTO " + conf.getRoot().getTable("TYPE_MODELE").getSQLName().quote() + "(" + SQLBase.quoteIdentifier("NOM") + ", "
+ SQLBase.quoteIdentifier("TABLE") + ", " + SQLBase.quoteIdentifier("DEFAULT_MODELE") + ", " + SQLBase.quoteIdentifier(SQLSyntax.ORDER_NAME) + ") VALUES" + valuesStr;
final String insertVals = "INSERT INTO " + rootCommon.getTable("TYPE_MODELE").getSQLName().quote() + "(" + SQLBase.quoteIdentifier("NOM") + ", " + SQLBase.quoteIdentifier("TABLE")
+ ", " + SQLBase.quoteIdentifier("DEFAULT_MODELE") + ", " + SQLBase.quoteIdentifier(SQLSyntax.ORDER_NAME) + ") VALUES" + valuesStr;
 
ds.execute(insertVals);
} catch (Exception ex) {
4271,24 → 4478,24
}
}
 
SQLTable.setUndefID(conf.getRoot().getSchema(), "DEVISE", 1);
SQLTable.setUndefID(conf.getRoot().getSchema(), "TYPE_MODELE", 1);
SQLTable.setUndefID(rootCommon.getSchema(), "DEVISE", 1);
SQLTable.setUndefID(rootCommon.getSchema(), "TYPE_MODELE", 1);
 
// DSN
final DSNInstallationUtils dsnUtils = new DSNInstallationUtils();
dsnUtils.updateDSNCommonTable(conf.getRoot());
 
dsnUtils.updateDSNCommonTable(rootCommon);
SQLRow rowRubNetPAS = createPasCommon(rootCommon);
// ECo contribution
final EcoContributionInstallationUtils ecoUtils = new EcoContributionInstallationUtils();
ecoUtils.updateEcoCommonTable(conf.getRoot());
ecoUtils.updateEcoCommonTable(rootCommon);
 
 
// we need to upgrade all roots
// ///////////////////////////
conf.getSystemRoot().mapAllRoots();
conf.getSystemRoot().refetch();
systemRoot.mapAllRoots();
systemRoot.refetch();
 
final Set<String> childrenNames = conf.getSystemRoot().getChildrenNames();
final Set<String> childrenNames = systemRoot.getChildrenNames();
 
SwingUtilities.invokeLater(new Runnable() {
 
4311,9 → 4518,9
}
});
i++;
final DBRoot root = conf.getSystemRoot().getRoot(childName);
final DBRoot root = systemRoot.getRoot(childName);
try {
conf.getSystemRoot().getDataSource().execute("CREATE LANGUAGE plpgsql;");
systemRoot.getDataSource().execute("CREATE LANGUAGE plpgsql;");
} catch (Exception e) {
System.err.println("Warning: cannot add language plpgsql" + e.getMessage());
}
4341,11 → 4548,10
SQLUtils.executeAtomic(ds, new SQLUtils.SQLFactory<Object>() {
@Override
public Object create() throws SQLException {
fixUnboundedVarchar(root);
fixUnboundedNumeric(root);
fixCompletion(root);
try {
updateSocieteSchema(root);
updateSocieteSchema(conf, root);
} catch (Exception e) {
throw new SQLException(e);
}
4363,6 → 4569,7
updateVille(root.getTable("ADRESSE"));
 
Updater_1_5.update(root);
 
SQLTable tableFpaye = root.getTable("FICHE_PAYE");
if (!tableFpaye.contains("REDUCTION_GVT")) {
final AlterTable alterB = new AlterTable(tableFpaye);
4393,7 → 4600,32
pos++;
}
}
if (rowRubNetPAS != null) {
SQLSelect sel = new SQLSelect();
sel.addSelect(root.getTable("SALARIE").getKey());
sel.addSelect(root.getTable("SALARIE").getField("ID_FICHE_PAYE"));
List<SQLRow> rowsSal = SQLRowListRSH.execute(sel);
int pos = 80;
 
for (SQLRow rowSal : rowsSal) {
 
SQLRowValues rowValsRubPas = new SQLRowValues(root.getTable("FICHE_PAYE_ELEMENT"));
rowValsRubPas.put("ID_FICHE_PAYE", rowSal.getForeignID("ID_FICHE_PAYE"));
rowValsRubPas.put("POSITION", pos);
rowValsRubPas.put("IDSOURCE", rowRubNetPAS.getID());
rowValsRubPas.put("SOURCE", rowRubNetPAS.getTable().getName());
rowValsRubPas.put("NOM", rowRubNetPAS.getString("NOM"));
rowValsRubPas.put("IN_PERIODE", Boolean.TRUE);
rowValsRubPas.put("IMPRESSION", Boolean.FALSE);
rowValsRubPas.put("VALIDE", Boolean.FALSE);
rowValsRubPas.commit();
}
 
}
 
// at the end to let Updater_1_5 change field types from varchar to text
fixUnboundedVarchar(root);
 
return null;
}
 
4408,4 → 4640,76
}
}
 
public SQLRow createPasCommon(DBRoot root) throws SQLException {
SQLRow rowRub = null;
 
SQLTable tableRubNet = root.getTable("RUBRIQUE_NET");
SQLTable caisseCot = root.getTable("CAISSE_COTISATION");
if (!tableRubNet.contains("PAS")) {
 
AlterTable alterTableCaisseCot = new AlterTable(caisseCot);
alterTableCaisseCot.addBooleanColumn("DGFIP", Boolean.FALSE, true);
root.getBase().getDataSource().execute(alterTableCaisseCot.asString());
root.refetchTable("CAISSE_COTISATION");
root.getSchema().updateVersion();
 
SQLRowValues rowValsCaisse = new SQLRowValues(caisseCot);
rowValsCaisse.put("ORG_PROTECTION_SOCIALE", Boolean.TRUE);
rowValsCaisse.put("DGFIP", Boolean.TRUE);
rowValsCaisse.put("NOM", "DGFIP");
SQLRow rowCaisseDGFIP = rowValsCaisse.commit();
 
AlterTable alterTableNet = new AlterTable(tableRubNet);
alterTableNet.addBooleanColumn("PAS", Boolean.FALSE, true);
alterTableNet.addBooleanColumn("PAS_CDD", Boolean.FALSE, true);
root.getBase().getDataSource().execute(alterTableNet.asString());
root.refetchTable("RUBRIQUE_NET");
root.getSchema().updateVersion();
 
SQLRowValues rowValsPASCDD = new SQLRowValues(tableRubNet);
rowValsPASCDD.put("ID_CAISSE_COTISATION", rowCaisseDGFIP.getID());
rowValsPASCDD.put("TAUX", "TAUX_PAS;");
rowValsPASCDD.put("BASE", "Math.max(0.0D,(Math.round(NET_IMP*100.0)/100.0)-597);");
rowValsPASCDD.put("NOM", "Prélévement à la source CDD moins de 2 mois ");
rowValsPASCDD.put("CODE", "PAS_NET_CDD");
rowValsPASCDD.put("MONTANT", "Math.round(Math.max(0.0D,((Math.round(NET_IMP*100.0)/100.0)-597)) * TAUX_PAS)/100.0;");
rowValsPASCDD.put("ID_IMPRESSION_RUBRIQUE", 4);
rowValsPASCDD.put("ID_TYPE_RUBRIQUE_NET", 3);
rowValsPASCDD.put("PAS_CDD", Boolean.TRUE);
rowValsPASCDD.putRowValues("ID_PERIODE_VALIDITE").put("JANVIER", Boolean.TRUE);
rowValsPASCDD.commit();
 
SQLRowValues rowValsPAS = new SQLRowValues(tableRubNet);
rowValsPAS.put("ID_CAISSE_COTISATION", rowCaisseDGFIP.getID());
rowValsPAS.put("TAUX", "TAUX_PAS;");
rowValsPAS.put("BASE", "Math.round(NET_IMP*100.0)/100.0;");
rowValsPAS.put("NOM", "Prélévement à la source");
rowValsPAS.put("CODE", "PAS_NET");
rowValsPAS.put("MONTANT", "Math.round((Math.round(NET_IMP*100.0)/100.0) * TAUX_PAS)/100.0;");
rowValsPAS.put("ID_IMPRESSION_RUBRIQUE", 4);
rowValsPAS.put("ID_TYPE_RUBRIQUE_NET", 3);
rowValsPAS.put("PAS", Boolean.TRUE);
rowValsPAS.putRowValues("ID_PERIODE_VALIDITE").put("JANVIER", Boolean.TRUE);
 
rowRub = rowValsPAS.commit();
 
SQLSelect sel = new SQLSelect();
sel.addSelect(root.findTable("PROFIL_PAYE").getKey());
List<SQLRow> rowsProfil = SQLRowListRSH.execute(sel);
int pos = 80;
for (SQLRow rowProfil : rowsProfil) {
 
SQLRowValues rowValsRubGvt = new SQLRowValues(root.findTable("PROFIL_PAYE_ELEMENT"));
rowValsRubGvt.put("ID_PROFIL_PAYE", rowProfil.getID());
rowValsRubGvt.put("POSITION", pos);
rowValsRubGvt.put("IDSOURCE", rowRub.getID());
rowValsRubGvt.put("SOURCE", rowRub.getTable().getName());
rowValsRubGvt.put("NOM", rowRub.getString("NOM"));
rowValsRubGvt.commit();
}
 
}
return rowRub;
}
 
}
/trunk/OpenConcerto/src/org/openconcerto/erp/config/DSNInstallationUtils.java
13,6 → 13,7
package org.openconcerto.erp.config;
 
import org.openconcerto.erp.config.DsnBrutCode.DsnTypeCodeBrut;
import org.openconcerto.sql.model.DBRoot;
import org.openconcerto.sql.model.SQLBase;
import org.openconcerto.sql.model.SQLName;
30,6 → 31,7
import org.openconcerto.sql.utils.ReOrder;
import org.openconcerto.sql.utils.SQLCreateTable;
import org.openconcerto.utils.Tuple2;
import org.openconcerto.utils.Tuple3;
 
import java.sql.SQLException;
import java.util.ArrayList;
626,6 → 628,7
dsnUpdateRubrique.updateRubriqueCotisation();
 
// PHASE 3
final SQLTable caisseCot = root.getTable("CAISSE_COTISATION");
{
SQLTable tableCaisseCotisation = root.findTable("CAISSE_COTISATION");
if (!tableCaisseCotisation.contains("ORG_PROTECTION_SOCIALE")) {
685,7 → 688,7
createCaisseREnseignement.addBooleanColumn("PAIEMENT_TRIMESTRIEL", Boolean.FALSE, false);
createCaisseREnseignement.addVarCharColumn("CODE_DELEGATAIRE", 256);
createCaisseREnseignement.addForeignColumn("ID_CAISSE_MODE_PAIEMENT", root.getTable("CAISSE_MODE_PAIEMENT"));
createCaisseREnseignement.addForeignColumn("ID_CAISSE_COTISATION", root.getTable("CAISSE_COTISATION"));
createCaisseREnseignement.addForeignColumn("ID_CAISSE_COTISATION", caisseCot);
createCaisseREnseignement.addForeignColumn("ID_SOCIETE_COMMON", root.getTable("SOCIETE_COMMON"));
root.getBase().getDataSource().execute(createCaisseREnseignement.asString());
insertUndef(createCaisseREnseignement);
937,7 → 940,7
final String string = sqlRow.getString("CODE");
mapCodeInd.put(string, sqlRow);
}
final SQLTable tableCaisse = root.getTable("CAISSE_COTISATION");
final SQLTable tableCaisse = caisseCot;
SQLSelect selCodeCodeCaisse = new SQLSelect();
selCodeCodeCaisse.addSelectStar(tableCaisse);
List<SQLRow> rowsCodeCaisse = SQLRowListRSH.execute(selCodeCodeCaisse);
991,7 → 994,7
 
if (!tableRubNet.contains("ID_CAISSE_COTISATION")) {
AlterTable alterRubNet = new AlterTable(tableRubNet);
alterRubNet.addForeignColumn("ID_CAISSE_COTISATION", root.getTable("CAISSE_COTISATION"));
alterRubNet.addForeignColumn("ID_CAISSE_COTISATION", caisseCot);
root.getBase().getDataSource().execute(alterRubNet.asString());
root.refetchTable(tableRubNet.getName());
root.getSchema().updateVersion();
1125,8 → 1128,79
}
}
 
if (!root.contains("TYPE_TAUX_PAS")) {
final SQLCreateTable createTableMotif = new SQLCreateTable(root, "TYPE_TAUX_PAS");
createTableMotif.addVarCharColumn("CODE", 25);
createTableMotif.addVarCharColumn("NOM", 512);
 
try {
root.getBase().getDataSource().execute(createTableMotif.asString());
insertUndef(createTableMotif);
root.refetchTable("TYPE_TAUX_PAS");
root.getSchema().updateVersion();
 
final SQLTable table = root.getTable("TYPE_TAUX_PAS");
List<Tuple2<String, String>> v = new ArrayList<Tuple2<String, String>>();
v.add(Tuple2.create("01", " Taux transmis par la DGFIP"));
v.add(Tuple2.create("10", " Barème horaire métropole"));
v.add(Tuple2.create("11", " Barème quotidien métropole"));
v.add(Tuple2.create("12", " Barème hebdomadaire métropole"));
v.add(Tuple2.create("13", " Barème mensuel métropole"));
v.add(Tuple2.create("14", " Barème trimestriel métropole"));
v.add(Tuple2.create("15", " Barème semestriel métropole"));
v.add(Tuple2.create("16", " Barème annuel métropole"));
v.add(Tuple2.create("17", " Barème mathématique sur base mensuelle métropole"));
v.add(Tuple2.create("18", " Barème mathématique sur base annuelle métropole"));
v.add(Tuple2.create("20", " Barème horaire Guadeloupe, Réunion et Martinique"));
v.add(Tuple2.create("21", " Barème quotidien Guadeloupe, Réunion et Martinique"));
v.add(Tuple2.create("22", " Barème hebdomadaire Guadeloupe, Réunion et Martinique"));
v.add(Tuple2.create("23", " Barème mensuel Guadeloupe, Réunion et Martinique"));
v.add(Tuple2.create("24", " Barème trimestriel Guadeloupe, Réunion et Martinique"));
v.add(Tuple2.create("25", " Barème semestriel Guadeloupe, Réunion et Martinique"));
v.add(Tuple2.create("26", " Barème annuel Guadeloupe, Réunion et Martinique"));
v.add(Tuple2.create("27", " Barème mathématique sur base mensuelle Guadeloupe, Réunion et Martinique"));
v.add(Tuple2.create("28", " Barème mathématique sur base annuelle Guadeloupe, Réunion et Martinique"));
v.add(Tuple2.create("30", " Barème horaire Guyane et Mayotte"));
v.add(Tuple2.create("31", " Barème quotidien Guyane et Mayotte"));
v.add(Tuple2.create("32", " Barème hebdomadaire Guyane et Mayotte"));
v.add(Tuple2.create("33", " Barème mensuel Guyane et Mayotte"));
v.add(Tuple2.create("34", " Barème trimestriel Guyane et Mayotte"));
v.add(Tuple2.create("35", " Barème semestriel Guyane et Mayotte"));
v.add(Tuple2.create("36", " Barème annuel Guyane et Mayotte"));
v.add(Tuple2.create("37", " Barème mathématique sur base mensuelle Guyane et Mayotte"));
v.add(Tuple2.create("38", " Barème mathématique sur base annuelle Guyane et Mayotte"));
v.add(Tuple2.create("99", " Indu relatif à un exercice antérieur – pas de taux de PAS"));
 
insertValues(v, table);
} catch (SQLException ex) {
throw new IllegalStateException("Erreur lors de la création de la table " + "TYPE_TAUX_PAS", ex);
}
}
 
// P19V01.2
final SQLTable tableCotInd = root.getTable("CODE_COTISATION_INDIVIDUELLE");
List<Tuple2<String, String>> vCodeIndiv = new ArrayList<>();
vCodeIndiv.add(Tuple2.create("104", "Pénibilité Cotisation de base"));
vCodeIndiv.add(Tuple2.create("105", "Montant de cotisation Régime Unifié Agirc-Arrco y compris Apec"));
vCodeIndiv.add(Tuple2.create("106", "Réduction générale des cotisations patronales Agirc-Arrco"));
insertValues(vCodeIndiv, tableCotInd);
 
final SQLTable tableCTP = root.getTable("CODE_CAISSE_TYPE_RUBRIQUE");
List<Tuple2<String, String>> vCTP = new ArrayList<>();
vCTP.add(Tuple2.create("003", "Réduction cotisations salariale heures supplémentaires"));
vCTP.add(Tuple2.create("510", "Prime exceptionnelle de pouvoir d’achat"));
insertValues(vCTP, tableCTP);
 
final SQLTable tableTypeBrut = root.getTable("CODE_TYPE_RUBRIQUE_BRUT");
List<Tuple3<String, String, String>> vbrutType = new ArrayList<>();
vbrutType.add(Tuple3.create("016", "[FP] Heures affectées à un travail d’aide à domicile", DsnTypeCodeBrut.REMUNERATION.getName()));
vbrutType.add(Tuple3.create("017", "Heures supplémentaires ou complémentaires aléatoires", DsnTypeCodeBrut.REMUNERATION.getName()));
vbrutType.add(Tuple3.create("018", "Heures supplémentaires structurelles", DsnTypeCodeBrut.REMUNERATION.getName()));
DsnBrutCode dsnBurCode = new DsnBrutCode();
dsnBurCode.updateTable(vbrutType, tableTypeBrut);
 
}
 
public void updateDSN(final DBRoot root) throws SQLException {
final SQLTable tableCodeStatutCat = root.getTable("CODE_STATUT_CATEGORIEL");
SQLRow rowNonCadre = tableCodeStatutCat.getRow(4);
/trunk/OpenConcerto/src/org/openconcerto/erp/config/mapping_en.xml
1,11 → 1,6
<?xml version="1.0" encoding="UTF-8" ?>
<ROOT>
<TABLE name="ACCES_SOCIETE">
<FIELD name="USER_COMMON" label="User" />
<FIELD name="ID_SOCIETE_COMMON" label="Allowed company access" />
</TABLE>
 
<TABLE name="ADRESSE_COMMON">
<element refid="common.address" name="address">
<FIELD name="RAISON_SOCIALE" label="Name" />
<FIELD name="RUE" label="Street" />
<FIELD name="PAYS" label="Country" />
15,19 → 10,17
<FIELD name="HAS_CEDEX" label="Cedex" />
<FIELD name="NUMERO_CANTON" label="State number" />
<FIELD name="NUMERO_COMMUNE" label="City number" />
</TABLE>
 
<TABLE name="CAISSE_COTISATION">
<FIELD name="NOM" label="Libellé" titlelabel="Libellé" />
<FIELD name="ID_ADRESSE_COMMON" label="Adresse" titlelabel="Adresse" />
</element>
<element refid="humanresources.payroll.CAISSE_COTISATION" nameClass="feminine" name="caisse">
<FIELD name="NOM" label="Libellé" />
<FIELD name="ID_ADRESSE_COMMON" label="Adresse" />
<FIELD name="TEL" label="Téléphone" titlelabel="Tél." />
<FIELD name="MAIL" label="Courriel" titlelabel="Courriel" />
<FIELD name="MAIL" label="Courriel" />
<FIELD name="TEL_PORTABLE" label="Téléphone portable" titlelabel="Tél. portable" />
<FIELD name="ID_COMPTE_PCE_TIERS" label="Compte tiers" titlelabel="Compte tiers" />
<FIELD name="ID_COMPTE_PCE_CHARGE" label="Compte charges" titlelabel="Compte charges" />
</TABLE>
 
<TABLE name="DEVISE">
<FIELD name="ID_COMPTE_PCE_TIERS" label="Compte tiers" />
<FIELD name="ID_COMPTE_PCE_CHARGE" label="Compte charges" />
</element>
<element refid="sales.price.DEVISE" nameClass="feminine" name="devise">
<FIELD name="CODE" label="Code" />
<FIELD name="NOM" label="Name" />
<FIELD name="LIBELLE" label="Label" />
35,21 → 28,20
<FIELD name="TAUX" label="Rate" />
<FIELD name="TAUX_COMMERCIAL" label="Rate for sales" />
<FIELD name="SYMBOLE" label="Symbol" />
</TABLE>
 
<TABLE name="EXERCICE_COMMON">
</element>
<element refid="finance.accounting.EXERCICE_COMMON" nameClass="masculine" name="exercice">
<FIELD name="NUMERO" label="Name" />
<FIELD name="DATE_DEB" label="Start date" />
<FIELD name="DATE_FIN" label="End date" />
<FIELD name="CLOTURE" label="Closed" />
<FIELD name="DATE_CLOTURE" label="Closed to" />
</TABLE>
 
<TABLE name="IMPRESSION_RUBRIQUE">
</element>
<element refid="humanresources.payroll.print" nameClass="feminine" name="impression de rubrique"
namePlural="impressions de rubrique">
<FIELD name="NOM" label="Label" />
</TABLE>
 
<TABLE name="INDICE">
</element>
<element refid="controle.IndiceSQLElement.INDICE" nameClass="masculine" name="indice d'ingénierie"
namePlural="indices d'ingénierie">
<FIELD name="ANNEE" label="Year" />
<FIELD name="JANVIER" label="January" />
<FIELD name="FEVRIER" label="February" />
63,117 → 55,103
<FIELD name="OCTOBRE" label="October" />
<FIELD name="NOVEMBRE" label="November" />
<FIELD name="DECEMBRE" label="December" />
</TABLE>
 
 
 
<TABLE name="PERIODE_VALIDITE">
<FIELD name="JANVIER" label="Janvier" titlelabel="Janvier" />
<FIELD name="FEVRIER" label="Février" titlelabel="Février" />
<FIELD name="MARS" label="Mars" titlelabel="Mars" />
<FIELD name="AVRIL" label="Avril" titlelabel="Avril" />
<FIELD name="MAI" label="Mai" titlelabel="Mai" />
<FIELD name="JUIN" label="Juin" titlelabel="Juin" />
<FIELD name="JUILLET" label="Juillet" titlelabel="Juillet" />
<FIELD name="AOUT" label="Aout" titlelabel="Aout" />
<FIELD name="SEPTEMBRE" label="Septembre" titlelabel="Septembre" />
<FIELD name="OCTOBRE" label="Octobre" titlelabel="Octobre" />
<FIELD name="NOVEMBRE" label="Novembre" titlelabel="Novembre" />
<FIELD name="DECEMBRE" label="Décembre" titlelabel="Décembre" />
</TABLE>
 
<TABLE name="OBJET">
<FIELD name="CODE" label="Code" titlelabel="Code" />
<FIELD name="NOM" label="Objet" titlelabel="Objet" />
<FIELD name="QUALIFICATION" label="Qualification" titlelabel="Qualification" />
<FIELD name="ID_DOMAINE" label="Domaine" titlelabel="Domaine" />
</TABLE>
 
 
<TABLE name="POINTAGE">
<FIELD name="ACTION" label="Action" titlelabel="Action" />
<FIELD name="ID_USER_COMMON" label="Utilisateur" titlelabel="Utilisateur" />
<FIELD name="CARTE" label="Carte" titlelabel="Carte" />
<FIELD name="DATE" label="Date" titlelabel="Date" />
</TABLE>
 
<TABLE name="POLE_PRODUIT">
<FIELD name="CODE" label="Code" titlelabel="Code" />
<FIELD name="NOM" label="Nom" titlelabel="Nom" />
<FIELD name="TEL" label="Téléphone" titlelabel="Téléphone" />
<FIELD name="FAX" label="Fax" titlelabel="Fax" />
<FIELD name="MAIL" label="E-Mail" titlelabel="E-Mail" />
<FIELD name="NOM_SECRETAIRE" label="Nom secrétaire" titlelabel="Nom secrétaire" />
<FIELD name="NOM_DIRECTEUR" label="Nom directeur" titlelabel="Nom directeur" />
<FIELD name="ID_ADRESSE_COMMON" label="Adresse" titlelabel="Adresse" />
</TABLE>
 
<TABLE name="PROFIL_PAYE">
</element>
<element refid="humanresources.payroll.validity" nameClass="feminine" name="période de validité"
namePlural="périodes de validité">
<FIELD name="JANVIER" label="Janvier" />
<FIELD name="FEVRIER" label="Février" />
<FIELD name="MARS" label="Mars" />
<FIELD name="AVRIL" label="Avril" />
<FIELD name="MAI" label="Mai" />
<FIELD name="JUIN" label="Juin" />
<FIELD name="JUILLET" label="Juillet" />
<FIELD name="AOUT" label="Aout" />
<FIELD name="SEPTEMBRE" label="Septembre" />
<FIELD name="OCTOBRE" label="Octobre" />
<FIELD name="NOVEMBRE" label="Novembre" />
<FIELD name="DECEMBRE" label="Décembre" />
</element>
<element refid="controle.ObjetSQLElement" name="object">
<FIELD name="CODE" label="Code" />
<FIELD name="NOM" label="Objet" />
<FIELD name="QUALIFICATION" label="Qualification" />
<FIELD name="ID_DOMAINE" label="Domaine" />
</element>
<element refid="humanresources.timesheet.PointageSQLElement" nameClass="masculine" name="pointage">
<FIELD name="ACTION" label="Action" />
<FIELD name="ID_USER_COMMON" label="Utilisateur" />
<FIELD name="CARTE" label="Carte" />
<FIELD name="DATE" label="Date" />
</element>
<element refid="humanresources.payroll.template" nameClass="masculine" name="profil de paye"
namePlural="profils de paye">
<FIELD name="NOM" label="Label" />
</TABLE>
<TABLE name="PROFIL_PAYE_ELEMENT">
<FIELD name="NOM" label="Libellé" titlelabel="Libellé" />
<FIELD name="ID_PROFIL_PAYE" label="Profil" titlelabel="Profil" />
<FIELD name="SOURCE" label="Source" titlelabel="Source" />
<FIELD name="IDSOURCE" label="ID Source" titlelabel="ID Source" />
<FIELD name="POSITION" label="Position" titlelabel="Position" />
</TABLE>
 
<TABLE name="RUBRIQUE_NET">
<FIELD name="CODE" label="Code" titlelabel="Code" />
<FIELD name="NOM" label="Libellé" titlelabel="Libellé" />
<FIELD name="BASE" label="Montant de base (BASE)" titlelabel="Montant de base (BASE)" />
<FIELD name="TAUX" label="Taux (TAUX)" titlelabel="Taux (TAUX)" />
<FIELD name="MONTANT" label="Montant (MONTANT)" titlelabel="Montant (MONTANT)" />
<FIELD name="BRUT" label="Brut" titlelabel="Brut" />
<FIELD name="IMPOSABLE" label="Imposable" titlelabel="Imposable" />
<FIELD name="FRAIS_PERS" label="Frais personnel" titlelabel="Frais personnel" />
<FIELD name="ID_PERIODE_VALIDITE" label="Période de validité" titlelabel="Période de validité" />
<FIELD name="ID_TYPE_RUBRIQUE_NET" label="Type" titlelabel="Type" />
<FIELD name="ID_IMPRESSION_RUBRIQUE" label="Impression" titlelabel="Impression" />
</TABLE>
<TABLE name="RUBRIQUE_BRUT">
<FIELD name="CODE" label="Code" titlelabel="Code" />
<FIELD name="NOM" label="Libellé" titlelabel="Libellé" />
<FIELD name="BASE" label="Montant de base (BASE)" titlelabel="Montant de base (BASE)" />
<FIELD name="TAUX" label="Taux (TAUX)" titlelabel="Taux (TAUX)" />
<FIELD name="MONTANT" label="Montant (MONTANT)" titlelabel="Montant (MONTANT)" />
<FIELD name="ID_PERIODE_VALIDITE" label="Période de validité" titlelabel="Période de validité" />
<FIELD name="ID_TYPE_RUBRIQUE_BRUT" label="Type" titlelabel="Type" />
<FIELD name="ID_IMPRESSION_RUBRIQUE" label="Impression" titlelabel="Impression" />
<FIELD name="IMPOSABLE" label="Imposable" titlelabel="Imposable" />
<FIELD name="PART_BRUT" label="Participe à la base brut" titlelabel="Participe à la base brut" />
<FIELD name="PART_CP" label="Participe aux congés payés" titlelabel="Participe aux congés payés" />
</TABLE>
<TABLE name="RUBRIQUE_COMM">
<FIELD name="CODE" label="Code" titlelabel="Code" />
<FIELD name="NOM" label="Libellé" titlelabel="Libellé" />
<FIELD name="NB_BASE" label="Montant de base (BASE)" titlelabel="Montant de base (BASE)" />
<FIELD name="TAUX_SAL" label="Taux Sal.(SAL)" titlelabel="Taux Sal.(SAL)" />
<FIELD name="MONTANT_SAL_AJ" label="Montant sal. à ajouter(MONTANT)" titlelabel="Montant sal. à ajouter(MONTANT)" />
<FIELD name="MONTANT_SAL_DED" label="Montant sal. à déduire(MONTANT)" titlelabel="Montant sal. à déduire(MONTANT)" />
<FIELD name="TAUX_PAT" label="Taux Sal.(PAT)" titlelabel="Taux Sal.(PAT)" />
<FIELD name="MONTANT_PAT" label="Montant pat.(MONTANT)" titlelabel="Montant pat.(MONTANT)" />
<FIELD name="ID_IMPRESSION_RUBRIQUE" label="Impression" titlelabel="Impression" />
<FIELD name="ID_PERIODE_VALIDITE" label="Période de validité" titlelabel="Période de validité" />
<FIELD name="NOM_VISIBLE" label="Afficher le nom de la rubrique" titlelabel="Afficher le nom de la rubrique" />
</TABLE>
 
<TABLE name="RUBRIQUE_COTISATION">
<FIELD name="CODE" label="Code" titlelabel="Code" />
<FIELD name="NOM" label="Libellé" titlelabel="Libellé" />
<FIELD name="ID_CAISSE_COTISATION" label="Caisse de cotisation" titlelabel="Caisse de cotisation" />
<FIELD name="BASE" label="Montant de base (BASE)" titlelabel="Montant de base (BASE)" />
<FIELD name="TX_SAL" label="Taux salarié (SAL) en %" titlelabel="Taux salarié (SAL) en %" />
<FIELD name="TX_PAT" label="Taux patronal (PAT) en %" titlelabel="Taux patronal (PAT) en %" />
<FIELD name="PART_CSG" label="Part CSG CRDS" titlelabel="Part CSG CRDS" />
<FIELD name="BRUT" label="Brut" titlelabel="Brut" />
<FIELD name="IMPOSABLE" label="Imposable" titlelabel="Imposable" />
<FIELD name="ID_IMPRESSION_RUBRIQUE" label="Impression" titlelabel="Impression" />
<FIELD name="ID_PERIODE_VALIDITE" label="Période de validité" titlelabel="Période de validité" />
</TABLE>
 
<TABLE name="SOCIETE_COMMON">
</element>
<element refid="humanresources.payroll.template.item" nameClass="masculine" name="élément d'un profil de paye"
namePlural="éléments de profils de paye">
<FIELD name="NOM" label="Libellé" />
<FIELD name="ID_PROFIL_PAYE" label="Profil" />
<FIELD name="SOURCE" label="Source" />
<FIELD name="IDSOURCE" label="ID Source" />
<FIELD name="POSITION" label="Position" />
</element>
<element refid="humanresources.payroll.category" nameClass="feminine" name="rubrique de net"
namePlural="rubriques de net">
<FIELD name="CODE" label="Code" />
<FIELD name="NOM" label="Libellé" />
<FIELD name="BASE" label="Montant de base (BASE)" />
<FIELD name="TAUX" label="Taux (TAUX)" />
<FIELD name="MONTANT" label="Montant (MONTANT)" />
<FIELD name="BRUT" label="Brut" />
<FIELD name="IMPOSABLE" label="Imposable" />
<FIELD name="FRAIS_PERS" label="Frais personnel" />
<FIELD name="ID_PERIODE_VALIDITE" label="Période de validité" />
<FIELD name="ID_TYPE_RUBRIQUE_NET" label="Type" />
<FIELD name="ID_IMPRESSION_RUBRIQUE" label="Impression" />
</element>
<element refid="humanresources.payroll.category.raw" nameClass="feminine" name="rubrique de brut"
namePlural="rubriques de brut">
<FIELD name="CODE" label="Code" />
<FIELD name="NOM" label="Libellé" />
<FIELD name="BASE" label="Montant de base (BASE)" />
<FIELD name="TAUX" label="Taux (TAUX)" />
<FIELD name="MONTANT" label="Montant (MONTANT)" />
<FIELD name="ID_PERIODE_VALIDITE" label="Période de validité" />
<FIELD name="ID_TYPE_RUBRIQUE_BRUT" label="Type" />
<FIELD name="ID_IMPRESSION_RUBRIQUE" label="Impression" />
<FIELD name="IMPOSABLE" label="Imposable" />
<FIELD name="PART_BRUT" label="Participe à la base brut" />
<FIELD name="PART_CP" label="Participe aux congés payés" />
</element>
<element refid="humanresources.payroll.category.comment" nameClass="feminine" name="rubrique de commentaire"
namePlural="rubriques de commentaire">
<FIELD name="CODE" label="Code" />
<FIELD name="NOM" label="Libellé" />
<FIELD name="NB_BASE" label="Montant de base (BASE)" />
<FIELD name="TAUX_SAL" label="Taux Sal.(SAL)" />
<FIELD name="MONTANT_SAL_AJ" label="Montant sal. à ajouter(MONTANT)" />
<FIELD name="MONTANT_SAL_DED" label="Montant sal. à déduire(MONTANT)" />
<FIELD name="TAUX_PAT" label="Taux Sal.(PAT)" />
<FIELD name="MONTANT_PAT" label="Montant pat.(MONTANT)" />
<FIELD name="ID_IMPRESSION_RUBRIQUE" label="Impression" />
<FIELD name="ID_PERIODE_VALIDITE" label="Période de validité" />
<FIELD name="NOM_VISIBLE" label="Afficher le nom de la rubrique" />
</element>
<element refid="humanresources.payroll.category.subscription" nameClass="feminine"
name="rubrique de cotisation" namePlural="rubriques de cotisation">
<FIELD name="CODE" label="Code" />
<FIELD name="NOM" label="Libellé" />
<FIELD name="ID_CAISSE_COTISATION" label="Caisse de cotisation" />
<FIELD name="BASE" label="Montant de base (BASE)" />
<FIELD name="TX_SAL" label="Taux salarié (SAL) en %" />
<FIELD name="TX_PAT" label="Taux patronal (PAT) en %" />
<FIELD name="PART_CSG" label="Part CSG CRDS" />
<FIELD name="BRUT" label="Brut" />
<FIELD name="IMPOSABLE" label="Imposable" />
<FIELD name="ID_IMPRESSION_RUBRIQUE" label="Impression" />
<FIELD name="ID_PERIODE_VALIDITE" label="Période de validité" />
</element>
<element refid="common.SOCIETE_COMMON" nameClass="feminine" name="société">
<FIELD name="DATABASE_NAME" label="DB Name" />
<FIELD name="NOM" label="Name" />
<FIELD name="ADRESSE" label="Address" />
193,17 → 171,18
<FIELD name="NUMERO_URSSAF" label="URSSAF number" />
<FIELD name="ID_DEVISE" label="Currency" />
<FIELD name="SEPA_CREDITOR_ID" label="SEPA Creditor Identifier" />
</TABLE>
 
<TABLE name="TYPE_MODELE">
</element>
<element refid="document.template-type" nameClass="masculine" name="type de modèle"
namePlural="types de modèles">
<FIELD name="NOM" label="Name" />
<FIELD name="TABLE" label="Table" />
</TABLE>
<TABLE name="VARIABLE_PAYE">
</element>
<element refid="humanresources.payroll.payment.variable" nameClass="feminine" name="variable de paye"
namePlural="variables de paye">
<FIELD name="VALEUR" label="Value" />
<FIELD name="NOM" label="Label" />
<FIELD name="CATEGORIE" label="Category" />
<FIELD name="FORMULE" label="Formula" />
<FIELD name="INFOS" label="Description" />
</TABLE>
</element>
</ROOT>
/trunk/OpenConcerto/src/org/openconcerto/erp/config/mapping-KD_fr.xml
2,10 → 2,10
<ROOT>
 
<TABLE name="AFFAIRE_ELEMENT">
<FIELD name="ACTIVITE" label="Domaine" titlelabel="Domaine" />
<FIELD name="SOUS_ACTIVITE" label="Sous domaine" titlelabel="Sous domaine" />
<FIELD name="POURCENT_REALISE" label="% déjà réalisé" titlelabel="% déjà réalisé" />
<FIELD name="TOTAL_HT_REALISE" label="Total déjà facturé" titlelabel="Total déjà facturé" />
<FIELD name="ACTIVITE" label="Domaine" />
<FIELD name="SOUS_ACTIVITE" label="Sous domaine" />
<FIELD name="POURCENT_REALISE" label="% déjà réalisé" />
<FIELD name="TOTAL_HT_REALISE" label="Total déjà facturé" />
<FIELD name="ID_CODE_MISSION" label="Code Mission" />
<FIELD name="ID_DEPARTEMENT" label="Département" />
<FIELD name="ID_TARIF_MISSION" label="Code Client" />
12,13 → 12,13
</TABLE>
 
<TABLE name="CODE_MISSION">
<FIELD name="ACTIVITE" label="Domaine" titlelabel="Domaine" />
<FIELD name="ACTIVITE" label="Domaine" />
<FIELD name="OBJET_INSPECTE" label="Objet inspecté" />
<FIELD name="DUREE_MISSION" label="Durée prévue" />
<FIELD name="SOUS_TRAITANT" label="Sous traitant" />
<FIELD name="MAQUETTE" label="Maquette" />
<FIELD name="CONDITIONS" label="Conditions d'intervention" />
<FIELD name="SOUS_ACTIVITE" label="Sous domaine" titlelabel="Sous domaine" />
<FIELD name="SOUS_ACTIVITE" label="Sous domaine" />
</TABLE>
 
<TABLE name="AVOIR_CLIENT_ELEMENT">
27,7 → 27,7
<FIELD name="ID_TARIF_MISSION" label="Code Tarif" />
</TABLE>
 
<TABLE name="DEVIS">
<element refid="sales.quote" nameClass="feminine" name="offre de service" namePlural="offres de service">
<FIELD name="ID_VERIFICATEUR" label="Vérificateur" />
<FIELD name="NUMERO" label="Numéro" />
<FIELD name="OBJET" label="Référence cmd client" />
37,7 → 37,7
<FIELD name="ID_USER_COMMON_SAISIE" label="Opératrice de saisie" />
<FIELD name="TEMPS_SAISIE" label="Temps de saisie" />
<FIELD name="DATE_SAISIE_REELLE" label="Date de saisie réelle" />
</TABLE>
</element>
 
<TABLE name="DEVIS_ELEMENT">
<FIELD name="ID_CODE_MISSION" label="Code Mission" />
47,12 → 47,12
 
 
<TABLE name="FICHE_RENDEZ_VOUS">
<FIELD name="ACTIVITE" label="Domaine" titlelabel="Domaine" />
<FIELD name="ACTIVITE" label="Domaine" />
</TABLE>
 
<TABLE name="FICHE_RENDEZ_VOUS_ELEMENT">
<FIELD name="ACTIVITE" label="Domaine" titlelabel="Domaine" />
<FIELD name="SOUS_ACTIVITE" label="Sous Domaine" titlelabel="Sous Domaine" />
<FIELD name="ACTIVITE" label="Domaine" />
<FIELD name="SOUS_ACTIVITE" label="Sous Domaine" />
</TABLE>
 
 
66,8 → 66,8
 
 
<TABLE name="PROPOSITION_ELEMENT">
<FIELD name="ACTIVITE" label="Domaine" titlelabel="Domaine" />
<FIELD name="SOUS_ACTIVITE" label="Sous Domaine" titlelabel="Sous Domaine" />
<FIELD name="ACTIVITE" label="Domaine" />
<FIELD name="SOUS_ACTIVITE" label="Sous Domaine" />
</TABLE>
 
<TABLE name="SAISIE_VENTE_FACTURE_ELEMENT">
75,9 → 75,9
<FIELD name="ID_DEPARTEMENT" label="Département" />
<FIELD name="ID_PERIODICITE" label="Pério. Contractuelle" />
<FIELD name="ID_TARIF_MISSION" label="Code Tarif" />
<FIELD name="ACTIVITE" label="Domaine" titlelabel="Domaine" />
<FIELD name="SOUS_ACTIVITE" label="Sous Domaine" titlelabel="Sous Domaine" />
<FIELD name="REPARTITION_POURCENT" label="Répartition %" titlelabel="Répartition %" />
<FIELD name="ACTIVITE" label="Domaine" />
<FIELD name="SOUS_ACTIVITE" label="Sous Domaine" />
<FIELD name="REPARTITION_POURCENT" label="Répartition %" />
</TABLE>
 
<TABLE name="AVOIR_CLIENT_ELEMENT">
85,13 → 85,13
<FIELD name="ID_DEPARTEMENT" label="Département" />
<FIELD name="ID_PERIODICITE" label="Pério. Contractuelle" />
<FIELD name="ID_TARIF_MISSION" label="Code Tarif" />
<FIELD name="ACTIVITE" label="Domaine" titlelabel="Domaine" />
<FIELD name="SOUS_ACTIVITE" label="Sous Domaine" titlelabel="Sous Domaine" />
<FIELD name="REPARTITION_POURCENT" label="Répartition %" titlelabel="Répartition %" />
<FIELD name="ACTIVITE" label="Domaine" />
<FIELD name="SOUS_ACTIVITE" label="Sous Domaine" />
<FIELD name="REPARTITION_POURCENT" label="Répartition %" />
</TABLE>
 
<TABLE name="SAISIE_VENTE_FACTURE">
<FIELD name="TYPE_INTERVENTION" label="Numéro Intervention" titlelabel="Numéro Intervention" />
<FIELD name="TYPE_INTERVENTION" label="Numéro Intervention" />
</TABLE>
 
<TABLE name="TARIF_MISSION_LIBELLE">
107,7 → 107,7
 
<TABLE name="AVOIR_CLIENT">
 
<FIELD name="NOM" label="Référence" titlelabel="Référence" />
<FIELD name="NOM" label="Référence" />
</TABLE>
 
</ROOT>
/trunk/OpenConcerto/src/org/openconcerto/erp/config/MainFrame.java
14,12 → 14,10
package org.openconcerto.erp.config;
 
import org.openconcerto.erp.action.AboutAction;
import org.openconcerto.erp.action.PreferencesAction;
import org.openconcerto.erp.core.common.ui.StatusPanel;
import org.openconcerto.erp.panel.UserExitConf;
import org.openconcerto.erp.panel.UserExitPanel;
import org.openconcerto.erp.rights.MenuComboRightEditor;
import org.openconcerto.sql.Configuration;
import org.openconcerto.sql.PropsConfiguration;
import org.openconcerto.sql.users.UserManager;
import org.openconcerto.sql.users.rights.UserRightsManager;
137,7 → 135,7
return this.todoPanel;
}
 
public MainFrame() {
public MainFrame(final PropsConfiguration conf) {
super();
 
this.setIconImage(new ImageIcon(MainFrame.class.getResource("frameicon.png")).getImage());
185,7 → 183,6
}
this.setMinimumSize(minSize);
 
final Configuration conf = Configuration.getInstance();
final File confFile = new File(conf.getConfDir(), "Configuration" + File.separator + "Frame" + File.separator + "mainFrame" + confSuffix + ".xml");
new WindowStateManager(this, confFile).loadState();
 
200,7 → 197,7
 
setInstance(this);
 
final Thread dbConn = ((PropsConfiguration) conf).createDBCheckThread(this, new Runnable() {
final Thread dbConn = conf.createDBCheckThread(this, new Runnable() {
@Override
public void run() {
// the user has already clicked "Quit" don't ask him again
403,7 → 400,7
 
// used by OSXAdapter
public final void preferences() {
new PreferencesAction().actionPerformed(null);
MenuManager.getInstance().getActionForId("preferences").actionPerformed(null);
}
 
public final void about() {
/trunk/OpenConcerto/src/org/openconcerto/erp/config/ComptaPropsConfiguration.java
15,7 → 15,6
 
import static java.util.Arrays.asList;
 
import org.openconcerto.erp.core.common.component.SocieteCommonSQLElement;
import org.openconcerto.erp.core.common.element.AdresseCommonSQLElement;
import org.openconcerto.erp.core.common.element.AdresseSQLElement;
import org.openconcerto.erp.core.common.element.BanqueSQLElement;
24,6 → 23,7
import org.openconcerto.erp.core.common.element.MoisSQLElement;
import org.openconcerto.erp.core.common.element.NumerotationAutoSQLElement;
import org.openconcerto.erp.core.common.element.PaysSQLElement;
import org.openconcerto.erp.core.common.element.SocieteCommonSQLElement;
import org.openconcerto.erp.core.common.element.StyleSQLElement;
import org.openconcerto.erp.core.common.element.TitrePersonnelSQLElement;
import org.openconcerto.erp.core.customerrelationship.customer.element.ClientDepartementSQLElement;
42,11 → 42,13
import org.openconcerto.erp.core.finance.accounting.element.AssociationAnalytiqueSQLElement;
import org.openconcerto.erp.core.finance.accounting.element.AssociationCompteAnalytiqueSQLElement;
import org.openconcerto.erp.core.finance.accounting.element.AxeAnalytiqueSQLElement;
import org.openconcerto.erp.core.finance.accounting.element.CategorieComptableSQLElement;
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement;
import org.openconcerto.erp.core.finance.accounting.element.ComptePCGSQLElement;
import org.openconcerto.erp.core.finance.accounting.element.DeviseHistoriqueSQLElement;
import org.openconcerto.erp.core.finance.accounting.element.EcritureSQLElement;
import org.openconcerto.erp.core.finance.accounting.element.ExerciceCommonSQLElement;
import org.openconcerto.erp.core.finance.accounting.element.FraisDocumentSQLElement;
import org.openconcerto.erp.core.finance.accounting.element.JournalSQLElement;
import org.openconcerto.erp.core.finance.accounting.element.MouvementSQLElement;
import org.openconcerto.erp.core.finance.accounting.element.NatureCompteSQLElement;
60,6 → 62,8
import org.openconcerto.erp.core.finance.payment.element.ChequeAEncaisserSQLElement;
import org.openconcerto.erp.core.finance.payment.element.ChequeAvoirClientSQLElement;
import org.openconcerto.erp.core.finance.payment.element.ChequeFournisseurSQLElement;
import org.openconcerto.erp.core.finance.payment.element.DepotChequeElementSQLElement;
import org.openconcerto.erp.core.finance.payment.element.DepotChequeSQLElement;
import org.openconcerto.erp.core.finance.payment.element.EncaisserMontantElementSQLElement;
import org.openconcerto.erp.core.finance.payment.element.EncaisserMontantSQLElement;
import org.openconcerto.erp.core.finance.payment.element.ModeDeReglementSQLElement;
71,10 → 75,10
import org.openconcerto.erp.core.finance.tax.element.EcoTaxeSQLElement;
import org.openconcerto.erp.core.finance.tax.element.TaxeComplementaireSQLElement;
import org.openconcerto.erp.core.finance.tax.element.TaxeSQLElement;
import org.openconcerto.erp.core.humanresources.employe.SituationFamilialeSQLElement;
import org.openconcerto.erp.core.humanresources.employe.element.CommercialSQLElement;
import org.openconcerto.erp.core.humanresources.employe.element.EtatCivilSQLElement;
import org.openconcerto.erp.core.humanresources.employe.element.ObjectifSQLElement;
import org.openconcerto.erp.core.humanresources.employe.element.SituationFamilialeSQLElement;
import org.openconcerto.erp.core.humanresources.payroll.element.AcompteSQLElement;
import org.openconcerto.erp.core.humanresources.payroll.element.AyantDroitContratPrevSQLElement;
import org.openconcerto.erp.core.humanresources.payroll.element.AyantDroitSQLElement;
122,6 → 126,7
import org.openconcerto.erp.core.humanresources.payroll.element.MotifArretTravailSQLElement;
import org.openconcerto.erp.core.humanresources.payroll.element.MotifFinContratSQLElement;
import org.openconcerto.erp.core.humanresources.payroll.element.MotifRepriseArretTravailSQLElement;
import org.openconcerto.erp.core.humanresources.payroll.element.PasSQLElement;
import org.openconcerto.erp.core.humanresources.payroll.element.PeriodeValiditeSQLElement;
import org.openconcerto.erp.core.humanresources.payroll.element.ProfilPayeElementSQLElement;
import org.openconcerto.erp.core.humanresources.payroll.element.ProfilPayeSQLElement;
136,6 → 141,7
import org.openconcerto.erp.core.humanresources.payroll.element.TypePreavisSQLElement;
import org.openconcerto.erp.core.humanresources.payroll.element.TypeRubriqueBrutSQLElement;
import org.openconcerto.erp.core.humanresources.payroll.element.TypeRubriqueNetSQLElement;
import org.openconcerto.erp.core.humanresources.payroll.element.TypeTauxPasSQLElement;
import org.openconcerto.erp.core.humanresources.payroll.element.VariablePayeSQLElement;
import org.openconcerto.erp.core.humanresources.payroll.element.VariableSalarieSQLElement;
import org.openconcerto.erp.core.humanresources.timesheet.element.PointageSQLElement;
160,9 → 166,12
import org.openconcerto.erp.core.sales.pos.io.BarcodeReader;
import org.openconcerto.erp.core.sales.price.element.DeviseSQLElement;
import org.openconcerto.erp.core.sales.price.element.TarifSQLElement;
import org.openconcerto.erp.core.sales.product.element.ArticleCatComptableSQLElement;
import org.openconcerto.erp.core.sales.product.element.ArticleCodeClientSQLElement;
import org.openconcerto.erp.core.sales.product.element.ArticleDesignationSQLElement;
import org.openconcerto.erp.core.sales.product.element.ArticleFournisseurSecondaireSQLElement;
import org.openconcerto.erp.core.sales.product.element.ArticleTarifSQLElement;
import org.openconcerto.erp.core.sales.product.element.CoutRevientSQLElement;
import org.openconcerto.erp.core.sales.product.element.EcoContributionSQLElement;
import org.openconcerto.erp.core.sales.product.element.FamilleArticleSQLElement;
import org.openconcerto.erp.core.sales.product.element.FamilleEcoContributionSQLElement;
173,6 → 182,7
import org.openconcerto.erp.core.sales.product.element.ReferenceArticleSQLElement;
import org.openconcerto.erp.core.sales.product.element.ReliquatSQLElement;
import org.openconcerto.erp.core.sales.product.element.ReliquatSQLElement.ReliquatBRSQLElement;
import org.openconcerto.erp.core.sales.product.element.SupplierPriceListSQLElement;
import org.openconcerto.erp.core.sales.product.element.UniteVenteArticleSQLElement;
import org.openconcerto.erp.core.sales.quote.element.DevisItemSQLElement;
import org.openconcerto.erp.core.sales.quote.element.DevisLogMailSQLElement;
202,6 → 212,9
import org.openconcerto.erp.core.supplychain.receipt.element.BonReceptionSQLElement;
import org.openconcerto.erp.core.supplychain.receipt.element.CodeFournisseurSQLElement;
import org.openconcerto.erp.core.supplychain.receipt.element.TransferReceiptSQLElement;
import org.openconcerto.erp.core.supplychain.stock.element.DepotStockSQLElement;
import org.openconcerto.erp.core.supplychain.stock.element.EtatStockItemSQLElement;
import org.openconcerto.erp.core.supplychain.stock.element.EtatStockSQLElement;
import org.openconcerto.erp.core.supplychain.stock.element.MouvementStockSQLElement;
import org.openconcerto.erp.core.supplychain.stock.element.StockSQLElement;
import org.openconcerto.erp.core.supplychain.supplier.element.EcheanceFournisseurSQLElement;
251,20 → 264,25
import org.openconcerto.erp.injector.BrFactureAchatSQLInjector;
import org.openconcerto.erp.injector.CommandeBlEltSQLInjector;
import org.openconcerto.erp.injector.CommandeBlSQLInjector;
import org.openconcerto.erp.injector.CommandeBrEltSQLInjector;
import org.openconcerto.erp.injector.CommandeBrSQLInjector;
import org.openconcerto.erp.injector.CommandeCliCommandeSQLInjector;
import org.openconcerto.erp.injector.CommandeFactureAchatSQLInjector;
import org.openconcerto.erp.injector.CommandeFactureClientSQLInjector;
import org.openconcerto.erp.injector.DevisBlEltSQLInjector;
import org.openconcerto.erp.injector.DevisBlSQLInjector;
import org.openconcerto.erp.injector.DevisCommandeFournisseurSQLInjector;
import org.openconcerto.erp.injector.DevisCommandeSQLInjector;
import org.openconcerto.erp.injector.DevisEltFactureEltSQLInjector;
import org.openconcerto.erp.injector.DevisFactureSQLInjector;
import org.openconcerto.erp.injector.DmdAchatDmdPrixEltSQLInjector;
import org.openconcerto.erp.injector.DmdPrixCmdSQLInjector;
import org.openconcerto.erp.injector.EcheanceEncaisseSQLInjector;
import org.openconcerto.erp.injector.EcheanceRegleSQLInjector;
import org.openconcerto.erp.injector.FactureAvoirSQLInjector;
import org.openconcerto.erp.injector.FactureBonSQLInjector;
import org.openconcerto.erp.injector.FactureCommandeSQLInjector;
import org.openconcerto.erp.modules.ModuleManager;
import org.openconcerto.erp.preferences.DefaultNXProps;
import org.openconcerto.erp.preferences.GestionClientPreferencePanel;
import org.openconcerto.erp.preferences.GestionCommercialeGlobalPreferencePanel;
332,10 → 350,6
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
 
import eu.medsea.mimeutil.MimeUtil;
import eu.medsea.mimeutil.detector.ExtensionMimeDetector;
import eu.medsea.mimeutil.detector.MagicMimeMimeDetector;
 
/***************************************************************************************************
* Configuration de la gestion: Une base commune "Common" --> société, user, tasks. Une base
* par défaut pour créer une société "Default". Un fichier mapping.xml pour la base commune.
359,8 → 373,6
 
public static final String DATA_DIR_VAR = "${data.dir}";
 
// private Logger rootLogger;
 
protected String version = "";
private static OOConnexion conn;
 
448,6 → 460,7
private boolean isPortable;
private File portableDir = null;
private Currency currency = null;
private final ModuleManager moduleMngr = new ModuleManager();
 
public ComptaPropsConfiguration(Properties props, final ProductInfo productInfo) {
super(props, productInfo);
523,8 → 536,8
} catch (Exception e) {
e.printStackTrace();
String s = ExceptionUtils.getStackTrace(e);
JOptionPane.showMessageDialog(new JFrame(), "Impossible récupérer les informations de connexion\n" + s + "\ntoken: " + token + "\nr: " + result);
ExceptionHandler.handle("Impossible récupérer les informations de connexion", e);
JOptionPane.showMessageDialog(new JFrame(),
"Impossible récupérer les informations de connexion\n" + s + "\ntoken: " + token + "\nr: " + result + "\nMerci de vérifier votre connexion internet.");
System.exit(1);
}
 
564,9 → 577,6
registerAccountingProvider();
registerCellValueProvider();
}
 
MimeUtil.registerMimeDetector(ExtensionMimeDetector.class.getName());
MimeUtil.registerMimeDetector(MagicMimeMimeDetector.class.getName());
}
 
private void registerAccountingProvider() {
675,15 → 685,6
return getProperty("token");
}
 
@Override
public void destroy() {
// since we used setupLogging() in the constructor (allows to remove confDir)
if (this.isMain) {
this.tearDownLogging(true);
}
super.destroy();
}
 
public final boolean isServerless() {
return this.isServerless;
}
789,40 → 790,61
 
}
 
protected File getMappingFile() {
return new File("mapping.xml");
}
 
@Override
protected SQLElementDirectory createDirectory() {
final SQLElementDirectory dir = super.createDirectory();
dir.addSQLElement(new AdresseCommonSQLElement());
dir.addSQLElement(new ExerciceCommonSQLElement());
dir.addSQLElement(DeviseSQLElement.class);
dir.addSQLElement(TypeModeleSQLElement.class);
dir.addSQLElement(new SocieteCommonSQLElement());
final DBRoot root = getRoot();
dir.addSQLElement(new AdresseCommonSQLElement(root));
dir.addSQLElement(new ExerciceCommonSQLElement(root));
dir.addSQLElement(DeviseSQLElement.class, root);
dir.addSQLElement(TypeModeleSQLElement.class, root);
dir.addSQLElement(new SocieteCommonSQLElement(root));
 
// DSN
dir.addSQLElement(CaisseCotisationRenseignentSQLElement.class);
dir.addSQLElement(CodeBaseAssujettieSQLElement.class);
dir.addSQLElement(ContratModaliteTempsSQLElement.class);
dir.addSQLElement(CodeCaisseTypeRubriqueSQLElement.class);
dir.addSQLElement(CodeTypeRubriqueBrutSQLElement.class);
dir.addSQLElement(MotifArretTravailSQLElement.class);
dir.addSQLElement(ContratDispositifPolitiqueSQLElement.class);
dir.addSQLElement(ContratDetacheExpatrieSQLElement.class);
dir.addSQLElement(ContratRegimeMaladieSQLElement.class);
dir.addSQLElement(ContratMotifRecoursSQLElement.class);
dir.addSQLElement(ContratRegimeVieillesseSQLElement.class);
dir.addSQLElement(MotifFinContratSQLElement.class);
dir.addSQLElement(MotifRepriseArretTravailSQLElement.class);
dir.addSQLElement(TypePreavisSQLElement.class);
dir.addSQLElement(DSNNatureSQLElement.class);
dir.addSQLElement(CaisseCotisationRenseignentSQLElement.class, root);
dir.addSQLElement(CodeBaseAssujettieSQLElement.class, root);
dir.addSQLElement(ContratModaliteTempsSQLElement.class, root);
dir.addSQLElement(CodeCaisseTypeRubriqueSQLElement.class, root);
dir.addSQLElement(CodeTypeRubriqueBrutSQLElement.class, root);
dir.addSQLElement(MotifArretTravailSQLElement.class, root);
dir.addSQLElement(ContratDispositifPolitiqueSQLElement.class, root);
dir.addSQLElement(ContratDetacheExpatrieSQLElement.class, root);
dir.addSQLElement(ContratRegimeMaladieSQLElement.class, root);
dir.addSQLElement(ContratMotifRecoursSQLElement.class, root);
dir.addSQLElement(ContratRegimeVieillesseSQLElement.class, root);
dir.addSQLElement(MotifFinContratSQLElement.class, root);
dir.addSQLElement(MotifRepriseArretTravailSQLElement.class, root);
dir.addSQLElement(TypePreavisSQLElement.class, root);
dir.addSQLElement(DSNNatureSQLElement.class, root);
dir.addSQLElement(TypeTauxPasSQLElement.class, root);
 
// ECO
dir.addSQLElement(FamilleEcoContributionSQLElement.class);
dir.addSQLElement(EcoContributionSQLElement.class);
dir.addSQLElement(FamilleEcoContributionSQLElement.class, root);
dir.addSQLElement(EcoContributionSQLElement.class, root);
 
dir.addSQLElement(new RubriqueCotisationSQLElement(root));
dir.addSQLElement(new RubriqueCommSQLElement(root));
dir.addSQLElement(new RubriqueNetSQLElement(root));
dir.addSQLElement(new RubriqueBrutSQLElement(root));
 
dir.addSQLElement(new CaisseCotisationSQLElement(root));
dir.addSQLElement(new ProfilPayeSQLElement(root));
dir.addSQLElement(new ProfilPayeElementSQLElement(root));
dir.addSQLElement(new PeriodeValiditeSQLElement(root));
 
dir.addSQLElement(new TypeRubriqueBrutSQLElement(root));
dir.addSQLElement(new TypeRubriqueNetSQLElement(root));
 
dir.addSQLElement(AyantDroitTypeSQLElement.class, root);
dir.addSQLElement(TypeComposantBaseAssujettieSQLElement.class, root);
dir.addSQLElement(CaisseModePaiementSQLElement.class, root);
dir.addSQLElement(CodeCotisationIndividuelleSQLElement.class, root);
dir.addSQLElement(CodeCotisationEtablissementSQLElement.class, root);
dir.addSQLElement(CodePenibiliteSQLElement.class, root);
dir.addSQLElement(new ImpressionRubriqueSQLElement(root));
 
dir.addSQLElement(new VariablePayeSQLElement(root));
 
return dir;
}
 
832,16 → 854,28
if (!this.getRootSociete().getTable("SAISIE_VENTE_FACTURE").contains("T_ACOMPTE")) {
throw new DBStructureItemNotFound("Base de données non à jour");
}
 
// Check 1.6 updated
if (!this.getRootSociete().contains("ETAT_STOCK")) {
throw new DBStructureItemNotFound("Base de données non à jour");
}
SQLElementDirectory dir = this.getDirectory();
 
dir.addSQLElement(AttachmentSQLElement.class);
 
 
dir.addSQLElement(EtatStockSQLElement.class);
dir.addSQLElement(EtatStockItemSQLElement.class);
dir.addSQLElement(ArticleTarifSQLElement.class);
dir.addSQLElement(CoutRevientSQLElement.class);
dir.addSQLElement(ReliquatBRSQLElement.class);
dir.addSQLElement(ReliquatSQLElement.class);
dir.addSQLElement(ProductQtyPriceSQLElement.class);
dir.addSQLElement(ProductItemSQLElement.class);
dir.addSQLElement(CategorieComptableSQLElement.class);
dir.addSQLElement(ArticleCatComptableSQLElement.class);
dir.addSQLElement(ArticleFournisseurSecondaireSQLElement.class);
dir.addSQLElement(SupplierPriceListSQLElement.class);
dir.addSQLElement(FraisDocumentSQLElement.class);
dir.addSQLElement(ArticleDesignationSQLElement.class);
dir.addSQLElement(BanqueSQLElement.class);
dir.addSQLElement(ClientDepartementSQLElement.class);
853,31 → 887,14
dir.addSQLElement(new SaisieKmItemSQLElement());
dir.addSQLElement(new EcritureSQLElement());
 
dir.addSQLElement(new SharedSQLElement("EMPLOYEUR_MULTIPLE"));
dir.addSQLElement(new SharedSQLElement(this, "EMPLOYEUR_MULTIPLE", "humanresources.multipleEmployer"));
dir.addSQLElement(PosteAnalytiqueSQLElement.class);
dir.addSQLElement(new SharedSQLElement("CLASSE_COMPTE"));
dir.addSQLElement(new SharedSQLElement(this, "CLASSE_COMPTE", "finance.accounting.accountClass"));
 
dir.addSQLElement(new CaisseCotisationSQLElement());
dir.addSQLElement(CaisseTicketSQLElement.class);
 
dir.addSQLElement(new ImpressionRubriqueSQLElement());
 
dir.addSQLElement(ModeleSQLElement.class);
 
dir.addSQLElement(new ProfilPayeSQLElement());
dir.addSQLElement(new ProfilPayeElementSQLElement());
dir.addSQLElement(new PeriodeValiditeSQLElement());
 
dir.addSQLElement(new RubriqueCotisationSQLElement());
dir.addSQLElement(new RubriqueCommSQLElement());
dir.addSQLElement(new RubriqueNetSQLElement());
dir.addSQLElement(new RubriqueBrutSQLElement());
 
dir.addSQLElement(new TypeRubriqueBrutSQLElement());
dir.addSQLElement(new TypeRubriqueNetSQLElement());
 
dir.addSQLElement(new VariablePayeSQLElement());
 
dir.addSQLElement(new AdresseSQLElement());
dir.addSQLElement(ArticleCodeClientSQLElement.class);
dir.addSQLElement(ReferenceArticleSQLElement.class);
900,6 → 917,8
dir.addSQLElement(new BonReceptionSQLElement());
dir.addSQLElement(new TransferReceiptSQLElement());
dir.addSQLElement(new ChequeAEncaisserSQLElement());
dir.addSQLElement(DepotChequeSQLElement.class);
dir.addSQLElement(DepotChequeElementSQLElement.class);
dir.addSQLElement(new ChequeAvoirClientSQLElement());
dir.addSQLElement(new ChequeFournisseurSQLElement());
dir.addSQLElement(new CustomerCategorySQLElement());
926,6 → 945,7
dir.addSQLElement(ChiffrageCommandeClientSQLElement.class);
 
dir.addSQLElement(new CommercialSQLElement());
 
dir.addSQLElement(ObjectifSQLElement.class);
dir.addSQLElement(new ComptePCESQLElement());
dir.addSQLElement(new ComptePCGSQLElement());
936,7 → 956,6
dir.addSQLElement(ContratPrevoyanceRubriqueNetSQLElement.class);
dir.addSQLElement(ContratPrevoyanceSalarieSQLElement.class);
dir.addSQLElement(AyantDroitSQLElement.class);
dir.addSQLElement(AyantDroitTypeSQLElement.class);
dir.addSQLElement(AyantDroitContratPrevSQLElement.class);
 
dir.addSQLElement(new CodeRegimeSQLElement());
948,13 → 967,10
dir.addSQLElement(new CodeStatutCategorielSQLElement());
dir.addSQLElement(CodeStatutCategorielConventionnelSQLElement.class);
dir.addSQLElement(new CodeStatutProfSQLElement());
dir.addSQLElement(CaisseModePaiementSQLElement.class);
dir.addSQLElement(CodeCotisationIndividuelleSQLElement.class);
dir.addSQLElement(CodeCotisationEtablissementSQLElement.class);
dir.addSQLElement(CodePenibiliteSQLElement.class);
dir.addSQLElement(CodePenibiliteContratSQLElement.class);
dir.addSQLElement(TypeComposantBaseAssujettieSQLElement.class);
 
dir.addSQLElement(PasSQLElement.class);
 
dir.addSQLElement(new CumulsCongesSQLElement());
dir.addSQLElement(new CumulsPayeSQLElement());
 
994,6 → 1010,7
dir.addSQLElement(new MoisSQLElement());
dir.addSQLElement(new MouvementSQLElement());
dir.addSQLElement(new MouvementStockSQLElement());
dir.addSQLElement(DepotStockSQLElement.class);
 
dir.addSQLElement(new NatureCompteSQLElement());
 
1003,8 → 1020,6
 
dir.addSQLElement(new PieceSQLElement());
 
dir.addSQLElement(new ProfilPayeElementSQLElement());
 
dir.addSQLElement(ReferenceClientSQLElement.class);
dir.addSQLElement(new RegimeBaseSQLElement());
dir.addSQLElement(new RelanceSQLElement());
1023,7 → 1038,7
dir.addSQLElement(new TransferInvoiceSQLElement());
// at the end since it specifies action which initialize foreign keys
dir.addSQLElement(AssociationAnalytiqueSQLElement.class);
dir.addSQLElement(new SaisieVenteFactureItemSQLElement());
dir.addSQLElement(new SaisieVenteFactureItemSQLElement(this));
 
dir.addSQLElement(SituationFamilialeSQLElement.class);
dir.addSQLElement(new StockSQLElement());
1115,7 → 1130,10
new DevisFactureSQLInjector(rootSociete);
new DevisCommandeSQLInjector(rootSociete);
new DevisCommandeFournisseurSQLInjector(rootSociete);
new DevisBlEltSQLInjector(rootSociete);
new DevisBlSQLInjector(rootSociete);
new CommandeBlEltSQLInjector(rootSociete);
new CommandeBrEltSQLInjector(rootSociete);
new CommandeBlSQLInjector(rootSociete);
new BonFactureSQLInjector(rootSociete);
new BonFactureEltSQLInjector(rootSociete);
1130,6 → 1148,7
 
if (rootSociete.contains("DEMANDE_PRIX_ACHAT_ELEMENT")) {
new DmdAchatDmdPrixEltSQLInjector(rootSociete);
new DmdPrixCmdSQLInjector(rootSociete);
}
 
}
1180,12 → 1199,14
showAs.show("CODE_STATUT_PROF", SQLRow.toList("CODE,NOM"));
showAs.show("CODE_STATUT_CATEGORIEL", SQLRow.toList("CODE,NOM"));
showAs.show("CODE_REGIME", SQLRow.toList("CODE,NOM"));
 
showAs.show("COMMANDE", "NUMERO", "DATE", "DATE_RECEPTION_DEMANDEE", "NOM", "ID_FOURNISSEUR");
if (root.contains("AFFAIRE")) {
if (root.getTable("COMMANDE_CLIENT").contains("ID_AFFAIRE")) {
showAs.show("COMMANDE_CLIENT", "NUMERO", "DATE", "ID_CLIENT", "ID_AFFAIRE", "NOM", "T_HT");
} else {
showAs.show("COMMANDE_CLIENT", "NUMERO", "DATE", "NOM", "ID_CLIENT", "T_HT");
showAs.show("COMMANDE_CLIENT", "NUMERO", "ID_CLIENT", "DATE", "NOM", "T_HT");
}
 
showAs.show("COMPTE_PCE", "NUMERO", "NOM");
showAs.show("COMPTE_PCG", "NUMERO", "NOM");
showAs.show("CONTACT", "NOM");
1250,7 → 1271,13
showAs.show("SALARIE", SQLRow.toList("CODE,NOM,PRENOM"));
 
showAs.show("SITUATION_FAMILIALE", "NOM");
 
if (root.getTable("STOCK").contains("ID_ARTICLE")) {
List<String> listFieldArtElt = new ArrayList<String>();
listFieldArtElt.add("CODE");
listFieldArtElt.add("NOM");
listFieldArtElt.add("ID_FAMILLE_ARTICLE");
showAs.showField("STOCK.ID_ARTICLE", listFieldArtElt);
}
showAs.show("STYLE", "NOM");
 
showAs.show("TAXE", "TAUX");
1299,8 → 1326,15
// don't die now, we might not need them
ExceptionHandler.handle("Impossible d'accéder aux préférences", e);
}
 
this.getModuleManager().addFactories(Gestion.MODULES_DIR);
this.getModuleManager().setup(this.getRootSociete(), this);
}
 
public final ModuleManager getModuleManager() {
return this.moduleMngr;
}
 
public void setupBarCodeIfNeeded() {
final DBRoot rootSociete = this.getRootSociete();
 
1341,16 → 1375,24
@Override
protected SQLServer createServer() {
if (GraphicsEnvironment.isHeadless()) {
SQLServer server = super.createServer();
return server;
return super.createServer();
}
InProgressFrame progress = new InProgressFrame();
progress.show("Connexion à votre base de données en cours");
if (isOnCloud) {
progress.show("Connexion au cloud en cours");
} else {
progress.show("Connexion à la base de données en cours");
}
try {
SQLServer server = super.createServer();
return server;
} catch (Throwable e) {
ExceptionHandler.die("Impossible de se connecter à la base de données.\nVérifiez votre connexion.", e);
if (isOnCloud) {
JOptionPane.showMessageDialog(null, "Impossible de se connecter au cloud.\n\nVérifiez votre connexion internet.", "Erreur", JOptionPane.ERROR_MESSAGE);
} else {
JOptionPane.showMessageDialog(null, "Impossible de se connecter à la base de données.\n\nVérifiez votre connexion.", "Erreur réseau", JOptionPane.ERROR_MESSAGE);
}
System.exit(1);
return null;
} finally {
progress.dispose();
/trunk/OpenConcerto/src/org/openconcerto/erp/config/mapping_es.xml
New file
0,0 → 1,263
<?xml version="1.0" encoding="UTF-8" ?>
<ROOT>
<element refid="common.address" nameClass="feminine" name="adresse">
<FIELD name="RAISON_SOCIALE" label="Razón social" />
<FIELD name="RUE" label="Calle" />
<FIELD name="PAYS" label="País" />
<FIELD name="CODE_POSTAL" label="Código postal" />
<FIELD name="VILLE" label="Ciudad" />
<FIELD name="CEDEX" label="Cedex" />
<FIELD name="HAS_CEDEX" label="Cedex" />
<FIELD name="NUMERO_CANTON" label="Número cantón" />
<FIELD name="NUMERO_COMMUNE" label="Número municipio" />
</element>
<element refid="humanresources.payroll.type.ayantdroit" nameClass="masculine" name="type d'ayant droit"
namePlural="types d'ayant droit">
<FIELD name="NOM" label="Tipo del derechohabiente" />
<FIELD name="CODE" label="Código del derechohabiente" />
</element>
<element refid="humanresources.rubriquecotisation.code" nameClass="masculine"
name="code rubrique de cotisation" namePlural="codes rubrique de cotisation">
<FIELD name="NOM" label="Concepto" />
<FIELD name="CODE" label="Código tipo empleado TGSS" />
</element>
<element refid="humanresources.baseassujettie.code" nameClass="masculine" name="code de base assujettie"
namePlural="codes base assujettie">
<FIELD name="NOM" label="Concepto" />
<FIELD name="CODE" label="Código Base sometida" />
</element>
<element refid="humanresources.payroll.composant.base.type" nameClass="masculine"
name="type de composant de base assujettie" namePlural="types de composant de base assujettie">
<FIELD name="NOM" label="Concepto" />
<FIELD name="CODE" label="Código componente Base sometida" />
</element>
<element refid="humanresources.payroll.cotisation.individuelle.code" nameClass="masculine"
name="code de cotisation individuelle" namePlural="codes de cotisation individuelle">
<FIELD name="NOM" label="Concepto" />
<FIELD name="CODE" label="Código cotisation individuelle (S21.G00.81)" />
</element>
<element refid="humanresources.payroll.CAISSE_COTISATION" nameClass="feminine" name="caisse">
<FIELD name="NOM" label="Concepto" />
<FIELD name="ID_ADRESSE_COMMON" label="Dirección" />
<FIELD name="TEL" label="Teléfono" titlelabel="Tel." />
<FIELD name="MAIL" label="Correo electrónico" />
<FIELD name="ORG_PROTECTION_SOCIALE" label="Org. protección sociale (inclus en DSN)" />
<FIELD name="TEL_PORTABLE" label="Teléfono móvil" titlelabel="Tel. móvil" />
<FIELD name="ID_COMPTE_PCE_TIERS" label="Cuenta tercera" />
<FIELD name="ID_COMPTE_PCE_CHARGE" label="Cuenta cargos" />
<FIELD name="NUMERO_COMPTE_PCE" label="Número cuenta tercera" />
<FIELD name="NUMERO_COMPTE_PCE_CHARGES" label="Número cuenta cargos" />
</element>
<element refid="humanresources.payroll.mode.paiement" nameClass="masculine" name="mode de paiement"
namePlural="modes de paiement">
<FIELD name="NOM" label="Forma de pago" />
<FIELD name="CODE" label="Código" />
</element>
<element refid="humanresources.payroll.CAISSE_COTISATION_RENSEIGNEMENT" nameClass="feminine"
name="caisse renseignement" namePlural="caisses renseignements">
<FIELD name="IDENTIFIANT" label="ID organísmo protección sociale" />
<FIELD name="SIRET" label="SIRET Pagador" />
<FIELD name="BIC" label="BIC de la cuenta retenida" />
<FIELD name="IBAN" label="IBAN de la cuenta retenida" />
<FIELD name="ENTITE_AFFECTATION" label="Entidad de asginación de operaciones" />
<FIELD name="CODE_DELEGATAIRE" label="Código delegado" />
<FIELD name="ORGANISME_COMPLEMENTAIRE" label="Organismo complementario" />
<FIELD name="ID_CAISSE_MODE_PAIEMENT" label="Forma de pago" />
<FIELD name="PAIEMENT_TRIMESTRIEL" label="Pago trimestral" />
<FIELD name="ID_CAISSE_COTISATION" label="Caja de cotizaciones" />
<FIELD name="ID_SOCIETE_COMMON" label="Sociedad" />
<FIELD name="JOUR_PAIEMENT" label="Pago el" />
</element>
<element refid="sales.price.DEVISE" nameClass="feminine" name="devise">
<FIELD name="CODE" label="Código" />
<FIELD name="NOM" label="Nombre" />
<FIELD name="LIBELLE" label="Concepto" />
<FIELD name="LIBELLE_CENT" label="Concepto de los centimos" />
<FIELD name="TAUX" label="Índice" />
<FIELD name="TAUX_COMMERCIAL" label="Índice comercial" />
<FIELD name="SYMBOLE" label="Símbolo" />
</element>
<element refid="controle.DomaineSQLElement" nameClass="masculine" name="domaine">
<FIELD name="NOM" label="Ámbito" />
<FIELD name="LABEL" label="Ámbito" />
<FIELD name="CODE" label="Código" />
<FIELD name="NUMERO" label="Código" />
<FIELD name="CONDITION" label="Condiciones" />
<FIELD name="Q18" label="Extensión Q18" />
</element>
<element refid="controle.EchantillonSQLElement.ECHANTILLON" nameClass="masculine" name="échantillon">
<FIELD name="NOM" label="Nombre" />
<FIELD name="PV_HT" label="Precio neto" />
<FIELD name="PV_TTC" label="Preco con IVA" />
</element>
<element refid="sales.product.ewaste-tax">
<FIELD name="CODE" label="Código" />
<FIELD name="NOM" label="Concepto" />
<FIELD name="ID_FAMILLE_ECO_CONTRIBUTION" label="Familia de eco-contribución" />
<FIELD name="TAUX" label="Valor" />
</element>
<element refid="sales.product.ewaste-family">
<FIELD name="NOM" label="Concepto" />
</element>
<element refid="finance.accounting.EXERCICE_COMMON" nameClass="masculine" name="exercice">
<FIELD name="NUMERO" label="Nombre" />
<FIELD name="DATE_DEB" label="Fecha de inicio" titlelabel="Inicio" />
<FIELD name="DATE_FIN" label="Fecha de fin" titlelabel="Fin" />
<FIELD name="CLOTURE" label="Cerrado" />
<FIELD name="DATE_CLOTURE" label="Cerrado hasta el" />
</element>
<element refid="humanresources.payroll.print" nameClass="feminine" name="impression de rubrique"
namePlural="impressions de rubrique">
<FIELD name="NOM" label="Concepto" />
</element>
<element refid="controle.IndiceSQLElement.INDICE" nameClass="masculine" name="indice d'ingénierie"
namePlural="indices d'ingénierie">
<FIELD name="ANNEE" label="Año" />
<FIELD name="JANVIER" label="Enero" />
<FIELD name="FEVRIER" label="Febrero" />
<FIELD name="MARS" label="Marzo" />
<FIELD name="AVRIL" label="Abril" />
<FIELD name="MAI" label="Mayo" />
<FIELD name="JUIN" label="Junio" />
<FIELD name="JUILLET" label="Julio" />
<FIELD name="AOUT" label="Agosto" />
<FIELD name="SEPTEMBRE" label="Septiembre" />
<FIELD name="OCTOBRE" label="Octubre" />
<FIELD name="NOVEMBRE" label="Noviembre" />
<FIELD name="DECEMBRE" label="Diciembre" />
</element>
<element refid="humanresources.payroll.validity" nameClass="feminine" name="période de validité"
namePlural="périodes de validité">
<FIELD name="JANVIER" label="Enero" />
<FIELD name="FEVRIER" label="Febrero" />
<FIELD name="MARS" label="Marzo" />
<FIELD name="AVRIL" label="Abril" />
<FIELD name="MAI" label="Mayo" />
<FIELD name="JUIN" label="Junio" />
<FIELD name="JUILLET" label="Julio" />
<FIELD name="AOUT" label="Agosto" />
<FIELD name="SEPTEMBRE" label="Septiembre" />
<FIELD name="OCTOBRE" label="Octubre" />
<FIELD name="NOVEMBRE" label="Noviembre" />
<FIELD name="DECEMBRE" label="Diciembre" />
</element>
<element refid="controle.ObjetSQLElement" nameClass="masculine" name="objet">
<FIELD name="CODE" label="Código" />
<FIELD name="NOM" label="Asunto" />
<FIELD name="QUALIFICATION" label="Califiación" />
<FIELD name="ID_DOMAINE" label="Ámbito" />
</element>
<element refid="humanresources.timesheet.PointageSQLElement" nameClass="masculine" name="pointage">
<FIELD name="ACTION" label="Acción" />
<FIELD name="ID_USER_COMMON" label="Usuario" />
<FIELD name="CARTE" label="Tarjeta" />
<FIELD name="DATE" label="Fecha" />
</element>
<element refid="humanresources.payroll.template" nameClass="masculine" name="profil de paye"
namePlural="profils de paye">
<FIELD name="NOM" label="Concepto del perfil" />
</element>
<element refid="humanresources.payroll.template.item" nameClass="masculine" name="élément d'un profil de paye"
namePlural="éléments de profils de paye">
<FIELD name="NOM" label="Concepto" />
<FIELD name="ID_PROFIL_PAYE" label="Perfil" />
<FIELD name="SOURCE" label="Fuente" />
<FIELD name="IDSOURCE" label="ID Fuente" />
<FIELD name="POSITION" label="Posición" />
</element>
<element refid="humanresources.payroll.category" nameClass="feminine" name="rubrique de net"
namePlural="rubriques de net">
<FIELD name="NUMERO_COMPTE_PCE_CHARGES" label="Numero cuenta cargos" />
<FIELD name="CODE" label="Código" />
<FIELD name="NOM" label="Concepto" />
<FIELD name="BASE" label="Valor de la base (BASE)" />
<FIELD name="TAUX" label="Índice (INDICE)" />
<FIELD name="MONTANT" label="Importe (IMPORTE)" />
<FIELD name="BRUT" label="Neto" />
<FIELD name="IMPOSABLE" label="Imponible" />
<FIELD name="FRAIS_PERS" label="Gastos Personal" />
<FIELD name="ID_PERIODE_VALIDITE" label="Periodo de vigencia" />
<FIELD name="ID_TYPE_RUBRIQUE_NET" label="Típo" />
<FIELD name="ID_IMPRESSION_RUBRIQUE" label="Impresión" />
</element>
<element refid="humanresources.payroll.category.raw" nameClass="feminine" name="rubrique de brut"
namePlural="rubriques de brut">
<FIELD name="CODE" label="Código" />
<FIELD name="NOM" label="Concepto" />
<FIELD name="BASE" label="Importe de la base (BASE)" />
<FIELD name="TAUX" label="Índice (INDICE)" />
<FIELD name="MONTANT" label="Importe (IMPORTE)" />
<FIELD name="ID_PERIODE_VALIDITE" label="Periodo de vigencia" />
<FIELD name="ID_TYPE_RUBRIQUE_BRUT" label="Típo" />
<FIELD name="ID_IMPRESSION_RUBRIQUE" label="Impresión" />
<FIELD name="IMPOSABLE" label="Imponible" />
<FIELD name="PART_BRUT" label="Participación a la base neta" />
<FIELD name="PART_CP" label="Participación a vacaciones remuneradas" />
</element>
<element refid="humanresources.payroll.category.comment" nameClass="feminine" name="rubrique de commentaire"
namePlural="rubriques de commentaire">
<FIELD name="CODE" label="Código" />
<FIELD name="NOM" label="Concepto" />
<FIELD name="NB_BASE" label="Importe de la base (BASE)" />
<FIELD name="TAUX_SAL" label="Indice Empl. (EMPL.)" />
<FIELD name="MONTANT_SAL_AJ" label="Importe empl. a añadir (IMPORTE)" />
<FIELD name="MONTANT_SAL_DED" label="Importe empl. a deducir (IMPORTE)" />
<FIELD name="TAUX_PAT" label="Indice Patr.(Patr.)" />
<FIELD name="MONTANT_PAT" label="Importe patr.(IMPORTE)" />
<FIELD name="ID_IMPRESSION_RUBRIQUE" label="Impresión" />
<FIELD name="ID_PERIODE_VALIDITE" label="Periodo de vigencia" />
<FIELD name="NOM_VISIBLE" label="Mostrar el nombre de la sección" />
</element>
<element refid="humanresources.payroll.category.subscription" nameClass="feminine"
name="rubrique de cotisation" namePlural="rubriques de cotisation">
<FIELD name="CODE" label="Código" />
<FIELD name="NOM" label="Concepto" />
<FIELD name="ID_CAISSE_COTISATION" label="Caisse de cotisation" />
<FIELD name="BASE" label="Importe de base (BASE)" />
<FIELD name="TX_SAL" label="Indice Empl. (EMPL.) en %" />
<FIELD name="TX_PAT" label="Indice Patronal (PAT) en %" />
<FIELD name="PART_CSG" label="Part CSG CRDS" />
<FIELD name="BRUT" label="Neto" />
<FIELD name="IMPOSABLE" label="Imponible" />
<FIELD name="ID_IMPRESSION_RUBRIQUE" label="Impresión" />
<FIELD name="ID_PERIODE_VALIDITE" label="Périodo de vigencia" />
<FIELD name="PART_CSG_SANS_ABATTEMENT" label="Part CSG CRDS sans abattement" />
<FIELD name="PART_PAT_IMPOSABLE" label="Immporte patronal imponible" />
<FIELD name="LIGNE_PAYE_SIMPLIFIEE" label="Ligne simplifiée associée" />
<FIELD name="ALLEGEMENT_COTISATION" label="Allégement de cotisation financé par l'Etat" />
</element>
<element refid="common.SOCIETE_COMMON" nameClass="feminine" name="société">
<FIELD name="DATABASE_NAME" label="Nombre" />
<FIELD name="NOM" label="Nombre" />
<FIELD name="ADRESSE" label="Dirección" />
<FIELD name="DATE_DEB_EX" label="Fecha inicio Ejercicio" />
<FIELD name="DATE_FIN_EX" label="Fecha de fin Ejercicio" />
<FIELD name="NUM_SIRET" label="Número CIF" />
<FIELD name="NUM_NII" label="Número NII" />
<FIELD name="NUM_APE" label="Número CNAE" />
<FIELD name="ID_EXERCICE_COMMON" label="Ejercicio" />
<FIELD name="NUM_TEL" label="Número teléfono" />
<FIELD name="NUM_FAX" label="Número de fax" />
<FIELD name="MAIL" label="Correo electrónico" />
<FIELD name="ID_ADRESSE_COMMON" label="Dirección" />
<FIELD name="TYPE" label="Tipo" />
<FIELD name="RCS" label="RMC" />
<FIELD name="CAPITAL" label="Capital" />
<FIELD name="NUMERO_URSSAF" label="Número TGSS" />
<FIELD name="ID_DEVISE" label="Divisa" />
<FIELD name="ORG_PROTECTION_SOCIAL_ID" label="CIF TGSS" />
</element>
<element refid="document.template-type" nameClass="masculine" name="type de modèle"
namePlural="types de modèles">
<FIELD name="NOM" label="Nombre" />
<FIELD name="TABLE" label="Tabla" />
</element>
<element refid="humanresources.payroll.payment.variable" nameClass="feminine" name="variable de paye"
namePlural="variables de paye">
<FIELD name="VALEUR" label="Valor" />
<FIELD name="NOM" label="Concepto" />
<FIELD name="CATEGORIE" label="Categoría" />
<FIELD name="FORMULE" label="Fórmula" />
<FIELD name="INFOS" label="Descripción" />
</element>
</ROOT>
/trunk/OpenConcerto/src/org/openconcerto/erp/config/DefaultMenuConfiguration.java
41,6 → 41,7
import org.openconcerto.erp.core.finance.accounting.action.ImpressionJournauxAnalytiqueAction;
import org.openconcerto.erp.core.finance.accounting.action.ImpressionLivrePayeAction;
import org.openconcerto.erp.core.finance.accounting.action.ImpressionRepartitionAnalytiqueAction;
import org.openconcerto.erp.core.finance.accounting.action.ListeDesCategorieComptableAction;
import org.openconcerto.erp.core.finance.accounting.action.ListeDesComptesAction;
import org.openconcerto.erp.core.finance.accounting.action.ListeDesDevisesAction;
import org.openconcerto.erp.core.finance.accounting.action.ListeDesEcrituresAction;
50,6 → 51,7
import org.openconcerto.erp.core.finance.accounting.action.ListeDesTauxDeChangeAction;
import org.openconcerto.erp.core.finance.accounting.action.ListeEcritureParClasseAction;
import org.openconcerto.erp.core.finance.accounting.action.NouveauClotureAction;
import org.openconcerto.erp.core.finance.accounting.action.NouveauClotureSansAnouveauxAction;
import org.openconcerto.erp.core.finance.accounting.action.NouveauLettrageAction;
import org.openconcerto.erp.core.finance.accounting.action.NouveauPointageAction;
import org.openconcerto.erp.core.finance.accounting.action.NouvelleValidationAction;
58,6 → 60,7
import org.openconcerto.erp.core.finance.payment.action.ListeDesChequesAEncaisserAction;
import org.openconcerto.erp.core.finance.payment.action.ListeDesChequesAvoirAction;
import org.openconcerto.erp.core.finance.payment.action.ListeDesChequesFournisseursAction;
import org.openconcerto.erp.core.finance.payment.action.ListeDesDepostChequesAction;
import org.openconcerto.erp.core.finance.payment.action.ListeDesEncaissementsAction;
import org.openconcerto.erp.core.finance.payment.action.ListeDesReferencesAction;
import org.openconcerto.erp.core.finance.payment.action.ListeDesRelancesAction;
107,6 → 110,7
import org.openconcerto.erp.core.sales.invoice.action.ListesFacturesClientsImpayeesAction;
import org.openconcerto.erp.core.sales.invoice.action.NouveauSaisieVenteComptoirAction;
import org.openconcerto.erp.core.sales.invoice.action.NouveauSaisieVenteFactureAction;
import org.openconcerto.erp.core.sales.invoice.report.ReportingClientPanel;
import org.openconcerto.erp.core.sales.order.action.ListeDesCommandesClientAction;
import org.openconcerto.erp.core.sales.order.action.ListeDesCommandesClientItemsAction;
import org.openconcerto.erp.core.sales.order.action.ListeDesElementsACommanderClientAction;
118,10 → 122,9
import org.openconcerto.erp.core.sales.product.action.ListeEcoContributionAction;
import org.openconcerto.erp.core.sales.product.action.ListeHistoCodeClientArticleAction;
import org.openconcerto.erp.core.sales.quote.action.ListeDesDevisAction;
import org.openconcerto.erp.core.sales.quote.action.ListeDesDevisActionTCP;
import org.openconcerto.erp.core.sales.quote.action.ListeDesElementsDevisAction;
import org.openconcerto.erp.core.sales.quote.action.ListeDesElementsPropositionsAction;
import org.openconcerto.erp.core.sales.quote.action.NouveauDevisAction;
import org.openconcerto.erp.core.sales.quote.action.NouvellePropositionAction;
import org.openconcerto.erp.core.sales.shipment.action.ListeDesBonsDeLivraisonAction;
import org.openconcerto.erp.core.sales.shipment.action.ListeDesReliquatsBonsLivraisonsAction;
import org.openconcerto.erp.core.sales.shipment.action.NouveauBonLivraisonAction;
135,12 → 138,16
import org.openconcerto.erp.core.supplychain.order.action.ListeSaisieAchatAction;
import org.openconcerto.erp.core.supplychain.order.action.NouveauSaisieAchatAction;
import org.openconcerto.erp.core.supplychain.order.action.NouvelleCommandeAction;
import org.openconcerto.erp.core.supplychain.order.action.NouvelleDemandePrixAction;
import org.openconcerto.erp.core.supplychain.order.action.NouvelleFactureFournisseurAction;
import org.openconcerto.erp.core.supplychain.product.action.ListeDesArticlesFournisseurAction;
import org.openconcerto.erp.core.supplychain.receipt.action.ListeDesBonsReceptionsAction;
import org.openconcerto.erp.core.supplychain.receipt.action.ListeDesReliquatsBonsReceptionsAction;
import org.openconcerto.erp.core.supplychain.receipt.action.NouveauBonReceptionAction;
import org.openconcerto.erp.core.supplychain.stock.action.ListeDesDepotsStocksAction;
import org.openconcerto.erp.core.supplychain.stock.action.ListeDesEtatsStocksAction;
import org.openconcerto.erp.core.supplychain.stock.action.ListeDesMouvementsStockAction;
import org.openconcerto.erp.core.supplychain.stock.action.ListeDesStocksAction;
import org.openconcerto.erp.core.supplychain.stock.action.NouvelleSaisieMouvementStockAction;
import org.openconcerto.erp.core.supplychain.supplier.action.ListeDesContactsFournisseursAction;
import org.openconcerto.erp.core.supplychain.supplier.action.ListeDesFournisseursAction;
148,6 → 155,7
import org.openconcerto.erp.core.supplychain.supplier.action.NouvelHistoriqueListeFournAction;
import org.openconcerto.erp.modules.ModuleFrame;
import org.openconcerto.erp.preferences.DefaultNXProps;
import org.openconcerto.erp.preferences.GestionArticleGlobalPreferencePanel;
import org.openconcerto.erp.preferences.GestionClientPreferencePanel;
import org.openconcerto.erp.rights.ComptaUserRight;
import org.openconcerto.erp.rights.NXRights;
306,6 → 314,7
gAccounting.addItem("accounting.chart");
gAccounting.addItem("accounting.list");
gAccounting.addItem("accounting.journal");
gAccounting.addItem("accounting.category.list");
gAccounting.addItem("accounting.checkDB");
gAccounting.addItem("accounting.currency");
gAccounting.addItem("accounting.currency.rates");
368,11 → 377,14
if (rights.haveRight(NXRights.GESTION_ENCAISSEMENT.getCode())) {
Group gCustomer = new Group("menu.payment.customer");
gCustomer.addItem("customer.invoice.unpaid.list");
gCustomer.addItem("customer.payment.report");
gCustomer.addItem("customer.dept.list");
gCustomer.addItem("customer.payment.list");
gCustomer.addItem("customer.payment.followup.list");
gCustomer.addItem("customer.payment.check.pending.list");
gCustomer.addItem("customer.payment.check.deposit.list");
gCustomer.addItem("customer.payment.check.pending.create");
gCustomer.addItem("customer.payment.check.deposit.list");
gCustomer.addItem("customer.payment.sddMessage.list");
gCustomer.addItem("customer.credit.check.list");
gCustomer.addItem("customer.credit.check.create");
516,7 → 528,12
gProduct.addItem("product.list");
// gProduct.addItem("product.customer.list");
// gProduct.addItem("product.supplychain.list");
if (prefs.getBoolean(GestionArticleGlobalPreferencePanel.STOCK_MULTI_DEPOT, false)) {
gProduct.addItem("stock.depot.list");
gProduct.addItem("stock.item.list");
}
gProduct.addItem("stock.io.list");
gProduct.addItem("stock.io.state");
gProduct.addItem("customer.order.waiting");
gProduct.addItem("supplier.order.waiting");
group.add(gProduct);
540,13 → 557,19
public void registerFilesMenuActions(final MenuAndActions mManager) {
mManager.putAction(new SauvegardeBaseAction(), "backup");
mManager.putAction(new AbstractAction() {
 
private ModuleFrame frame = null;
 
@Override
public void actionPerformed(ActionEvent e) {
FrameUtil.show(ModuleFrame.getInstance());
if (this.frame == null) {
this.frame = new ModuleFrame(getConfiguration().getModuleManager());
}
this.frame.setLocationRelativeTo(null);
FrameUtil.show(this.frame);
}
}, "modules");
if (!Gestion.MAC_OS_X) {
mManager.putAction(new PreferencesAction(), "preferences");
mManager.putAction(new PreferencesAction(getConfiguration().getModuleManager()), "preferences");
mManager.putAction(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
554,51 → 577,54
}
}, "quit");
}
}
 
public void registerCreationMenuActions(final MenuAndActions mManager) {
final Boolean bModeVenteComptoir = DefaultNXProps.getInstance().getBooleanValue("ArticleVenteComptoir", true);
final UserRights rights = UserRightsManager.getCurrentUserRights();
final ComptaPropsConfiguration conf = this.getConfiguration();
 
if (rights.haveRight(ComptaUserRight.MENU)) {
mManager.putAction(new NouvelleSaisieKmAction(), "accounting.entry.create");
mManager.putAction(new NouvelleSaisieKmAction(conf), "accounting.entry.create");
mManager.putAction(new SaisieJournalAction(), "accounting.entry.ledger.create");
}
 
 
mManager.putAction(new NouveauDevisAction(), "customer.quote.create");
mManager.putAction(new NouveauDevisAction(conf), "customer.quote.create");
 
mManager.putAction(new NouveauBonLivraisonAction(), "customer.delivery.create");
mManager.putAction(new NouvelleCommandeClientAction(), "customer.order.create");
mManager.putAction(new NouveauBonLivraisonAction(conf), "customer.delivery.create");
mManager.putAction(new NouvelleCommandeClientAction(conf), "customer.order.create");
if (bModeVenteComptoir && rights.haveRight("VENTE_COMPTOIR")) {
mManager.putAction(new NouveauSaisieVenteComptoirAction(), "pos.sale.create");
mManager.putAction(new NouveauSaisieVenteComptoirAction(conf), "pos.sale.create");
}
mManager.putAction(new NouveauSaisieVenteFactureAction(), "customer.invoice.create");
mManager.putAction(new NouveauSaisieVenteFactureAction(conf), "customer.invoice.create");
 
mManager.putAction(new NouveauAvoirClientAction(), "customer.credit.create");
mManager.putAction(new NouveauAvoirClientAction(conf), "customer.credit.create");
 
if (rights.haveRight(NXRights.LOCK_MENU_ACHAT.getCode())) {
mManager.putAction(new NouvelleCommandeAction(), "supplier.order.create");
mManager.putAction(new NouveauBonReceptionAction(), "supplier.receipt.create");
mManager.putAction(new NouveauSaisieAchatAction(), "supplier.purchase.create");
mManager.putAction(new NouvelleFactureFournisseurAction(), "supplier.invoice.purchase.create");
mManager.putAction(new NouvelAvoirFournisseurAction(), "supplier.credit.create");
mManager.putAction(new NouvelleSaisieMouvementStockAction(), "stock.io.create");
mManager.putAction(new NouvelleDemandePrixAction(conf), "supplier.order.ask.create");
mManager.putAction(new NouvelleCommandeAction(conf), "supplier.order.create");
mManager.putAction(new NouveauBonReceptionAction(conf), "supplier.receipt.create");
mManager.putAction(new NouveauSaisieAchatAction(conf), "supplier.purchase.create");
mManager.putAction(new NouvelleFactureFournisseurAction(conf), "supplier.invoice.purchase.create");
mManager.putAction(new NouvelAvoirFournisseurAction(conf), "supplier.credit.create");
mManager.putAction(new NouvelleSaisieMouvementStockAction(conf), "stock.io.create");
}
 
}
 
public void registerListMenuActions(final MenuAndActions mManager) {
final ComptaPropsConfiguration conf = this.configuration;
final Boolean bModeVenteComptoir = DefaultNXProps.getInstance().getBooleanValue("ArticleVenteComptoir", true);
 
// FIXME conf.getCurrentUserRights();
final UserRights rights = UserRightsManager.getCurrentUserRights();
 
mManager.putAction(new ListeDesClientsAction(), "customer.list");
SQLPreferences prefs = SQLPreferences.getMemCached(configuration.getRootSociete());
mManager.putAction(new ListeDesClientsAction(conf), "customer.list");
SQLPreferences prefs = SQLPreferences.getMemCached(conf.getRootSociete());
if (prefs.getBoolean(GestionClientPreferencePanel.DISPLAY_CLIENT_DPT, false)) {
mManager.putAction(new ListeDesDepartementsClientsAction(), "customer.department.list");
mManager.putAction(new ListeDesDepartementsClientsAction(conf), "customer.department.list");
}
mManager.putAction(new ListeDesContactsAction(), "contact.list");
mManager.putAction(new ListeDesContactsAction(conf), "contact.list");
 
if (rights.haveRight(NXRights.ACCES_HISTORIQUE.getCode())) {
mManager.putAction(new NouvelHistoriqueListeClientAction(), "customer.history");
605,15 → 631,17
}
 
 
mManager.putAction(new ListeDesDevisAction(), "customer.quote.list");
 
mManager.putAction(new ListeDesDevisAction(conf), "customer.quote.list");
 
 
 
mManager.putAction(new ListeDesCommandesClientAction(), "customer.order.list");
mManager.putAction(new ListeDesFacturationCommandesClientAction(), "customer.order.invoice.list");
mManager.putAction(new ListeDesCommandesClientItemsAction(), "customer.order.list.details");
mManager.putAction(new ListeDesBonsDeLivraisonAction(), "customer.delivery.list");
if (configuration.getRootSociete().contains("RELIQUAT_BL")) {
mManager.registerAction("customer.delivery.reliquat.list", new ListeDesReliquatsBonsLivraisonsAction());
mManager.putAction(new ListeDesFacturationCommandesClientAction(conf), "customer.order.invoice.list");
mManager.putAction(new ListeDesCommandesClientItemsAction(conf), "customer.order.list.details");
mManager.putAction(new ListeDesBonsDeLivraisonAction(conf), "customer.delivery.list");
if (conf.getRootSociete().contains("RELIQUAT_BL")) {
mManager.putAction(new ListeDesReliquatsBonsLivraisonsAction(), "customer.delivery.reliquat.list");
}
 
boolean useListDesVentesAction = bModeVenteComptoir;
625,8 → 653,8
mManager.putAction(new ListeSaisieVenteFactureAction(), "customer.invoice.list");
}
 
mManager.putAction(new ListeDesAvoirsClientsAction(), "customer.credit.list");
mManager.putAction(new ListeDesFactureItemsAction(), "customer.invoice.details.list");
mManager.putAction(new ListeDesAvoirsClientsAction(conf), "customer.credit.list");
mManager.putAction(new ListeDesFactureItemsAction(conf), "customer.invoice.details.list");
 
mManager.putAction(new ListeDesFournisseursAction(), "supplier.list");
mManager.putAction(new ListeDesContactsFournisseursAction(), "supplier.contact.list");
633,21 → 661,24
mManager.putAction(new NouvelHistoriqueListeFournAction(), "supplier.history");
if (rights.haveRight(NXRights.LOCK_MENU_ACHAT.getCode())) {
mManager.putAction(new ListeDesCommandesAction(), "supplier.order.list");
mManager.putAction(new ListeDesDemandesPrixAction(), "supplier.order.ask");
mManager.putAction(new ListeDesDemandesAchatsAction(), "supplier.order.preview");
mManager.putAction(new ListeDesDemandesPrixAction(conf), "supplier.order.ask");
mManager.putAction(new ListeDesDemandesAchatsAction(conf), "supplier.order.preview");
mManager.putAction(new ListeDesReliquatsBonsReceptionsAction(), "supplier.receipt.reliquat.list");
mManager.registerAction("supplier.receipt.list", new ListeDesBonsReceptionsAction());
mManager.registerAction("supplier.purchase.list", new ListeSaisieAchatAction());
mManager.registerAction("supplier.invoice.purchase.list", new ListeDesFacturesFournisseurAction());
mManager.registerAction("supplier.credit.list", new ListeDesAvoirsFournisseurAction());
mManager.putAction(new ListeDesBonsReceptionsAction(), "supplier.receipt.list");
mManager.putAction(new ListeSaisieAchatAction(), "supplier.purchase.list");
mManager.putAction(new ListeDesFacturesFournisseurAction(), "supplier.invoice.purchase.list");
mManager.putAction(new ListeDesAvoirsFournisseurAction(), "supplier.credit.list");
}
 
mManager.registerAction("product.list", new ListeDesArticlesAction());
mManager.registerAction("product.customer.list", new ListeHistoCodeClientArticleAction());
mManager.registerAction("product.supplychain.list", new ListeDesArticlesFournisseurAction());
mManager.registerAction("stock.io.list", new ListeDesMouvementsStockAction());
mManager.registerAction("customer.order.waiting", new ListeDesElementsACommanderClientAction());
mManager.registerAction("supplier.order.waiting", new ListeDesElementsACommanderAction());
mManager.putAction(new ListeDesArticlesAction(), "product.list");
mManager.putAction(new ListeHistoCodeClientArticleAction(), "product.customer.list");
mManager.putAction(new ListeDesArticlesFournisseurAction(), "product.supplychain.list");
mManager.putAction(new ListeDesDepotsStocksAction(), "stock.depot.list");
mManager.putAction(new ListeDesStocksAction(), "stock.item.list");
mManager.putAction(new ListeDesMouvementsStockAction(conf), "stock.io.list");
mManager.putAction(new ListeDesEtatsStocksAction(conf), "stock.io.state");
mManager.putAction(new ListeDesElementsACommanderClientAction(conf), "customer.order.waiting");
mManager.putAction(new ListeDesElementsACommanderAction(conf), "supplier.order.waiting");
 
 
 
654,51 → 685,52
}
 
public void registerAccountingMenuActions(final MenuAndActions mManager) {
mManager.registerAction("accounting.balance", new EtatBalanceAction());
mManager.registerAction("accounting.client.balance", new BalanceAgeeAction());
mManager.registerAction("accounting.analytical.ledger", new ImpressionJournauxAnalytiqueAction());
mManager.registerAction("accounting.ledger", new EtatJournauxAction());
mManager.registerAction("accounting.general.ledger", new EtatGrandLivreAction());
mManager.registerAction("accounting.entries.ledger", new ListeDesEcrituresAction());
mManager.registerAction("accounting.analytical.entries.ledger", new ListeDesEcrituresAnalytiquesAction());
mManager.registerAction("accounting.analytical.dpt", new ListeDesPostesAnalytiquesAction());
mManager.registerAction("accounting.analytical.ledger.global", new ImpressionRepartitionAnalytiqueAction());
mManager.registerAction("accounting.entries.list", new ListeEcritureParClasseAction());
mManager.registerAction("accounting.validating", new NouvelleValidationAction());
mManager.registerAction("accounting.closing", new NouveauClotureAction());
mManager.registerAction("accounting.import", new ImportEcritureAction());
mManager.registerAction("accounting.export", new ExportRelationExpertAction());
mManager.putAction(new EtatBalanceAction(), "accounting.balance");
mManager.putAction(new BalanceAgeeAction(), "accounting.client.balance");
mManager.putAction(new ImpressionJournauxAnalytiqueAction(), "accounting.analytical.ledger");
mManager.putAction(new EtatJournauxAction(), "accounting.ledger");
mManager.putAction(new EtatGrandLivreAction(), "accounting.general.ledger");
mManager.putAction(new ListeDesEcrituresAction(), "accounting.entries.ledger");
mManager.putAction(new ListeDesEcrituresAnalytiquesAction(), "accounting.analytical.entries.ledger");
mManager.putAction(new ListeDesPostesAnalytiquesAction(), "accounting.analytical.dpt");
mManager.putAction(new ImpressionRepartitionAnalytiqueAction(), "accounting.analytical.ledger.global");
mManager.putAction(new ListeEcritureParClasseAction(), "accounting.entries.list");
mManager.putAction(new NouvelleValidationAction(), "accounting.validating");
mManager.putAction(new NouveauClotureAction(), "accounting.closing");
mManager.putAction(new ImportEcritureAction(), "accounting.import");
mManager.putAction(new ExportRelationExpertAction(), "accounting.export");
}
 
public void registerStatsDocumentsActions(final MenuAndActions mManager) {
// mManager.registerAction("accounting.vat.report", new DeclarationTVAAction());
mManager.registerAction("accounting.costs.report", new EtatChargeAction());
mManager.registerAction("accounting.balance.report", new CompteResultatBilanAction());
mManager.registerAction("employe.social.report", new N4DSAction());
// mManager.registerAction("accounting.2050Report", new CompteResultatBilan2050Action());
// mManager.putAction("accounting.vat.report", new DeclarationTVAAction());
mManager.putAction(new EtatChargeAction(), "accounting.costs.report");
mManager.putAction(new CompteResultatBilanAction(), "accounting.balance.report");
mManager.putAction(new N4DSAction(), "employe.social.report");
// mManager.putAction("accounting.2050Report", new CompteResultatBilan2050Action());
}
 
public void registerStatsMenuActions(final MenuAndActions mManager) {
 
 
mManager.registerAction("sales.graph", new EvolutionCAAction());
mManager.registerAction("sales.graph.cumulate", new EvolutionCACumulAction());
mManager.putAction(new EvolutionCAAction(), "sales.graph");
mManager.putAction(new EvolutionCACumulAction(), "sales.graph.cumulate");
 
mManager.registerAction("sales.graph.cmd", new EvolutionCmdAction());
mManager.registerAction("sales.graph.cmd.cumulate", new EvolutionCmdCumulAction());
mManager.putAction(new EvolutionCmdAction(), "sales.graph.cmd");
mManager.putAction(new EvolutionCmdCumulAction(), "sales.graph.cmd.cumulate");
 
mManager.registerAction("sales.margin.graph", new EvolutionMargeAction());
mManager.registerAction("sales.list.reporting", new GenReportingVenteAction(false));
mManager.registerAction("order.list.reporting", new GenReportingVenteAction(true));
mManager.registerAction("sales.list.report", new GenListeVenteAction());
mManager.registerAction("sales.list.stock.report", new GenEtatStockAction());
mManager.putAction(new EvolutionMargeAction(), "sales.margin.graph");
mManager.putAction(new GenReportingVenteAction(false), "sales.list.reporting");
mManager.putAction(new GenReportingVenteAction(true), "order.list.reporting");
// mManager.putAction("sales.list.reporting", new GenReportingVenteAction());
mManager.putAction(new GenListeVenteAction(), "sales.list.report");
mManager.putAction(new GenEtatStockAction(), "sales.list.stock.report");
 
mManager.registerAction("sales.product.graph", new VenteArticleGraphAction());
mManager.registerAction("sales.product.margin.graph", new VenteArticleMargeGraphAction());
mManager.registerAction("sales.product.family.graph", new VenteArticleFamilleGraphAction());
mManager.registerAction("sales.list.graph", new EtatVenteAction());
mManager.putAction(new VenteArticleGraphAction(), "sales.product.graph");
mManager.putAction(new VenteArticleMargeGraphAction(), "sales.product.margin.graph");
mManager.putAction(new VenteArticleFamilleGraphAction(), "sales.product.family.graph");
mManager.putAction(new EtatVenteAction(), "sales.list.graph");
 
mManager.registerAction("sales.report.ecocontribution", new AbstractAction("Reporting Eco Contribution") {
mManager.putAction(new AbstractAction("Reporting Eco Contribution") {
 
@Override
public void actionPerformed(ActionEvent e) {
706,9 → 738,9
PanelFrame frame = new PanelFrame(new ReportingEcoContributionPanel(), "Reporting Eco Contribution");
frame.setVisible(true);
}
});
}, "sales.report.ecocontribution");
 
mManager.registerAction("sales.report.taxesupp", new AbstractAction("Reporting Taxes complémentaires") {
mManager.putAction(new AbstractAction("Reporting Taxes complémentaires") {
 
@Override
public void actionPerformed(ActionEvent e) {
716,12 → 748,13
PanelFrame frame = new PanelFrame(new ReportingTaxeComplementairePanel(), "Reporting Taxes complémentaires");
frame.setVisible(true);
}
});
}, "sales.report.taxesupp");
 
}
 
public void registerPaymentMenuActions(final MenuAndActions mManager) {
final UserRights rights = UserRightsManager.getCurrentUserRights();
final ComptaPropsConfiguration conf = getConfiguration();
 
if (rights.haveRight(ComptaUserRight.MENU) || rights.haveRight(ComptaUserRight.POINTAGE_LETTRAGE)) {
mManager.putAction(new NouveauPointageAction(), "payment.checking.create");
731,29 → 764,40
if (rights.haveRight(NXRights.GESTION_ENCAISSEMENT.getCode())) {
mManager.putAction(new ListesFacturesClientsImpayeesAction(), "customer.invoice.unpaid.list");
mManager.putAction(new ListeDebiteursAction(), "customer.dept.list");
mManager.putAction(new AbstractAction("Relevé client") {
@Override
public void actionPerformed(ActionEvent arg0) {
 
PanelFrame frame = new PanelFrame(new ReportingClientPanel(), "Reporting client");
frame.setVisible(true);
 
}
}, "customer.payment.report");
mManager.putAction(new ListeDesEncaissementsAction(), "customer.payment.list");
mManager.putAction(new ListeDesRelancesAction(), "customer.payment.followup.list");
mManager.putAction(new ListeDesChequesAEncaisserAction(), "customer.payment.check.pending.list");
mManager.putAction(new NouveauListeDesChequesAEncaisserAction(), "customer.payment.check.pending.create");
mManager.putAction(new ListeSDDMessageAction(configuration.getDirectory()), "customer.payment.sddMessage.list");
mManager.putAction(new ListeDesDepostChequesAction(), "customer.payment.check.deposit.list");
mManager.putAction(new NouveauListeDesChequesAEncaisserAction(conf), "customer.payment.check.pending.create");
mManager.putAction(new ListeSDDMessageAction(conf.getDirectory()), "customer.payment.sddMessage.list");
mManager.putAction(new ListeDesChequesAvoirAction(), "customer.credit.check.list");
mManager.putAction(new NouveauDecaissementChequeAvoirAction(), "customer.credit.check.create");
mManager.putAction(new NouveauDecaissementChequeAvoirAction(conf), "customer.credit.check.create");
}
if (rights.haveRight(NXRights.LOCK_MENU_ACHAT.getCode())) {
mManager.putAction(new ListesFacturesFournImpayeesAction(), "supplier.invoice.unpaid.list");
mManager.putAction(new ListeDesTraitesFournisseursAction(), "supplier.bill.list");
mManager.putAction(new ListeDesChequesFournisseursAction(), "supplier.payment.check.list");
mManager.putAction(new NouveauListeDesChequesADecaisserAction(), "supplier.payment.check.pending.list");
mManager.putAction(new NouveauListeDesChequesADecaisserAction(conf), "supplier.payment.check.pending.list");
}
 
}
 
public void registerPayrollMenuActions(final MenuAndActions mManager) {
final ComptaPropsConfiguration conf = getConfiguration();
mManager.putAction(new ImpressionLivrePayeAction(), "payroll.list.report.print");
mManager.putAction(new ListeDesProfilsPayeAction(), "payroll.profile.list");
mManager.putAction(new NouvelHistoriqueFichePayeAction(), "payroll.history");
mManager.putAction(new EditionFichePayeAction(), "payroll.create");
mManager.putAction(new NouvelAcompteAction(), "payroll.deposit.create");
mManager.putAction(new NouvelAcompteAction(conf), "payroll.deposit.create");
mManager.putAction(new ListeDesSalariesAction(), "employee.list");
mManager.putAction(new ListeDesContratsPrevoyanceAction(), "employee.contrat.prev.list");
mManager.putAction(new ListeDesCaissesCotisationsAction(), "payroll.caisse");
775,6 → 819,7
 
mManager.putAction(new ListeDesJournauxAction(), "accounting.journal");
mManager.putAction(new ListeDesDevisesAction(), "accounting.currency");
mManager.putAction(new ListeDesCategorieComptableAction(), "accounting.category.list");
mManager.putAction(new ListeDesTauxDeChangeAction(), "accounting.currency.rates");
mManager.putAction(new AbstractAction("Check DB") {
@Override
803,7 → 848,7
mManager.putAction(new ListeDesSocietesCommonsAction(), "enterprise.list");
 
mManager.putAction(new ListeBanqueAction(), "divison.bank.list");
mManager.putAction(new NouvelleSocieteAction(), "enterprise.create");
mManager.putAction(new NouvelleSocieteAction(this.getConfiguration()), "enterprise.create");
}
 
public void registerHelpMenuActions(final MenuAndActions mManager) {
813,7 → 858,8
 
public void registerHelpTestActions(final MenuAndActions mManager) {
 
// mManager.registerAction("test.export.ecrp", new ExportPointageAction());
mManager.putAction(new NouveauClotureSansAnouveauxAction(), "accounting.closing.sansanouveaux");
// mManager.putAction("test.export.ecrp", new ExportPointageAction());
 
}
}
/trunk/OpenConcerto/src/org/openconcerto/erp/config/translation_fr.xml
9,8 → 9,6
<menu id="menu.create" label="Saisie" />
<menu id="accounting" label="Comptabilité" />
<menu id="accounting.entry.create" label="Ecritures comptables" />
<menu id="customer" label="Clients" />
<menu id="customer.quote.create" label="Devis" />
<menu id="customer.letter.create" label="Courrier" />
<menu id="customer.proposal.create" label="Proposition" />
<menu id="project.create" label="Affaire" />
17,27 → 15,19
<menu id="appointment.create" label="Fiche de rendez-vous" />
<menu id="mission.create" label="Ordre de mission" />
<menu id="mission.notice.create" label="Avis d'intervention" />
<menu id="customer.delivery.create" label="Bon de livraison" />
<menu id="customer.order.create" label="Commande" />
<menu id="pos.sale.create" label="Vente comptoir" />
<menu id="customer.invoice.create" label="Facture" />
<menu id="kd.invoice.create" label="Facture CTC" />
<menu id="customer.credit.create" label="Facture d'avoir" />
<menu id="supplier" label="Fournisseur" />
<menu id="supplier.order.create" label="Commande fournisseur" />
<menu id="supplier.receipt.create" label="Bon de réception" />
<menu id="supplier.purchase.create" label="Achat fournisseur" />
<menu id="supplier.invoice.purchase.create" label="Facture fournisseur" />
<menu id="supplier.credit.create" label="Avoir fournisseur" />
<menu id="stock.io.create" label="Mouvement de stock" />
 
 
<!-- List -->
<menu id="menu.list" label="Gestion" />
<menu id="menu.list.customer" label="Gestion des clients" />
<menu id="customer.list" label="Liste des clients" />
<menu id="contact.list" label="Liste des contacts clients" />
<menu id="customer.history" label="Historique des clients" />
<menu id="customer.quote.list" label="Liste des devis" />
<menu id="customer.proposal.list" label="Liste des propositions" />
<menu id="customer.proposal.item.list" label="Liste des éléments de proposition" />
<menu id="menu.list.mission" label="Missions" />
49,11 → 39,9
<menu id="mission.order.list" label="" />
<menu id="mission.notice.list" label="" />
<menu id="customer.order.list" label="Liste des commandes" />
<menu id="customer.delivery.list" label="Liste des bons de livraison" />
<menu id="customer.order.waiting" label="Liste des éléments en attente de livraison" />
<menu id="customer.order.invoice.list" label="Echéancier de commandes clients" />
<menu id="sales.list" label="Liste des ventes" />
<menu id="customer.invoice.list" label="Liste des factures" />
<menu id="payment.factoring.create" label="" />
<menu id="payment.factoring.list" label="" />
<menu id="customer.credit.list" label="Liste des avoirs" />
<menu id="menu.list.supplier" label="Fournisseurs" />
<menu id="supplier.list" label="Liste des fournisseurs" />
60,17 → 48,18
<menu id="supplier.contact.list" label="Liste des contacts fournisseurs" />
<menu id="supplier.history" label="Historique des fournisseurs" />
<menu id="supplier.order.list" label="Liste des commandes fournisseurs" />
<menu id="supplier.receipt.list" label="Liste des bons de réception" />
<menu id="supplier.order.waiting" label="Liste des éléments en attente de réception" />
<menu id="supplier.purchase.list" label="Liste des saisies d'achat" />
<menu id="supplier.invoice.purchase.list" label="Liste des factures fournisseurs" />
<menu id="supplier.credit.list" label="Liste des avoirs fournisseurs" />
<menu id="product.list" label="Liste des articles" />
<menu id="product.reference.list" label="Liste des références" />
<menu id="stock.io.list" label="Listes des mouvements de stock" />
<menu id="menu.list.pos" label="Point de vente" />
<menu id="pos.receipt.list" label="Liste des tickets de caisse" />
<menu id="pos.sales.report" label="Liste des ventes en caisse" />
<menu id="sales.report" label="" />
 
 
<!-- Accounting -->
<menu id="menu.accounting" label="Comptabilité" />
<menu id="accounting.balance" label="Balance" />
110,6 → 99,7
<menu id="customer.payment.followup.list" label="Liste des relances" />
<menu id="customer.payment.check.pending.list" label="Chèques des clients" />
<menu id="customer.payment.check.pending.create" label="Chèques à encaisser" />
<menu id="customer.payment.check.deposit.list" label="Liste des dépôts de chèques" />
<menu id="customer.payment.sddMessage.list" label="Liste des ordres de prélèvement SEPA" />
<menu id="customer.credit.check.list" label="Chèques d'avoir" />
<menu id="customer.credit.check.create" label="Chèques d'avoir à décaisser" />
148,7 → 138,6
<menu id="enterprise.create" label="Nouvelle société" />
<menu id="mission.sample.list" label="" />
<menu id="mission.code.list" label="" />
<menu id="department.list" label="" />
<!-- Test -->
<menu id="menu.test" label="En test" />
<!-- Help -->
162,7 → 151,6
<menu id="menu.contact.list" label="Contacts" />
<menu id="menu.customer.quote.list" label="Devis" />
<menu id="menu.customer.order.list" label="Commandes" />
<menu id="menu.customer.delivery.list" label="Bons de livraison" />
<menu id="menu.customer.invoice.list" label="Factures" />
<menu id="menu.customer.credit.list" label="Avoirs" />
 
189,6 → 177,8
<action id="sales.quote.create.supplier.order" label="Transférer en commande" />
<action id="sales.quote.clone" label="Créer à partir de" />
<action id="sales.quote.create.customer.order" label="Transfert vers commande client" />
<action id="sales.quote.create.customer.delivery" label="Transfert vers bon de livraison" />
<action id="sales.quote.accept.create.customer.order" label="Marquer comme accepté et Transfert en commande client" />
<!-- Customer -->
<action id="customerrelationship.customer.label.print" label="Imprimer l'étiquette client" />
272,7 → 262,7
<item id="product.bom.expose" label="Exposer la nomenclature" />
<item id="product.bom.flat" label="Applatir la nomenclature" />
 
<item id="sales.order.invoice.global" label="Facturaction globale" />
<item id="sales.order.invoice.global" label="Facturation globale" />
<item id="sales.order.invoice.partial" label="Facturation intermédiaire" />
<item id="sales.order.invoice.rest" label="Facturation du solde" />
 
304,11 → 294,11
<item id="paye.simplifie.ignore" label="Ligne ignorée" />
 
<!-- Groupe Paye Simplifiée -->
<item id="sante" label="ASSURANCE SANTE" />
<item id="sante" label="SANTE" />
<item id="accident" label="ASSURANCE ACCIDENTS DU TRAVAIL-MALADIE PROFESSIONNELLES" />
<item id="retraite.noncadre" label="ASSURANCE RETRAITE" />
<item id="retraite.cadre" label="ASSURANCE RETRAITE" />
<item id="famille" label="ALLOCATIONS FAMILIALES" />
<item id="famille" label="FAMILLE" />
<item id="chomage.noncadre" label="ASSURANCE CHÔMAGE" />
<item id="chomage.cadre" label="ASSURANCE CHÔMAGE" />
<item id="autres" label="AUTRES CONTRIBUTIONS DUES PAR L'EMPLOYEUR" />
315,6 → 305,6
<item id="cotisations.convention" label="COTISATIONS DE CONVENTION COLLECTIVE OU STATUAIRES" />
<item id="csg.nonimp" label="CSG/CRDS déductible de l'impôt sur le revenu" />
<item id="csg.imp" label="CSG/CRDS non déductible à l'impôt sur le revenu" />
<item id="allegement" label="ALLEGEMENT DE COTISATIONS" />
<item id="allegement" label="Exonération de cotisations employeur" />
 
</translation>
/trunk/OpenConcerto/src/org/openconcerto/erp/config/mappingCompta_fr.xml
1,97 → 1,100
<?xml version="1.0" encoding="UTF-8" ?>
<ROOT>
<TABLE name="ACOMPTE">
<FIELD name="ID_SALARIE" label="Salarié" titlelabel="Salarié" />
<FIELD name="MONTANT" label="Montant" titlelabel="Montant" />
<FIELD name="ID_MOUVEMENT" label="Mouvement" titlelabel="Mouvement" />
</TABLE>
 
<TABLE name="ADRESSE">
<FIELD name="TYPE" label="Type" titlelabel="Type" />
<element refid="humanresources.payroll.advance" nameClass="masculine" name="acompte">
<FIELD name="ID_SALARIE" label="Salarié" />
<FIELD name="MONTANT" label="Montant" />
<FIELD name="ID_MOUVEMENT" label="Mouvement" />
</element>
<element refid="address" nameClass="feminine" name="adresse">
<FIELD name="TYPE" label="Type" />
<FIELD name="LIBELLE" label="Libellé" />
<FIELD name="RAISON_SOCIALE" label="Raison sociale" titlelabel="Raison sociale" />
<FIELD name="RUE" label="Rue" titlelabel="Rue" />
<FIELD name="RAISON_SOCIALE" label="Raison sociale" />
<FIELD name="RUE" label="Rue" />
<FIELD name="PROVINCE" label="Province / état" titlelabel="Province" />
<FIELD name="PAYS" label="Pays" titlelabel="Pays" />
<FIELD name="CEDEX" label="Cedex" titlelabel="Cedex" />
<FIELD name="HAS_CEDEX" label="Cedex" titlelabel="Cedex" />
<FIELD name="CODE_POSTAL" label="Code postal" titlelabel="Code postal" />
<FIELD name="VILLE" label="Ville" titlelabel="Ville" />
<FIELD name="PAYS" label="Pays" />
<FIELD name="CEDEX" label="Cedex" />
<FIELD name="HAS_CEDEX" label="Cedex" />
<FIELD name="CODE_POSTAL" label="Code postal" />
<FIELD name="VILLE" label="Ville" />
<FIELD name="DEST" label="Nom du Destinataire" titlelabel="Destinataire" />
<FIELD name="NUMERO_CANTON" label="Numéro canton" titlelabel="Numéro canton" />
<FIELD name="NUMERO_COMMUNE" label="Numéro commune" titlelabel="Numéro commune" />
<FIELD name="NUMERO_CANTON" label="Numéro canton" />
<FIELD name="NUMERO_COMMUNE" label="Numéro commune" />
<FIELD name="TYPE" label="Type" />
<FIELD name="EMAIL_CONTACT" label="Email contact" />
<FIELD name="DISTRICT" label="District" />
<FIELD name="DEPARTEMENT" label="Département" />
</TABLE>
<TABLE name="AFFACTURAGE">
<FIELD name="NB_FACT" label="Nombre de factures" titlelabel="Nombre de factures" />
<FIELD name="MONTANT_FACT" label="Montant" titlelabel="Montant" />
<FIELD name="DATE" label="Date" titlelabel="Date" />
</TABLE>
<TABLE name="AFFAIRE">
<FIELD name="ID_CLIENT" label="Client" titlelabel="Client" />
<FIELD name="CCI" label="CCI" titlelabel="CCI" />
</element>
<element refid="controle.factoring" nameClass="masculine" name="envoi en affacturage"
namePlural="envois en affacturage">
<FIELD name="NB_FACT" label="Nombre de factures" />
<FIELD name="MONTANT_FACT" label="Montant" />
<FIELD name="DATE" label="Date" />
</element>
<element refid="controle.project" nameClass="feminine" name="affaire">
<FIELD name="ID_CLIENT" label="Client" />
<FIELD name="CCI" label="CCI" />
<FIELD name="TYPE_ETABLISSEMENT" label="Type d'établissement" />
<FIELD name="DUREE_TRAVAUX" label="Durée des travaux" />
<FIELD name="CCI" label="CCI" titlelabel="CCI" />
<FIELD name="ID_VERIFICATEUR" label="Chargé d'affaire" titlelabel="Chargé d'affaire" />
<FIELD name="DATE_DEMARRAGE" label="Date de démarrage" titlelabel="Date de démarrage" />
<FIELD name="MARCHE" label="Marché" titlelabel="Marché" />
<FIELD name="NUMERO" label="Numéro affaire" titlelabel="Numéro affaire" />
<FIELD name="DATE" label="Date" titlelabel="Date" />
<FIELD name="ID_CONTACT_COM" label="Contact commercial" titlelabel="Contact commercial" />
<FIELD name="ID_CONTACT_TECH" label="Contact technique" titlelabel="Contact technique" />
<FIELD name="ID_PROPOSITION" label="Proposition" titlelabel="Proposition" />
<FIELD name="OBJET" label="Affaire" titlelabel="Affaire" />
<FIELD name="CCI" label="CCI" />
<FIELD name="ID_VERIFICATEUR" label="Chargé d'affaire" />
<FIELD name="DATE_DEMARRAGE" label="Date de démarrage" />
<FIELD name="MARCHE" label="Marché" />
<FIELD name="NUMERO" label="Numéro affaire" />
<FIELD name="DATE" label="Date" />
<FIELD name="ID_CONTACT_COM" label="Contact commercial" />
<FIELD name="ID_CONTACT_TECH" label="Contact technique" />
<FIELD name="ID_PROPOSITION" label="Proposition" />
<FIELD name="OBJET" label="Affaire" />
<FIELD name="TOTAL_HT" label="Total HT" />
<FIELD name="MONTANT_FACTURE" label="Montant HT facturé" titlelabel="Montant HT facturé" />
<FIELD name="REFERENCE" label="Nos références" titlelabel="Nos références" />
<FIELD name="SITUATION_ADMIN" label="Situation administrative" titlelabel="Situation administrative" />
<FIELD name="REFERENCE_CLIENT" label="Références client" titlelabel="Références client" />
<FIELD name="ACTIVITE" label="Activité" titlelabel="Activité" />
<FIELD name="INFOS" label="Informations complémentaires" titlelabel="Informations complémentaires" />
<FIELD name="INFOS_ETIQUETTE" label="Informations étiquette" titlelabel="Informations étiquette" />
<FIELD name="MONTANT_REVISABLE" label="Révisable" titlelabel="Révisable" />
<FIELD name="ID_ADRESSE" label="Adresse de facturation" titlelabel="Adresse de facturation" />
<FIELD name="ID_ADRESSE_COURRIER_1" label="Adresse de courrier 1" titlelabel="Adresse de courrier 1" />
<FIELD name="ID_ADRESSE_COURRIER_2" label="Adresse de courrier 2" titlelabel="Adresse de courrier 2" />
<FIELD name="ID_ADRESSE_COURRIER_3" label="Adresse de courrier 3" titlelabel="Adresse de courrier 3" />
</TABLE>
<TABLE name="AFFAIRE_ELEMENT">
<FIELD name="FIN_CONTRAT" label="Fin de contrat" titlelabel="Fin de contrat" />
<FIELD name="DATE_FIN_CONTRAT" label="Date de fin de contrat" titlelabel="Date de fin de contrat" />
<FIELD name="MONTANT_FACTURE" label="Montant HT facturé" />
<FIELD name="REFERENCE" label="Nos références" />
<FIELD name="SITUATION_ADMIN" label="Situation administrative" />
<FIELD name="REFERENCE_CLIENT" label="Références client" />
<FIELD name="ACTIVITE" label="Activité" />
<FIELD name="INFOS" label="Informations complémentaires" />
<FIELD name="INFOS_ETIQUETTE" label="Informations étiquette" />
<FIELD name="MONTANT_REVISABLE" label="Révisable" />
<FIELD name="ID_ADRESSE" label="Adresse de facturation" />
<FIELD name="ID_ADRESSE_COURRIER_1" label="Adresse de courrier 1" />
<FIELD name="ID_ADRESSE_COURRIER_2" label="Adresse de courrier 2" />
<FIELD name="ID_ADRESSE_COURRIER_3" label="Adresse de courrier 3" />
</element>
<element refid="controle.AffaireElementSQLElement.project.item" nameClass="feminine"
name="mission de l'affaire" namePlural="missions de l'affaire">
<FIELD name="FIN_CONTRAT" label="Fin de contrat" />
<FIELD name="DATE_FIN_CONTRAT" label="Date de fin de contrat" />
<FIELD name="CODE" label="Code" />
<FIELD name="DUREE_PREVISIONNELLE" label="Durée prévue" titlelabel="Durée prévue" />
<FIELD name="ID_DOSSIER" label="Dossier" titlelabel="Dossier" />
<FIELD name="ID_TAXE" label="TVA" titlelabel="TVA" />
<FIELD name="DUREE_PREVISIONNELLE" label="Durée prévue" />
<FIELD name="ID_DOSSIER" label="Dossier" />
<FIELD name="ID_TAXE" label="TVA" />
<FIELD name="NOM" label="Libellé" />
<FIELD name="ACTIVITE" label="Activité" titlelabel="Activité" />
<FIELD name="SOUS_ACTIVITE" label="Sous activité" titlelabel="Sous activité" />
<FIELD name="MONTANT_HT" label="Montant HT" titlelabel="Montant HT" />
<FIELD name="ID_PERIODICITE" label="Périodicité" titlelabel="Périodicité" />
<FIELD name="INDICE_0" label="Indice 0" titlelabel="Indice 0" />
<FIELD name="NOMBRE" label="Nombre" titlelabel="Nombre" />
<FIELD name="Q18" label="Extension Q18" titlelabel="Extension Q18" />
<FIELD name="TARIF_Q18_HT" label="Tarif Q18 HT" titlelabel="Tarif Q18 HT" />
<FIELD name="OBJET_INSPECTE" label="Objet inspecté" titlelabel="Objet inspecté" />
<FIELD name="PV_UNIT_HT" label="PV unitaire HT" titlelabel="PV unitaire HT" />
<FIELD name="MONTANT_HT" label="Montant HT" titlelabel="Montant HT" />
<FIELD name="REFERENTIEL_INSPECTION" label="Référentiel inspection" titlelabel="Référentiel inspection" />
<FIELD name="LOCAL_OBJET_INSPECTE" label="Localisation objet" titlelabel="Localisation objet" />
<FIELD name="ID_SECTEUR_ACTIVITE" label="Secteur d'activité" titlelabel="Secteur d'activité" />
<FIELD name="ID_NATURE_MISSION" label="Nature mission" titlelabel="Nature mission" />
<FIELD name="ID_DOMAINE" label="Domaine" titlelabel="Domaine" />
<FIELD name="REPARTITION_POURCENT" label="Répartition %" titlelabel="Répartition %" />
<FIELD name="MONTANT_REVISABLE" label="Révisable" titlelabel="Révisable" />
<FIELD name="INFOS_OBJET_INSPECTE" label="Commentaires objet" titlelabel="Commentaires objet" />
<FIELD name="ID_SITE_INTERVENTION" label="Site d'intervention" titlelabel="Site d'intervention" />
<FIELD name="SITUATION_ADMIN" label="Situation administrative" titlelabel="Situation administrative" />
<FIELD name="NOTA" label="Nota" titlelabel="Nota" />
</TABLE>
 
<TABLE name="ARTICLE">
<FIELD name="ACTIVITE" label="Activité" />
<FIELD name="SOUS_ACTIVITE" label="Sous activité" />
<FIELD name="MONTANT_HT" label="Montant HT" />
<FIELD name="ID_PERIODICITE" label="Périodicité" />
<FIELD name="INDICE_0" label="Indice 0" />
<FIELD name="NOMBRE" label="Nombre" />
<FIELD name="Q18" label="Extension Q18" />
<FIELD name="TARIF_Q18_HT" label="Tarif Q18 HT" />
<FIELD name="OBJET_INSPECTE" label="Objet inspecté" />
<FIELD name="PV_UNIT_HT" label="PV unitaire HT" />
<FIELD name="MONTANT_HT" label="Montant HT" />
<FIELD name="REFERENTIEL_INSPECTION" label="Référentiel inspection" />
<FIELD name="LOCAL_OBJET_INSPECTE" label="Localisation objet" />
<FIELD name="ID_SECTEUR_ACTIVITE" label="Secteur d'activité" />
<FIELD name="ID_NATURE_MISSION" label="Nature mission" />
<FIELD name="ID_DOMAINE" label="Domaine" />
<FIELD name="REPARTITION_POURCENT" label="Répartition %" />
<FIELD name="MONTANT_REVISABLE" label="Révisable" />
<FIELD name="INFOS_OBJET_INSPECTE" label="Commentaires objet" />
<FIELD name="ID_SITE_INTERVENTION" label="Site d'intervention" />
<FIELD name="SITUATION_ADMIN" label="Situation administrative" />
<FIELD name="NOTA" label="Nota" />
</element>
<element refid="sales.product.ref" nameClass="masculine" name="article">
<FIELD name="MARGE_WITH_COUT_REVIENT" label="Inclure le coût de revient dans le calcul du prix de vente" />
<FIELD name="ID_COUT_REVIENT" label="%CR" />
<FIELD name="QTE_UNITAIRE" label="Quantité unitaire par défaut" />
<FIELD name="MASQUE_CAISSE" label="Ne pas charger sur la caisse" />
<FIELD name="TARE" label="Tare" />
<FIELD name="IFCO" label="IFCO" />
98,50 → 101,50
<FIELD name="MATIERE" label="Matière" />
<FIELD name="ID_TAXE_COMPLEMENTAIRE" label="Taxe complémentaire" />
<FIELD name="ID_ECO_CONTRIBUTION" label="Eco contribution" />
<FIELD name="ID_UNITE_VENTE" label="Unité de vente" titlelabel="Unité de vente" />
<FIELD name="QTE_ACHAT" label="Quantité multiple d'achat à respecter" titlelabel="Quantité multiple d'achat à respecter" />
<FIELD name="CODE_BARRE" label="Code barres" titlelabel="Code barres" />
<FIELD name="INFOS" label="Informations complémentaires" titlelabel="Informations complémentaires" />
<FIELD name="ID_FOURNISSEUR" label="Fournisseur principal" titlelabel="Fournisseur principal" />
<FIELD name="GESTION_STOCK" label="Gérer le stock" titlelabel="Gérer le stock" />
<FIELD name="CODE_DOUANIER" label="Code douanier" titlelabel="Code douanier" />
<FIELD name="ID_PAYS" label="Pays d'origine" titlelabel="Pays d'origine" />
<FIELD name="QTE_MIN" label="Quantité minimum à stocker" titlelabel="Quantité minimum à stocker" />
<FIELD name="ETIQUETTE" label="Libellé étiquette" titlelabel="Libellé étiquette" />
<FIELD name="CODE" label="Code article" titlelabel="Code article" />
<FIELD name="NOM" label="Désignation" titlelabel="Désignation" />
<FIELD name="ID_UNITE_VENTE" label="Unité de vente" />
<FIELD name="QTE_ACHAT" label="Quantité multiple d'achat à respecter" />
<FIELD name="CODE_BARRE" label="Code barres" />
<FIELD name="INFOS" label="Informations complémentaires" />
<FIELD name="ID_FOURNISSEUR" label="Fournisseur principal" />
<FIELD name="GESTION_STOCK" label="Gérer le stock" />
<FIELD name="CODE_DOUANIER" label="Code douanier" />
<FIELD name="ID_PAYS" label="Pays d'origine" />
<FIELD name="QTE_MIN" label="Quantité minimum à stocker" />
<FIELD name="ETIQUETTE" label="Libellé étiquette" />
<FIELD name="CODE" label="Code article" />
<FIELD name="NOM" label="Désignation" />
<FIELD name="PA_HT" label="Prix d'achat HT" />
<FIELD name="PV_HT" label="Prix de vente HT" />
<FIELD name="PV_TTC" label="Prix de vente TTC" />
<FIELD name="ID_TAXE" label="Taxe" titlelabel="Taxe" />
<FIELD name="ID_TAXE" label="Taxe" />
<FIELD name="POIDS" label="Poids en Kg" titlelabel="Poids" />
<FIELD name="SERVICE" label="Service" titlelabel="Service" />
<FIELD name="ID_STOCK" label="Stock" titlelabel="Stock" />
<FIELD name="PRIX_METRIQUE_VT_1" label="P.V. UV HT" titlelabel="P.V. UV HT" />
<FIELD name="PRIX_METRIQUE_HA_1" label="P.A. UV HT" titlelabel="P.A. UV HT" />
<FIELD name="VALEUR_METRIQUE_1" label="Longueur par défaut" titlelabel="Longueur par défaut" />
<FIELD name="ID_METRIQUE_1" label="Métrique" titlelabel="Métrique" />
<FIELD name="PRIX_METRIQUE_VT_2" label="P.V. HT" titlelabel="P.V. HT" />
<FIELD name="PRIX_METRIQUE_HA_2" label="P.A. HT" titlelabel="P.A. HT" />
<FIELD name="VALEUR_METRIQUE_2" label="Largeur" titlelabel="Largeur" />
<FIELD name="ID_METRIQUE_2" label="Métrique" titlelabel="Métrique" />
<FIELD name="SERVICE" label="Service" />
<FIELD name="ID_STOCK" label="Stock" />
<FIELD name="PRIX_METRIQUE_VT_1" label="P.V. UV HT" />
<FIELD name="PRIX_METRIQUE_HA_1" label="P.A. UV HT" />
<FIELD name="VALEUR_METRIQUE_1" label="Longueur par défaut" />
<FIELD name="ID_METRIQUE_1" label="Métrique" />
<FIELD name="PRIX_METRIQUE_VT_2" label="P.V. HT" />
<FIELD name="PRIX_METRIQUE_HA_2" label="P.A. HT" />
<FIELD name="VALEUR_METRIQUE_2" label="Largeur" />
<FIELD name="ID_METRIQUE_2" label="Métrique" />
<FIELD name="PRIX_METRIQUE_VT_3" label="P.V. HT" />
<FIELD name="PRIX_METRIQUE_HA_3" label="P.A. HT" />
<FIELD name="VALEUR_METRIQUE_3" label="poids / m²" titlelabel="poids / m²" />
<FIELD name="ID_METRIQUE_3" label="Métrique" titlelabel="Métrique" />
<FIELD name="ID_MODE_VENTE_ARTICLE" label="Mode de vente" titlelabel="Mode de vente" />
<FIELD name="ID_FAMILLE_ARTICLE" label="Famille" titlelabel="Famille" />
<FIELD name="OBSOLETE" label="Obsolete" titlelabel="Obsolete" />
<FIELD name="PRIX_REVENTE_HT" label="Prix de revente ht" titlelabel="Prix de revente ht" />
<FIELD name="PRIX_FINAL_TTC" label="Prix client final ttc" titlelabel="Prix client final ttc" />
<FIELD name="ID_ECOTAXE" label="Ecotaxe" titlelabel="Ecotaxe" />
<FIELD name="ID_COMPTE_PCE" label="Compte spécifique de vente" titlelabel="Compte spécifique de vente" />
<FIELD name="ID_COMPTE_PCE_ACHAT" label="Compte spécifique d'achat" titlelabel="Compte spécifique d'achat" />
<FIELD name="VALEUR_METRIQUE_3" label="poids / m²" />
<FIELD name="ID_METRIQUE_3" label="Métrique" />
<FIELD name="ID_MODE_VENTE_ARTICLE" label="Mode de vente" />
<FIELD name="ID_FAMILLE_ARTICLE" label="Famille" />
<FIELD name="OBSOLETE" label="Obsolete" />
<FIELD name="PRIX_REVENTE_HT" label="Prix de revente ht" />
<FIELD name="PRIX_FINAL_TTC" label="Prix client final ttc" />
<FIELD name="ID_ECOTAXE" label="Ecotaxe" />
<FIELD name="ID_COMPTE_PCE" label="Compte spécifique de vente" />
<FIELD name="ID_COMPTE_PCE_ACHAT" label="Compte spécifique d'achat" />
<FIELD name="SKU" label="SKU" />
<FIELD name="ID_DEPOT_STOCK" label="Dépôt Stock" />
</TABLE>
 
<TABLE name="ARTICLE_CATEGORIE_COMPTABLE">
</element>
<element refid="sales.product.compta" nameClass="feminine" name="liaison article catégorie comptable"
namePlural="liaisons article catégorie comptable">
<FIELD name="ID_ARTICLE" label="Article" />
<FIELD name="ID_CATEGORIE_COMPTABLE" label="Catégorie comptable" />
<FIELD name="ID_TAXE_ACHAT" label="Taxe achat associée" />
148,43 → 151,40
<FIELD name="ID_TAXE_VENTE" label="Taxe vente associée" />
<FIELD name="ID_COMPTE_PCE_VENTE" label="Compte spécifique de vente" />