OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 151 | Rev 177 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
18 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
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.ui;
15
 
16
import org.openconcerto.erp.core.sales.pos.model.Article;
17
import org.openconcerto.erp.core.sales.pos.model.Paiement;
174 ilm 18
import org.openconcerto.erp.core.sales.pos.model.TicketItem;
18 ilm 19
 
20
import java.awt.Color;
21
import java.awt.Dimension;
22
import java.awt.Font;
23
import java.awt.Graphics;
24
import java.awt.Graphics2D;
25
import java.awt.RenderingHints;
26
import java.awt.event.KeyEvent;
27
import java.awt.event.MouseEvent;
28
import java.awt.event.MouseListener;
29
import java.awt.geom.Rectangle2D;
174 ilm 30
import java.math.BigDecimal;
142 ilm 31
import java.util.List;
18 ilm 32
 
83 ilm 33
import javax.swing.JOptionPane;
18 ilm 34
import javax.swing.JPanel;
35
 
36
public class PaiementPanel extends JPanel implements CaisseListener, MouseListener, BarcodeListener {
142 ilm 37
    private static final int PAYMENT_POS_Y = 50;
38
    private static final int PAYMENT_LINE_HEIGHT = 60;
39
 
18 ilm 40
    private CaisseControler controller;
41
    private String calculatorValue = "";
142 ilm 42
    int calcHeight = 5 * 68;
43
    int calcWidth = 4 * 69;
44
    int BUTTON_SIZE = 64;
18 ilm 45
    /**
46
     * Mode '+' ajout d'une quantité '*' multiplication '-' soustraction ' ' remplacement
132 ilm 47
     */
18 ilm 48
    private char mode = ' ';
49
    private boolean init = true;
50
 
51
    public PaiementPanel(CaisseControler controller) {
52
        this.controller = controller;
53
        this.controller.addCaisseListener(this);
54
        this.controller.addBarcodeListener(this);
55
        this.setOpaque(false);
142 ilm 56
 
18 ilm 57
        this.addMouseListener(this);
58
 
59
        this.setLayout(null);
60
        StatusBar st = new StatusBar();
61
        st.setTitle("Règlement");
62
        st.setLocation(0, 0);
63
        st.setSize(320, (int) st.getPreferredSize().getHeight());
64
 
65
        this.add(st);
66
 
67
    }
68
 
69
    @Override
70
    public void paint(Graphics g) {
174 ilm 71
 
142 ilm 72
        Graphics2D g2 = (Graphics2D) g;
73
        g.setColor(new Color(250, 250, 250));
67 ilm 74
        g.fillRect(0, 0, this.getWidth(), this.getHeight());
75
 
142 ilm 76
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
174 ilm 77
        g.setColor(Color.LIGHT_GRAY);
18 ilm 78
        g.drawLine(0, 0, 0, this.getHeight());
142 ilm 79
        int y = PAYMENT_POS_Y;
174 ilm 80
        for (Paiement p : this.controller.getPaiements()) {
18 ilm 81
            if (p.getType() == Paiement.CB) {
142 ilm 82
                drawMontant(g, "CB", p, 242 - 15, y, true);
18 ilm 83
            } else if (p.getType() == Paiement.CHEQUE) {
142 ilm 84
                drawMontant(g, "Chèque", p, 242 - 15, y, true);
18 ilm 85
            } else if (p.getType() == Paiement.ESPECES) {
142 ilm 86
                drawMontant(g, "Espèces", p, 300 - 45, y, false);
87
            } else if (p.getType() == Paiement.SOLDE) {
88
                drawMontant(g, "Solde", p, 300 - 45, y, false);
18 ilm 89
            }
142 ilm 90
            y += PAYMENT_LINE_HEIGHT;
18 ilm 91
        }
142 ilm 92
 
93
        drawKey(g2, "0", 0, 0, 2, 1, CaissePanel.DARK_BLUE);
94
        drawKey(g2, ".", 2, 0, 1, 1, CaissePanel.DARK_BLUE);
95
 
96
        drawKey(g2, "1", 0, 1, 1, 1, CaissePanel.DARK_BLUE);
97
        drawKey(g2, "2", 1, 1, 1, 1, CaissePanel.DARK_BLUE);
98
        drawKey(g2, "3", 2, 1, 1, 1, CaissePanel.DARK_BLUE);
99
        drawKey(g2, "=", 3, 1, 1, 2, CaissePanel.DARK_BLUE);
100
 
101
        drawKey(g2, "4", 0, 2, 1, 1, CaissePanel.DARK_BLUE);
102
        drawKey(g2, "5", 1, 2, 1, 1, CaissePanel.DARK_BLUE);
103
        drawKey(g2, "6", 2, 2, 1, 1, CaissePanel.DARK_BLUE);
104
 
105
        drawKey(g2, "7", 0, 3, 1, 1, CaissePanel.DARK_BLUE);
106
        drawKey(g2, "8", 1, 3, 1, 1, CaissePanel.DARK_BLUE);
107
        drawKey(g2, "9", 2, 3, 1, 1, CaissePanel.DARK_BLUE);
108
        drawKey(g2, "+", 3, 3, 1, 2, CaissePanel.DARK_BLUE);
109
 
110
        drawKey(g2, "C", 0, 4, 2, 1, CaissePanel.LIGHT_BLUE);
111
        drawKey(g2, "x", 2, 4, 1, 1, CaissePanel.DARK_BLUE);
112
        drawKey(g2, "-", 3, 4, 1, 1, CaissePanel.DARK_BLUE);
113
 
18 ilm 114
        drawCalculator(g);
115
        super.paint(g);
174 ilm 116
 
18 ilm 117
    }
118
 
142 ilm 119
    private void drawKey(Graphics2D g2, String string, int col, int row, int w, int h, Color color) {
120
        // background
121
        g2.setColor(color);
122
        g2.fillRect(3 + col * 69, this.getHeight() - (68 * (row + 1)) + 2, 69 * w - 5, 68 * h - 4);
123
        // label
124
        g2.setColor(Color.WHITE);
125
        g2.setFont(g2.getFont().deriveFont(32f));
126
        final int width2 = (int) g2.getFontMetrics().getStringBounds(string, g2).getWidth();
127
        int x = -width2 / 2 + (69) / 2 + col * 69;
128
        int y = this.getHeight() - (row * 68 + 20);
18 ilm 129
 
142 ilm 130
        g2.drawString(string, x, y);
18 ilm 131
    }
132
 
142 ilm 133
    public int getLCDY() {
134
        return this.getHeight() - this.calcHeight - 66;
135
    }
136
 
137
    public int getLCDHeight() {
138
        return 64;
139
    }
140
 
18 ilm 141
    private void drawCalculator(Graphics g) {
142
        Graphics2D g2 = (Graphics2D) g;
67 ilm 143
 
142 ilm 144
        // LCD
174 ilm 145
        if (this.controller.getArticleSelected() != null || this.controller.getPaiementSelected() != null) {
142 ilm 146
            g.setColor(new Color(232, 242, 254));
147
        } else {
148
            g.setColor(new Color(240, 240, 240));
149
        }
150
        g.fillRect(3, getLCDY(), this.getWidth() - 5, getLCDHeight());
151
        //
152
        int y = this.getHeight() - this.calcHeight - 10;
18 ilm 153
        g.setFont(new Font("Arial", Font.PLAIN, 32));
154
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
174 ilm 155
        final Article article = this.controller.getArticleSelected();
18 ilm 156
        g.setColor(Color.DARK_GRAY);
157
        if (article != null) {
174 ilm 158
            String string = this.calculatorValue;
18 ilm 159
            g.setFont(g.getFont().deriveFont(52f));
160
            Rectangle2D r1 = g.getFontMetrics().getStringBounds(string, g2);
142 ilm 161
            g.drawString(string, (int) (260 - r1.getWidth()), y);
18 ilm 162
            g.setFont(g.getFont().deriveFont(14f));
67 ilm 163
            g.drawString("Quantité", 10, 460 + y);
18 ilm 164
 
165
        } else {
174 ilm 166
            final Paiement paiement = this.controller.getPaiementSelected();
18 ilm 167
            if (paiement != null) {
174 ilm 168
                String string = this.calculatorValue;
18 ilm 169
                g.setFont(g.getFont().deriveFont(52f));
170
                Rectangle2D r1 = g.getFontMetrics().getStringBounds(string, g2);
142 ilm 171
                g.drawString(string, (int) (260 - r1.getWidth()), y);
18 ilm 172
                g.setFont(g.getFont().deriveFont(14f));
173
                String str = "Paiement ";
174
                if (paiement.getType() == Paiement.CB) {
175
                    str += " CB";
176
                } else if (paiement.getType() == Paiement.ESPECES) {
177
                    str += " en espèces";
178
                } else if (paiement.getType() == Paiement.CHEQUE) {
179
                    str += " par chèque";
142 ilm 180
                } else if (paiement.getType() == Paiement.SOLDE) {
181
                    str += " depuis solde";
18 ilm 182
                }
142 ilm 183
                g.drawString(str, 10, y - 40);
18 ilm 184
            }
185
        }
186
        g.setFont(g.getFont().deriveFont(14f));
174 ilm 187
        g.drawString("" + this.mode, 10, y - 20);
18 ilm 188
    }
189
 
190
    private char getToucheFrom(int x, int y) {
142 ilm 191
        int yy = (this.getHeight() - y) / 68;
192
        int xx = x / 69;
18 ilm 193
        switch (yy) {
194
        case 0:
195
            if (xx == 0) {
196
                return '0';
197
            } else if (xx == 1) {
198
                return '0';
199
            } else if (xx == 2) {
200
                return '.';
201
            } else if (xx == 3) {
202
                return '=';
203
            } else {
204
                break;
205
            }
206
        case 1:
207
            if (xx == 0) {
208
                return '1';
209
            } else if (xx == 1) {
210
                return '2';
211
            } else if (xx == 2) {
212
                return '3';
213
            } else if (xx == 3) {
214
                return '=';
215
            } else {
216
                break;
217
            }
218
        case 2:
219
            if (xx == 0) {
220
                return '4';
221
            } else if (xx == 1) {
222
                return '5';
223
            } else if (xx == 2) {
224
                return '6';
225
            } else if (xx == 3) {
226
                return '+';
227
            } else {
228
                break;
229
            }
230
        case 3:
231
            if (xx == 0) {
232
                return '7';
233
            } else if (xx == 1) {
234
                return '8';
235
            } else if (xx == 2) {
236
                return '9';
237
            } else if (xx == 3) {
238
                return '+';
239
            } else {
240
                break;
241
            }
242
        case 4:
243
            if (xx == 0) {
244
                return 'c';
245
            } else if (xx == 1) {
246
                return 'c';
247
            } else if (xx == 2) {
248
                return '*';
249
            } else if (xx == 3) {
250
                return '-';
251
            } else {
252
                break;
253
            }
254
 
255
        }
256
        return '?';
257
    }
258
 
142 ilm 259
    private void drawMontant(Graphics g, String label, Paiement p, int x, int y, boolean showAdd) {
18 ilm 260
        y = y + 36;
261
        Graphics2D g2 = (Graphics2D) g;
142 ilm 262
 
18 ilm 263
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
151 ilm 264
        int cents = p.getCents();
265
        int euros = p.getEuros();
142 ilm 266
        // Background
267
        g.setColor(new Color(240, 240, 240));
268
        g.fillRect(3, y - 36, this.getWidth() - 5, 44);
269
 
270
        g.setColor(CaissePanel.DARK_BLUE);
271
 
272
        g.fillRect(3, y - 36, 95, 44);
273
 
274
        if (showAdd) {
275
            g.setColor(CaissePanel.DARK_BLUE);
276
            g.fillRect(this.getWidth() - 46, y - 36, 44, 44);
277
        }
278
        // Label
279
        g.setFont(g.getFont().deriveFont(20f));
280
        g.setFont(g.getFont().deriveFont(Font.BOLD));
281
 
282
        g.setColor(Color.WHITE);
283
        g.drawString(label, 10, y - 8);
284
        if (showAdd) {
285
            g.drawString("+", this.getWidth() - 32, y - 8);
286
        }
287
        // Cents
288
        g.setColor(Color.GRAY);
18 ilm 289
        String sCents = String.valueOf(cents);
290
        if (sCents.length() < 2) {
291
            sCents = "0" + sCents;
292
        }
293
        g.setFont(getFont().deriveFont(18f));
294
        Rectangle2D r1 = g.getFontMetrics().getStringBounds(sCents, g2);
295
        g.drawString(sCents, (int) (x - r1.getWidth()), y);
142 ilm 296
        // Euros
18 ilm 297
        g.setFont(g.getFont().deriveFont(36f));
298
        g.setFont(g.getFont().deriveFont(Font.BOLD));
142 ilm 299
        g.setColor(Color.BLACK);
18 ilm 300
        String sEuros = String.valueOf(euros) + ".";
301
        Rectangle2D r2 = g.getFontMetrics().getStringBounds(sEuros, g2);
302
        g.drawString(sEuros, (int) (x - r1.getWidth() - r2.getWidth()), y);
303
    }
304
 
305
    @Override
306
    public Dimension getPreferredSize() {
174 ilm 307
        return new Dimension(this.calcWidth, 768);
18 ilm 308
    }
309
 
310
    public Dimension getMinimumSize() {
174 ilm 311
        return new Dimension(this.calcWidth, 768);
18 ilm 312
    }
313
 
314
    @Override
315
    public void caisseStateChanged() {
174 ilm 316
        if (this.controller.getArticleSelected() != null) {
18 ilm 317
            initCaisseArticle();
174 ilm 318
        } else if (this.controller.getPaiementSelected() != null) {
18 ilm 319
            initCaissePaiement();
320
        }
142 ilm 321
        // Add / Remove solde if needed
322
        boolean soldeIsShown = false;
174 ilm 323
        for (Paiement p : this.controller.getPaiements()) {
142 ilm 324
            if (p.getType() == Paiement.SOLDE) {
325
                soldeIsShown = true;
326
                break;
327
            }
328
        }
18 ilm 329
 
174 ilm 330
        if (this.controller.isClientDefined()) {
331
            if (!soldeIsShown && this.controller.getClient().getSolde().signum() == 1) {
142 ilm 332
                // add
174 ilm 333
                this.controller.addPaiement(new Paiement(Paiement.SOLDE));
142 ilm 334
            }
335
        } else {
336
            if (soldeIsShown) {
337
                // remove
174 ilm 338
                final List<Paiement> paiements = this.controller.getPaiements();
142 ilm 339
                for (int i = 0; i < paiements.size(); i++) {
340
                    final Paiement p = paiements.get(i);
341
                    if (p.getType() == Paiement.SOLDE) {
174 ilm 342
                        this.controller.getPaiements().remove(i);
142 ilm 343
                        break;
344
                    }
345
                }
346
            }
347
        }
18 ilm 348
        repaint();
349
 
350
    }
351
 
352
    private void initCaisseArticle() {
174 ilm 353
        if (this.controller.getTicketItemSelected() != null) {
354
            this.calculatorValue = this.controller.getTicketItemSelected().getQty().toPlainString();
355
        } else {
356
            this.calculatorValue = "";
357
        }
358
        this.init = true;
359
        this.mode = ' ';
18 ilm 360
    }
361
 
362
    private void initCaissePaiement() {
174 ilm 363
        this.calculatorValue = TicketCellRenderer.centsToString(this.controller.getPaiementSelected().getMontantInCents());
364
        this.init = true;
365
        this.mode = ' ';
18 ilm 366
    }
367
 
368
    @Override
369
    public void mouseClicked(MouseEvent e) {
142 ilm 370
        // Nothing to do here
18 ilm 371
    }
372
 
373
    @Override
374
    public void mouseEntered(MouseEvent e) {
142 ilm 375
        // Nothing to do here
18 ilm 376
    }
377
 
378
    @Override
379
    public void mouseExited(MouseEvent e) {
142 ilm 380
        // Nothing to do here
18 ilm 381
    }
382
 
383
    @Override
384
    public void mousePressed(MouseEvent e) {
142 ilm 385
        if (e.getY() > getLCDY() && e.getY() < (getLCDY() + getLCDHeight())) {
386
            lcdPressed();
387
            return;
388
        }
389
 
18 ilm 390
        char c = getToucheFrom(e.getX(), e.getY());
391
        if (c != '?') {
392
            handleCharacter(c);
393
        } else {
394
            Paiement p = getPaiementFrom(e.getY());
395
            if (p != null) {
174 ilm 396
                if (e.getX() > this.getWidth() - 68 && p.getType() != Paiement.ESPECES && this.controller.canAddPaiement(p.getType())) {
18 ilm 397
                    p = new Paiement(p.getType());
174 ilm 398
                    this.controller.addPaiement(p);
18 ilm 399
                }
174 ilm 400
                this.controller.autoFillPaiement(p);
18 ilm 401
                this.calculatorValue = TicketCellRenderer.centsToString(p.getMontantInCents());
149 ilm 402
                if (p.getType() == Paiement.ESPECES) {
403
                    try {
174 ilm 404
                        this.controller.openDrawer();
149 ilm 405
                    } catch (Throwable ex) {
406
                        JOptionPane.showMessageDialog(PaiementPanel.this, "Ouverture du tiroir caisse impossible");
407
                    }
408
                } else if (p.getType() == Paiement.CB) {
174 ilm 409
                    this.controller.sendCBRequest(p);
18 ilm 410
                }
132 ilm 411
 
18 ilm 412
            }
174 ilm 413
            this.controller.setPaiementSelected(p);
18 ilm 414
        }
415
    }
416
 
142 ilm 417
    public void lcdPressed() {
418
        System.err.println("PaiementPanel.lcdPressed()");
174 ilm 419
        final TicketItem articleSelected = this.controller.getTicketItemSelected();
142 ilm 420
        if (articleSelected != null) {
174 ilm 421
            this.controller.openPriceEditor(articleSelected);
142 ilm 422
        }
423
        repaint();
424
 
425
    }
426
 
18 ilm 427
    private void handleCharacter(char c) {
428
        System.out.println("Handle: " + c);
429
        if (c == '?')
430
            return;
174 ilm 431
        final TicketItem article = this.controller.getTicketItemSelected();
18 ilm 432
 
433
        if (c == '+' || c == '-' || c == '*') {
174 ilm 434
            this.mode = c;
18 ilm 435
 
436
            repaint();
437
            return;
438
        }
439
 
440
        if (article != null) {
441
            // Changement de quantité
442
            if (c == 'c' || c == '/') {
443
                System.out.println("Clear quantité");
174 ilm 444
                this.mode = ' ';
445
                this.controller.removeTicketItem(article);
18 ilm 446
            } else if (c == '=' || c == '\n') {
174 ilm 447
                if (!this.init) {
448
                    BigDecimal v = new BigDecimal(this.calculatorValue);
449
                    if (this.mode == ' ') {
450
                        article.setQty(v);
451
                    } else if (this.mode == '+') {
452
                        article.setQty(article.getQty().add(v));
453
                    } else if (this.mode == '-') {
454
                        article.setQty(article.getQty().subtract(v));
455
                    } else if (this.mode == '*') {
456
                        article.setQty(article.getQty().multiply(v));
18 ilm 457
                    }
174 ilm 458
                    // Reselect to fire a refresh
459
                    this.controller.setTicketItemSelected(article);
18 ilm 460
                }
461
                initCaisseArticle();
462
            } else if (Character.isDigit(c)) {
174 ilm 463
                if (this.init) {
464
                    this.calculatorValue = "";
465
                    this.init = false;
18 ilm 466
                }
174 ilm 467
                if (this.calculatorValue.length() < 8) {
468
                    this.calculatorValue += c;
18 ilm 469
                }
470
            }
174 ilm 471
            if (article.getArticle().getSalesUnit() != null && c == '.' && (this.calculatorValue.indexOf('.') < 0)) {
472
                this.calculatorValue += ".";
473
            }
18 ilm 474
 
475
        } else {
174 ilm 476
            final Paiement paiement = this.controller.getPaiementSelected();
18 ilm 477
            if (paiement != null) {
478
                // Changement de paiement
479
                if (c == 'c' || c == '/') {
480
                    System.out.println("Clear paiement");
174 ilm 481
                    this.mode = ' ';
482
                    this.controller.clearPaiement(paiement);
483
                } else if (c == '.' && (this.calculatorValue.indexOf('.') < 0)) {
484
                    this.calculatorValue += ".";
18 ilm 485
                } else if (c == '=' || c == '\n') {
174 ilm 486
                    if (!this.init) {
18 ilm 487
                        int v = getCentsFrom(this.calculatorValue);
174 ilm 488
                        if (this.mode == ' ') {
489
                            this.controller.setPaiementValue(paiement, v);
490
                        } else if (this.mode == '+') {
491
                            this.controller.setPaiementValue(paiement, paiement.getMontantInCents() + v);
492
                        } else if (this.mode == '-') {
493
                            this.controller.setPaiementValue(paiement, paiement.getMontantInCents() - v);
494
                        } else if (this.mode == '*') {
495
                            this.controller.setPaiementValue(paiement, paiement.getMontantInCents() * v);
18 ilm 496
                        }
497
                    }
498
                    initCaissePaiement();
174 ilm 499
                    this.controller.setPaiementSelected(null);
18 ilm 500
                } else if (Character.isDigit(c)) {
174 ilm 501
                    if (this.init) {
502
                        this.calculatorValue = "";
503
                        this.init = false;
18 ilm 504
                    }
174 ilm 505
                    if (this.calculatorValue.length() < 9) {
506
                        int i = this.calculatorValue.indexOf('.');
507
                        if (i < 0 || (this.calculatorValue.length() - i < 3)) {
508
                            this.calculatorValue += c;
142 ilm 509
                        }
18 ilm 510
                    }
511
                }
512
            }
513
        }
514
        repaint();
515
    }
516
 
517
    private int getCentsFrom(String str) {
518
        int i = str.indexOf('.');
519
        if (i >= 0) {
520
            String euros = str.substring(0, i);
521
            String cents = str.substring(i + 1);
522
            if (cents.length() == 1) {
523
                cents += "0";
524
            }
525
            int e = 0;
526
            if (euros.length() > 0) {
527
                e = Integer.parseInt(euros);
528
            }
529
            int c = 0;
530
            if (cents.length() > 0) {
531
                c = Integer.parseInt(cents);
532
            }
533
            return e * 100 + c;
534
        }
535
        return Integer.parseInt(str) * 100;
536
 
537
    }
538
 
539
    @Override
540
    public void mouseReleased(MouseEvent e) {
142 ilm 541
        // Nothing to do here
18 ilm 542
    }
543
 
544
    @Override
545
    public void barcodeRead(String code) {
142 ilm 546
        // Nothing to do here
18 ilm 547
    }
548
 
549
    private Paiement getPaiementFrom(int y) {
142 ilm 550
        int index = (y - PAYMENT_POS_Y) / PAYMENT_LINE_HEIGHT;
174 ilm 551
        if (index < this.controller.getPaiements().size() && index >= 0) {
552
            return this.controller.getPaiements().get(index);
18 ilm 553
        }
554
        return null;
555
    }
556
 
557
    @Override
558
    public void keyReceived(KeyEvent e) {
559
        if (e.getID() == KeyEvent.KEY_TYPED) {
560
            System.out.println("PaiementPanel.keyPressed()" + e.getKeyChar());
561
            handleCharacter(e.getKeyChar());
562
        }
563
 
564
    }
565
 
566
}