OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 83 | Rev 93 | Go to most recent revision | 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;
90 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.SQLTable;
23
import org.openconcerto.sql.model.Where;
24
import org.openconcerto.sql.utils.SQLUtils;
90 ilm 25
import org.openconcerto.utils.DecimalUtils;
26
import org.openconcerto.utils.ListMap;
83 ilm 27
import org.openconcerto.utils.RTInterruptedException;
28
import org.openconcerto.utils.cc.ITransformer;
29
 
30
import java.math.BigDecimal;
31
import java.sql.SQLException;
32
import java.text.SimpleDateFormat;
33
import java.util.ArrayList;
34
import java.util.List;
35
 
90 ilm 36
import javax.swing.JOptionPane;
37
import javax.swing.SwingUtilities;
38
 
83 ilm 39
import org.apache.commons.dbutils.ResultSetHandler;
40
 
41
public class StockItemsUpdater {
42
 
43
    private final StockLabel label;
44
    private final List<? extends SQLRowAccessor> items;
45
    private final Type type;
46
    private final boolean createMouvementStock;
47
    private final SQLRowAccessor rowSource;
48
 
49
    public static enum Type {
50
 
51
        VIRTUAL_RECEPT(true, true), REAL_RECEPT(true, false), VIRTUAL_DELIVER(false, true), REAL_DELIVER(false, false);
52
 
53
        private boolean entry, virtual;
54
 
55
        Type(boolean entry, boolean virtual) {
56
            this.entry = entry;
57
            this.virtual = virtual;
58
        }
59
 
60
        public boolean isEntry() {
61
            return entry;
62
        }
63
 
64
        public boolean isVirtual() {
65
            return virtual;
66
        }
67
    };
68
 
69
    public StockItemsUpdater(StockLabel label, SQLRowAccessor rowSource, List<? extends SQLRowAccessor> items, Type t) {
70
        this(label, rowSource, items, t, true);
71
    }
72
 
73
    public StockItemsUpdater(StockLabel label, SQLRowAccessor rowSource, List<? extends SQLRowAccessor> items, Type t, boolean createMouvementStock) {
74
        this.label = label;
75
        this.items = items;
76
        this.type = t;
77
        this.createMouvementStock = createMouvementStock;
78
        this.rowSource = rowSource;
79
    }
80
 
81
    List<String> requests = new ArrayList<String>();
82
 
83
    public void update() throws SQLException {
84
        final SQLTable stockTable = this.rowSource.getTable().getTable("STOCK");
85
 
86
        if (this.createMouvementStock) {
87
            clearExistingMvt(this.rowSource);
88
        }
89
 
90
        // Mise à jour des stocks des articles non composés
91
        List<StockItem> stockItems = fetch();
92
 
90 ilm 93
        final ListMap<SQLRow, SQLRowValues> cmd = new ListMap<SQLRow, SQLRowValues>();
94
 
83 ilm 95
        for (StockItem stockItem : stockItems) {
96
            if (stockItem.isStockInit()) {
97
                requests.add(stockItem.getUpdateRequest());
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());
104
                SQLRowValues rowValsArt = stockItem.getArticle().createEmptyUpdateRow();
105
                rowValsArt.put("ID_STOCK", rowVals);
106
                rowValsArt.commit();
107
            }
90 ilm 108
            stockItem.fillCommandeFournisseur(cmd);
83 ilm 109
        }
110
 
111
        List<? extends ResultSetHandler> handlers = new ArrayList<ResultSetHandler>(requests.size());
112
        for (String s : requests) {
113
            handlers.add(null);
114
        }
115
        // FIXME FIRE TABLE CHANGED TO UPDATE ILISTE ??
116
        SQLUtils.executeMultiple(stockTable.getDBSystemRoot(), requests, handlers);
117
 
118
        final DBRoot root = this.rowSource.getTable().getDBRoot();
119
        if (root.contains("ARTICLE_ELEMENT")) {
120
            ComposedItemStockUpdater comp = new ComposedItemStockUpdater(root, stockItems);
121
            comp.update();
122
        }
123
 
90 ilm 124
        // FIXME Créer une interface de saisie de commande article en dessous du seuil mini de stock
125
        if (cmd.size() > 0) {
126
            String msg = "Les articles suivants sont inférieurs au stock minimum : \n";
127
            for (SQLRow row : cmd.keySet()) {
128
                for (SQLRowValues rowVals : cmd.get(row)) {
129
                    msg += rowVals.getString("CODE") + " " + rowVals.getString("NOM") + "\n";
130
                }
131
            }
132
            final String msgFinal = msg;
133
            SwingUtilities.invokeLater(new Runnable() {
134
 
135
                @Override
136
                public void run() {
137
                    JOptionPane.showMessageDialog(null, msgFinal, "Alerte de stock minimum", JOptionPane.WARNING_MESSAGE);
138
                }
139
            });
140
        }
141
 
83 ilm 142
    }
143
 
144
    /**
145
     * Suppression des anciens mouvements
146
     *
147
     * @param rowSource
148
     * @throws SQLException
149
     * @throws RTInterruptedException
150
     */
151
    private void clearExistingMvt(SQLRowAccessor rowSource) throws RTInterruptedException, SQLException {
152
 
153
        List<String> multipleRequests = new ArrayList<String>();
154
 
155
        final SQLTable table = this.rowSource.getTable().getTable("MOUVEMENT_STOCK");
156
        SQLRowValues rowVals = new SQLRowValues(table);
157
        rowVals.put("QTE", null);
158
        rowVals.put("REEL", null);
159
        SQLRowValues rowValsArt = new SQLRowValues(this.rowSource.getTable().getTable("ARTICLE"));
160
        SQLRowValues rowValsStock = new SQLRowValues(this.rowSource.getTable().getTable("STOCK"));
161
        rowValsStock.put("QTE_REEL", null);
162
        rowValsStock.put("QTE_TH", null);
163
        rowValsStock.put("QTE_RECEPT_ATTENTE", null);
164
        rowValsStock.put("QTE_LIV_ATTENTE", null);
165
 
166
        rowValsArt.put("ID_STOCK", rowValsStock);
167
        rowVals.put("ID_ARTICLE", rowValsArt);
168
 
169
        SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(rowVals);
170
        fetcher.setSelTransf(new ITransformer<SQLSelect, SQLSelect>() {
171
 
172
            @Override
173
            public SQLSelect transformChecked(SQLSelect input) {
174
                Where w = new Where(table.getField("SOURCE"), "=", StockItemsUpdater.this.rowSource.getTable().getName());
175
                w = w.and(new Where(table.getField("IDSOURCE"), "=", StockItemsUpdater.this.rowSource.getID()));
176
                input.setWhere(w);
177
                return input;
178
            }
179
        });
180
 
181
        List<SQLRowValues> result = fetcher.fetch();
182
        for (SQLRowValues sqlRowValues : result) {
183
            StockItem item = new StockItem(sqlRowValues.getForeign("ID_ARTICLE"));
184
            final StockItem.Type t;
185
            if (sqlRowValues.getBoolean("REEL")) {
186
                t = StockItem.Type.REEL;
187
            } else {
188
                t = StockItem.Type.THEORIQUE;
189
            }
190
            item.updateQty(sqlRowValues.getFloat("QTE"), t, true);
191
            String req = "UPDATE " + sqlRowValues.getTable().getSQLName().quote() + " SET \"ARCHIVE\"=1 WHERE \"ID\"=" + sqlRowValues.getID();
192
            multipleRequests.add(req);
193
            multipleRequests.add(item.getUpdateRequest());
194
        }
195
 
196
        List<? extends ResultSetHandler> handlers = new ArrayList<ResultSetHandler>(multipleRequests.size());
197
        for (String s : multipleRequests) {
198
            handlers.add(null);
199
        }
200
        SQLUtils.executeMultiple(table.getDBSystemRoot(), multipleRequests, handlers);
201
    }
202
 
203
    /**
204
     * Récupére les stocks associés aux articles non composés et les met à jour
205
     *
206
     * @return la liste des stocks à jour
207
     */
208
    private List<StockItem> fetch() {
209
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
210
        List<StockItem> stockItems = new ArrayList<StockItem>(items.size());
211
        StockItem.Type stockItemType = this.type.isVirtual() ? StockItem.Type.THEORIQUE : StockItem.Type.REEL;
212
        for (SQLRowAccessor item : items) {
213
 
214
            if (!item.isForeignEmpty("ID_ARTICLE")) {
215
                SQLRowAccessor article = item.getForeign("ID_ARTICLE");
216
 
217
                // FIXME Create FIELD COMPOSED
218
                // if (!article.getBoolean("COMPOSED") && article.getBoolean("GESTION_STOCK")) {
219
                if (article.getBoolean("GESTION_STOCK")) {
220
                    StockItem stockItem = new StockItem(article);
221
 
222
                    final int qte = item.getInt("QTE");
223
                    final BigDecimal qteUV = item.getBigDecimal("QTE_UNITAIRE");
90 ilm 224
                    double qteFinal = qteUV.multiply(new BigDecimal(qte), DecimalUtils.HIGH_PRECISION).doubleValue();
83 ilm 225
                    if (!this.type.isEntry()) {
226
                        qteFinal = -qteFinal;
227
                    }
228
                    stockItem.updateQty(qteFinal, stockItemType);
229
                    stockItems.add(stockItem);
230
                    if (this.createMouvementStock) {
231
                        String mvtStockQuery = "INSERT INTO " + article.getTable().getTable("MOUVEMENT_STOCK").getSQLName().quote()
232
                                + " (\"QTE\",\"DATE\",\"ID_ARTICLE\",\"SOURCE\",\"IDSOURCE\",\"NOM\",\"REEL\") VALUES(" + qteFinal + ",'" + dateFormat.format(this.rowSource.getDate("DATE").getTime())
233
                                + "'," + article.getID() + ",'" + this.rowSource.getTable().getName() + "'," + this.rowSource.getID() + ",'" + this.label.getLabel(this.rowSource, item) + "',"
234
                                + String.valueOf(!this.type.isVirtual()) + ")";
235
                        this.requests.add(mvtStockQuery);
236
                    }
237
                }
238
            }
239
        }
240
        return stockItems;
241
    }
242
}