OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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

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