OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 156 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
83 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
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
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.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 package org.openconcerto.erp.core.supplychain.stock.element;
15
 
16
import org.openconcerto.sql.model.DBRoot;
156 ilm 17
import org.openconcerto.sql.model.SQLRow;
83 ilm 18
import org.openconcerto.sql.model.SQLRowAccessor;
19
import org.openconcerto.sql.model.SQLRowValues;
20
import org.openconcerto.sql.model.SQLRowValuesListFetcher;
21
import org.openconcerto.sql.model.SQLSelect;
22
import org.openconcerto.sql.model.SQLSelectJoin;
23
import org.openconcerto.sql.model.SQLTable;
180 ilm 24
import org.openconcerto.sql.model.SQLTableEvent;
25
import org.openconcerto.sql.model.SQLTableEvent.Mode;
83 ilm 26
import org.openconcerto.sql.model.Where;
27
import org.openconcerto.sql.request.UpdateBuilder;
28
import org.openconcerto.sql.utils.SQLUtils;
156 ilm 29
import org.openconcerto.utils.ExceptionHandler;
30
import org.openconcerto.utils.Tuple2;
83 ilm 31
import org.openconcerto.utils.cc.ITransformer;
32
 
33
import java.sql.SQLException;
34
import java.util.ArrayList;
156 ilm 35
import java.util.Collection;
83 ilm 36
import java.util.HashMap;
93 ilm 37
import java.util.HashSet;
83 ilm 38
import java.util.List;
39
import java.util.Map;
93 ilm 40
import java.util.Set;
83 ilm 41
 
42
import org.apache.commons.dbutils.ResultSetHandler;
43
 
44
public class ComposedItemStockUpdater {
45
 
46
    private final List<StockItem> itemsUpdated;
47
    private final DBRoot root;
48
 
156 ilm 49
    /// FIXME mettre à jour les stocks des kits à partir des feuilles
50
 
83 ilm 51
    /**
93 ilm 52
     * Met à jour les stocks des nomenclature composé par un des articles de itemsUpdated
83 ilm 53
     *
54
     * @param root
55
     * @param itemsUpdated liste des StockItem non composés qui ont été mis à jour
56
     */
57
    public ComposedItemStockUpdater(DBRoot root, List<StockItem> itemsUpdated) {
58
        this.itemsUpdated = itemsUpdated;
59
        this.root = root;
60
    }
61
 
62
    /**
63
     * Mise à jour des stocks en fonction des composants de l'article
64
     *
65
     * @throws SQLException
66
     */
67
    public void update() throws SQLException {
142 ilm 68
        // Liste des nomenclatures dépendantes des itemsUpdated
83 ilm 69
        List<StockItem> items = getAllComposedItemToUpdate();
156 ilm 70
        updateNomenclature(items);
71
    }
83 ilm 72
 
156 ilm 73
    public void updateNomenclature(List<StockItem> items) throws SQLException {
74
 
83 ilm 75
        // Fecth des articles liés
76
        getAllChildren(items);
77
 
156 ilm 78
        List<StockItem> removedBadItem = new ArrayList<>();
83 ilm 79
        // Mise à jour des stocks
80
        for (StockItem stockItem : items) {
156 ilm 81
            if (!stockItem.updateQtyFromChildren()) {
82
                removedBadItem.add(stockItem);
83
            }
83 ilm 84
        }
156 ilm 85
        items.removeAll(removedBadItem);
83 ilm 86
 
87
        SQLTable stockTable = root.getTable("STOCK");
88
        List<String> requests = new ArrayList<String>();
89
        for (StockItem stockItem : items) {
90
            if (stockItem.isStockInit()) {
91
                UpdateBuilder update = new UpdateBuilder(stockTable);
156 ilm 92
                update.setWhere(new Where(stockTable.getKey(), "=", stockItem.stock.getID()));
83 ilm 93
                update.setObject("QTE_REEL", stockItem.getRealQty());
94
                update.setObject("QTE_TH", stockItem.getVirtualQty());
95
                update.setObject("QTE_LIV_ATTENTE", stockItem.getDeliverQty());
96
                update.setObject("QTE_RECEPT_ATTENTE", stockItem.getReceiptQty());
97
                requests.add(update.asString());
98
            } else {
99
                SQLRowValues rowVals = new SQLRowValues(stockTable);
100
                rowVals.put("QTE_REEL", stockItem.getRealQty());
101
                rowVals.put("QTE_TH", stockItem.getVirtualQty());
102
                rowVals.put("QTE_LIV_ATTENTE", stockItem.getDeliverQty());
103
                rowVals.put("QTE_RECEPT_ATTENTE", stockItem.getReceiptQty());
156 ilm 104
                rowVals.put("ID_ARTICLE", stockItem.getArticle().getID());
105
                rowVals.put("ID_DEPOT_STOCK", stockItem.stock.getForeignID("ID_DEPOT_STOCK"));
106
                rowVals.commit();
107
                if (stockItem.getArticle().getForeignID("ID_DEPOT_STOCK") == stockItem.stock.getForeignID("ID_DEPOT_STOCK")) {
108
                    SQLRowValues rowValsArt = stockItem.getArticle().createEmptyUpdateRow();
109
                    rowValsArt.put("ID_STOCK", rowVals);
110
                    rowValsArt.commit();
111
                }
83 ilm 112
            }
113
        }
114
 
115
        List<? extends ResultSetHandler> handlers = new ArrayList<ResultSetHandler>(requests.size());
116
        for (String s : requests) {
117
            handlers.add(null);
118
        }
180 ilm 119
 
83 ilm 120
        SQLUtils.executeMultiple(stockTable.getDBSystemRoot(), requests, handlers);
180 ilm 121
        stockTable.fire(new SQLTableEvent(stockTable, SQLRow.NONEXISTANT_ID, Mode.ROW_UPDATED));
83 ilm 122
    }
123
 
124
    /**
125
     * Associe les StockItems liés aux items passés en parametres
126
     *
127
     * @param items liste des stockitems d'article composé
128
     */
129
    private void getAllChildren(List<StockItem> items) {
130
        final SQLTable tableArticle = this.root.getTable("ARTICLE");
156 ilm 131
        final int undefDepot = tableArticle.getTable("DEPOT_STOCK").getUndefinedID();
83 ilm 132
        final SQLRowValues rowValsArt = new SQLRowValues(tableArticle);
133
        rowValsArt.put(tableArticle.getKey().getName(), null);
134
 
156 ilm 135
        SQLRowValues rowValsStock = new SQLRowValues(this.root.getTable("STOCK"));
83 ilm 136
        rowValsStock.put("QTE_REEL", null);
137
        rowValsStock.put("QTE_TH", null);
138
        rowValsStock.put("QTE_RECEPT_ATTENTE", null);
139
        rowValsStock.put("QTE_LIV_ATTENTE", null);
156 ilm 140
        rowValsStock.put("ID_DEPOT_STOCK", null);
141
        rowValsStock.put("ID_ARTICLE", rowValsArt);
83 ilm 142
 
143
        final SQLTable tableArticleElt = this.root.getTable("ARTICLE_ELEMENT");
144
        SQLRowValues rowValsArtItem = new SQLRowValues(tableArticleElt);
145
        rowValsArtItem.put("ID_ARTICLE", rowValsArt);
146
        rowValsArtItem.put("QTE", null);
147
        rowValsArtItem.put("QTE_UNITAIRE", null);
148
        rowValsArtItem.put("ID_ARTICLE_PARENT", null);
149
 
150
        final List<Integer> ids = new ArrayList<Integer>();
156 ilm 151
        Map<Tuple2<Integer, Integer>, StockItem> mapItem = new HashMap<Tuple2<Integer, Integer>, StockItem>();
83 ilm 152
        for (StockItem stockItem : items) {
153
            final int id = stockItem.getArticle().getID();
154
            ids.add(id);
156 ilm 155
            if (stockItem.stock.getForeignID("ID_DEPOT_STOCK") != undefDepot) {
156
                mapItem.put(Tuple2.create(id, stockItem.stock.getForeignID("ID_DEPOT_STOCK")), stockItem);
157
            }
83 ilm 158
        }
159
 
160
        SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowValsArtItem);
161
        fetcher.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() {
162
 
163
            @Override
164
            public SQLSelect transformChecked(SQLSelect input) {
165
                Where w = new Where(tableArticleElt.getField("ID_ARTICLE_PARENT"), ids);
166
                input.setWhere(w);
167
                return input;
168
            }
169
        });
170
 
171
        List<SQLRowValues> values = fetcher.fetch();
172
        for (SQLRowValues sqlRowValues : values) {
173
 
174
            final SQLRowAccessor article = sqlRowValues.getForeign("ID_ARTICLE");
175
            final SQLRowAccessor articleParent = sqlRowValues.getForeign("ID_ARTICLE_PARENT");
156 ilm 176
            if (article != null && !article.isUndefined()) {
177
                final Collection<? extends SQLRowAccessor> referentStockRows = article.getReferentRows(this.root.getTable("STOCK"));
178
 
179
                {
180
                    // Init Stock if no depot
181
                    if (referentStockRows.size() == 0) {
182
                        // init default stock depot
183
                        SQLRowValues rowVals = new SQLRowValues(article.getTable().getTable("STOCK"));
184
                        rowVals.put("ID_ARTICLE", article.getID());
185
                        rowVals.put("ID_DEPOT_STOCK", DepotStockSQLElement.DEFAULT_ID);
186
                        try {
187
                            SQLRow rowStock = rowVals.commit();
188
                            article.createEmptyUpdateRow().put("ID_STOCK", rowStock.getID()).commit();
189
 
190
                            System.err.println("NO DEPOT STOCK FOR ITEM " + articleParent.getID() + " -- PARENT " + articleParent.getID());
191
                            StockItem stockItem = mapItem.get(Tuple2.create(articleParent.getID(), DepotStockSQLElement.DEFAULT_ID));
192
                            if (stockItem != null) {
193
                                stockItem.addItemComponent(new StockItemComponent(new StockItem(article, rowStock), sqlRowValues.getBigDecimal("QTE_UNITAIRE"), sqlRowValues.getInt("QTE")));
194
                            } else {
195
                                System.err.println("Unable to find stock of item ARTICLE " + articleParent.getID() + " DEPOT " + DepotStockSQLElement.DEFAULT_ID);
196
                            }
197
                        } catch (SQLException e) {
198
                            ExceptionHandler.handle("Erreur lors de l'initialisation du stock de l'article", e);
199
                        }
200
                    }
201
                }
202
 
203
                for (SQLRowAccessor sqlRowAccessor : referentStockRows) {
204
                    StockItem stockItem = mapItem.get(Tuple2.create(articleParent.getID(), sqlRowAccessor.getForeignID("ID_DEPOT_STOCK")));
205
                    if (stockItem != null) {
206
                        stockItem.addItemComponent(new StockItemComponent(new StockItem(article, sqlRowAccessor), sqlRowValues.getBigDecimal("QTE_UNITAIRE"), sqlRowValues.getInt("QTE")));
207
                    } else if (sqlRowAccessor.getForeignID("ID_DEPOT_STOCK") == sqlRowAccessor.getTable().getForeignTable("ID_DEPOT_STOCK").getUndefinedID()) {
208
                        stockItem = mapItem.get(Tuple2.create(articleParent.getID(), DepotStockSQLElement.DEFAULT_ID));
209
                        stockItem.addItemComponent(new StockItemComponent(new StockItem(article, sqlRowAccessor), sqlRowValues.getBigDecimal("QTE_UNITAIRE"), sqlRowValues.getInt("QTE")));
210
                    } else {
211
                        System.err.println("Unable to find stock of item ARTICLE " + articleParent.getID() + " DEPOT " + sqlRowAccessor.getForeignID("ID_DEPOT_STOCK"));
212
                    }
213
                }
214
            }
83 ilm 215
        }
216
    }
217
 
218
    /**
219
     * @return l'ensemble des stockItems composés à mettre à jour
220
     */
221
    private List<StockItem> getAllComposedItemToUpdate() {
93 ilm 222
        // Liste des ids des artciles non composé mis à jour
223
        Set<Integer> ids = new HashSet<Integer>(itemsUpdated.size());
83 ilm 224
        for (StockItem stockItem : itemsUpdated) {
225
            ids.add(stockItem.getArticle().getID());
226
        }
142 ilm 227
        // Liste des nomenclatures dépendantes des itemsUpdated
83 ilm 228
        List<SQLRowValues> list = getComposedItemToUpdate(ids);
229
        int size = list.size();
230
 
93 ilm 231
        Map<Integer, SQLRowValues> result = new HashMap<Integer, SQLRowValues>(ids.size());
232
        for (SQLRowValues sqlRowValues : list) {
233
            result.put(sqlRowValues.getID(), sqlRowValues);
234
        }
156 ilm 235
        // Liste des nomenclatures dépendantes des nomenclatures (kit dans kits)
83 ilm 236
        while (size > 0) {
237
 
238
            List<SQLRowValues> l = getComposedItemToUpdate(ids);
93 ilm 239
            for (SQLRowValues sqlRowValues : l) {
240
                result.put(sqlRowValues.getID(), sqlRowValues);
241
            }
83 ilm 242
            size = l.size();
243
            if (size > 0) {
244
                ids.clear();
245
                for (SQLRowValues r : l) {
156 ilm 246
                    ids.add(r.getForeignID("ID_ARTICLE"));
83 ilm 247
                }
248
            }
249
        }
250
 
93 ilm 251
        List<StockItem> items = new ArrayList<StockItem>(result.size());
252
        for (SQLRowValues rowVals : result.values()) {
83 ilm 253
 
156 ilm 254
            StockItem item = new StockItem(rowVals.getForeign("ID_ARTICLE"), rowVals);
83 ilm 255
            items.add(item);
256
        }
257
        return items;
258
    }
259
 
260
    /**
261
     *
262
     * @param ids
263
     * @return l'ensemble des Articles composés avec un des articles en parametres
264
     */
93 ilm 265
    private List<SQLRowValues> getComposedItemToUpdate(final Set<Integer> ids) {
83 ilm 266
 
267
        final SQLTable tableArticle = this.root.getTable("ARTICLE");
268
        final SQLRowValues rowValsArt = new SQLRowValues(tableArticle);
269
        rowValsArt.put(tableArticle.getKey().getName(), null);
270
 
156 ilm 271
        SQLRowValues rowValsStock = new SQLRowValues(this.root.getTable("STOCK"));
83 ilm 272
        rowValsStock.put("QTE_REEL", null);
273
        rowValsStock.put("QTE_TH", null);
274
        rowValsStock.put("QTE_RECEPT_ATTENTE", null);
275
        rowValsStock.put("QTE_LIV_ATTENTE", null);
156 ilm 276
        rowValsStock.put("ID_ARTICLE", rowValsArt);
277
        rowValsStock.put("ID_DEPOT_STOCK", null);
83 ilm 278
 
279
        final SQLTable tableArticleElt = this.root.getTable("ARTICLE_ELEMENT");
156 ilm 280
        // SQLRowValues rowValsArtItem = new SQLRowValues(tableArticleElt);
281
        // rowValsArtItem.put("ID_ARTICLE_PARENT", rowValsArt);
83 ilm 282
        // rowValsArtItem.put("QTE", null);
283
        // rowValsArtItem.put("QTE_UNITAIRE", null);
284
 
156 ilm 285
        SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowValsStock);
83 ilm 286
        fetcher.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() {
287
 
288
            @Override
289
            public SQLSelect transformChecked(SQLSelect input) {
156 ilm 290
                SQLSelectJoin joinFromField = input.addJoin("RIGHT", tableArticleElt, new Where(tableArticleElt.getField("ID_ARTICLE_PARENT"), "=", input.getTable("STOCK").getField("ID_ARTICLE")));
83 ilm 291
                Where w = new Where(joinFromField.getJoinedTable().getField("ID_ARTICLE"), ids);
292
                joinFromField.setWhere(w);
156 ilm 293
                input.clearOrder();
294
                input.setDistinct(true);
83 ilm 295
                return input;
296
            }
297
        });
298
 
299
        return fetcher.fetch();
300
    }
301
}