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
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.sales.pos.ui;
15
 
144 ilm 16
import org.openconcerto.erp.config.ComptaPropsConfiguration;
17
import org.openconcerto.erp.config.Gestion;
132 ilm 18
import org.openconcerto.erp.core.sales.pos.POSConfiguration;
182 ilm 19
import org.openconcerto.erp.core.sales.pos.model.Article;
142 ilm 20
import org.openconcerto.erp.core.sales.pos.model.Client;
144 ilm 21
import org.openconcerto.erp.core.sales.pos.model.DBState;
182 ilm 22
import org.openconcerto.erp.core.sales.pos.model.Paiement;
144 ilm 23
import org.openconcerto.erp.core.sales.pos.model.ReceiptCode;
24
import org.openconcerto.erp.core.sales.pos.model.RegisterDB;
25
import org.openconcerto.erp.core.sales.pos.model.RegisterFiles;
26
import org.openconcerto.erp.core.sales.pos.model.RegisterLog;
27
import org.openconcerto.erp.core.sales.pos.model.RegisterState;
28
import org.openconcerto.erp.core.sales.pos.model.RegisterState.Status;
18 ilm 29
import org.openconcerto.erp.core.sales.pos.model.Ticket;
174 ilm 30
import org.openconcerto.erp.core.sales.pos.model.TicketItem;
156 ilm 31
import org.openconcerto.erp.utils.TM;
61 ilm 32
import org.openconcerto.sql.PropsConfiguration;
73 ilm 33
import org.openconcerto.sql.RemoteShell;
144 ilm 34
import org.openconcerto.sql.element.SQLElementDirectory;
61 ilm 35
import org.openconcerto.sql.model.SQLBase;
142 ilm 36
import org.openconcerto.sql.model.SQLRowAccessor;
144 ilm 37
import org.openconcerto.sql.model.SQLRowValues;
156 ilm 38
import org.openconcerto.sql.model.SQLRowValuesListFetcher;
18 ilm 39
import org.openconcerto.sql.sqlobject.ElementComboBox;
40
import org.openconcerto.utils.ClassPathLoader;
41
import org.openconcerto.utils.ExceptionHandler;
144 ilm 42
import org.openconcerto.utils.cc.ExnTransformer;
18 ilm 43
 
142 ilm 44
import java.awt.Container;
67 ilm 45
import java.awt.Dimension;
149 ilm 46
import java.awt.Frame;
142 ilm 47
import java.awt.Point;
67 ilm 48
import java.awt.Toolkit;
142 ilm 49
import java.awt.event.MouseEvent;
18 ilm 50
import java.io.File;
144 ilm 51
import java.io.IOException;
18 ilm 52
import java.net.MalformedURLException;
144 ilm 53
import java.sql.SQLException;
54
import java.text.ParseException;
55
import java.util.EnumSet;
132 ilm 56
import java.util.List;
182 ilm 57
import java.util.Map;
156 ilm 58
import java.util.Objects;
149 ilm 59
import java.util.Set;
144 ilm 60
import java.util.concurrent.Callable;
61
import java.util.concurrent.FutureTask;
62
import java.util.logging.Level;
156 ilm 63
import java.util.logging.Logger;
18 ilm 64
 
65
import javax.swing.JFrame;
67 ilm 66
import javax.swing.JOptionPane;
142 ilm 67
import javax.swing.JPanel;
18 ilm 68
import javax.swing.SwingUtilities;
69
import javax.swing.ToolTipManager;
70
 
144 ilm 71
import org.jdom2.JDOMException;
72
 
18 ilm 73
public class CaisseFrame extends JFrame {
156 ilm 74
    private final POSConfiguration posConf;
144 ilm 75
    private final ComptaPropsConfiguration conf;
76
    private final RegisterFiles files;
77
    private final RegisterDB registerDB;
142 ilm 78
    final CaissePanel mainPanel;
18 ilm 79
 
156 ilm 80
    CaisseFrame(final POSConfiguration posConf, final ComptaPropsConfiguration conf, final RegisterFiles files, final RegisterDB registerDB) throws Exception {
81
        this.posConf = posConf;
144 ilm 82
        this.conf = conf;
83
        this.files = files;
84
        this.registerDB = registerDB;
142 ilm 85
        this.mainPanel = new CaissePanel(this);
86
        setContentPane(mainPanel);
18 ilm 87
        setFocusable(true);
88
    }
89
 
156 ilm 90
    public final POSConfiguration getPOSConf() {
91
        return this.posConf;
92
    }
93
 
144 ilm 94
    public final ComptaPropsConfiguration getConf() {
95
        return this.conf;
96
    }
97
 
98
    public final RegisterFiles getFiles() {
99
        return this.files;
100
    }
101
 
102
    public final RegisterDB getDB() {
103
        return this.registerDB;
104
    }
105
 
18 ilm 106
    public static void main(String[] args) {
142 ilm 107
        System.setProperty(SQLRowAccessor.ACCESS_DB_IF_NEEDED_PROP, "true");
18 ilm 108
        try {
109
            System.out.println("Lancement du module de caisse");
110
            ToolTipManager.sharedInstance().setInitialDelay(0);
132 ilm 111
            RemoteShell.startDefaultInstance(null, null);
61 ilm 112
 
113
            System.setProperty(PropsConfiguration.REDIRECT_TO_FILE, "true");
114
            System.setProperty(SQLBase.ALLOW_OBJECT_REMOVAL, "true");
115
 
116
            ExceptionHandler.setForceUI(true);
117
            ExceptionHandler.setForumURL("http://www.openconcerto.org/forum");
144 ilm 118
            ExceptionHandler.setThrowableHandler(Gestion.createDefaultThrowableHandler());
18 ilm 119
            // SpeedUp Linux
120
            System.setProperty("sun.java2d.pmoffscreen", "false");
80 ilm 121
            System.setProperty(SQLBase.STRUCTURE_USE_XML, "true");
61 ilm 122
            System.setProperty(PropsConfiguration.REDIRECT_TO_FILE, "true");
156 ilm 123
            final POSConfiguration posConf = POSConfiguration.setInstance();
124
            if (posConf.isUsingJPos()) {
18 ilm 125
                ClassPathLoader c = ClassPathLoader.getInstance();
126
                try {
156 ilm 127
                    final List<String> posDirectories = posConf.getJPosDirectories();
132 ilm 128
                    for (String posDirectory : posDirectories) {
129
                        if (posDirectory != null && !posDirectory.trim().isEmpty()) {
130
                            c.addJarFromDirectory(new File(posDirectory.trim()));
131
                        }
18 ilm 132
                    }
133
                } catch (MalformedURLException e) {
134
                    e.printStackTrace();
135
                }
136
                c.load();
137
 
138
            }
156 ilm 139
            final ComptaPropsConfiguration conf = posConf.createConnexion();
177 ilm 140
            final TM erpTM = conf.getERP_TM();
144 ilm 141
 
156 ilm 142
            final int userID = posConf.getUserID();
143
            final int posID = posConf.getPosID();
144
            final RegisterFiles registerFiles = new RegisterFiles(posConf.getRootDir(), true, posConf.getPosID());
145
            final RegisterDB registerDB = new RegisterDB(conf.getDirectory(), conf.getProductInfo(), posConf.getPosID());
146
            // check if register exists
147
            final SQLRowValuesListFetcher fetcher = SQLRowValuesListFetcher.create(new SQLRowValues(registerDB.getRegisterTable()));
148
            if (fetcher.fetchOne(posID) == null) {
149
                SwingUtilities.invokeLater(() -> {
177 ilm 150
                    JOptionPane.showMessageDialog(null, erpTM.translate("register.missing", posID), erpTM.translate("register.missing.title"), JOptionPane.ERROR_MESSAGE);
156 ilm 151
                });
152
                posConf.closeConnexion();
153
                return;
154
            }
149 ilm 155
            // check before changing any state
177 ilm 156
            final boolean quit = registerDB.fetchRegisterState().checkIfMoved(erpTM);
149 ilm 157
            if (quit) {
156 ilm 158
                quit(posConf);
149 ilm 159
                return;
160
            }
161
 
156 ilm 162
            final Logger logger = POSConfiguration.getLogger();
163
            final RegisterState reconciledState;
164
            try {
165
                reconciledState = registerFiles.doWithLock(new ExnTransformer<RegisterFiles, RegisterState, Exception>() {
166
                    @Override
167
                    public RegisterState transformChecked(RegisterFiles input) throws Exception {
168
                        return reconcileFSandDB(posConf, conf.getDirectory(), input, registerDB);
144 ilm 169
                    }
156 ilm 170
                });
171
            } catch (ReconcileException re) {
172
                logger.log(Level.WARNING, "States couldn’t be reconciled, local : " + re.getLocalState() + ", remote : " + re.getRemoteState(), re);
173
                final String generalMsg;
174
                boolean onlyOptionPane = false;
175
                if (re instanceof OutsideMeddlingException) {
177 ilm 176
                    generalMsg = erpTM.translate("register.notReconciled.outsideMeddling") + '\n';
156 ilm 177
                    onlyOptionPane = true;
178
                } else if (re instanceof ResumeException) {
177 ilm 179
                    generalMsg = erpTM.translate("register.notReconciled.resumeFailed") + '\n';
156 ilm 180
                } else {
181
                    generalMsg = "";
144 ilm 182
                }
177 ilm 183
                final String message = erpTM.trM("register.notReconciled." + re.getTranslationKey(), "localDate", re.getLocalState().copyDate(), "remoteDate", re.getRemoteState().copyDate());
156 ilm 184
                if (onlyOptionPane) {
185
                    SwingUtilities.invokeLater(() -> {
177 ilm 186
                        JOptionPane.showMessageDialog(null, generalMsg + message, erpTM.translate("register.notReconciled.title"), JOptionPane.ERROR_MESSAGE);
156 ilm 187
                    });
188
                } else {
189
                    ExceptionHandler.handle(generalMsg + message, re);
190
                }
191
                // ATTN this calls ComptaPropsConfiguration.tearDownLogging(), so even syserr is
192
                // closed.
193
                posConf.closeConnexion();
194
                return;
195
            } catch (Exception e) {
196
                throw new IOException("Couldn't reconcile local and remote state", e);
197
            }
198
            logger.log(Level.INFO, "FS and DB states reconciled : {0}", reconciledState);
144 ilm 199
 
200
            System.setProperty("awt.useSystemAAFontSettings", "on");
201
            System.setProperty("swing.aatext", "true");
202
            System.setProperty(ElementComboBox.CAN_MODIFY, "true");
203
 
204
            RegisterState state = reconciledState;
205
            if (reconciledState.getStatus() == Status.CLOSED) {
206
                final FutureTask<Boolean> askUserCallable = new FutureTask<>(new Callable<Boolean>() {
207
                    @Override
208
                    public Boolean call() throws Exception {
209
                        final int ans = JOptionPane.showConfirmDialog(null, "La caisse n’est pas ouverte, voulez-vous l’ouvrir ?", "Caisse fermée", JOptionPane.YES_NO_OPTION);
210
                        return ans == JOptionPane.YES_OPTION;
211
 
212
                    }
213
                });
214
                SwingUtilities.invokeLater(askUserCallable);
215
                final boolean userAgreed = askUserCallable.get();
216
                if (userAgreed) {
217
                    final RegisterLog newLog = registerFiles.open(userID, registerDB);
218
                    state = newLog.getRegisterState();
219
                }
220
            }
221
            if (state.getStatus() != Status.OPEN) {
156 ilm 222
                logger.log(Level.FINE, "State not open ({0}), exiting", state);
223
                posConf.closeConnexion();
144 ilm 224
                return;
225
            }
156 ilm 226
            logger.log(Level.INFO, "FS and DB states open, opening UI");
144 ilm 227
 
18 ilm 228
            SwingUtilities.invokeLater(new Runnable() {
229
                public void run() {
230
 
231
                    try {
156 ilm 232
                        CaisseFrame f = new CaisseFrame(posConf, conf, registerFiles, registerDB);
18 ilm 233
                        f.setUndecorated(true);
234
                        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
235
 
236
                        f.pack();
151 ilm 237
                        if (System.getProperty("os.name").toLowerCase().startsWith("mac os x")) {
238
                            f.setLocation(0, 24);
239
                        } else {
240
                            f.setLocation(0, 0);
241
                        }
67 ilm 242
                        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
156 ilm 243
                        if (posConf.getScreenWidth() > 0 && posConf.getScreenHeight() > 0) {
244
                            f.setSize(new Dimension(posConf.getScreenWidth() - f.getX(), posConf.getScreenHeight() - f.getY()));
83 ilm 245
                        } else {
151 ilm 246
                            f.setSize(new Dimension(screenSize.getSize().width - f.getX(), screenSize.getSize().height - f.getY()));
83 ilm 247
                        }
18 ilm 248
                        System.out.println("Affichage de l'interface");
249
                        f.setVisible(true);
174 ilm 250
                        if (screenSize.getWidth() < 1024 || screenSize.getHeight() < 720) {
67 ilm 251
                            JOptionPane.showMessageDialog(f,
174 ilm 252
                                    "La résolution de votre écran est trop faible.\nLa largeur doit être au minium de 1024 pixels.\nLa hauteur doit être au minium de 720 pixels.");
67 ilm 253
                        }
182 ilm 254
 
255
                        // if(
256
                        // registerFiles.getLastLog().getLastFundEvent(EventType.CASHFUND_OPENING)
257
                        // == null ) {
258
                        // TODO f.showComptage(EventType.CASHFUND_OPENING, f.getControler());
259
                        // }
83 ilm 260
                    } catch (Throwable e) {
261
                        // Catch throwable to be able to see NoClassDefFound and other hard issues
18 ilm 262
                        ExceptionHandler.handle("Erreur d'initialisation de la caisse (main)", e);
263
                    }
264
 
265
                }
266
            });
83 ilm 267
        } catch (Throwable e) {
268
            // Catch throwable to be able to see NoClassDefFound and other hard issues
18 ilm 269
            ExceptionHandler.handle("Erreur d'initialisation de la caisse", e);
270
        }
271
    }
272
 
156 ilm 273
    public static class ReconcileException extends IllegalStateException {
274
        private RegisterState localState, remoteState;
275
        private final String translationKey;
276
 
277
        protected ReconcileException(final String msg, final String key) {
278
            this(msg, key, null);
279
        }
280
 
281
        protected ReconcileException(final String msg, final String key, final Throwable cause) {
282
            super(Objects.requireNonNull(msg, "message"), cause);
283
            this.translationKey = Objects.requireNonNull(key, "translation key");
284
        }
285
 
286
        public final RegisterState getLocalState() {
287
            return this.localState;
288
        }
289
 
290
        public final RegisterState getRemoteState() {
291
            return this.remoteState;
292
        }
293
 
294
        public final String getTranslationKey() {
295
            return this.translationKey;
296
        }
297
 
298
        protected final ReconcileException init(final RegisterState localState, final RegisterState remoteState) {
299
            this.localState = Objects.requireNonNull(localState, "local state");
300
            this.remoteState = Objects.requireNonNull(remoteState, "remote state");
301
            return this;
302
        }
303
    }
304
 
305
    // the FS and/or DB states were modified outside of this software.
306
    public static final class OutsideMeddlingException extends ReconcileException {
307
        protected OutsideMeddlingException(final String msg, final String key) {
308
            super(msg, key);
309
        }
310
    }
311
 
312
    // the opening or closure was interrupted, the process was resumed but it failed.
313
    public static final class ResumeException extends ReconcileException {
314
        protected ResumeException(final String msg, final String key, final Throwable cause) {
315
            super(msg, key, Objects.requireNonNull(cause, "missing cause"));
316
        }
317
    }
318
 
319
    /*
320
     * List of translations keys.
321
     */
322
    private static final String unknownTK = "unknown";
323
    // localOpen
324
    private static final String open_datesMismatch = "open.datesMismatch";
325
    private static final String localOpen_remoteClosed = "localOpen_remoteClosed";
326
    private static final String localOpen_remoteMissing = "localOpen_remoteMissing";
327
    // remoteOpen
328
    private static final String localMissing_remoteReopen = "localMissing_remoteReopen";
329
    private static final String localOpenFailed_remoteOpen = "localOpenFailed_remoteOpen";
330
    private static final String localClosed_remoteCloseFailed = "localClosed_remoteCloseFailed";
331
    private static final String localClosed_remoteOpen_datesMismatch = "localClosed_remoteOpen.datesMismatch";
332
    // both closed
333
    private static final String localMissing_remoteClosed = "localMissing_remoteClosed";
334
    private static final String closed_datesMismatch = "closed.datesMismatch";
335
    private static final String localClosed_remoteMissing = "localClosed_remoteMissing";
336
 
337
    private static RegisterState reconcileFSandDB(final POSConfiguration posConf, final SQLElementDirectory dir, final RegisterFiles files, final RegisterDB registerDB)
144 ilm 338
            throws IOException, JDOMException, ParseException, SQLException {
339
 
340
        // *** find local and remote states
341
        final RegisterLog lastLog = files.getLastLog();
342
        POSConfiguration.getLogger().log(Level.CONFIG, "Found last log {0}", lastLog);
343
 
344
        RegisterState localState;
345
        if (lastLog == null) {
346
            final List<File> remainingReceipts = ReceiptCode.getReceiptsToImport(files.getPosID());
347
            localState = new RegisterState(remainingReceipts.isEmpty() ? Status.CLOSED : Status.OBSOLETE, null);
348
        } else {
349
            localState = lastLog.getRegisterState();
350
        }
351
        POSConfiguration.getLogger().log(Level.CONFIG, "FS state {0}", localState);
352
 
353
        final DBState fetchedState = registerDB.fetchRegisterState();
354
        RegisterState remoteState = fetchedState.getRegisterState();
355
        POSConfiguration.getLogger().log(Level.CONFIG, "DB state {0}", fetchedState);
356
 
357
        // *** import remaining obsolete receipts
358
        if (localState.getStatus() == Status.OBSOLETE) {
359
            if (remoteState.hasDate())
360
                throw new IllegalStateException("There remains obsolete receipts but DB can no longer import them : " + remoteState);
156 ilm 361
            final List<Ticket> allTickets = posConf.allTickets();
144 ilm 362
            POSConfiguration.getLogger().log(Level.INFO, "{0} obsolete receipt(s) will be stored in the DB", allTickets.size());
156 ilm 363
            posConf.commitAll(allTickets);
144 ilm 364
            final List<File> remainingReceipts = ReceiptCode.getReceiptsToImport(files.getPosID());
365
            if (!remainingReceipts.isEmpty())
366
                throw new IllegalStateException("Not all obsolete receipts could be imported : " + remainingReceipts);
367
            localState = new RegisterState(Status.CLOSED, null);
368
            POSConfiguration.getLogger().log(Level.FINE, "All obsolete receipts have been stored in the DB");
369
        }
370
        final EnumSet<Status> validStatus = EnumSet.of(Status.OPEN, Status.CLOSED);
371
        if (!validStatus.contains(localState.getStatus()))
372
            throw new IllegalStateException("Unexpected local status :" + localState);
373
        if (!validStatus.contains(remoteState.getStatus()))
374
            throw new IllegalStateException("Unexpected remote status :" + remoteState);
375
 
376
        // *** reconcile if possible
377
        if (!localState.equals(remoteState)) {
378
            POSConfiguration.getLogger().log(Level.INFO, "Different FS and DB state, will try to reconcile\nFS " + localState + " with\nDB " + remoteState);
156 ilm 379
            final int userID = posConf.getUserID();
144 ilm 380
 
381
            // OK because of the check above
382
            final boolean localOpen = localState.getStatus() == Status.OPEN;
383
            final boolean remoteOpen = remoteState.getStatus() == Status.OPEN;
384
            // Time line
385
            // 0
386
            // Open DB
387
            // 1
388
            // Open Local
389
            // 2
390
            // Create tickets...
391
            // 3
392
            // Close Local
393
            // 4
394
            // Close DB
395
            // 5
396
            // Open DB
397
            // 6
398
            // Open Local
399
            // 7
400
            try {
401
                if (localOpen) {
402
                    if (remoteOpen) {
156 ilm 403
                        throw new OutsideMeddlingException("Both open with but with different dates", open_datesMismatch);
144 ilm 404
                    } else {
405
                        // DB is at 0 or 5, local is at 2
156 ilm 406
                        throw new OutsideMeddlingException("local is open but the DB isn't", remoteState.hasDate() ? localOpen_remoteClosed : localOpen_remoteMissing);
144 ilm 407
                    }
408
                } else if (remoteOpen) {
409
                    assert remoteState.hasDate() : "Remote state open without date : " + remoteState;
410
                    final SQLRowValues lastClosure = fetchedState.getLastClosureEntry();
411
                    final java.util.Date lastClosureDate = lastClosure == null ? null : lastClosure.getDate("DATE").getTime();
412
                    if (!localState.hasDate()) {
413
                        // at 1
414
                        // MAYBE allow it for new install, for now the receipts must be copied
415
                        // over
416
                        if (lastClosureDate != null)
156 ilm 417
                            throw new OutsideMeddlingException("DB was closed and now open, but local log is missing", localMissing_remoteReopen);
144 ilm 418
                        try {
419
                            localState = files.open(userID, fetchedState).getRegisterState();
420
                        } catch (Exception e) {
156 ilm 421
                            throw new ResumeException("The local opening (following the already open DB) failed", localOpenFailed_remoteOpen, e);
144 ilm 422
                        }
423
                    } else if (remoteState.compareDateTo(lastLog.getFirstRegisterEvent().getDate()) == 0) {
424
                        // at 4
425
                        try {
156 ilm 426
                            remoteState = registerDB.close(posConf, files.getLastLog()).getRegisterState();
144 ilm 427
                        } catch (Exception e) {
156 ilm 428
                            throw new ResumeException("The closure of the DB (following the already closed local) failed", localClosed_remoteCloseFailed, e);
144 ilm 429
                        }
430
                    } else if (lastClosureDate != null && localState.compareDateTo(lastClosureDate) == 0) {
431
                        // at 6, TODO factor with above
432
                        try {
433
                            localState = files.open(userID, fetchedState).getRegisterState();
434
                        } catch (Exception e) {
156 ilm 435
                            throw new ResumeException("The local opening (following the already open DB) failed", localOpenFailed_remoteOpen, e);
144 ilm 436
                        }
437
                    } else {
438
                        // DB is at 1, local is between 4 and 6
156 ilm 439
                        throw new OutsideMeddlingException("DB was opened for a different date", localClosed_remoteOpen_datesMismatch);
144 ilm 440
                    }
441
                } else {
156 ilm 442
                    assert !localOpen && !remoteOpen;
144 ilm 443
                    if (!localState.hasDate()) {
444
                        assert remoteState.hasDate() : "Both closed with no dates, but not equal";
445
                        // DB is at 5, local is at 0
446
                        // MAYBE allow it for new install, for now the receipts must be copied
447
                        // over
156 ilm 448
                        throw new OutsideMeddlingException("DB was opened and closed, but local log is missing", localMissing_remoteClosed);
144 ilm 449
                    } else if (remoteState.hasDate()) {
450
                        // DB is at 5, local is at 5 but not for the same day
451
                        assert remoteState.compareDateTo(localState) != 0 : "Both closed with equal dates, but not equal";
156 ilm 452
                        throw new OutsideMeddlingException("DB was opened and closed for a different date", closed_datesMismatch);
144 ilm 453
                    } else {
454
                        // DB is at 0, local is between 4 and 6
156 ilm 455
                        throw new OutsideMeddlingException("DB was never opened but local was closed", localClosed_remoteMissing);
144 ilm 456
                    }
457
                }
156 ilm 458
            } catch (ReconcileException e) {
459
                throw e.init(localState, remoteState);
144 ilm 460
            } catch (Exception e) {
156 ilm 461
                throw new ReconcileException("Unknown exception", unknownTK, e).init(localState, remoteState);
144 ilm 462
            }
463
        }
464
        if (!remoteState.equals(localState))
465
            throw new IllegalStateException("Unexpected state");
466
        return remoteState;
467
    }
468
 
182 ilm 469
    public static void quit(final POSConfiguration posConf) {
149 ilm 470
        POSConfiguration.getLogger().log(Level.INFO, "User exit");
156 ilm 471
        posConf.closeConnexion();
149 ilm 472
        Frame[] l = Frame.getFrames();
473
        for (int i = 0; i < l.length; i++) {
474
            Frame f = l[i];
475
            System.err.println(f.getName() + " " + f + " Displayable: " + f.isDisplayable() + " Valid: " + f.isValid() + " Active: " + f.isActive());
476
        }
477
        Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
478
        for (Thread thread : threadSet) {
479
            if (!thread.isDaemon()) {
480
                System.err.println(thread.getName() + " " + thread.getId() + " not daemon");
481
            }
482
        }
483
    }
484
 
485
    @Override
486
    public void dispose() {
156 ilm 487
        quit(this.posConf);
149 ilm 488
        // Fermeture
489
        this.getControler().setLCD("   CAISSE FERMEE    ", "", 0);
490
        super.dispose();
491
    }
492
 
18 ilm 493
    public void showMenu() {
494
        System.out.println("CaisseFrame.showMenu()");
142 ilm 495
        final CaisseMenuPanel panel = new CaisseMenuPanel(this);
149 ilm 496
        showPanel(panel);
497
        this.getControler().setLCD("OpenConcerto", "Menu", 0);
142 ilm 498
 
149 ilm 499
    }
500
 
151 ilm 501
    public void showPanel(final JPanel panel) {
149 ilm 502
        this.invalidate();
503
        final int x = (getWidth() - panel.getPreferredSize().width) / 2;
504
        final int y = 100;
505
        final POSGlassPane glassPane2 = new POSGlassPane(panel, x, y) {
142 ilm 506
            @Override
507
            public void mousePressed(MouseEvent e) {
508
                Point containerPoint = SwingUtilities.convertPoint(this, e.getPoint(), panel);
509
                if (containerPoint.x < 0 || containerPoint.x > panel.getWidth() || containerPoint.y < 0 || containerPoint.y > panel.getHeight()) {
510
                    setGlassPane(new JPanel());
511
                    getGlassPane().setVisible(false);
512
                }
513
                super.mousePressed(e);
514
            }
515
 
516
        };
517
        this.setGlassPane(glassPane2);
518
        this.getGlassPane().setVisible(true);
18 ilm 519
        this.validate();
520
        this.repaint();
521
    }
522
 
174 ilm 523
    public void showPriceEditor(TicketItem item, CaisseControler caisseControler) {
142 ilm 524
        getControler().disableBarcodeReader();
525
        System.out.println("CaisseFrame.showPriceEditor()");
18 ilm 526
        this.invalidate();
174 ilm 527
        final PriceEditorPanel panel = new PriceEditorPanel(this, item);
142 ilm 528
 
529
        final POSGlassPane glassPane2 = new POSGlassPane(panel, (getWidth() - panel.getPreferredSize().width) / 2, 100) {
530
            @Override
531
            public void mousePressed(MouseEvent e) {
532
                Point containerPoint = SwingUtilities.convertPoint(this, e.getPoint(), panel);
533
                if (containerPoint.x < 0 || containerPoint.x > panel.getWidth() || containerPoint.y < 0 || containerPoint.y > panel.getHeight()) {
534
                    setGlassPane(new JPanel());
535
                    getGlassPane().setVisible(false);
536
                    getControler().enableBarcodeReader();
537
 
538
                }
539
                super.mousePressed(e);
540
            }
541
 
542
        };
543
        this.setGlassPane(glassPane2);
544
        this.getGlassPane().setVisible(true);
18 ilm 545
        this.validate();
546
        this.repaint();
142 ilm 547
 
18 ilm 548
    }
549
 
142 ilm 550
    public void showCaisse() {
551
        getControler().enableBarcodeReader();
552
        setGlassPane(new JPanel());
553
        getGlassPane().setVisible(false);
554
 
555
        System.out.println("CaisseFrame.showCaisse()");
556
        this.setContentPane(this.mainPanel);
557
        this.getControler().setLCD("OpenConcerto", "Caisse", 0);
558
        this.getControler().setLCDDefaultDisplay(5);
559
    }
560
 
18 ilm 561
    public void showTickets(Ticket t) {
562
        System.out.println("CaisseFrame.showMenu()");
142 ilm 563
        final ListeDesTicketsPanel panel = new ListeDesTicketsPanel(this);
18 ilm 564
        panel.setSelectedTicket(t);
565
        this.setContentPane(panel);
566
    }
567
 
132 ilm 568
    public CaisseControler getControler() {
142 ilm 569
        return this.mainPanel.getControler();
132 ilm 570
    }
142 ilm 571
 
572
    public void showClients() {
573
        System.out.println("CaisseFrame.showClients()");
574
        final ListeDesClientsPanel panel = new ListeDesClientsPanel(this);
575
        this.setContentPane(panel);
576
    }
577
 
578
    public void setClient(Client client) {
579
        System.err.println("CaisseFrame.setClient() " + client.getFullName());
580
        this.getControler().setClient(client);
581
 
582
    }
583
 
584
    @Override
585
    public void setContentPane(Container contentPane) {
586
        this.invalidate();
587
        setGlassPane(new JPanel());
588
        getGlassPane().setVisible(false);
589
        super.setContentPane(contentPane);
590
        this.validate();
591
        this.repaint();
592
    }
174 ilm 593
 
594
    public void showPostalCodeFrame(CaissePanel caissePanel) {
595
        System.out.println("CaisseFrame.showPostalCodeFrame()");
596
        this.invalidate();
597
        final PostalCodeEditorPanel panel = new PostalCodeEditorPanel(this, caissePanel);
598
        final POSGlassPane glassPane2 = new POSGlassPane(panel, (getWidth() - panel.getPreferredSize().width) / 2, 100);
599
        this.setGlassPane(glassPane2);
600
        this.getGlassPane().setVisible(true);
601
        this.validate();
602
        this.repaint();
182 ilm 603
    }
174 ilm 604
 
182 ilm 605
    public void showCBPanel(Paiement p) {
606
        getControler().disableBarcodeReader();
607
        System.out.println("CaisseFrame.showCBPanel()");
608
        this.invalidate();
609
        final CBPanel panel = new CBPanel(this, this.getControler(), p);
610
 
611
        final POSGlassPane glassPane2 = new POSGlassPane(panel, (getWidth() - panel.getPreferredSize().width) / 2, 100);
612
        this.setGlassPane(glassPane2);
613
        this.getGlassPane().setVisible(true);
614
        this.validate();
615
        this.repaint();
174 ilm 616
    }
182 ilm 617
 
618
    public void showArticleSelector(List<Article> list, ArticleSelectionListener articleSelectionListener) {
619
        getControler().disableBarcodeReader();
620
 
621
        this.invalidate();
622
        final ArticleSelectorDialogPanel panel = new ArticleSelectorDialogPanel(this, list, articleSelectionListener);
623
 
624
        final int x = (getWidth() - panel.getPreferredSize().width) / 2;
625
        final int y = 100;
626
        System.out.println("CaisseFrame.showArticleSelector() at " + x + "," + y + " " + panel.getPreferredSize().width + "x" + panel.getPreferredSize().height + " : " + list.size()
627
                + " products (barcode : " + list.get(0).getBarCode() + ")");
628
        final POSGlassPane glassPane2 = new POSGlassPane(panel, x, y);
629
        this.setGlassPane(glassPane2);
630
        this.getGlassPane().setVisible(true);
631
        this.validate();
632
        this.repaint();
633
 
634
    }
635
 
636
    public void showStockErrorPanel(Map<TicketItem, Integer> missingQty, Runnable runnable) {
637
        getControler().disableBarcodeReader();
638
 
639
        this.invalidate();
640
        final StockErrorPanel panel = new StockErrorPanel(this, missingQty, runnable);
641
 
642
        final int x = (getWidth() - panel.getPreferredSize().width) / 2;
643
        final int y = 100;
644
        System.out.println("CaisseFrame.showStockErrorPanel() at " + x + "," + y + " " + panel.getPreferredSize().width + "x" + panel.getPreferredSize().height + " : " + missingQty.size());
645
        final POSGlassPane glassPane2 = new POSGlassPane(panel, x, y);
646
        this.setGlassPane(glassPane2);
647
        this.getGlassPane().setVisible(true);
648
        this.validate();
649
        this.repaint();
650
 
651
    }
652
 
653
    public void showTicketClientNamePanel(Ticket ticket) {
654
        getControler().disableBarcodeReader();
655
 
656
        this.invalidate();
657
        final TicketClientNamePanel panel = new TicketClientNamePanel(this, ticket);
658
 
659
        final int x = (getWidth() - panel.getPreferredSize().width) / 2;
660
        final int y = 100;
661
        System.out.println("CaisseFrame.showTicketClientNamePanel() at " + x + "," + y + " " + panel.getPreferredSize().width + "x" + panel.getPreferredSize().height + " : " + ticket);
662
        final POSGlassPane glassPane2 = new POSGlassPane(panel, x, y);
663
        this.setGlassPane(glassPane2);
664
        this.getGlassPane().setVisible(true);
665
        this.validate();
666
        this.repaint();
667
 
668
    }
18 ilm 669
}