OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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