OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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

Rev Author Line No. Line
132 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.
132 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.sales.pos;
15
 
144 ilm 16
import org.openconcerto.erp.action.NouvelleConnexionAction;
132 ilm 17
import org.openconcerto.erp.config.ComptaPropsConfiguration;
18
import org.openconcerto.erp.config.MainFrame;
19
import org.openconcerto.erp.core.common.ui.TotalCalculator;
20
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement;
21
import org.openconcerto.erp.core.finance.accounting.element.JournalSQLElement;
22
import org.openconcerto.erp.core.finance.payment.element.TypeReglementSQLElement;
23
import org.openconcerto.erp.core.finance.tax.model.TaxeCache;
149 ilm 24
import org.openconcerto.erp.core.sales.pos.io.Printable;
132 ilm 25
import org.openconcerto.erp.core.sales.pos.io.TicketPrinter;
26
import org.openconcerto.erp.core.sales.pos.model.Article;
142 ilm 27
import org.openconcerto.erp.core.sales.pos.model.Client;
132 ilm 28
import org.openconcerto.erp.core.sales.pos.model.Paiement;
29
import org.openconcerto.erp.core.sales.pos.model.ReceiptCode;
144 ilm 30
import org.openconcerto.erp.core.sales.pos.model.RegisterFiles.HashMode;
31
import org.openconcerto.erp.core.sales.pos.model.RegisterLogEntry.ReceiptEntry;
132 ilm 32
import org.openconcerto.erp.core.sales.pos.model.Ticket;
174 ilm 33
import org.openconcerto.erp.core.sales.pos.model.TicketItem;
132 ilm 34
import org.openconcerto.erp.core.sales.pos.model.TicketLine;
35
import org.openconcerto.erp.core.supplychain.stock.element.StockItemsUpdater;
36
import org.openconcerto.erp.core.supplychain.stock.element.StockItemsUpdater.TypeStockUpdate;
37
import org.openconcerto.erp.core.supplychain.stock.element.StockLabel;
38
import org.openconcerto.erp.generationEcritures.GenerationMvtTicketCaisse;
39
import org.openconcerto.erp.generationEcritures.GenerationMvtVirement;
40
import org.openconcerto.erp.generationEcritures.GenerationReglementVenteNG;
41
import org.openconcerto.erp.model.PrixTTC;
42
import org.openconcerto.erp.preferences.DefaultNXProps;
43
import org.openconcerto.sql.Configuration;
44
import org.openconcerto.sql.element.SQLElement;
174 ilm 45
import org.openconcerto.sql.element.SQLElementDirectory;
132 ilm 46
import org.openconcerto.sql.model.SQLBase;
144 ilm 47
import org.openconcerto.sql.model.SQLDataSource;
132 ilm 48
import org.openconcerto.sql.model.SQLRow;
49
import org.openconcerto.sql.model.SQLRowAccessor;
174 ilm 50
import org.openconcerto.sql.model.SQLRowListRSH;
132 ilm 51
import org.openconcerto.sql.model.SQLRowValues;
142 ilm 52
import org.openconcerto.sql.model.SQLRowValuesListFetcher;
132 ilm 53
import org.openconcerto.sql.model.SQLSelect;
54
import org.openconcerto.sql.model.SQLSelectHandlerBuilder;
55
import org.openconcerto.sql.model.SQLTable;
56
import org.openconcerto.sql.model.Where;
57
import org.openconcerto.sql.utils.SQLUtils;
142 ilm 58
import org.openconcerto.utils.BaseDirs;
132 ilm 59
import org.openconcerto.utils.DecimalUtils;
60
import org.openconcerto.utils.ExceptionHandler;
61
import org.openconcerto.utils.i18n.TranslationManager;
62
 
182 ilm 63
import java.awt.GraphicsDevice;
64
import java.awt.GraphicsEnvironment;
132 ilm 65
import java.io.File;
66
import java.io.FileOutputStream;
67
import java.io.IOException;
68
import java.math.BigDecimal;
69
import java.math.RoundingMode;
144 ilm 70
import java.nio.file.Path;
132 ilm 71
import java.sql.SQLException;
72
import java.util.ArrayList;
142 ilm 73
import java.util.Collections;
74
import java.util.Comparator;
132 ilm 75
import java.util.Date;
174 ilm 76
import java.util.HashMap;
144 ilm 77
import java.util.Iterator;
132 ilm 78
import java.util.List;
174 ilm 79
import java.util.Map;
144 ilm 80
import java.util.logging.Logger;
132 ilm 81
 
82
import javax.swing.JOptionPane;
83
import javax.swing.SwingUtilities;
84
 
85
import org.jdom2.Document;
86
import org.jdom2.Element;
156 ilm 87
import org.jdom2.JDOMException;
132 ilm 88
import org.jdom2.input.SAXBuilder;
89
import org.jdom2.output.Format;
90
import org.jdom2.output.XMLOutputter;
91
 
92
public class POSConfiguration {
144 ilm 93
 
94
    private static final Logger LOG = Logger.getLogger(org.openconcerto.erp.config.Log.get().getName() + ".pos");
95
 
96
    public static final Logger getLogger() {
97
        return LOG;
98
    }
99
 
100
    public static final void checkRegisterID(final int fsID, final int dbID) {
101
        if (fsID != dbID)
102
            throw new IllegalArgumentException("Not same register, FS " + fsID + ", DB " + dbID);
103
    }
104
 
132 ilm 105
    private static final String POS_CONFIGURATION_FILENAME = "pos.xml";
106
    private static POSConfiguration instance;
142 ilm 107
 
108
    private final File confFile;
132 ilm 109
    private int screenWidth, screenHeight;
110
    private TicketPrinterConfiguration ticketPrinterConf1, ticketPrinterConf2;
111
    private int userID = 2;
112
    private int companyID = 42;
113
    private int posID = 2;
182 ilm 114
    private int depotStockId = 2;
132 ilm 115
    private int scanDelay = 80;
116
 
182 ilm 117
    private List<TicketLine> headerLines = new ArrayList<>();
118
    private List<TicketLine> footerLines = new ArrayList<>();
132 ilm 119
    // Terminal CB
120
    private String creditCardPort = "";
121
    // LCD
142 ilm 122
    private String LCDType = "serial";
123
    private String LCDPort = "";
132 ilm 124
    private String LCDLine1 = "Bienvenue";
125
    private String LCDLine2 = "ILM Informatique";
126
 
174 ilm 127
    private boolean askPostalCode = false;
128
 
156 ilm 129
    public static POSConfiguration createInstance() throws JDOMException, IOException {
130
        POSConfiguration res = new POSConfiguration(getConfigFile(new File(".")));
131
        res.loadConfiguration();
132
        return res;
133
    }
134
 
135
    @Deprecated
136
    public static synchronized POSConfiguration setInstance() throws JDOMException, IOException {
132 ilm 137
        if (instance == null) {
156 ilm 138
            instance = createInstance();
139
        } else {
140
            throw new IllegalStateException("already set");
132 ilm 141
        }
142
        return instance;
143
    }
144
 
156 ilm 145
    @Deprecated
146
    public static synchronized POSConfiguration getInstance() {
147
        return instance;
148
    }
149
 
142 ilm 150
    private POSConfiguration(final File confFile) {
151
        this.confFile = confFile;
132 ilm 152
        ticketPrinterConf1 = new TicketPrinterConfiguration();
153
        ticketPrinterConf2 = new TicketPrinterConfiguration();
154
        // Desactivate second printer by default
155
        ticketPrinterConf2.setCopyCount(0);
156
    }
157
 
158
    public TicketPrinterConfiguration getTicketPrinterConfiguration1() {
159
        return ticketPrinterConf1;
160
    }
161
 
162
    public TicketPrinterConfiguration getTicketPrinterConfiguration2() {
163
        return ticketPrinterConf2;
164
    }
165
 
166
    public boolean isConfigurationFileCreated() {
167
        File file = getConfigFile();
168
        if (file == null) {
169
            return false;
170
        }
171
        return file.exists();
172
    }
173
 
174
    // Screen
175
    public int getScreenWidth() {
182 ilm 176
        if (screenWidth == 0) {
177
            GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
178
            screenWidth = gd.getDisplayMode().getWidth();
179
        }
132 ilm 180
        return screenWidth;
181
    }
182
 
183
    public int getScreenHeight() {
182 ilm 184
        if (screenHeight == 0) {
185
            GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
186
            screenHeight = gd.getDisplayMode().getHeight();
187
        }
132 ilm 188
        return screenHeight;
189
    }
190
 
191
    // Database connection
192
    public int getUserID() {
193
        return userID;
194
    }
195
 
196
    public void setUserID(int userID) {
197
        this.userID = userID;
198
    }
199
 
200
    public int getCompanyID() {
201
        return companyID;
202
    }
203
 
204
    public void setCompanyID(int companyID) {
205
        this.companyID = companyID;
206
    }
207
 
208
    // POS id
209
    public int getPosID() {
210
        return posID;
211
    }
212
 
213
    public void setPosID(int posID) {
214
        this.posID = posID;
215
    }
182 ilm 216
    // Depot stock
132 ilm 217
 
182 ilm 218
    public void setDepotID(int depotStockId) {
219
        this.depotStockId = depotStockId;
220
 
221
    }
222
 
223
    public int getDepotID() {
224
        return depotStockId;
225
    }
226
 
132 ilm 227
    public int getScanDelay() {
228
        return scanDelay;
229
    }
230
 
231
    /**
232
     * Set barcode scanner delay
233
     */
234
    public void setScanDelay(int ms) {
235
        this.scanDelay = ms;
236
    }
237
 
238
    public String getCreditCardPort() {
239
        return creditCardPort;
240
    }
241
 
242
    /**
243
     * Set the serial port of the credit card device
244
     */
245
    public void setCreditCardPort(String creditCardPort) {
246
        this.creditCardPort = creditCardPort;
247
    }
248
 
142 ilm 249
    private static File getConfigFile(final File wd) {
132 ilm 250
        final File wdFile = new File(wd + "/Configuration", POS_CONFIGURATION_FILENAME);
251
        final File confFile;
252
        if (wdFile.isFile()) {
253
            confFile = wdFile;
254
        } else {
142 ilm 255
            try {
256
                final File preferencesFolder = BaseDirs.create(ComptaPropsConfiguration.productInfo).getPreferencesFolderToWrite();
257
                confFile = new File(preferencesFolder, POS_CONFIGURATION_FILENAME);
258
            } catch (IOException e) {
259
                throw new IllegalStateException("Couldn't get folder", e);
132 ilm 260
            }
261
        }
262
        return confFile;
263
    }
264
 
142 ilm 265
    public final File getConfigFile() {
266
        return this.confFile;
132 ilm 267
    }
268
 
144 ilm 269
    public ComptaPropsConfiguration createConnexion() {
132 ilm 270
        final ComptaPropsConfiguration conf = ComptaPropsConfiguration.create();
177 ilm 271
        TranslationManager.addTranslationStreamFromClass(MainFrame.class);
272
        TranslationManager.createDefaultInstance();
132 ilm 273
 
274
        Configuration.setInstance(conf);
275
        try {
144 ilm 276
            conf.getUserManager().setCurrentUserID(getUserID());
277
            conf.setUpSocieteDataBaseConnexion(getCompanyID());
132 ilm 278
        } catch (Exception e) {
144 ilm 279
            JOptionPane.showMessageDialog(null, "Impossible de configurer la connexion à la base de donnée.\n ID société: " + getCompanyID() + " \n ID utilisateur: " + getUserID());
132 ilm 280
            e.printStackTrace();
144 ilm 281
            System.exit(2);
132 ilm 282
        }
283
 
174 ilm 284
        NouvelleConnexionAction.initCache(conf, -1);
285
        TaxeCache.getCache();
144 ilm 286
        return conf;
132 ilm 287
    }
288
 
144 ilm 289
    public final Path getRootDir() throws IOException {
290
        return Configuration.getInstance().getBaseDirs().getAppDataFolderToWrite().toPath();
291
    }
292
 
293
    public final void closeConnexion() {
294
        Configuration.setInstance(null, true);
295
    }
296
 
132 ilm 297
    public void commitAll(final List<Ticket> tickets) {
298
        // createConnexion();
299
        try {
300
            SQLUtils.executeAtomic(Configuration.getInstance().getSystemRoot().getDataSource(), new SQLUtils.SQLFactory<Object>() {
301
                @Override
302
                public Object create() throws SQLException {
151 ilm 303
 
144 ilm 304
                    final int imported = importReceipts(tickets, null);
132 ilm 305
 
306
                    // mark imported
307
                    for (Ticket ticket : tickets) {
308
                        final ReceiptCode code = ticket.getReceiptCode();
309
                        try {
310
                            // it's OK if some files cannot be moved, the next call will try again
311
                            // (the above code doesn't import duplicates)
312
                            code.markImported();
313
                        } catch (IOException e) {
314
                            e.printStackTrace();
315
                        }
316
                    }
317
                    // archive to avoid parsing more and more receipts
318
                    try {
319
                        // it's OK if some files cannot be moved, the next call will try again
320
                        ReceiptCode.archiveCompletelyImported();
321
                    } catch (IOException e) {
322
                        e.printStackTrace();
323
                    }
324
                    final String count = imported + "/" + tickets.size();
325
                    SwingUtilities.invokeLater(new Runnable() {
326
 
327
                        @Override
328
                        public void run() {
329
                            JOptionPane.showMessageDialog(null, count + " ticket(s) importé(s). Clôture de la caisse terminée.");
330
                        }
331
                    });
332
                    return null;
333
                }
334
            });
335
        } catch (Exception exn) {
336
            ExceptionHandler.handle("Une erreur est survenue pendant la clôture.", exn);
337
        }
338
 
339
    }
340
 
144 ilm 341
    public final int importReceipts(final List<Ticket> tickets, final List<ReceiptEntry> entries) throws SQLException {
342
        if (entries != null && entries.size() != tickets.size())
343
            throw new IllegalArgumentException("Size mismatch");
344
 
345
        final int defaultIDClient = getClientCaisse().getID();
174 ilm 346
        final SQLElementDirectory directory = Configuration.getInstance().getDirectory();
347
        SQLElement elt = directory.getElement("TICKET_CAISSE");
348
        SQLElement eltFact = directory.getElement("SAISIE_VENTE_FACTURE_ELEMENT");
349
        SQLElement eltEnc = directory.getElement("ENCAISSER_MONTANT");
350
        SQLElement eltMode = directory.getElement("MODE_REGLEMENT");
351
        SQLElement eltArticle = directory.getElement("ARTICLE");
144 ilm 352
        final SQLDataSource ds = elt.getTable().getDBSystemRoot().getDataSource();
353
        int imported = 0;
354
 
174 ilm 355
        //
356
        final SQLSelect selUniteVente = new SQLSelect();
357
        selUniteVente.addSelectStar(directory.getElement("UNITE_VENTE").getTable());
358
        final Map<String, Integer> mapUniteVenteName = new HashMap<>();
359
        for (SQLRow row : SQLRowListRSH.execute(selUniteVente)) {
360
            mapUniteVenteName.put(row.getString("CODE"), row.getID());
361
        }
362
 
144 ilm 363
        final Iterator<ReceiptEntry> entriesIter = entries == null ? null : entries.iterator();
364
        for (Ticket ticket : tickets) {
365
            SQLSelect sel = new SQLSelect();
366
            sel.addSelectFunctionStar("COUNT");
367
            sel.setWhere(new Where(elt.getTable().getField("NUMERO"), "=", ticket.getCode()));
368
            // if entries is null, it's the obsolete way when there was no opening/closure
369
            if (entries != null || ((Number) ds.executeScalar(sel.asString())).intValue() == 0) {
370
                final ReceiptEntry entry;
371
                if (entriesIter == null) {
372
                    entry = null;
373
                } else {
374
                    entry = entriesIter.next();
375
                    if (entry == null)
376
                        throw new IllegalArgumentException("Null log entry for " + ticket);
377
                    else if (!entry.getCodeString().equals(ticket.getCode()))
378
                        throw new IllegalArgumentException("Code mismatch for " + ticket);
379
                }
380
 
381
                SQLRowValues rowVals = new SQLRowValues(elt.getTable());
382
                rowVals.put("NUMERO", ticket.getCode());
383
                rowVals.put("DATE", ticket.getCreationDate());
384
                rowVals.put("ID_CAISSE", getPosID());
174 ilm 385
                if (elt.getTable().contains("CODE_POSTAL")) {
386
                    rowVals.put("CODE_POSTAL", ticket.getCodePostal());
387
                }
144 ilm 388
                if (entry != null) {
389
                    rowVals.put("FILE_HASH", entry.getFileHash());
390
                    rowVals.put("FILE_HASH_PREVIOUS", ticket.getPreviousHash());
391
                }
392
                int idClient = ticket.getClient().getId();
393
                if (idClient <= 0) {
394
                    idClient = defaultIDClient;
395
                }
396
 
182 ilm 397
                rowVals.put("ID_CLIENT", idClient);
398
                SQLRow rowClient = elt.getTable().getForeignTable("ID_CLIENT").getRow(idClient);
399
                SQLRowAccessor rowCat = rowClient.getNonEmptyForeign("ID_CATEGORIE_COMPTABLE");
400
 
156 ilm 401
                // TODO fusionner TotalCalculator avec Ticket.GetTotalCalcutor
182 ilm 402
                TotalCalculator calc = new TotalCalculator("T_PA_HT", "T_PV_HT", null, rowCat);
156 ilm 403
 
144 ilm 404
                String val = DefaultNXProps.getInstance().getStringProperty("ArticleService");
405
                Boolean bServiceActive = Boolean.valueOf(val);
406
                calc.setServiceActive(bServiceActive != null && bServiceActive);
407
 
408
                // Articles
174 ilm 409
                for (TicketItem item : ticket.getItems()) {
144 ilm 410
                    SQLRowValues rowValsElt = new SQLRowValues(eltFact.getTable());
174 ilm 411
                    final Article article = item.getArticle();
412
                    final BigDecimal nb = item.getQty();
182 ilm 413
 
414
                    rowValsElt.put("ID_DEPOT_STOCK", getDepotID());
415
 
174 ilm 416
                    if (article.getSalesUnit() == null) {
417
                        rowValsElt.put("QTE", nb.intValue());
418
                    } else {
419
                        rowValsElt.put("QTE", 1);
420
                        rowValsElt.put("QTE_UNITAIRE", nb);
421
                    }
182 ilm 422
 
423
                    rowValsElt.put("PV_HT", article.getPriceWithoutTax(nb, false));
144 ilm 424
                    Float tauxFromId = TaxeCache.getCache().getTauxFromId(article.getIdTaxe());
174 ilm 425
                    BigDecimal tauxTVA = BigDecimal.valueOf(tauxFromId).movePointLeft(2).add(BigDecimal.ONE);
182 ilm 426
                    final BigDecimal valueHT = article.getPriceWithoutTax(nb, true).multiply(nb, DecimalUtils.HIGH_PRECISION);
144 ilm 427
 
174 ilm 428
                    if (article.getSalesUnit() != null) {
429
                        rowValsElt.put("ID_UNITE_VENTE", mapUniteVenteName.get(article.getSalesUnit()));
430
                    }
144 ilm 431
                    rowValsElt.put("T_PV_HT", valueHT);
432
                    rowValsElt.put("T_PV_TTC", valueHT.multiply(tauxTVA, DecimalUtils.HIGH_PRECISION));
433
                    rowValsElt.put("ID_TAXE", article.getIdTaxe());
434
                    rowValsElt.put("CODE", article.getCode());
182 ilm 435
                    rowValsElt.put("POURCENT_REMISE", article.getDiscountPct().movePointRight(2));
436
                    rowValsElt.put("ECO_CONTRIBUTION", article.getEcoTaxe());
437
                    rowValsElt.put("T_ECO_CONTRIBUTION", article.getEcoTaxe().multiply(nb));
144 ilm 438
                    rowValsElt.put("NOM", article.getName());
439
                    rowValsElt.put("ID_TICKET_CAISSE", rowVals);
440
                    rowValsElt.put("ID_ARTICLE", article.getId());
441
                    calc.addLine(rowValsElt, eltArticle.getTable().getRow(article.getId()), 0, false);
442
                }
443
                calc.checkResult();
444
                long longValueTotalHT = calc.getTotalHT().movePointRight(2).setScale(0, RoundingMode.HALF_UP).longValue();
445
                rowVals.put("TOTAL_HT", longValueTotalHT);
446
 
447
                long longValueTotal = calc.getTotalTTC().movePointRight(2).setScale(0, RoundingMode.HALF_UP).longValue();
448
                rowVals.put("TOTAL_TTC", longValueTotal);
449
                long longValueTotalTVA = calc.getTotalTVA().movePointRight(2).setScale(0, RoundingMode.HALF_UP).longValue();
450
                rowVals.put("TOTAL_TVA", longValueTotalTVA);
451
 
452
                // Paiements
453
                for (Paiement paiement : ticket.getPaiements()) {
151 ilm 454
                    if (paiement.getMontantInCents() != 0 && paiement.getType() != Paiement.SOLDE) {
144 ilm 455
 
456
                        SQLRowValues rowValsElt = new SQLRowValues(eltEnc.getTable());
457
                        SQLRowValues rowValsEltMode = new SQLRowValues(eltMode.getTable());
458
                        if (paiement.getType() == Paiement.CB) {
459
                            rowValsEltMode.put("ID_TYPE_REGLEMENT", TypeReglementSQLElement.CB);
460
                        } else if (paiement.getType() == Paiement.CHEQUE) {
461
                            rowValsEltMode.put("ID_TYPE_REGLEMENT", TypeReglementSQLElement.CHEQUE);
462
                        } else if (paiement.getType() == Paiement.ESPECES) {
463
                            rowValsEltMode.put("ID_TYPE_REGLEMENT", TypeReglementSQLElement.ESPECE);
464
                        }
465
 
466
                        rowValsElt.put("ID_MODE_REGLEMENT", rowValsEltMode);
467
                        rowValsElt.put("ID_CLIENT", idClient);
468
 
469
                        long montant = Long.valueOf(paiement.getMontantInCents());
156 ilm 470
                        // Check si montant especes > especes données alors montant especes =
471
                        // montant donné - montant rendu
472
                        // TODO gérer ce cas si paiement multiple
144 ilm 473
                        if (ticket.getPaiements().size() == 1 && paiement.getType() == Paiement.ESPECES) {
474
                            montant = longValueTotal;
475
                        }
476
                        rowValsElt.put("MONTANT", montant);
477
                        rowValsElt.put("NOM", "Ticket " + ticket.getCode());
478
                        rowValsElt.put("DATE", ticket.getCreationDate());
479
                        rowValsElt.put("ID_TICKET_CAISSE", rowVals);
480
 
481
                    }
482
                }
483
 
484
                SQLRow rowFinal = rowVals.insert();
485
                imported++;
486
                GenerationMvtTicketCaisse mvt = new GenerationMvtTicketCaisse(rowFinal);
487
                final Integer idMvt;
488
                try {
489
                    idMvt = mvt.genereMouvement().call();
490
 
491
                    SQLRowValues valTicket = rowFinal.asRowValues();
492
                    valTicket.put("ID_MOUVEMENT", Integer.valueOf(idMvt));
493
                    rowFinal = valTicket.update();
494
 
495
                    // msie à jour du mouvement
496
                    List<SQLRow> rowsEnc = rowFinal.getReferentRows(eltEnc.getTable());
497
                    long totalEnc = 0;
498
                    for (SQLRow sqlRow : rowsEnc) {
499
                        long montant = sqlRow.getLong("MONTANT");
500
                        PrixTTC ttc = new PrixTTC(montant);
501
                        totalEnc += montant;
502
                        new GenerationReglementVenteNG(
503
                                "Règlement " + sqlRow.getForeignRow("ID_MODE_REGLEMENT").getForeignRow("ID_TYPE_REGLEMENT").getString("NOM") + " Ticket " + rowFinal.getString("NUMERO"),
504
                                sqlRow.getForeign("ID_CLIENT"), ttc, sqlRow.getDate("DATE").getTime(), sqlRow.getForeignRow("ID_MODE_REGLEMENT"), rowFinal, rowFinal.getForeignRow("ID_MOUVEMENT"),
505
                                false);
506
                    }
507
                    if (totalEnc > longValueTotal) {
174 ilm 508
                        final SQLTable table = directory.getElement("TYPE_REGLEMENT").getTable();
144 ilm 509
                        int idComptePceCaisse = table.getRow(TypeReglementSQLElement.ESPECE).getInt("ID_COMPTE_PCE_CLIENT");
510
                        if (idComptePceCaisse == table.getUndefinedID()) {
511
                            idComptePceCaisse = ComptePCESQLElement.getId(ComptePCESQLElement.getComptePceDefault("VenteEspece"));
512
                        }
513
                        new GenerationMvtVirement(idComptePceCaisse, rowFinal.getForeign("ID_CLIENT").getInt("ID_COMPTE_PCE"), 0, totalEnc - longValueTotal,
514
                                "Rendu sur règlement " + " Ticket " + rowFinal.getString("NUMERO"), new Date(), JournalSQLElement.CAISSES, " Ticket " + rowFinal.getString("NUMERO")).genereMouvement();
515
                    }
516
                } catch (Exception exn) {
517
                    exn.printStackTrace();
518
                    throw new SQLException(exn);
519
                }
520
                updateStock(rowFinal.getID());
521
 
522
            }
523
        }
524
        return imported;
525
    }
526
 
132 ilm 527
    private SQLRow rowClient = null;
528
 
529
    private SQLRow getClientCaisse() throws SQLException {
530
        if (rowClient == null) {
531
            SQLElement elt = Configuration.getInstance().getDirectory().getElement("CLIENT");
532
            SQLSelect sel = new SQLSelect();
533
            sel.addSelectStar(elt.getTable());
534
            sel.setWhere(new Where(elt.getTable().getField("NOM"), "=", "Caisse OpenConcerto"));
535
            @SuppressWarnings("unchecked")
536
            List<SQLRow> l = (List<SQLRow>) elt.getTable().getBase().getDataSource().execute(sel.asString(), new SQLSelectHandlerBuilder(sel).createHandler());
182 ilm 537
            if (!l.isEmpty()) {
132 ilm 538
                rowClient = l.get(0);
539
            } else {
540
                SQLRowValues rowValues = new SQLRowValues(elt.getTable());
541
                rowValues.put("NOM", "Caisse OpenConcerto");
542
                SQLRowValues rowValuesMode = new SQLRowValues(elt.getTable().getTable("MODE_REGLEMENT"));
543
                rowValuesMode.put("ID_TYPE_REGLEMENT", TypeReglementSQLElement.CB);
544
                rowValues.put("ID_MODE_REGLEMENT", rowValuesMode);
545
 
546
                // Select Compte client par defaut
547
                final SQLBase base = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete();
548
                final SQLTable tablePrefCompte = base.getTable("PREFS_COMPTE");
549
                final SQLRow rowPrefsCompte = tablePrefCompte.getRow(2);
550
 
551
                int idDefaultCompteClient = rowPrefsCompte.getInt("ID_COMPTE_PCE_CLIENT");
552
                if (idDefaultCompteClient <= 1) {
553
                    try {
554
                        idDefaultCompteClient = ComptePCESQLElement.getIdComptePceDefault("Clients");
555
                    } catch (Exception e) {
556
                        e.printStackTrace();
557
                    }
558
                }
559
 
560
                rowValues.put("ID_COMPTE_PCE", idDefaultCompteClient);
561
                rowClient = rowValues.insert();
562
            }
563
        }
564
        return rowClient;
565
 
566
    }
567
 
568
    private void updateStock(int id) throws SQLException {
569
        final SQLRow row = getClientCaisse().getTable().getTable("TICKET_CAISSE").getRow(id);
570
        StockItemsUpdater stockUpdater = new StockItemsUpdater(new StockLabel() {
571
            @Override
572
            public String getLabel(SQLRowAccessor rowOrigin, SQLRowAccessor rowElt) {
573
                return "Ticket N°" + rowOrigin.getString("NUMERO");
574
            }
156 ilm 575
        }, row, row.getReferentRows(getClientCaisse().getTable().getTable("SAISIE_VENTE_FACTURE_ELEMENT")), TypeStockUpdate.REAL_VIRTUAL_DELIVER);
132 ilm 576
        stockUpdater.update();
577
    }
578
 
174 ilm 579
    public List<Ticket> allTickets() throws IOException {
132 ilm 580
        final List<Ticket> l = new ArrayList<Ticket>();
581
        for (final File f : ReceiptCode.getReceiptsToImport(getPosID())) {
144 ilm 582
            // old receipts have no hash files
583
            final Ticket ticket = Ticket.parseFile(f, HashMode.NOT_REQUIRED);
174 ilm 584
            l.add(ticket);
132 ilm 585
        }
586
        return l;
587
    }
588
 
589
    public List<TicketLine> getHeaderLines() {
590
        return headerLines;
591
    }
592
 
593
    public void setHeaderLines(List<TicketLine> headerLines) {
594
        this.headerLines = headerLines;
595
    }
596
 
597
    public List<TicketLine> getFooterLines() {
598
        return footerLines;
599
    }
600
 
601
    public void setFooterLines(List<TicketLine> footerLines) {
602
        this.footerLines = footerLines;
603
    }
604
 
156 ilm 605
    private void loadConfiguration() throws JDOMException, IOException {
132 ilm 606
        if (!isConfigurationFileCreated()) {
607
            System.err.println("POSConfiguration.loadConfigurationFromXML() configuration not loaded. " + getConfigFile().getAbsolutePath() + " missing.");
608
            return;
609
        }
610
 
611
        final SAXBuilder builder = new SAXBuilder();
612
        File file = getConfigFile();
613
 
156 ilm 614
        System.out.println("POSConfiguration.loadConfigurationFromXML() loading " + file.getAbsolutePath());
615
        Document document = builder.build(file);
616
        // config
617
        final Element rootElement = document.getRootElement();
618
        setUserID(Integer.valueOf(rootElement.getAttributeValue("userID", "2")));
619
        setCompanyID(Integer.valueOf(rootElement.getAttributeValue("societeID", "42")));
620
        setPosID(Integer.valueOf(rootElement.getAttributeValue("caisseID", "2")));
182 ilm 621
        setDepotID(Integer.valueOf(rootElement.getAttributeValue("depotID", "2")));
156 ilm 622
        setScanDelay(Integer.valueOf(rootElement.getAttributeValue("scanDelay", "80")));
174 ilm 623
        setAskPostalCode(rootElement.getAttributeValue("askPostalCode", "false").equals("true"));
624
 
156 ilm 625
        // screen
626
        final List<Element> children = rootElement.getChildren("screen");
627
        if (children != null) {
628
            for (Element e : children) {
629
                this.screenWidth = Integer.valueOf(e.getAttributeValue("width", "0"));
630
                this.screenHeight = Integer.valueOf(e.getAttributeValue("height", "0"));
132 ilm 631
            }
156 ilm 632
        }
633
        // credit card
634
        final List<Element> childrenCreditCard = rootElement.getChildren("creditcard");
635
        if (childrenCreditCard != null) {
636
            for (Element e : childrenCreditCard) {
637
                this.creditCardPort = e.getAttributeValue("port", "");
132 ilm 638
            }
156 ilm 639
        }
640
        // lcd
641
        final List<Element> childrenLCD = rootElement.getChildren("lcd");
642
        if (childrenLCD != null) {
643
            for (Element e : childrenLCD) {
644
                this.LCDType = e.getAttributeValue("type", "serial");
645
                this.LCDPort = e.getAttributeValue("port", "");
646
                this.LCDLine1 = e.getAttributeValue("line1", "");
647
                this.LCDLine2 = e.getAttributeValue("line2", "");
132 ilm 648
            }
156 ilm 649
        }
132 ilm 650
 
156 ilm 651
        // header
652
        final List<Element> headers = rootElement.getChildren("header");
653
        if (headers != null) {
654
            for (Element header : headers) {
655
                this.headerLines.add(new TicketLine(header.getValue(), header.getAttributeValue("style")));
132 ilm 656
            }
156 ilm 657
        }
658
        // footer
659
        final List<Element> footers = rootElement.getChildren("footer");
660
        if (footers != null) {
661
            for (Element header : footers) {
662
                this.footerLines.add(new TicketLine(header.getValue(), header.getAttributeValue("style")));
132 ilm 663
            }
664
        }
156 ilm 665
        // ticket printers
666
        final List<Element> printers = rootElement.getChildren("ticketPrinter");
174 ilm 667
        if (!printers.isEmpty()) {
156 ilm 668
            configureTicketPrinter(this.ticketPrinterConf1, printers.get(0));
669
        }
670
        if (printers.size() > 1) {
671
            configureTicketPrinter(this.ticketPrinterConf2, printers.get(1));
672
        }
132 ilm 673
    }
674
 
675
    private void configureTicketPrinter(TicketPrinterConfiguration conf, Element element) {
676
        conf.setType(element.getAttributeValue("type"));
677
        conf.setName(element.getAttributeValue("name"));
678
        conf.setCopyCount(Integer.parseInt(element.getAttributeValue("copyCount")));
679
        conf.setTicketWidth(Integer.parseInt(element.getAttributeValue("ticketWidth")));
680
        conf.setFolder(element.getAttributeValue("folder", ""));
681
    }
682
 
683
    private Element getElementFromConfiguration(TicketPrinterConfiguration conf) {
684
        final Element element = new Element("ticketPrinter");
685
        element.setAttribute("type", conf.getType());
686
        element.setAttribute("name", conf.getName());
687
        element.setAttribute("copyCount", String.valueOf(conf.getCopyCount()));
688
        element.setAttribute("ticketWidth", String.valueOf(conf.getTicketWidth()));
689
        element.setAttribute("folder", conf.getFolder());
690
        return element;
691
    }
692
 
693
    public void saveConfiguration() {
694
        final File file = getConfigFile();
144 ilm 695
        if (file.exists() && !file.canWrite()) {
696
            JOptionPane.showMessageDialog(null, "Impossible d'enregistrer le fichier : " + file.getAbsolutePath() + "\nMerci d'accorder les droits d'écriture à ce fichier.");
697
            return;
698
        }
132 ilm 699
        final XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
700
        try {
701
            System.out.println("Saving:" + file.getAbsolutePath());
702
            final FileOutputStream fileOutputStream = new FileOutputStream(file);
703
            final Document doc = new Document();
704
            final Element configElement = new Element("config");
705
            configElement.setAttribute("userID", String.valueOf(this.userID));
706
            configElement.setAttribute("societeID", String.valueOf(this.companyID));
707
            configElement.setAttribute("caisseID", String.valueOf(this.posID));
182 ilm 708
            configElement.setAttribute("depotID", String.valueOf(this.depotStockId));
132 ilm 709
            configElement.setAttribute("scanDelay", String.valueOf(this.scanDelay));
174 ilm 710
            configElement.setAttribute("askPostalCode", this.askPostalCode ? "true" : "false");
132 ilm 711
            doc.addContent(configElement);
712
            // screen size
713
            final Element screenElement = new Element("screen");
714
            screenElement.setAttribute("width", String.valueOf(this.screenWidth));
715
            screenElement.setAttribute("height", String.valueOf(this.screenHeight));
716
            configElement.addContent(screenElement);
717
            // credit card
718
            final Element creditCardElement = new Element("creditcard");
719
            creditCardElement.setAttribute("port", this.creditCardPort);
720
            configElement.addContent(creditCardElement);
721
            // LCD
722
            final Element lcdElement = new Element("lcd");
142 ilm 723
            lcdElement.setAttribute("type", this.LCDType);
724
            lcdElement.setAttribute("port", this.LCDPort);
132 ilm 725
            lcdElement.setAttribute("line1", this.LCDLine1);
726
            lcdElement.setAttribute("line2", this.LCDLine2);
727
            configElement.addContent(lcdElement);
728
 
729
            // header
730
            for (TicketLine line : this.headerLines) {
731
                Element e = new Element("header");
732
                final String style = line.getStyle();
733
                if (style != null && !style.isEmpty()) {
734
                    e.setAttribute("style", style);
735
                }
736
                e.setText(line.getText());
737
                configElement.addContent(e);
738
            }
739
            // footer
740
            for (TicketLine line : this.footerLines) {
741
                Element e = new Element("footer");
742
                final String style = line.getStyle();
743
                if (style != null && !style.isEmpty()) {
744
                    e.setAttribute("style", style);
745
                }
746
                e.setText(line.getText());
747
                configElement.addContent(e);
748
            }
749
            // ticket printer
750
            configElement.addContent(getElementFromConfiguration(this.ticketPrinterConf1));
751
            configElement.addContent(getElementFromConfiguration(this.ticketPrinterConf2));
752
            outputter.output(doc, fileOutputStream);
753
            fileOutputStream.close();
754
        } catch (Exception e) {
755
            e.printStackTrace();
756
            ExceptionHandler.handle("Erreur lors de la sauvegarde de la configuration de la caisse.\n" + file.getAbsolutePath());
757
        }
758
 
759
    }
760
 
149 ilm 761
    public void print(Printable ticket) {
151 ilm 762
        print(ticket, 0);
132 ilm 763
    }
764
 
151 ilm 765
    public void print(Printable ticket, int additionnalCopy) {
766
        print(ticket, this.ticketPrinterConf1, additionnalCopy);
767
        print(ticket, this.ticketPrinterConf2, additionnalCopy);
768
    }
769
 
149 ilm 770
    public void printOnceOnFirstPrinter(Printable ticket) {
771
        if (this.ticketPrinterConf1.isValid()) {
772
            final TicketPrinter prt = this.ticketPrinterConf1.createTicketPrinter();
773
            ticket.print(prt, this.ticketPrinterConf1.getTicketWidth());
774
        }
775
    }
776
 
777
    public void print(Printable ticket, TicketPrinterConfiguration conf) {
151 ilm 778
        print(ticket, conf, 0);
779
    }
780
 
781
    public void print(Printable ticket, TicketPrinterConfiguration conf, int additionnalCopy) {
782
        int copyCount = conf.getCopyCount() + additionnalCopy;
783
        if (conf.isValid() && copyCount > 0) {
132 ilm 784
            final TicketPrinter prt = conf.createTicketPrinter();
151 ilm 785
            for (int i = 0; i < copyCount; i++) {
132 ilm 786
                ticket.print(prt, conf.getTicketWidth());
787
            }
788
        }
789
    }
790
 
791
    public boolean isUsingJPos() {
792
        return false;
793
    }
794
 
182 ilm 795
    public List<String> getJPosDirectories() {
132 ilm 796
        final ArrayList<String> result = new ArrayList<String>();
797
        return result;
798
    }
799
 
142 ilm 800
    public String getLCDPort() {
801
        return LCDPort;
132 ilm 802
    }
803
 
142 ilm 804
    public void setLCDPort(String port) {
805
        this.LCDPort = port;
132 ilm 806
    }
807
 
808
    public String getLCDLine1() {
809
        return this.LCDLine1;
810
    }
811
 
812
    public void setLCDLine1(String text) {
813
        this.LCDLine1 = text;
814
    }
815
 
816
    public String getLCDLine2() {
817
        return this.LCDLine2;
818
    }
819
 
820
    public void setLCDLine2(String text) {
821
        this.LCDLine2 = text;
822
    }
823
 
142 ilm 824
    public List<Client> allClients() {
825
        SQLElement elt = Configuration.getInstance().getDirectory().getElement("CLIENT");
826
        SQLRowValues r = new SQLRowValues(elt.getTable());
827
        r.putNulls("NOM", "SOLDE_COMPTE");
828
        SQLRowValues rAdresse = new SQLRowValues(Configuration.getInstance().getDirectory().getElement("ADRESSE").getTable());
829
        rAdresse.putNulls("RUE", "VILLE");
830
        r.put("ID_ADRESSE", rAdresse);
831
        SQLRowValuesListFetcher f = new SQLRowValuesListFetcher(r);
832
        List<SQLRowValues> result = f.fetch();
833
        List<Client> l = new ArrayList<Client>();
834
 
835
        for (SQLRowValues sqlRowValues : result) {
836
            Client c = new Client(sqlRowValues.getID(), sqlRowValues.getString("NOM"), sqlRowValues.getBigDecimal("SOLDE_COMPTE"));
837
            final SQLRowAccessor foreign = sqlRowValues.getForeign("ID_ADRESSE");
182 ilm 838
            c.setAdresse(foreign.getString("RUE") + "\n" + foreign.getString("VILLE"));
142 ilm 839
            l.add(c);
840
        }
841
        Collections.sort(l, new Comparator<Client>() {
842
 
843
            @Override
844
            public int compare(Client o1, Client o2) {
845
                return o1.getFullName().compareToIgnoreCase(o2.getFullName());
846
            }
847
        });
848
        l.add(0, Client.NONE);
849
        return l;
850
    }
851
 
852
    public void setLCDType(String type) {
853
        this.LCDType = type;
854
 
855
    }
856
 
857
    public String getLCDType() {
858
        return this.LCDType;
859
    }
174 ilm 860
 
861
    public boolean askPostalCode() {
862
        return this.askPostalCode;
863
    }
864
 
865
    public void setAskPostalCode(boolean askPostalCode) {
866
        this.askPostalCode = askPostalCode;
867
    }
182 ilm 868
 
132 ilm 869
}