OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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

Rev Author Line No. Line
18 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
182 ilm 4
 * Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
18 ilm 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
 
182 ilm 16
import org.openconcerto.erp.config.ComptaPropsConfiguration;
18 ilm 17
import org.openconcerto.erp.core.common.element.ComptaSQLConfElement;
156 ilm 18
import org.openconcerto.erp.core.common.ui.PanelFrame;
19
import org.openconcerto.erp.core.sales.product.action.InventairePanel;
20
import org.openconcerto.erp.generationDoc.gestcomm.FicheArticleXmlSheet;
21
import org.openconcerto.erp.model.MouseSheetXmlListeListener;
18 ilm 22
import org.openconcerto.sql.element.BaseSQLComponent;
23
import org.openconcerto.sql.element.SQLComponent;
182 ilm 24
import org.openconcerto.sql.element.SQLElement;
25
import org.openconcerto.sql.model.DBRoot;
26
import org.openconcerto.sql.model.SQLInjector;
174 ilm 27
import org.openconcerto.sql.model.SQLRow;
156 ilm 28
import org.openconcerto.sql.model.SQLRowAccessor;
29
import org.openconcerto.sql.model.SQLRowValues;
30
import org.openconcerto.sql.model.SQLRowValuesListFetcher;
182 ilm 31
import org.openconcerto.sql.model.SQLSelect;
156 ilm 32
import org.openconcerto.sql.model.SQLTable;
33
import org.openconcerto.sql.model.Where;
185 ilm 34
import org.openconcerto.sql.request.ListSQLRequest;
35
import org.openconcerto.sql.request.ComboSQLRequest.KeepMode;
156 ilm 36
import org.openconcerto.sql.sqlobject.ElementComboBox;
182 ilm 37
import org.openconcerto.sql.users.rights.UserRightsManager;
156 ilm 38
import org.openconcerto.sql.view.list.IListe;
185 ilm 39
import org.openconcerto.sql.view.list.SQLTableModelSourceOnline;
156 ilm 40
import org.openconcerto.sql.view.list.IListeAction.IListeEvent;
41
import org.openconcerto.sql.view.list.RowAction.PredicateRowAction;
18 ilm 42
import org.openconcerto.ui.DefaultGridBagConstraints;
156 ilm 43
import org.openconcerto.ui.FrameUtil;
182 ilm 44
import org.openconcerto.utils.DecimalUtils;
132 ilm 45
import org.openconcerto.utils.ListMap;
18 ilm 46
 
47
import java.awt.GridBagConstraints;
48
import java.awt.GridBagLayout;
156 ilm 49
import java.awt.event.ActionEvent;
182 ilm 50
import java.math.BigDecimal;
156 ilm 51
import java.sql.SQLException;
52
import java.util.Arrays;
53
import java.util.Collection;
54
import java.util.HashSet;
18 ilm 55
import java.util.List;
156 ilm 56
import java.util.Set;
18 ilm 57
 
156 ilm 58
import javax.swing.AbstractAction;
18 ilm 59
import javax.swing.JLabel;
182 ilm 60
import javax.swing.JOptionPane;
18 ilm 61
import javax.swing.JTextField;
62
 
63
public class StockSQLElement extends ComptaSQLConfElement {
64
 
65
    public StockSQLElement() {
66
        super("STOCK", "un stock", "stocks");
182 ilm 67
        getRowActions().addAll(new MouseSheetXmlListeListener(this, FicheArticleXmlSheet.class).getRowActions());
156 ilm 68
        PredicateRowAction stock = new PredicateRowAction(new AbstractAction("Mettre à jour les stocks") {
69
 
70
            @Override
71
            public void actionPerformed(ActionEvent e) {
182 ilm 72
                if (UserRightsManager.getCurrentUserRights().canAdd(getTable().getDBRoot().getTable("STOCK"))) {
185 ilm 73
                    final PanelFrame p = new PanelFrame(new InventairePanel(IListe.get(e), IListe.get(e).getSelectedRowAccessors()), "Mise à jour des stocks");
182 ilm 74
                    FrameUtil.show(p);
75
                } else {
76
                    JOptionPane.showMessageDialog(null, "Vous n'avez les droits suffisants pour modifier manuellement les stocks!");
77
                }
78
            }
79
        }, true, false);
80
        stock.setPredicate(IListeEvent.getNonEmptySelectionPredicate());
81
        getRowActions().add(stock);
156 ilm 82
 
182 ilm 83
        PredicateRowAction cmd = new PredicateRowAction(new AbstractAction("Passer une commande") {
156 ilm 84
 
182 ilm 85
            @Override
86
            public void actionPerformed(ActionEvent e) {
87
 
88
                transfertCommande(IListe.get(e).getSelectedRowAccessors());
89
 
156 ilm 90
            }
91
        }, true, false);
182 ilm 92
        cmd.setPredicate(IListeEvent.getNonEmptySelectionPredicate());
93
        getRowActions().add(cmd);
18 ilm 94
    }
95
 
96
    protected List<String> getListFields() {
156 ilm 97
        return Arrays.asList("ID_ARTICLE", "QTE_MIN", "QTE_TH", "QTE_REEL", "QTE_LIV_ATTENTE", "QTE_RECEPT_ATTENTE", "ID_DEPOT_STOCK");
18 ilm 98
    }
99
 
156 ilm 100
    @Override
101
    public Set<String> getReadOnlyFields() {
102
        Set<String> s = new HashSet<>();
103
        if (getTable().contains("ID_ARTICLE")) {
104
            s.add("ID_ARTICLE");
105
        }
106
        s.add("QTE_TH");
107
        s.add("QTE_REEL");
108
        s.add("QTE_LIV_ATTENTE");
109
        s.add("QTE_RECEPT_ATTENTE");
110
        if (getTable().contains("ID_DEPOT_STOCK")) {
111
            s.add("ID_DEPOT_STOCK");
112
        }
113
        return s;
114
    }
115
 
116
    @Override
18 ilm 117
    protected List<String> getComboFields() {
156 ilm 118
        return Arrays.asList("ID_DEPOT_STOCK", "QTE_REEL");
18 ilm 119
    }
120
 
83 ilm 121
    @Override
156 ilm 122
    protected String getParentFFName() {
123
        return "ID_ARTICLE";
83 ilm 124
    }
125
 
132 ilm 126
    @Override
127
    public ListMap<String, String> getShowAs() {
156 ilm 128
        if (getTable().contains("ID_DEPOT_STOCK")) {
174 ilm 129
            return ListMap.singleton(null, "QTE_TH", "QTE_REEL", "QTE_MIN", "QTE_LIV_ATTENTE", "QTE_RECEPT_ATTENTE", "ID_DEPOT_STOCK");
156 ilm 130
        } else {
131
            return ListMap.singleton(null, "QTE_TH", "QTE_REEL", "QTE_LIV_ATTENTE", "QTE_RECEPT_ATTENTE");
132
        }
132 ilm 133
    }
134
 
156 ilm 135
    public static SQLRowAccessor getStockFetched(SQLRowAccessor rowValsSource) {
136
        SQLRowAccessor rowStock = null;
137
        final int idDepot;
138
        if (rowValsSource.getForeign("ID_DEPOT_STOCK") != null && !rowValsSource.isForeignEmpty("ID_DEPOT_STOCK")) {
139
            idDepot = rowValsSource.getForeignID("ID_DEPOT_STOCK");
140
        } else {
141
            idDepot = rowValsSource.getForeign("ID_ARTICLE").getForeignID("ID_DEPOT_STOCK");
142
        }
143
        SQLTable stockTable = rowValsSource.getTable().getTable("STOCK");
144
 
145
        Collection<? extends SQLRowAccessor> rows = rowValsSource.getForeign("ID_ARTICLE").getReferentRows(stockTable);
146
        for (SQLRowAccessor sqlRowAccessor : rows) {
147
            if (sqlRowAccessor.getForeignID("ID_DEPOT_STOCK") == idDepot) {
148
                rowStock = sqlRowAccessor;
149
                break;
150
            }
151
        }
152
 
153
        return rowStock;
154
    }
155
 
185 ilm 156
    @Override
157
    protected SQLTableModelSourceOnline instantiateTableSourceOnline(ListSQLRequest req) {
158
        return new SQLTableModelSourceOnline(req, this, KeepMode.ROW);
159
    }
160
 
182 ilm 161
    public static SQLRowAccessor getStock(SQLRowAccessor rowValsSource) throws SQLException {
156 ilm 162
 
163
        SQLRowAccessor rowStock = null;
164
        final int idDepot;
165
        if (rowValsSource.getForeign("ID_DEPOT_STOCK") != null && !rowValsSource.isForeignEmpty("ID_DEPOT_STOCK")) {
166
            idDepot = rowValsSource.getForeignID("ID_DEPOT_STOCK");
167
        } else {
174 ilm 168
            SQLRowAccessor rowValsArt = rowValsSource.getForeign("ID_ARTICLE");
169
            if (rowValsArt.getObject("ID_DEPOT_STOCK") == null) {
170
                rowValsArt = rowValsArt.asRow();
171
                ((SQLRow) rowValsArt).fetchValues();
172
                System.err.println("REFETCH ARTICLE");
173
                Thread.dumpStack();
174
            }
175
            idDepot = rowValsArt.getForeignID("ID_DEPOT_STOCK");
156 ilm 176
        }
182 ilm 177
        final int idArticle = rowValsSource.getForeignID("ID_ARTICLE");
178
        DBRoot root = rowValsSource.getTable().getDBRoot();
179
 
180
        SQLTable stockTable = root.getTable("STOCK");
156 ilm 181
        SQLRowValues putRowValuesStock = new SQLRowValues(stockTable);
182
        putRowValuesStock.putNulls(stockTable.getTable().getFieldsName());
183
 
184
        SQLRowValuesListFetcher fetch = SQLRowValuesListFetcher.create(putRowValuesStock);
182 ilm 185
        Where w = new Where(stockTable.getField("ID_DEPOT_STOCK"), "=", idDepot);
186
 
187
        Where w2 = new Where(stockTable.getField("ID_ARTICLE"), "=", idArticle);
156 ilm 188
        Collection<SQLRowValues> rowValsResult = fetch.fetch(w.and(w2));
189
        if (rowValsResult.isEmpty()) {
190
            SQLRowValues rowValsStock = new SQLRowValues(stockTable);
182 ilm 191
            rowValsStock.put("ID_ARTICLE", idArticle);
156 ilm 192
            rowValsStock.put("ID_DEPOT_STOCK", idDepot);
193
            rowValsStock.put("QTE_TH", 0F);
194
            rowValsStock.put("QTE_REEL", 0F);
195
            rowValsStock.put("QTE_RECEPT_ATTENTE", 0F);
196
            rowValsStock.put("QTE_LIV_ATTENTE", 0F);
182 ilm 197
 
198
            rowStock = rowValsStock.insert();
199
            if (idDepot == DepotStockSQLElement.DEFAULT_ID) {
200
                rowValsSource.getForeign("ID_ARTICLE").createEmptyUpdateRow().put("ID_STOCK", rowStock.getID()).commit();
156 ilm 201
            }
182 ilm 202
 
156 ilm 203
        } else if (rowValsResult.size() == 1) {
204
            rowStock = rowValsResult.iterator().next();
205
        } else if (rowValsResult.size() > 1) {
206
            throw new IllegalStateException("2 lignes de stocks pour le même dépôt! Article " + rowValsSource.getForeign("ID_ARTICLE").getID() + " Depot " + idDepot);
207
        }
208
        return rowStock;
209
    }
210
 
182 ilm 211
    /**
212
     * Stock d'un article dans un dépôt donné
213
     *
214
     * @param idDepot dépôt
215
     * @param idArticle article
216
     * @param createIfMissing initialisation du stock à 0 si n'existe pas
217
     * @return le stock (null si createIfMissing à false et que que le stock n'existe pas)
218
     */
219
    public SQLRow getStock(int idDepot, int idArticle, boolean createIfMissing) throws SQLException {
220
        final SQLTable stockTable = getTable();
221
        final SQLRowValues putRowValuesStock = new SQLRowValues(stockTable);
222
        putRowValuesStock.putNulls(stockTable.getFieldsName());
223
        final SQLRowValuesListFetcher fetch = SQLRowValuesListFetcher.create(putRowValuesStock);
224
        final Where w = new Where(stockTable.getField("ID_DEPOT_STOCK"), "=", idDepot);
225
        final Where w2 = new Where(stockTable.getField("ID_ARTICLE"), "=", idArticle);
226
        final Collection<SQLRowValues> rowValsResult = fetch.fetch(w.and(w2));
227
        SQLRow result;
228
        if (rowValsResult.isEmpty()) {
229
            if (!createIfMissing) {
230
                return null;
231
            }
232
            final SQLRowValues rowValsStock = new SQLRowValues(stockTable);
233
            rowValsStock.put("ID_ARTICLE", idArticle);
234
            rowValsStock.put("ID_DEPOT_STOCK", idDepot);
235
            rowValsStock.put("QTE_TH", 0F);
236
            rowValsStock.put("QTE_REEL", 0F);
237
            rowValsStock.put("QTE_RECEPT_ATTENTE", 0F);
238
            rowValsStock.put("QTE_LIV_ATTENTE", 0F);
239
            result = rowValsStock.insert();
240
 
241
        } else if (rowValsResult.size() == 1) {
242
            result = rowValsResult.iterator().next().asRow();
243
        } else {
244
            throw new IllegalStateException("2 lignes de stocks pour le même dépôt! Article " + idArticle + " Depot " + idDepot);
245
        }
246
        return result;
247
    }
248
 
18 ilm 249
    /*
250
     * (non-Javadoc)
251
     *
252
     * @see org.openconcerto.devis.SQLElement#getComponent()
253
     */
254
    public SQLComponent createComponent() {
255
 
256
        return new BaseSQLComponent(this) {
257
 
258
            public void addViews() {
259
                this.setLayout(new GridBagLayout());
260
                final GridBagConstraints c = new DefaultGridBagConstraints();
261
 
156 ilm 262
                // Article
263
                JLabel labelA = new JLabel(getLabelFor("ID_ARTICLE"));
264
                c.weightx = 0;
265
                this.add(labelA, c);
266
 
267
                c.gridx++;
268
                ElementComboBox boxA = new ElementComboBox();
269
                this.add(boxA, c);
270
 
271
                // Depot
272
                JLabel labelD = new JLabel(getLabelFor("ID_DEPOT_STOCK"));
273
                c.gridx++;
274
                c.weightx = 0;
275
                this.add(labelD, c);
276
 
277
                c.gridx++;
278
                ElementComboBox boxD = new ElementComboBox();
279
                this.add(boxD, c);
280
 
18 ilm 281
                // Qté Réelle
282
                JLabel labelQteR = new JLabel(getLabelFor("QTE_REEL"));
156 ilm 283
                c.gridx = 0;
284
                c.gridy++;
285
                c.weightx = 0;
18 ilm 286
                this.add(labelQteR, c);
287
 
288
                c.gridx++;
156 ilm 289
                JTextField textQteReel = new JTextField(6);
290
                this.add(textQteReel, c);
18 ilm 291
 
156 ilm 292
                // Qté Réelle
293
                JLabel labelQteT = new JLabel(getLabelFor("QTE_TH"));
294
                c.gridx++;
295
                c.weightx = 0;
296
                this.add(labelQteT, c);
18 ilm 297
 
156 ilm 298
                c.gridx++;
299
                JTextField textQteT = new JTextField(6);
300
                this.add(textQteT, c);
301
 
302
                // Qté Réelle
303
                JLabel labelQteRe = new JLabel(getLabelFor("QTE_RECEPT_ATTENTE"));
304
                c.gridx = 0;
305
                c.gridy++;
306
                c.weightx = 0;
307
                this.add(labelQteRe, c);
308
 
309
                c.gridx++;
310
                JTextField textQteRe = new JTextField(6);
311
                this.add(textQteRe, c);
312
 
313
                JLabel labelQteL = new JLabel(getLabelFor("QTE_LIV_ATTENTE"));
314
                c.gridx++;
315
                c.weightx = 0;
316
                this.add(labelQteL, c);
317
 
318
                c.gridx++;
319
                JTextField textQteL = new JTextField(6);
320
                this.add(textQteL, c);
321
 
322
                // Qté Min
323
                JLabel labelQteTMin = new JLabel(getLabelFor("QTE_MIN"));
324
                c.gridx = 0;
325
                c.gridy++;
326
                c.weightx = 0;
327
                this.add(labelQteTMin, c);
328
 
329
                c.gridx++;
330
                JTextField textQteMin = new JTextField(6);
331
                this.add(textQteMin, c);
332
 
333
                this.addSQLObject(textQteReel, "QTE_REEL");
334
                this.addSQLObject(textQteT, "QTE_TH");
335
                this.addSQLObject(textQteMin, "QTE_MIN");
336
                this.addSQLObject(textQteL, "QTE_LIV_ATTENTE");
337
                this.addSQLObject(textQteRe, "QTE_RECEPT_ATTENTE");
338
                this.addSQLObject(boxA, "ID_ARTICLE");
339
                this.addSQLObject(boxD, "ID_DEPOT_STOCK");
18 ilm 340
            }
341
        };
342
    }
156 ilm 343
 
182 ilm 344
    /**
345
     * Transfert d'une commande en commande fournisseur
346
     *
347
     * @param commandeID
348
     */
349
    public void transfertCommande(List<SQLRowAccessor> rows) {
350
 
351
        ComptaPropsConfiguration.getInstanceCompta().getNonInteractiveSQLExecutor().execute(new Runnable() {
352
 
353
            @Override
354
            public void run() {
355
 
356
                SQLTable tableCmdElt = getDirectory().getElement("COMMANDE_ELEMENT").getTable();
357
                SQLElement eltArticle = getDirectory().getElement("ARTICLE");
358
 
359
                final ListMap<SQLRow, SQLRowValues> map = new ListMap<SQLRow, SQLRowValues>();
360
 
361
                for (SQLRowAccessor sqlRow : rows) {
362
 
363
                    SQLRowAccessor rowArticleFind = sqlRow.getForeign("ID_ARTICLE");
364
                    int qte = 1;
365
                    BigDecimal qteUV = BigDecimal.ONE;
366
 
367
                    qte = -Math.round(sqlRow.getFloat("QTE_TH") - sqlRow.getFloat("QTE_MIN"));
368
 
369
                    SQLInjector inj = SQLInjector.getInjector(eltArticle.getTable(), tableCmdElt);
370
                    SQLRowValues rowValsElt = new SQLRowValues(inj.createRowValuesFrom(rowArticleFind.asRow()));
371
                    rowValsElt.put("ID_DEPOT_STOCK", sqlRow.getForeignID("ID_DEPOT_STOCK"));
372
                    rowValsElt.put("QTE", qte);
373
                    rowValsElt.put("QTE_UNITAIRE", qteUV);
374
 
375
                    rowValsElt.put("T_POIDS", rowValsElt.getLong("POIDS") * rowValsElt.getInt("QTE"));
376
                    // TODO récupérer le prix depuis les tarifs d'achat
377
                    rowValsElt.put("T_PA_HT", ((BigDecimal) rowValsElt.getObject("PA_HT")).multiply(new BigDecimal(rowValsElt.getInt("QTE")), DecimalUtils.HIGH_PRECISION));
378
                    rowValsElt.put("T_PA_TTC",
379
                            ((BigDecimal) rowValsElt.getObject("T_PA_HT")).multiply(new BigDecimal((rowValsElt.getForeign("ID_TAXE").getFloat("TAUX") / 100.0 + 1.0)), DecimalUtils.HIGH_PRECISION));
380
                    final SQLRow fournisseur = rowArticleFind.asRow().getForeignRow("ID_FOURNISSEUR");
381
                    if (fournisseur != null && !fournisseur.isUndefined() && !rowArticleFind.isUndefined()) {
382
                        SQLRowValues rowValsCode = new SQLRowValues(tableCmdElt.getForeignTable("ID_CODE_FOURNISSEUR"));
383
                        rowValsCode.putNulls("ID");
384
                        final Where w = new Where(rowValsCode.getTable().getField("ID_ARTICLE"), "=", rowArticleFind.getID())
385
                                .and(new Where(rowValsCode.getTable().getField("ID_FOURNISSEUR"), "=", fournisseur.getID()));
386
                        final List<SQLRowValues> fetch = SQLRowValuesListFetcher.create(rowValsCode).fetch(w);
387
                        for (SQLRowValues sqlRowAccessor : fetch) {
185 ilm 388
                            rowValsElt.put("ID_CODE_FOURNISSEUR", sqlRowAccessor);
182 ilm 389
                        }
390
                    }
391
                    map.add(fournisseur, rowValsElt);
392
                }
393
 
394
                MouvementStockSQLElement.createCommandeF(map, null, "");
395
            }
396
        });
397
 
398
    }
399
 
156 ilm 400
    @Override
401
    protected String createCode() {
402
        return "supplychain.stock";
403
    }
18 ilm 404
}