OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 142 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 142 Rev 156
1
/*
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 * 
3
 * 
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 * 
5
 * 
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
9
 * language governing permissions and limitations under the License.
10
 * 
10
 * 
11
 * When distributing the software, include this License Header Notice in each file.
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
12
 */
13
 
13
 
14
 package org.openconcerto.erp.core.supplychain.stock.element;
14
 package org.openconcerto.erp.core.supplychain.stock.element;
15
 
15
 
16
import org.openconcerto.erp.core.sales.product.model.ProductComponent;
16
import org.openconcerto.erp.core.sales.product.model.ProductComponent;
17
import org.openconcerto.erp.core.sales.product.model.ProductHelper;
17
import org.openconcerto.erp.core.sales.product.model.ProductHelper;
18
import org.openconcerto.erp.core.supplychain.stock.element.StockItem.TypeStockMouvement;
18
import org.openconcerto.erp.core.supplychain.stock.element.StockItem.TypeStockMouvement;
19
import org.openconcerto.sql.model.ConnectionHandlerNoSetup;
19
import org.openconcerto.sql.model.ConnectionHandlerNoSetup;
20
import org.openconcerto.sql.model.DBRoot;
20
import org.openconcerto.sql.model.DBRoot;
21
import org.openconcerto.sql.model.SQLDataSource;
21
import org.openconcerto.sql.model.SQLDataSource;
22
import org.openconcerto.sql.model.SQLRow;
22
import org.openconcerto.sql.model.SQLRow;
23
import org.openconcerto.sql.model.SQLRowAccessor;
23
import org.openconcerto.sql.model.SQLRowAccessor;
24
import org.openconcerto.sql.model.SQLRowValues;
24
import org.openconcerto.sql.model.SQLRowValues;
25
import org.openconcerto.sql.model.SQLRowValuesListFetcher;
25
import org.openconcerto.sql.model.SQLRowValuesListFetcher;
26
import org.openconcerto.sql.model.SQLSelect;
26
import org.openconcerto.sql.model.SQLSelect;
27
import org.openconcerto.sql.model.SQLTable;
27
import org.openconcerto.sql.model.SQLTable;
28
import org.openconcerto.sql.model.Where;
28
import org.openconcerto.sql.model.Where;
29
import org.openconcerto.sql.utils.SQLUtils;
29
import org.openconcerto.sql.utils.SQLUtils;
30
import org.openconcerto.utils.DecimalUtils;
30
import org.openconcerto.utils.DecimalUtils;
31
import org.openconcerto.utils.ExceptionHandler;
31
import org.openconcerto.utils.ExceptionHandler;
32
import org.openconcerto.utils.ListMap;
32
import org.openconcerto.utils.ListMap;
33
import org.openconcerto.utils.RTInterruptedException;
33
import org.openconcerto.utils.RTInterruptedException;
34
import org.openconcerto.utils.Tuple3;
34
import org.openconcerto.utils.Tuple3;
35
import org.openconcerto.utils.cc.ITransformer;
35
import org.openconcerto.utils.cc.ITransformer;
36
 
36
 
37
import java.awt.GraphicsEnvironment;
37
import java.awt.GraphicsEnvironment;
38
import java.io.IOException;
38
import java.io.IOException;
39
import java.math.BigDecimal;
39
import java.math.BigDecimal;
40
import java.math.RoundingMode;
40
import java.math.RoundingMode;
41
import java.sql.SQLException;
41
import java.sql.SQLException;
42
import java.text.SimpleDateFormat;
42
import java.text.SimpleDateFormat;
43
import java.util.ArrayList;
43
import java.util.ArrayList;
44
import java.util.Date;
44
import java.util.Date;
45
import java.util.HashMap;
45
import java.util.HashMap;
46
import java.util.List;
46
import java.util.List;
47
import java.util.Map;
47
import java.util.Map;
48
 
48
 
49
import javax.swing.JOptionPane;
49
import javax.swing.JOptionPane;
50
import javax.swing.SwingUtilities;
50
import javax.swing.SwingUtilities;
51
 
51
 
52
import org.apache.commons.dbutils.ResultSetHandler;
52
import org.apache.commons.dbutils.ResultSetHandler;
53
 
53
 
54
public class StockItemsUpdater {
54
public class StockItemsUpdater {
55
 
55
 
56
    private final StockLabel label;
56
    private final StockLabel label;
57
    private final List<? extends SQLRowAccessor> items;
57
    private final List<? extends SQLRowAccessor> items;
58
    private final TypeStockUpdate type;
58
    private final TypeStockUpdate type;
59
    private final boolean createMouvementStock;
59
    private final boolean createMouvementStock;
60
    private final SQLRowAccessor rowSource;
60
    private final SQLRowAccessor rowSource;
-
 
61
    private boolean resetStockTH = false;
61
 
62
 
62
    private boolean headless = false;
63
    private boolean headless = false;
63
 
64
 
64
    public static enum TypeStockUpdate {
65
    public static enum TypeStockUpdate {
65
 
66
 
66
        VIRTUAL_RECEPT(true, TypeStockMouvement.THEORIQUE), REAL_RECEPT(true, TypeStockMouvement.REEL), VIRTUAL_DELIVER(false, TypeStockMouvement.THEORIQUE), REAL_DELIVER(false,
67
        VIRTUAL_RECEPT(true, TypeStockMouvement.THEORIQUE), REAL_RECEPT(true, TypeStockMouvement.REEL), VIRTUAL_DELIVER(false, TypeStockMouvement.THEORIQUE), REAL_DELIVER(false,
67
                TypeStockMouvement.REEL), REAL_VIRTUAL_RECEPT(true,
68
                TypeStockMouvement.REEL), REAL_VIRTUAL_RECEPT(true,
68
                        TypeStockMouvement.REEL_THEORIQUE), RETOUR_AVOIR_CLIENT(true, TypeStockMouvement.RETOUR), REAL_VIRTUAL_DELIVER(false, TypeStockMouvement.REEL_THEORIQUE);
69
                        TypeStockMouvement.REEL_THEORIQUE), RETOUR_AVOIR_CLIENT(true, TypeStockMouvement.RETOUR), REAL_VIRTUAL_DELIVER(false, TypeStockMouvement.REEL_THEORIQUE);
69
 
70
 
70
        private final boolean entry;
71
        private final boolean entry;
71
        private final TypeStockMouvement type;
72
        private final TypeStockMouvement type;
72
 
73
 
73
        /**
74
        /**
74
         * 
75
         * 
75
         * @param entry
76
         * @param entry
76
         */
77
         */
77
        TypeStockUpdate(boolean entry, TypeStockMouvement type) {
78
        TypeStockUpdate(boolean entry, TypeStockMouvement type) {
78
            this.entry = entry;
79
            this.entry = entry;
79
            this.type = type;
80
            this.type = type;
80
        }
81
        }
81
 
82
 
82
        public boolean isEntry() {
83
        public boolean isEntry() {
83
            return entry;
84
            return entry;
84
        }
85
        }
85
 
86
 
86
        public TypeStockMouvement getType() {
87
        public TypeStockMouvement getType() {
87
            return type;
88
            return type;
88
        }
89
        }
89
    };
90
    };
90
 
91
 
91
    public StockItemsUpdater(StockLabel label, SQLRowAccessor rowSource, List<? extends SQLRowAccessor> items, TypeStockUpdate t) {
92
    public StockItemsUpdater(StockLabel label, SQLRowAccessor rowSource, List<? extends SQLRowAccessor> items, TypeStockUpdate t) {
92
        this(label, rowSource, items, t, true);
93
        this(label, rowSource, items, t, true);
93
    }
94
    }
94
 
95
 
95
    public StockItemsUpdater(StockLabel label, SQLRowAccessor rowSource, List<? extends SQLRowAccessor> items, TypeStockUpdate t, boolean createMouvementStock) {
96
    public StockItemsUpdater(StockLabel label, SQLRowAccessor rowSource, List<? extends SQLRowAccessor> items, TypeStockUpdate t, boolean createMouvementStock) {
96
        this.label = label;
97
        this.label = label;
97
        this.items = items;
98
        this.items = items;
98
        this.type = t;
99
        this.type = t;
99
        this.createMouvementStock = createMouvementStock;
100
        this.createMouvementStock = createMouvementStock;
100
        this.rowSource = rowSource;
101
        this.rowSource = rowSource;
101
        this.headless = GraphicsEnvironment.isHeadless();
102
        this.headless = GraphicsEnvironment.isHeadless();
102
    }
103
    }
103
 
104
 
104
    public void setHeadless(boolean headless) {
105
    public void setHeadless(boolean headless) {
105
        this.headless = headless;
106
        this.headless = headless;
106
    }
107
    }
107
 
108
 
108
    List<Tuple3<SQLRowAccessor, Integer, BigDecimal>> reliquat = new ArrayList<Tuple3<SQLRowAccessor, Integer, BigDecimal>>();
109
    List<Tuple3<SQLRowAccessor, Integer, BigDecimal>> reliquat = new ArrayList<Tuple3<SQLRowAccessor, Integer, BigDecimal>>();
109
 
110
 
110
    public void addReliquat(SQLRowAccessor article, int qte, BigDecimal qteUnit) {
111
    public void addReliquat(SQLRowAccessor article, int qte, BigDecimal qteUnit) {
111
        reliquat.add(Tuple3.create(article, qte, qteUnit));
112
        reliquat.add(Tuple3.create(article, qte, qteUnit));
112
    }
113
    }
113
 
114
 
114
    List<String> requests = new ArrayList<String>();
115
    List<String> requests = new ArrayList<String>();
115
 
116
 
116
    public void update() throws SQLException {
117
    public void update() throws SQLException {
117
        final SQLTable stockTable = this.rowSource.getTable().getTable("STOCK");
118
        final SQLTable stockTable = this.rowSource.getTable().getTable("STOCK");
118
 
119
 
119
        if (this.createMouvementStock) {
120
        if (this.createMouvementStock) {
120
            clearExistingMvt(this.rowSource);
121
            clearExistingMvt(this.rowSource);
121
        }
122
        }
122
 
123
 
123
        // Mise à jour des stocks des articles non composés
124
        // Mise à jour des stocks des articles non composés
124
        List<StockItem> stockItems = fetch();
125
        List<StockItem> stockItems = fetch();
125
 
126
 
126
        final ListMap<SQLRow, SQLRowValues> cmd = new ListMap<SQLRow, SQLRowValues>();
127
        final ListMap<SQLRow, SQLRowValues> cmd = new ListMap<SQLRow, SQLRowValues>();
127
 
128
 
128
        for (StockItem stockItem : stockItems) {
129
        for (StockItem stockItem : stockItems) {
129
 
130
 
130
            if (stockItem.isStockInit()) {
131
            if (stockItem.isStockInit()) {
131
                requests.add(stockItem.getUpdateRequest());
132
                requests.add(stockItem.getUpdateRequest());
132
            } else {
133
            } else {
133
                SQLRowValues rowVals = new SQLRowValues(stockTable);
134
                SQLRowValues rowVals = new SQLRowValues(stockTable);
134
                rowVals.put("QTE_REEL", stockItem.getRealQty());
135
                rowVals.put("QTE_REEL", stockItem.getRealQty());
135
                rowVals.put("QTE_TH", stockItem.getVirtualQty());
136
                rowVals.put("QTE_TH", stockItem.getVirtualQty());
136
                rowVals.put("QTE_LIV_ATTENTE", stockItem.getDeliverQty());
137
                rowVals.put("QTE_LIV_ATTENTE", stockItem.getDeliverQty());
137
                rowVals.put("QTE_RECEPT_ATTENTE", stockItem.getReceiptQty());
138
                rowVals.put("QTE_RECEPT_ATTENTE", stockItem.getReceiptQty());
-
 
139
                rowVals.put("ID_ARTICLE", stockItem.getArticle().getID());
-
 
140
                rowVals.put("ID_DEPOT_STOCK", stockItem.stock.getForeignID("ID_DEPOT_STOCK"));
-
 
141
                rowVals.commit();
-
 
142
                if (stockItem.getArticle().getForeignID("ID_DEPOT_STOCK") == stockItem.stock.getForeignID("ID_DEPOT_STOCK")) {
138
                SQLRowValues rowValsArt = stockItem.getArticle().createEmptyUpdateRow();
143
                    SQLRowValues rowValsArt = stockItem.getArticle().createEmptyUpdateRow();
139
                rowValsArt.put("ID_STOCK", rowVals);
144
                    rowValsArt.put("ID_STOCK", rowVals);
140
                rowValsArt.commit();
145
                    rowValsArt.commit();
141
            }
146
                }
-
 
147
            }
142
            if (!this.type.isEntry()) {
148
            if (!this.type.isEntry()) {
143
                stockItem.fillCommandeFournisseur(cmd);
149
                stockItem.fillCommandeFournisseur(cmd);
144
            }
150
            }
145
        }
151
        }
146
 
152
 
147
        final List<? extends ResultSetHandler> handlers = new ArrayList<ResultSetHandler>(requests.size());
153
        final List<? extends ResultSetHandler> handlers = new ArrayList<ResultSetHandler>(requests.size());
148
        for (String s : requests) {
154
        for (String s : requests) {
149
            handlers.add(null);
155
            handlers.add(null);
150
        }
156
        }
151
        // FIXME FIRE TABLE CHANGED TO UPDATE ILISTE ??
157
        // FIXME FIRE TABLE CHANGED TO UPDATE ILISTE ??
152
        try {
158
        try {
153
            SQLUtils.executeAtomic(stockTable.getDBSystemRoot().getDataSource(), new ConnectionHandlerNoSetup<Object, IOException>() {
159
            SQLUtils.executeAtomic(stockTable.getDBSystemRoot().getDataSource(), new ConnectionHandlerNoSetup<Object, IOException>() {
154
                @Override
160
                @Override
155
                public Object handle(SQLDataSource ds) throws SQLException, IOException {
161
                public Object handle(SQLDataSource ds) throws SQLException, IOException {
156
                    SQLUtils.executeMultiple(stockTable.getDBSystemRoot(), requests, handlers);
162
                    SQLUtils.executeMultiple(stockTable.getDBSystemRoot(), requests, handlers);
157
                    return null;
163
                    return null;
158
                }
164
                }
159
            });
165
            });
160
        } catch (IOException e) {
166
        } catch (IOException e) {
161
            ExceptionHandler.handle("Erreur de la mise à jour des stocks!", e);
167
            ExceptionHandler.handle("Erreur de la mise à jour des stocks!", e);
162
        }
168
        }
163
 
169
 
164
        final DBRoot root = this.rowSource.getTable().getDBRoot();
170
        final DBRoot root = this.rowSource.getTable().getDBRoot();
165
        if (root.contains("ARTICLE_ELEMENT")) {
171
        if (root.contains("ARTICLE_ELEMENT")) {
166
            // Mise à jour des stocks des nomenclatures
172
            // Mise à jour des stocks des nomenclatures
167
            ComposedItemStockUpdater comp = new ComposedItemStockUpdater(root, stockItems);
173
            ComposedItemStockUpdater comp = new ComposedItemStockUpdater(root, stockItems);
168
            comp.update();
174
            comp.update();
169
        }
175
        }
170
 
176
 
171
        // FIXME Créer une interface de saisie de commande article en dessous du seuil mini de stock
177
        // FIXME Créer une interface de saisie de commande article en dessous du seuil mini de stock
172
        if (!headless && cmd.size() > 0) {
178
        if (!headless && cmd.size() > 0) {
173
            String msg = "Les articles suivants sont inférieurs au stock minimum : \n";
179
            String msg = "Les articles suivants sont inférieurs au stock minimum : \n";
174
            for (SQLRow row : cmd.keySet()) {
180
            for (SQLRow row : cmd.keySet()) {
175
                for (SQLRowValues rowVals : cmd.get(row)) {
181
                for (SQLRowValues rowVals : cmd.get(row)) {
176
                    msg += rowVals.getString("CODE") + " " + rowVals.getString("NOM") + "\n";
182
                    msg += rowVals.getString("CODE") + " " + rowVals.getString("NOM") + "\n";
177
                }
183
                }
178
            }
184
            }
179
            final String msgFinal = msg;
185
            final String msgFinal = msg;
180
            SwingUtilities.invokeLater(new Runnable() {
186
            SwingUtilities.invokeLater(new Runnable() {
181
 
187
 
182
                @Override
188
                @Override
183
                public void run() {
189
                public void run() {
184
                    JOptionPane.showMessageDialog(null, msgFinal, "Alerte de stock minimum", JOptionPane.WARNING_MESSAGE);
190
                    JOptionPane.showMessageDialog(null, msgFinal, "Alerte de stock minimum", JOptionPane.WARNING_MESSAGE);
185
                }
191
                }
186
            });
192
            });
187
        }
193
        }
188
 
194
 
189
    }
195
    }
190
 
196
 
191
    /**
197
    /**
192
     * Suppression des anciens mouvements
198
     * Suppression des anciens mouvements
193
     * 
199
     * 
194
     * @param rowSource
200
     * @param rowSource
195
     * @throws SQLException
201
     * @throws SQLException
196
     * @throws RTInterruptedException
202
     * @throws RTInterruptedException
197
     */
203
     */
198
    private void clearExistingMvt(SQLRowAccessor rowSource) throws RTInterruptedException, SQLException {
204
    private void clearExistingMvt(SQLRowAccessor rowSource) throws RTInterruptedException, SQLException {
199
 
205
 
200
        List<String> multipleRequests = new ArrayList<String>();
206
        List<String> multipleRequests = new ArrayList<String>();
201
 
207
 
202
        final SQLTable table = this.rowSource.getTable().getTable("MOUVEMENT_STOCK");
208
        final SQLTable table = this.rowSource.getTable().getTable("MOUVEMENT_STOCK");
203
        SQLRowValues rowVals = new SQLRowValues(table);
209
        SQLRowValues rowVals = new SQLRowValues(table);
204
        rowVals.put("QTE", null);
210
        rowVals.put("QTE", null);
205
        rowVals.put("REEL", null);
211
        rowVals.put("REEL", null);
206
        SQLRowValues rowValsArt = new SQLRowValues(this.rowSource.getTable().getTable("ARTICLE"));
212
        SQLRowValues rowValsArt = new SQLRowValues(this.rowSource.getTable().getTable("ARTICLE"));
207
        SQLRowValues rowValsStock = new SQLRowValues(this.rowSource.getTable().getTable("STOCK"));
213
        SQLRowValues rowValsStock = new SQLRowValues(this.rowSource.getTable().getTable("STOCK"));
208
        rowValsStock.put("QTE_REEL", null);
214
        rowValsStock.put("QTE_REEL", null);
209
        rowValsStock.put("QTE_TH", null);
215
        rowValsStock.put("QTE_TH", null);
210
        rowValsStock.put("QTE_RECEPT_ATTENTE", null);
216
        rowValsStock.put("QTE_RECEPT_ATTENTE", null);
211
        rowValsStock.put("QTE_LIV_ATTENTE", null);
217
        rowValsStock.put("QTE_LIV_ATTENTE", null);
212
 
218
 
213
        rowValsArt.put("ID_STOCK", rowValsStock);
219
        rowVals.put("ID_STOCK", rowValsStock);
214
        rowVals.put("ID_ARTICLE", rowValsArt);
220
        rowVals.put("ID_ARTICLE", rowValsArt);
215
 
221
 
216
        SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowVals);
222
        SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowVals);
217
        fetcher.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() {
223
        fetcher.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() {
218
 
224
 
219
            @Override
225
            @Override
220
            public SQLSelect transformChecked(SQLSelect input) {
226
            public SQLSelect transformChecked(SQLSelect input) {
221
                Where w = new Where(table.getField("SOURCE"), "=", StockItemsUpdater.this.rowSource.getTable().getName());
227
                Where w = new Where(table.getField("SOURCE"), "=", StockItemsUpdater.this.rowSource.getTable().getName());
222
                w = w.and(new Where(table.getField("IDSOURCE"), "=", StockItemsUpdater.this.rowSource.getID()));
228
                w = w.and(new Where(table.getField("IDSOURCE"), "=", StockItemsUpdater.this.rowSource.getID()));
223
                input.setWhere(w);
229
                input.setWhere(w);
224
                return input;
230
                return input;
225
            }
231
            }
226
        });
232
        });
227
 
233
 
228
        // On stocke les items pour le calcul total des stocks (sinon le calcul est faux si
234
        // On stocke les items pour le calcul total des stocks (sinon le calcul est faux si
229
        // l'article apparait plusieurs fois
235
        // l'article apparait plusieurs fois
230
        // ou si
236
        // ou si
231
        // on archive un mvt reel et theorique)
237
        // on archive un mvt reel et theorique)
232
        Map<Number, StockItem> items = new HashMap<Number, StockItem>();
238
        Map<Number, StockItem> items = new HashMap<Number, StockItem>();
233
        List<SQLRowValues> result = fetcher.fetch();
239
        List<SQLRowValues> result = fetcher.fetch();
234
        for (SQLRowValues sqlRowValues : result) {
240
        for (SQLRowValues sqlRowValues : result) {
235
            final StockItem item;
241
            final StockItem item;
236
            if (!items.containsKey(sqlRowValues.getForeignIDNumber("ID_ARTICLE"))) {
242
            if (!items.containsKey(sqlRowValues.getForeignIDNumber("ID_STOCK"))) {
237
                item = new StockItem(sqlRowValues.getForeign("ID_ARTICLE"));
243
                item = new StockItem(sqlRowValues.getForeign("ID_ARTICLE"), sqlRowValues.getForeign("ID_STOCK"));
238
                items.put(sqlRowValues.getForeignIDNumber("ID_ARTICLE"), item);
244
                items.put(sqlRowValues.getForeignIDNumber("ID_STOCK"), item);
239
            } else {
245
            } else {
240
                item = items.get(sqlRowValues.getForeignIDNumber("ID_ARTICLE"));
246
                item = items.get(sqlRowValues.getForeignIDNumber("ID_STOCK"));
241
            }
247
            }
242
            final TypeStockMouvement t;
248
            final TypeStockMouvement t;
243
            if (sqlRowValues.getBoolean("REEL")) {
249
            if (sqlRowValues.getBoolean("REEL")) {
244
                t = TypeStockMouvement.REEL;
250
                t = TypeStockMouvement.REEL;
245
            } else {
251
            } else {
246
                t = TypeStockMouvement.THEORIQUE;
252
                t = TypeStockMouvement.THEORIQUE;
247
            }
253
            }
248
            item.updateQty(sqlRowValues.getFloat("QTE"), t, true);
254
            item.updateQty(sqlRowValues.getFloat("QTE"), t, true);
249
            String req = "UPDATE " + sqlRowValues.getTable().getSQLName().quote() + " SET \"ARCHIVE\"=1 WHERE \"ID\"=" + sqlRowValues.getID();
255
            String req = "UPDATE " + sqlRowValues.getTable().getSQLName().quote() + " SET \"ARCHIVE\"=1 WHERE \"ID\"=" + sqlRowValues.getID();
250
            multipleRequests.add(req);
256
            multipleRequests.add(req);
251
            multipleRequests.add(item.getUpdateRequest());
257
            multipleRequests.add(item.getUpdateRequest());
252
        }
258
        }
253
 
259
 
254
        List<? extends ResultSetHandler> handlers = new ArrayList<ResultSetHandler>(multipleRequests.size());
260
        List<? extends ResultSetHandler> handlers = new ArrayList<ResultSetHandler>(multipleRequests.size());
255
        for (String s : multipleRequests) {
261
        for (String s : multipleRequests) {
256
            handlers.add(null);
262
            handlers.add(null);
257
        }
263
        }
258
        SQLUtils.executeMultiple(table.getDBSystemRoot(), multipleRequests, handlers);
264
        SQLUtils.executeMultiple(table.getDBSystemRoot(), multipleRequests, handlers);
259
    }
265
    }
260
 
266
 
261
    private void fillProductComponent(List<ProductComponent> productComponents, int qte, int index, int level) {
267
    private void fillProductComponent(List<ProductComponent> productComponents, int qte, int index, int level) {
262
        if (level > 0) {
268
        if (level > 0) {
263
            for (int i = index; i < items.size(); i++) {
269
            for (int i = index; i < items.size(); i++) {
264
                SQLRowAccessor r = items.get(i);
270
                SQLRowAccessor r = items.get(i);
265
 
271
 
266
                if (!r.getTable().contains("NIVEAU") || r.getInt("NIVEAU") >= level) {
272
                if (!r.getTable().contains("NIVEAU") || r.getInt("NIVEAU") >= level) {
267
                    // On ne calcul pas les stocks pour les éléments ayant des fils (le mouvement de
273
                    // On ne calcul pas les stocks pour les éléments ayant des fils (le mouvement de
268
                    // stock
274
                    // stock
269
                    // des fils impactera les stocks automatiquement)
275
                    // des fils impactera les stocks automatiquement)
270
                    if (r.getTable().contains("NIVEAU")) {
276
                    if (r.getTable().contains("NIVEAU")) {
271
                        if (i + 1 < items.size()) {
277
                        if (i + 1 < items.size()) {
272
                            SQLRowAccessor rNext = items.get(i + 1);
278
                            SQLRowAccessor rNext = items.get(i + 1);
273
                            if (rNext.getInt("NIVEAU") > r.getInt("NIVEAU")) {
279
                            if (rNext.getInt("NIVEAU") > r.getInt("NIVEAU")) {
274
                                fillProductComponent(productComponents, qte * r.getInt("QTE"), i + 1, rNext.getInt("NIVEAU"));
280
                                fillProductComponent(productComponents, qte * r.getInt("QTE"), i + 1, rNext.getInt("NIVEAU"));
275
                                continue;
281
                                continue;
276
                            }
282
                            }
277
                        }
283
                        }
278
                    }
284
                    }
279
                    if ((!r.getTable().contains("NIVEAU") || r.getInt("NIVEAU") == level) && !r.isForeignEmpty("ID_ARTICLE") && r.getForeign("ID_ARTICLE") != null) {
285
                    if ((!r.getTable().contains("NIVEAU") || r.getInt("NIVEAU") == level) && !r.isForeignEmpty("ID_ARTICLE") && r.getForeign("ID_ARTICLE") != null) {
280
                        productComponents.add(ProductComponent.createFrom(r, qte));
286
                        productComponents.add(ProductComponent.createFrom(r, qte, r));
281
                    }
287
                    }
282
                } else if (r.getInt("NIVEAU") < level) {
288
                } else if (r.getInt("NIVEAU") < level) {
283
                    // BREAK si on sort de l'article composé
289
                    // BREAK si on sort de l'article composé
284
                    break;
290
                    break;
285
                }
291
                }
286
            }
292
            }
287
        }
293
        }
288
    }
294
    }
289
 
295
 
290
    /**
296
    /**
291
     * Récupére les stocks associés aux articles non composés (inclus les fils des nomenclatures) et
297
     * Récupére les stocks associés aux articles non composés (inclus les fils des nomenclatures) et
292
     * les met à jour
298
     * les met à jour
293
     * 
299
     * 
294
     * @return la liste des stocks à jour
300
     * @return la liste des stocks à jour
295
     */
301
     */
296
    private List<StockItem> fetch() {
302
    private List<StockItem> fetch() {
297
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
303
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
298
        List<StockItem> stockItems = new ArrayList<StockItem>(items.size());
304
        Map<Number, StockItem> stockItems = new HashMap<Number, StockItem>();
-
 
305
 
299
        String mvtStockTableQuoted = rowSource.getTable().getTable("MOUVEMENT_STOCK").getSQLName().quote();
306
        String mvtStockTableQuoted = rowSource.getTable().getTable("MOUVEMENT_STOCK").getSQLName().quote();
300
 
307
 
301
        // Liste des éléments à mettre à jour
308
        // Liste des éléments à mettre à jour
302
        List<ProductComponent> productComponents = new ArrayList<ProductComponent>();
309
        List<ProductComponent> productComponents = new ArrayList<ProductComponent>();
303
        fillProductComponent(productComponents, 1, 0, 1);
310
        fillProductComponent(productComponents, 1, 0, 1);
304
        // for (int i = 0; i < items.size(); i++) {
311
        // for (int i = 0; i < items.size(); i++) {
305
        // SQLRowAccessor r = items.get(i);
312
        // SQLRowAccessor r = items.get(i);
306
        //
313
        //
307
        // // On ne calcul pas les stocks pour les éléments ayant des fils (le mouvement de stock
314
        // // On ne calcul pas les stocks pour les éléments ayant des fils (le mouvement de stock
308
        // // des fils impactera les stocks automatiquement)
315
        // // des fils impactera les stocks automatiquement)
309
        // if (r.getTable().contains("NIVEAU")) {
316
        // if (r.getTable().contains("NIVEAU")) {
310
        // if (i + 1 < items.size()) {
317
        // if (i + 1 < items.size()) {
311
        // SQLRowAccessor rNext = items.get(i + 1);
318
        // SQLRowAccessor rNext = items.get(i + 1);
312
        // if (rNext.getInt("NIVEAU") > r.getInt("NIVEAU")) {
319
        // if (rNext.getInt("NIVEAU") > r.getInt("NIVEAU")) {
313
        // continue;
320
        // continue;
314
        // }
321
        // }
315
        // }
322
        // }
316
        // }
323
        // }
317
        // if (!r.isForeignEmpty("ID_ARTICLE")) {
324
        // if (!r.isForeignEmpty("ID_ARTICLE")) {
318
        // productComponents.add(ProductComponent.createFrom(r));
325
        // productComponents.add(ProductComponent.createFrom(r));
319
        // }
326
        // }
320
        // }
327
        // }
321
 
328
 
322
        // Liste des articles non composés à mettre à jour (avec les fils des nomenclatures)
329
        // Liste des articles non composés à mettre à jour (avec les fils des nomenclatures)
323
        ProductHelper helper = new ProductHelper(rowSource.getTable().getDBRoot());
330
        ProductHelper helper = new ProductHelper(rowSource.getTable().getDBRoot());
324
        List<ProductComponent> boms = helper.getChildWithQtyFrom(productComponents);
331
        List<ProductComponent> boms = helper.getChildWithQtyFrom(productComponents);
325
 
332
 
326
        for (ProductComponent productComp : boms) {
333
        for (ProductComponent productComp : boms) {
327
 
334
 
328
            if (productComp.getProduct().getBoolean("GESTION_STOCK") && productComp.getQty().signum() != 0) {
335
            if (productComp.getProduct().getBoolean("GESTION_STOCK") && productComp.getQty().signum() != 0) {
-
 
336
                final StockItem stockItem;
-
 
337
                if (!stockItems.containsKey(productComp.getStock().getID())) {
329
                StockItem stockItem = new StockItem(productComp.getProduct());
338
                    stockItem = new StockItem(productComp.getProduct(), productComp.getStock());
-
 
339
                    stockItems.put(productComp.getStock().getID(), stockItem);
-
 
340
                } else {
-
 
341
                    stockItem = stockItems.get(productComp.getStock().getID());
-
 
342
                }
330
                double qteFinal = productComp.getQty().doubleValue();
343
                double qteFinal = productComp.getQty().doubleValue();
331
 
344
 
332
                // reliquat
345
                // reliquat
333
                for (Tuple3<SQLRowAccessor, Integer, BigDecimal> t : reliquat) {
346
                for (Tuple3<SQLRowAccessor, Integer, BigDecimal> t : reliquat) {
334
                    if (stockItem.getArticle() != null && stockItem.getArticle().equalsAsRow(t.get0())) {
347
                    if (stockItem.getArticle() != null && stockItem.getArticle().equalsAsRow(t.get0())) {
335
                        double qteFinalReliquat = t.get2().multiply(new BigDecimal(t.get1()), DecimalUtils.HIGH_PRECISION).doubleValue();
348
                        double qteFinalReliquat = t.get2().multiply(new BigDecimal(t.get1()), DecimalUtils.HIGH_PRECISION).doubleValue();
336
                        qteFinal -= qteFinalReliquat;
349
                        qteFinal -= qteFinalReliquat;
337
                    }
350
                    }
338
                }
351
                }
339
                if (!this.type.isEntry()) {
352
                if (!this.type.isEntry()) {
340
                    qteFinal = -qteFinal;
353
                    qteFinal = -qteFinal;
341
                }
354
                }
342
 
355
 
343
                stockItem.updateQty(qteFinal, this.type.getType());
356
                stockItem.updateQty(qteFinal, this.type.getType());
344
                stockItems.add(stockItem);
-
 
-
 
357
 
345
                if (this.createMouvementStock) {
358
                if (this.createMouvementStock) {
346
                    final Date time = this.rowSource.getDate("DATE").getTime();
359
                    final Date time = this.rowSource.getDate("DATE").getTime();
347
                    BigDecimal prc = productComp.getPRC(time);
360
                    BigDecimal prc = productComp.getPRC(time);
348
                    if (this.type.getType() == TypeStockMouvement.REEL || this.type.getType() == TypeStockMouvement.REEL_THEORIQUE || this.type.getType() == TypeStockMouvement.RETOUR) {
361
                    if (this.type.getType() == TypeStockMouvement.REEL || this.type.getType() == TypeStockMouvement.REEL_THEORIQUE || this.type.getType() == TypeStockMouvement.RETOUR) {
349
                        String mvtStockQuery = "INSERT INTO " + mvtStockTableQuoted + " (\"QTE\",\"DATE\",\"ID_ARTICLE\",\"SOURCE\",\"IDSOURCE\",\"NOM\",\"REEL\",\"ORDRE\"";
362
                        String mvtStockQuery = "INSERT INTO " + mvtStockTableQuoted + " (\"QTE\",\"DATE\",\"ID_ARTICLE\",\"ID_STOCK\",\"SOURCE\",\"IDSOURCE\",\"NOM\",\"REEL\",\"ORDRE\"";
350
 
363
 
351
                        if (prc != null) {
364
                        if (prc != null) {
352
                            mvtStockQuery += ",\"PRICE\"";
365
                            mvtStockQuery += ",\"PRICE\"";
353
                        }
366
                        }
354
 
367
 
355
                        mvtStockQuery += ") VALUES(" + qteFinal + ",'" + dateFormat.format(time) + "'," + productComp.getProduct().getID() + ",'" + this.rowSource.getTable().getName() + "',"
368
                        mvtStockQuery += ") VALUES(" + qteFinal + ",'" + dateFormat.format(time) + "'," + productComp.getProduct().getID() + "," + productComp.getStock().getID() + ",'"
356
                                + this.rowSource.getID() + ",'" + this.label.getLabel(this.rowSource, productComp.getProduct()) + "',true, (SELECT (MAX(\"ORDRE\")+1) FROM " + mvtStockTableQuoted
369
                                + this.rowSource.getTable().getName() + "'," + this.rowSource.getID() + ",'" + this.label.getLabel(this.rowSource, productComp.getProduct())
357
                                + ")";
370
                                + "',true, (SELECT (MAX(\"ORDRE\")+1) FROM " + mvtStockTableQuoted + ")";
358
                        if (prc != null) {
371
                        if (prc != null) {
359
                            mvtStockQuery += "," + prc.setScale(6, RoundingMode.HALF_UP).toString();
372
                            mvtStockQuery += "," + prc.setScale(6, RoundingMode.HALF_UP).toString();
360
                        }
373
                        }
361
                        mvtStockQuery += ")";
374
                        mvtStockQuery += ")";
362
                        this.requests.add(mvtStockQuery);
375
                        this.requests.add(mvtStockQuery);
363
                    }
376
                    }
364
                    if (this.type.getType() == TypeStockMouvement.THEORIQUE || this.type.getType() == TypeStockMouvement.REEL_THEORIQUE || this.type.getType() == TypeStockMouvement.RETOUR) {
377
                    if (this.type.getType() == TypeStockMouvement.THEORIQUE || this.type.getType() == TypeStockMouvement.REEL_THEORIQUE || this.type.getType() == TypeStockMouvement.RETOUR) {
365
                        String mvtStockQuery = "INSERT INTO " + mvtStockTableQuoted + " (\"QTE\",\"DATE\",\"ID_ARTICLE\",\"SOURCE\",\"IDSOURCE\",\"NOM\",\"REEL\",\"ORDRE\"";
378
                        String mvtStockQuery = "INSERT INTO " + mvtStockTableQuoted + " (\"QTE\",\"DATE\",\"ID_ARTICLE\",\"ID_STOCK\",\"SOURCE\",\"IDSOURCE\",\"NOM\",\"REEL\",\"ORDRE\"";
366
                        if (prc != null) {
379
                        if (prc != null) {
367
                            mvtStockQuery += ",\"PRICE\"";
380
                            mvtStockQuery += ",\"PRICE\"";
368
                        }
381
                        }
369
 
382
 
370
                        mvtStockQuery += ") VALUES(" + qteFinal + ",'" + dateFormat.format(time) + "'," + productComp.getProduct().getID() + ",'" + this.rowSource.getTable().getName() + "',"
383
                        mvtStockQuery += ") VALUES(" + qteFinal + ",'" + dateFormat.format(time) + "'," + productComp.getProduct().getID() + "," + productComp.getStock().getID() + ",'"
371
                                + this.rowSource.getID() + ",'" + this.label.getLabel(this.rowSource, productComp.getProduct()) + "',false, (SELECT (MAX(\"ORDRE\")+1) FROM " + mvtStockTableQuoted
384
                                + this.rowSource.getTable().getName() + "'," + this.rowSource.getID() + ",'" + this.label.getLabel(this.rowSource, productComp.getProduct())
372
                                + ")";
385
                                + "',false, (SELECT (MAX(\"ORDRE\")+1) FROM " + mvtStockTableQuoted + ")";
373
                        if (prc != null) {
386
                        if (prc != null) {
374
                            mvtStockQuery += "," + prc.setScale(6, RoundingMode.HALF_UP).toString();
387
                            mvtStockQuery += "," + prc.setScale(6, RoundingMode.HALF_UP).toString();
375
                        }
388
                        }
376
                        mvtStockQuery += ")";
389
                        mvtStockQuery += ")";
377
                        this.requests.add(mvtStockQuery);
390
                        this.requests.add(mvtStockQuery);
378
                    }
391
                    }
379
                }
392
                }
380
            }
393
            }
381
        }
394
        }
382
 
395
 
-
 
396
        return new ArrayList<StockItem>(stockItems.values());
-
 
397
    }
-
 
398
 
-
 
399
    public void setResetStockTH(boolean resetStockTH) {
383
        return stockItems;
400
        this.resetStockTH = resetStockTH;
384
    }
401
    }
385
}
402
}