OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 156 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 156 Rev 174
1
/*
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 * 
3
 * 
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 * 
5
 * 
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
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
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
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.
9
 * language governing permissions and limitations under the License.
10
 * 
10
 * 
11
 * When distributing the software, include this License Header Notice in each file.
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
12
 */
13
 
13
 
14
 package org.openconcerto.erp.core.sales.pos.model;
14
 package org.openconcerto.erp.core.sales.pos.model;
15
 
15
 
16
import org.openconcerto.erp.config.ComptaPropsConfiguration;
16
import org.openconcerto.erp.config.ComptaPropsConfiguration;
17
import org.openconcerto.erp.core.common.ui.TotalCalculator;
17
import org.openconcerto.erp.core.common.ui.TotalCalculator;
18
import org.openconcerto.erp.core.customerrelationship.customer.element.CompteClientTransactionSQLELement;
18
import org.openconcerto.erp.core.customerrelationship.customer.element.CompteClientTransactionSQLELement;
19
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement;
19
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement;
20
import org.openconcerto.erp.core.finance.accounting.element.JournalSQLElement;
20
import org.openconcerto.erp.core.finance.accounting.element.JournalSQLElement;
21
import org.openconcerto.erp.core.finance.tax.model.TaxeCache;
21
import org.openconcerto.erp.core.finance.tax.model.TaxeCache;
22
import org.openconcerto.erp.core.sales.pos.POSConfiguration;
22
import org.openconcerto.erp.core.sales.pos.POSConfiguration;
23
import org.openconcerto.erp.core.sales.pos.io.DefaultTicketPrinter;
23
import org.openconcerto.erp.core.sales.pos.io.DefaultTicketPrinter;
24
import org.openconcerto.erp.core.sales.pos.io.Printable;
24
import org.openconcerto.erp.core.sales.pos.io.Printable;
25
import org.openconcerto.erp.core.sales.pos.io.TicketPrinter;
25
import org.openconcerto.erp.core.sales.pos.io.TicketPrinter;
26
import org.openconcerto.erp.core.sales.pos.model.RegisterFiles.HashMode;
26
import org.openconcerto.erp.core.sales.pos.model.RegisterFiles.HashMode;
-
 
27
import org.openconcerto.erp.core.sales.pos.ui.CaissePanel;
27
import org.openconcerto.erp.core.sales.pos.ui.TicketCellRenderer;
28
import org.openconcerto.erp.core.sales.pos.ui.TicketCellRenderer;
28
import org.openconcerto.erp.generationEcritures.GenerationEcritures;
29
import org.openconcerto.erp.generationEcritures.GenerationEcritures;
29
import org.openconcerto.erp.generationEcritures.GenerationMvtVirement;
30
import org.openconcerto.erp.generationEcritures.GenerationMvtVirement;
30
import org.openconcerto.erp.preferences.DefaultNXProps;
31
import org.openconcerto.erp.preferences.DefaultNXProps;
31
import org.openconcerto.sql.Configuration;
32
import org.openconcerto.sql.Configuration;
32
import org.openconcerto.sql.element.SQLElementDirectory;
33
import org.openconcerto.sql.element.SQLElementDirectory;
-
 
34
import org.openconcerto.sql.model.SQLBackgroundTableCache;
-
 
35
import org.openconcerto.sql.model.SQLBackgroundTableCacheItem;
33
import org.openconcerto.sql.model.SQLRow;
36
import org.openconcerto.sql.model.SQLRow;
34
import org.openconcerto.sql.model.SQLRowAccessor;
37
import org.openconcerto.sql.model.SQLRowAccessor;
35
import org.openconcerto.sql.model.SQLRowValues;
38
import org.openconcerto.sql.model.SQLRowValues;
36
import org.openconcerto.sql.model.SQLTable;
39
import org.openconcerto.sql.model.SQLTable;
37
import org.openconcerto.sql.utils.SQLUtils;
40
import org.openconcerto.sql.utils.SQLUtils;
38
import org.openconcerto.utils.DecimalUtils;
41
import org.openconcerto.utils.DecimalUtils;
39
import org.openconcerto.utils.Pair;
-
 
40
import org.openconcerto.utils.Tuple2;
42
import org.openconcerto.utils.Tuple2;
41
import org.openconcerto.utils.XMLDateFormat;
43
import org.openconcerto.utils.XMLDateFormat;
42
 
44
 
43
import java.io.File;
45
import java.io.File;
44
import java.io.IOException;
46
import java.io.IOException;
45
import java.math.BigDecimal;
47
import java.math.BigDecimal;
46
import java.math.RoundingMode;
48
import java.math.RoundingMode;
47
import java.nio.file.Files;
49
import java.nio.file.Files;
48
import java.nio.file.Path;
50
import java.nio.file.Path;
49
import java.sql.SQLException;
51
import java.sql.SQLException;
50
import java.text.SimpleDateFormat;
52
import java.text.SimpleDateFormat;
51
import java.util.ArrayList;
53
import java.util.ArrayList;
52
import java.util.Calendar;
54
import java.util.Calendar;
53
import java.util.Collections;
55
import java.util.Collections;
54
import java.util.Comparator;
56
import java.util.Comparator;
55
import java.util.Date;
57
import java.util.Date;
56
import java.util.List;
58
import java.util.List;
57
import java.util.Locale;
59
import java.util.Locale;
58
import java.util.Map;
60
import java.util.Map;
59
 
61
 
60
import org.jdom2.Attribute;
62
import org.jdom2.Attribute;
61
import org.jdom2.Document;
63
import org.jdom2.Document;
62
import org.jdom2.Element;
64
import org.jdom2.Element;
63
 
65
 
64
public class Ticket implements Printable {
66
public class Ticket implements Printable {
65
 
67
 
66
    private static final XMLDateFormat DATE_FMT = new XMLDateFormat();
68
    private static final XMLDateFormat DATE_FMT = new XMLDateFormat();
67
 
69
 
68
    // Propre a ticket
70
    // Propre a ticket
69
    private final List<Paiement> paiements = new ArrayList<Paiement>();
71
    private final List<Paiement> paiements = new ArrayList<>();
70
    private final List<Pair<Article, Integer>> items = new ArrayList<Pair<Article, Integer>>();
72
    private final List<TicketItem> items = new ArrayList<>();
71
    private Calendar creationCal;
73
    private Calendar creationCal;
72
    private Client client = Client.NONE;
74
    private Client client = Client.NONE;
73
    private final int number;
75
    private final int number;
74
    private final String previousHash;
76
    private final String previousHash;
75
    private boolean additionnalCopyRequested = false;
77
    private boolean additionnalCopyRequested = false;
76
 
-
 
-
 
78
    private String codePostal = "";
77
    // Propre à la caisse
79
    // Propre à la caisse
78
    private final int caisseNumber;
80
    private final int caisseNumber;
79
 
81
 
80
    private static final SQLTable tableArticle = Configuration.getInstance().getRoot().findTable("ARTICLE");
82
    private static final SQLTable tableArticle = Configuration.getInstance().getRoot().findTable("ARTICLE");
81
 
83
 
82
    public static Ticket getTicketFromCode(final String code, final RegisterFiles registerFiles) {
84
    public static Ticket getTicketFromCode(final String code, final RegisterFiles registerFiles) {
83
        try {
85
        try {
84
            final ReceiptCode receiptCode = new ReceiptCode(code);
86
            final ReceiptCode receiptCode = new ReceiptCode(code);
85
            final Path receiptFile = registerFiles.getReceiptFile(receiptCode);
87
            final Path receiptFile = registerFiles.getReceiptFile(receiptCode);
86
            if (receiptFile != null && Files.exists(receiptFile)) {
88
            if (receiptFile != null && Files.exists(receiptFile)) {
87
                return parseFile(receiptFile.toFile());
89
                return parseFile(receiptFile.toFile());
88
            } else {
90
            } else {
89
                // old location
91
                // old location
90
                return parseFile(receiptCode.getFile());
92
                return parseFile(receiptCode.getFile());
91
            }
93
            }
92
        } catch (final Exception e) {
94
        } catch (final Exception e) {
93
            return null;
95
            return null;
94
        }
96
        }
95
    }
97
    }
96
 
98
 
-
 
99
    public String getCodePostal() {
-
 
100
        return this.codePostal;
-
 
101
    }
-
 
102
 
-
 
103
    public void setCodePostal(String codePostal) {
-
 
104
        this.codePostal = codePostal;
-
 
105
 
-
 
106
    }
-
 
107
 
97
    public void setClient(final Client client) {
108
    public void setClient(final Client client) {
98
        this.client = client;
109
        this.client = client;
99
    }
110
    }
100
 
111
 
101
    public Client getClient() {
112
    public Client getClient() {
102
        return this.client;
113
        return this.client;
103
    }
114
    }
104
 
115
 
105
    public static Ticket parseFile(final File file) {
116
    public static Ticket parseFile(final File file) throws IOException {
106
        return parseFile(file, HashMode.REQUIRED);
117
        return parseFile(file, HashMode.REQUIRED);
107
    }
118
    }
108
 
119
 
109
    public static Ticket parseFile(final File file, final HashMode hashMode) {
120
    public static Ticket parseFile(final File file, final HashMode hashMode) throws IOException {
110
        if (!file.exists()) {
-
 
111
            return null;
-
 
112
        }
-
 
113
 
-
 
114
        try {
121
        try {
115
            // XML Reading
122
            // XML Reading
116
 
123
 
117
            final Document document = RegisterFiles.parse(file.toPath(), hashMode);
124
            final Document document = RegisterFiles.parse(file.toPath(), hashMode);
118
            final Element root = document.getRootElement();
125
            final Element root = document.getRootElement();
119
            final ReceiptCode receiptCode = new ReceiptCode(root.getAttributeValue("code"));
126
            final ReceiptCode receiptCode = new ReceiptCode(root.getAttributeValue("code"));
120
            final String creationDateAttr = root.getAttributeValue("creationDate");
127
            final String creationDateAttr = root.getAttributeValue("creationDate");
121
            final Calendar c = (Calendar) receiptCode.getDay().clone();
128
            final Calendar c = (Calendar) receiptCode.getDay().clone();
122
            if (creationDateAttr == null) {
129
            if (creationDateAttr == null) {
123
                final String h = root.getAttributeValue("hour");
130
                final String h = root.getAttributeValue("hour");
124
                final String m = root.getAttributeValue("minute");
131
                final String m = root.getAttributeValue("minute");
125
                c.set(Calendar.HOUR_OF_DAY, Integer.parseInt(h));
132
                c.set(Calendar.HOUR_OF_DAY, Integer.parseInt(h));
126
                c.set(Calendar.MINUTE, Integer.parseInt(m));
133
                c.set(Calendar.MINUTE, Integer.parseInt(m));
127
            } else {
134
            } else {
128
                c.setTime((Date) DATE_FMT.parseObject(creationDateAttr));
135
                c.setTime((Date) DATE_FMT.parseObject(creationDateAttr));
129
            }
136
            }
130
            final String client = root.getAttributeValue("clientID", "1");
137
            final String client = root.getAttributeValue("clientID", "1");
131
            final Ticket t = new Ticket(receiptCode, c, root.getAttributeValue("previousHash"));
138
            final Ticket t = new Ticket(receiptCode, c, root.getAttributeValue("previousHash"));
132
            t.setClient(new Client(Integer.parseInt(client), "", BigDecimal.ZERO));
139
            t.setClient(new Client(Integer.parseInt(client), "", BigDecimal.ZERO));
133
 
140
 
-
 
141
            t.setCodePostal(root.getAttributeValue("codePostal", ""));
-
 
142
 
134
            // article
143
            // article
135
            final List<Element> children = root.getChildren("article");
144
            final List<Element> children = root.getChildren("article");
136
            for (final Element element : children) {
145
            for (final Element element : children) {
137
                final int qte = Integer.parseInt(element.getAttributeValue("qte"));
146
                final BigDecimal qte = new BigDecimal(element.getAttributeValue("qte"));
138
                final BigDecimal prix_unitaire_cents_ht = new BigDecimal(element.getAttributeValue("prixHT"));
147
                final BigDecimal prix_unitaire_cents_ht = new BigDecimal(element.getAttributeValue("prixHT"));
139
                final int idTaxe = Integer.parseInt(element.getAttributeValue("idTaxe"));
148
                final int idTaxe = Integer.parseInt(element.getAttributeValue("idTaxe"));
140
                final BigDecimal prix_unitaire_cents = new BigDecimal(element.getAttributeValue("prix"));
149
                final BigDecimal prix_unitaire_cents = new BigDecimal(element.getAttributeValue("prix"));
141
                final String categorie = element.getAttributeValue("categorie");
150
                final String categorie = element.getAttributeValue("categorie");
142
                final String name = element.getValue();
151
                final String name = element.getValue();
143
                final String codebarre = element.getAttributeValue("codebarre");
152
                final String codebarre = element.getAttributeValue("codebarre");
144
                final String codeArt = element.getAttributeValue("code");
153
                final String codeArt = element.getAttributeValue("code");
-
 
154
                final String salesUnit = element.getAttributeValue("unit");
145
                final Categorie cat = new Categorie(categorie);
155
                final Categorie cat = new Categorie(categorie);
146
 
156
 
147
                final String valueID = element.getAttributeValue("id");
157
                final String valueID = element.getAttributeValue("id");
148
 
158
 
149
                final int id = valueID == null || valueID.trim().length() == 0 ? tableArticle.getUndefinedID() : Integer.parseInt(valueID);
159
                final int id = valueID == null || valueID.trim().length() == 0 ? tableArticle.getUndefinedID() : Integer.parseInt(valueID);
150
                final Article art = new Article(cat, name, id);
160
                final Article art = new Article(cat, name, id);
151
                art.setPriceWithTax(prix_unitaire_cents);
161
                art.setPriceWithTax(prix_unitaire_cents);
152
                art.setCode(codeArt);
162
                art.setCode(codeArt);
153
                art.setPriceWithoutTax(prix_unitaire_cents_ht);
163
                art.setPriceWithoutTax(prix_unitaire_cents_ht);
154
                art.setIdTaxe(idTaxe);
164
                art.setIdTaxe(idTaxe);
155
                art.setBarCode(codebarre);
165
                art.setBarCode(codebarre);
-
 
166
                art.setSalesUnit(salesUnit);
156
                final Pair<Article, Integer> line = new Pair<Article, Integer>(art, qte);
167
                final TicketItem line = new TicketItem(art, qte);
157
                t.items.add(line);
168
                t.items.add(line);
158
 
169
 
159
            }
170
            }
160
            // paiement
171
            // paiement
161
            final List<Element> payChildren = root.getChildren("paiement");
172
            final List<Element> payChildren = root.getChildren("paiement");
162
            for (final Element element : payChildren) {
173
            for (final Element element : payChildren) {
163
 
174
 
164
                final String type = element.getAttributeValue("type");
175
                final String type = element.getAttributeValue("type");
165
                final int montant_cents = Integer.parseInt(element.getAttributeValue("montant"));
176
                final int montant_cents = Integer.parseInt(element.getAttributeValue("montant"));
166
                if (montant_cents != 0) {
177
                if (montant_cents != 0) {
167
                    int tp = Paiement.ESPECES;
178
                    int tp = Paiement.ESPECES;
168
                    if (type.equals("CB")) {
179
                    if (type.equals("CB")) {
169
                        tp = Paiement.CB;
180
                        tp = Paiement.CB;
170
                    } else if (type.equals("CHEQUE")) {
181
                    } else if (type.equals("CHEQUE")) {
171
                        tp = Paiement.CHEQUE;
182
                        tp = Paiement.CHEQUE;
172
                    } else if (type.equals("ESPECES")) {
183
                    } else if (type.equals("ESPECES")) {
173
                        tp = Paiement.ESPECES;
184
                        tp = Paiement.ESPECES;
174
                    } else if (type.equals("SOLDE")) {
185
                    } else if (type.equals("SOLDE")) {
175
                        tp = Paiement.SOLDE;
186
                        tp = Paiement.SOLDE;
176
                    }
187
                    }
177
                    final Paiement p = new Paiement(tp);
188
                    final Paiement p = new Paiement(tp);
178
                    p.setMontantInCents(montant_cents);
189
                    p.setMontantInCents(montant_cents);
179
                    t.paiements.add(p);
190
                    t.paiements.add(p);
180
                }
191
                }
181
            }
192
            }
182
 
193
 
183
            return t;
194
            return t;
184
        } catch (final Exception e) {
195
        } catch (IOException e) {
185
            System.err.println("Error with ticket : " + file + " : " + e.getMessage());
-
 
186
            e.printStackTrace();
196
            throw e;
187
            return null;
197
        } catch (Exception e) {
-
 
198
            throw new IOException("Couldn't parse " + file, e);
188
        }
199
        }
189
    }
200
    }
190
 
201
 
191
    // TODO receiptCode should be immutable and the day part should be the current accounting day
202
    // TODO receiptCode should be immutable and the day part should be the current accounting day
192
    // not the day of the present time. E.g. for work day beginning at 15:00, even at 3:00 the
203
    // not the day of the present time. E.g. for work day beginning at 15:00, even at 3:00 the
193
    // receipt code should contain the previous day.
204
    // receipt code should contain the previous day.
194
    // The creationCal should only be set once the ticket is done (i.e. no further modifications
205
    // The creationCal should only be set once the ticket is done (i.e. no further modifications
195
    // should be allowed)
206
    // should be allowed)
196
 
207
 
197
    // create new ticket, i.e. null creationDate since it's not done
208
    // create new ticket, i.e. null creationDate since it's not done
198
    public Ticket(final int caisse, final int number, final String previousHash) {
209
    public Ticket(final int caisse, final int number, final String previousHash) {
199
        this(new ReceiptCode(caisse, Calendar.getInstance(), number), null, previousHash);
210
        this(new ReceiptCode(caisse, Calendar.getInstance(), number), null, previousHash);
200
    }
211
    }
201
 
212
 
202
    // re-create existing ticket
213
    // re-create existing ticket
203
    public Ticket(final ReceiptCode code, final Calendar creationDate, final String previousHash) {
214
    public Ticket(final ReceiptCode code, final Calendar creationDate, final String previousHash) {
204
        this.caisseNumber = code.getCaisseNb();
215
        this.caisseNumber = code.getCaisseNb();
205
        this.number = code.getDayIndex();
216
        this.number = code.getDayIndex();
206
        this.previousHash = previousHash;
217
        this.previousHash = previousHash;
207
        this.setCreationCal(creationDate);
218
        this.setCreationCal(creationDate);
208
    }
219
    }
209
 
220
 
210
    public final String getPreviousHash() {
221
    public final String getPreviousHash() {
211
        return this.previousHash;
222
        return this.previousHash;
212
    }
223
    }
213
 
224
 
-
 
225
    public void clear() {
-
 
226
        this.client = Client.NONE;
-
 
227
        this.codePostal = "";
-
 
228
        this.paiements.clear();
-
 
229
 
-
 
230
    }
-
 
231
 
214
    public final ReceiptCode getReceiptCode() {
232
    public final ReceiptCode getReceiptCode() {
215
        // TODO replace our fields by one ReceiptCode
233
        // TODO replace our fields by one ReceiptCode
216
        return new ReceiptCode(this.getCaisseNumber(), this.getCreationCal(), this.getNumber());
234
        return new ReceiptCode(this.getCaisseNumber(), this.getCreationCal(), this.getNumber());
217
    }
235
    }
218
 
236
 
219
    public String getCode() {
237
    public String getCode() {
220
        return getReceiptCode().getCode();
238
        return getReceiptCode().getCode();
221
    }
239
    }
222
 
240
 
223
    /**
241
    /**
224
     * Numero du ticket fait ce jour, compteur remis à 1 chaque jour
242
     * Numero du ticket fait ce jour, compteur remis à 1 chaque jour
225
     * 
243
     * 
226
     * @return the index of this ticket, inside its day.
244
     * @return the index of this ticket, inside its day.
227
     */
245
     */
228
    public int getNumber() {
246
    public int getNumber() {
229
        return this.number;
247
        return this.number;
230
    }
248
    }
231
 
249
 
232
    /**
250
    /**
233
     * Numero de la caisse, de 1 à n
251
     * Numero de la caisse, de 1 à n
234
     */
252
     */
235
    final int getCaisseNumber() {
253
    final int getCaisseNumber() {
236
        return this.caisseNumber;
254
        return this.caisseNumber;
237
    }
255
    }
238
 
256
 
239
    public String save(final RegisterFiles files, final SQLElementDirectory dir) throws IOException, SQLException {
257
    public String save(final RegisterFiles files, final SQLElementDirectory dir) throws IOException, SQLException {
240
        final String fileHash = files.save(this);
258
        final String fileHash = files.save(this);
241
        // FIXME handle failure
259
        // FIXME handle failure
242
        this.handleSolde(dir);
260
        this.handleSolde(dir);
243
        return fileHash;
261
        return fileHash;
244
    }
262
    }
245
 
263
 
246
    final byte[] saveToFile(final Path f) throws IOException {
264
    final byte[] saveToFile(final Path f) throws IOException {
247
        final Calendar c = getCreationCal();
265
        final Calendar c = getCreationCal();
248
 
266
 
249
        final Element topLevel = new Element("ticket");
267
        final Element topLevel = new Element("ticket");
250
        topLevel.setAttribute(new Attribute("code", this.getCode()));
268
        topLevel.setAttribute(new Attribute("code", this.getCode()));
251
        if (this.getPreviousHash() != null)
269
        if (this.getPreviousHash() != null)
252
            topLevel.setAttribute("previousHash", this.getPreviousHash());
270
            topLevel.setAttribute("previousHash", this.getPreviousHash());
253
        topLevel.setAttribute("creationDate", DATE_FMT.format(c.getTime()));
271
        topLevel.setAttribute("creationDate", DATE_FMT.format(c.getTime()));
254
        topLevel.setAttribute("clientID", String.valueOf(this.client.getId()));
272
        topLevel.setAttribute("clientID", String.valueOf(this.client.getId()));
-
 
273
        topLevel.setAttribute("codePostal", this.codePostal);
255
        // Articles
274
        // Articles
256
        for (final Pair<Article, Integer> item : this.items) {
275
        for (final TicketItem item : this.items) {
257
            final Element e = new Element("article");
276
            final Element e = new Element("article");
258
            e.setAttribute("qte", String.valueOf(item.getSecond()));
277
            e.setAttribute("qte", String.valueOf(item.getQty()));
259
            // Prix unitaire
278
            // Prix unitaire
-
 
279
            final Article article = item.getArticle();
260
            e.setAttribute("prix", String.valueOf(item.getFirst().getPriceWithTax()));
280
            e.setAttribute("prix", String.valueOf(article.getPriceWithTax()));
261
            e.setAttribute("prixHT", String.valueOf(item.getFirst().getPriceWithoutTax()));
281
            e.setAttribute("prixHT", String.valueOf(article.getPriceWithoutTax()));
262
            e.setAttribute("idTaxe", String.valueOf(item.getFirst().getIdTaxe()));
282
            e.setAttribute("idTaxe", String.valueOf(article.getIdTaxe()));
263
            e.setAttribute("categorie", item.getFirst().getCategorie().getName());
283
            e.setAttribute("categorie", article.getCategorie().getName());
264
            e.setAttribute("codebarre", item.getFirst().getBarCode());
284
            e.setAttribute("codebarre", article.getBarCode());
265
            e.setAttribute("code", item.getFirst().getCode());
285
            e.setAttribute("code", article.getCode());
266
            e.setAttribute("id", String.valueOf(item.getFirst().getId()));
286
            e.setAttribute("id", String.valueOf(article.getId()));
-
 
287
            if (article.getSalesUnit() != null) {
-
 
288
                e.setAttribute("unit", article.getSalesUnit());
-
 
289
            }
267
            e.setText(item.getFirst().getName());
290
            e.setText(article.getName());
268
            topLevel.addContent(e);
291
            topLevel.addContent(e);
269
        }
292
        }
270
        // Paiements
293
        // Paiements
271
        for (final Paiement paiement : this.paiements) {
294
        for (final Paiement paiement : this.paiements) {
272
            final int montantInCents = paiement.getMontantInCents();
295
            final int montantInCents = paiement.getMontantInCents();
273
            if (montantInCents != 0) {
296
            if (montantInCents != 0) {
274
                final Element e = new Element("paiement");
297
                final Element e = new Element("paiement");
275
                String type = "";
298
                String type = "";
276
                if (paiement.getType() == Paiement.CB) {
299
                if (paiement.getType() == Paiement.CB) {
277
                    type = "CB";
300
                    type = "CB";
278
                } else if (paiement.getType() == Paiement.CHEQUE) {
301
                } else if (paiement.getType() == Paiement.CHEQUE) {
279
                    type = "CHEQUE";
302
                    type = "CHEQUE";
280
                } else if (paiement.getType() == Paiement.ESPECES) {
303
                } else if (paiement.getType() == Paiement.ESPECES) {
281
                    type = "ESPECES";
304
                    type = "ESPECES";
282
                } else if (paiement.getType() == Paiement.SOLDE) {
305
                } else if (paiement.getType() == Paiement.SOLDE) {
283
                    type = "SOLDE";
306
                    type = "SOLDE";
284
                }
307
                }
285
                e.setAttribute("type", type);
308
                e.setAttribute("type", type);
286
                e.setAttribute("montant", String.valueOf(montantInCents));
309
                e.setAttribute("montant", String.valueOf(montantInCents));
287
                topLevel.addContent(e);
310
                topLevel.addContent(e);
288
            }
311
            }
289
        }
312
        }
290
        return RegisterFiles.save(new Document(topLevel), f);
313
        return RegisterFiles.save(new Document(topLevel), f);
291
    }
314
    }
292
 
315
 
293
    private final void handleSolde(final SQLElementDirectory dir) throws SQLException {
316
    private final void handleSolde(final SQLElementDirectory dir) throws SQLException {
294
        final SQLTable table = dir.getElement(CompteClientTransactionSQLELement.class).getTable();
317
        final SQLTable table = dir.getElement(CompteClientTransactionSQLELement.class).getTable();
295
        final SQLTable tablePrefCompte = table.getDBRoot().findTable("PREFS_COMPTE");
318
        final SQLTable tablePrefCompte = table.getDBRoot().findTable("PREFS_COMPTE");
296
        final SQLRow rowPrefsCompte = tablePrefCompte.getRow(2);
319
        final SQLRow rowPrefsCompte = tablePrefCompte.getRow(2);
297
        final Calendar c = getCreationCal();
320
        final Calendar c = getCreationCal();
298
        SQLUtils.executeAtomic(table.getDBSystemRoot().getDataSource(), new SQLUtils.SQLFactory<Object>() {
321
        SQLUtils.executeAtomic(table.getDBSystemRoot().getDataSource(), new SQLUtils.SQLFactory<Object>() {
299
            @Override
322
            @Override
300
            public Object create() throws SQLException {
323
            public Object create() throws SQLException {
301
                for (final Paiement paiement : Ticket.this.paiements) {
324
                for (final Paiement paiement : Ticket.this.paiements) {
302
                    final int montantInCents = paiement.getMontantInCents();
325
                    final int montantInCents = paiement.getMontantInCents();
303
                    if (montantInCents > 0 && paiement.getType() == Paiement.SOLDE) {
326
                    if (montantInCents > 0 && paiement.getType() == Paiement.SOLDE) {
304
                        final SQLRowValues rowValsTransact = new SQLRowValues(table);
327
                        final SQLRowValues rowValsTransact = new SQLRowValues(table);
305
                        rowValsTransact.put("ID_CLIENT", Ticket.this.client.getId());
328
                        rowValsTransact.put("ID_CLIENT", Ticket.this.client.getId());
306
 
329
 
307
                        rowValsTransact.put("DATE", c.getTime());
330
                        rowValsTransact.put("DATE", c.getTime());
308
                        final BigDecimal amountTransaction = new BigDecimal(montantInCents).movePointLeft(2);
331
                        final BigDecimal amountTransaction = new BigDecimal(montantInCents).movePointLeft(2);
309
                        rowValsTransact.put("MONTANT", amountTransaction.negate());
332
                        rowValsTransact.put("MONTANT", amountTransaction.negate());
310
 
333
 
311
                        SQLRow rowTransact = rowValsTransact.commit();
334
                        SQLRow rowTransact = rowValsTransact.commit();
312
                        final GenerationEcritures ecr = new GenerationEcritures();
335
                        final GenerationEcritures ecr = new GenerationEcritures();
313
                        final int idMvt = ecr.getNewMouvement(table.getName(), rowTransact.getID(), 1, "Transact. " + Ticket.this.client.getFullName() + " Ticket " + getCode());
336
                        final int idMvt = ecr.getNewMouvement(table.getName(), rowTransact.getID(), 1, "Transact. " + Ticket.this.client.getFullName() + " Ticket " + getCode());
314
                        rowTransact = rowTransact.createEmptyUpdateRow().put("ID_MOUVEMENT", idMvt).commit();
337
                        rowTransact = rowTransact.createEmptyUpdateRow().put("ID_MOUVEMENT", idMvt).commit();
315
 
338
 
316
                        // mise à jour du solde
339
                        // mise à jour du solde
317
                        final SQLTable tableClient = table.getForeignTable("ID_CLIENT");
340
                        final SQLTable tableClient = table.getForeignTable("ID_CLIENT");
318
                        final SQLRow row = tableClient.getRow(Ticket.this.client.getId());
341
                        final SQLRow row = tableClient.getRow(Ticket.this.client.getId());
319
                        final BigDecimal solde = row.getBigDecimal("SOLDE_COMPTE");
342
                        final BigDecimal solde = row.getBigDecimal("SOLDE_COMPTE");
320
                        final BigDecimal nouveauSolde = solde.subtract(amountTransaction);
343
                        final BigDecimal nouveauSolde = solde.subtract(amountTransaction);
321
                        row.createEmptyUpdateRow().put("SOLDE_COMPTE", nouveauSolde).commit();
344
                        row.createEmptyUpdateRow().put("SOLDE_COMPTE", nouveauSolde).commit();
322
 
345
 
323
                        // Créeation des réglements et écritures
346
                        // Créeation des réglements et écritures
324
 
347
 
325
                        int idCompteAvanceClient = rowPrefsCompte.getInt("ID_COMPTE_PCE_AVANCE_CLIENT");
348
                        int idCompteAvanceClient = rowPrefsCompte.getInt("ID_COMPTE_PCE_AVANCE_CLIENT");
326
                        int idCompteClient = row.getInt("ID_COMPTE_PCE");
349
                        int idCompteClient = row.getInt("ID_COMPTE_PCE");
327
                        if (idCompteAvanceClient <= 1) {
350
                        if (idCompteAvanceClient <= 1) {
328
                            idCompteAvanceClient = ComptePCESQLElement.getIdComptePceDefault("AvanceClients");
351
                            idCompteAvanceClient = ComptePCESQLElement.getIdComptePceDefault("AvanceClients");
329
                        }
352
                        }
330
 
353
 
331
                        // compte Clients
354
                        // compte Clients
332
                        if (idCompteClient <= 1) {
355
                        if (idCompteClient <= 1) {
333
                            idCompteClient = rowPrefsCompte.getInt("ID_COMPTE_PCE_CLIENT");
356
                            idCompteClient = rowPrefsCompte.getInt("ID_COMPTE_PCE_CLIENT");
334
                            if (idCompteClient <= 1) {
357
                            if (idCompteClient <= 1) {
335
                                idCompteClient = ComptePCESQLElement.getIdComptePceDefault("Clients");
358
                                idCompteClient = ComptePCESQLElement.getIdComptePceDefault("Clients");
336
                            }
359
                            }
337
                        }
360
                        }
338
                        new GenerationMvtVirement(idCompteAvanceClient, idCompteClient, 0, montantInCents, "Utilisation compte client", c.getTime(), JournalSQLElement.VENTES, "Ticket N°" + getCode())
361
                        new GenerationMvtVirement(idCompteAvanceClient, idCompteClient, 0, montantInCents, "Utilisation compte client", c.getTime(), JournalSQLElement.VENTES, "Ticket N°" + getCode())
339
                                .genereMouvement();
362
                                .genereMouvement();
340
                    }
363
                    }
341
                }
364
                }
342
                return null;
365
                return null;
343
            }
366
            }
344
        });
367
        });
345
    }
368
    }
346
 
369
 
347
    @Override
370
    @Override
348
    public void print(final TicketPrinter prt, final int ticketWidth) {
371
    public void print(final TicketPrinter prt, final int ticketWidth) {
349
        final int maxWidth = ticketWidth;
372
        final int maxWidth = ticketWidth;
350
        final int MAX_PRICE_WIDTH = 8;
373
        final int MAX_PRICE_WIDTH = 8;
351
        final int MAX_QTE_WIDTH = 5;
374
        final int MAX_QTE_WIDTH = 5;
352
        prt.clearBuffer("receipt " + this.getCode());
375
        prt.clearBuffer("receipt " + this.getCode());
353
        final List<TicketLine> headers = POSConfiguration.getInstance().getHeaderLines();
376
        final List<TicketLine> headers = POSConfiguration.getInstance().getHeaderLines();
354
        for (final TicketLine line : headers) {
377
        for (final TicketLine line : headers) {
355
            prt.addToBuffer(line);
378
            prt.addToBuffer(line);
356
        }
379
        }
357
 
380
 
358
        // Date
381
        // Date
359
        prt.addToBuffer("");
382
        prt.addToBuffer("");
360
        final SimpleDateFormat df = new SimpleDateFormat("EEEE d MMMM yyyy à HH:mm", Locale.FRENCH);
383
        final SimpleDateFormat df = new SimpleDateFormat("EEEE d MMMM yyyy à HH:mm", Locale.FRENCH);
361
        prt.addToBuffer(DefaultTicketPrinter.formatCenter(maxWidth, "Le " + df.format(getCreationDate())));
384
        prt.addToBuffer(DefaultTicketPrinter.formatCenter(maxWidth, "Le " + df.format(getCreationDate())));
362
        prt.addToBuffer("");
385
        prt.addToBuffer("");
363
        List<Pair<Article, Integer>> itemsToPrint = new ArrayList<>(this.items);
386
        List<TicketItem> itemsToPrint = new ArrayList<>(this.items);
364
        Collections.sort(itemsToPrint, new Comparator<Pair<Article, Integer>>() {
387
        Collections.sort(itemsToPrint, new Comparator<TicketItem>() {
365
 
388
 
366
            @Override
389
            @Override
367
            public int compare(Pair<Article, Integer> o1, Pair<Article, Integer> o2) {
390
            public int compare(TicketItem o1, TicketItem o2) {
368
                final Article p1 = o1.getFirst();
391
                final Article p1 = o1.getArticle();
369
                final Article p2 = o2.getFirst();
392
                final Article p2 = o2.getArticle();
370
                final Categorie c1 = p1.getCategorie();
393
                final Categorie c1 = p1.getCategorie();
371
                final Categorie c2 = p2.getCategorie();
394
                final Categorie c2 = p2.getCategorie();
372
                if (c1.equals(c2)) {
395
                if (c1.equals(c2)) {
373
                    return p1.getName().compareTo(p2.getName());
396
                    return p1.getName().compareTo(p2.getName());
374
                }
397
                }
375
                // Unknown first
398
                // Unknown first
376
                if (c1.isUnknown()) {
399
                if (c1.isUnknown()) {
377
                    return -1;
400
                    return -1;
378
                }
401
                }
379
                if (c2.isUnknown()) {
402
                if (c2.isUnknown()) {
380
                    return 1;
403
                    return 1;
381
                }
404
                }
382
                // Sort by name
405
                // Sort by name
383
                return c1.getName().compareTo(c2.getName());
406
                return c1.getName().compareTo(c2.getName());
384
            }
407
            }
385
        });
408
        });
386
        Categorie currentCategorie = null;
409
        Categorie currentCategorie = null;
387
        for (final Pair<Article, Integer> item : this.items) {
410
        for (final TicketItem item : this.items) {
388
            final Article article = item.getFirst();
411
            final Article article = item.getArticle();
-
 
412
            System.err.println("Ticket.print()" + item);
389
            if (currentCategorie == null || !currentCategorie.getName().equals(article.getCategorie().getName())) {
413
            if (currentCategorie == null || !currentCategorie.getName().equals(article.getCategorie().getName())) {
390
                // Print category name, except for unknown
414
                // Print category name, except for unknown
391
                currentCategorie = article.getCategorie();
415
                currentCategorie = article.getCategorie();
392
                if (!currentCategorie.isUnknown()) {
416
                if (!currentCategorie.isUnknown()) {
393
                    prt.addToBuffer(currentCategorie.getName(), TicketPrinter.BOLD);
417
                    prt.addToBuffer(currentCategorie.getName(), TicketPrinter.BOLD);
394
                }
418
                }
395
            }
419
            }
396
            final Integer nb = item.getSecond();
420
            final BigDecimal nb = item.getQty();
397
            final Float tauxFromId = TaxeCache.getCache().getTauxFromId(article.getIdTaxe());
421
            final Float tauxFromId = TaxeCache.getCache().getTauxFromId(article.getIdTaxe());
398
            final BigDecimal tauxTVA = new BigDecimal(tauxFromId).movePointLeft(2).add(BigDecimal.ONE);
422
            final BigDecimal tauxTVA = BigDecimal.valueOf(tauxFromId).movePointLeft(2).add(BigDecimal.ONE);
399
            final BigDecimal unitPrice = article.getPriceWithoutTax().multiply(tauxTVA, DecimalUtils.HIGH_PRECISION);
423
            final BigDecimal unitPrice = article.getPriceWithoutTax().multiply(tauxTVA, DecimalUtils.HIGH_PRECISION);
400
            final BigDecimal multiply = article.getPriceWithoutTax().multiply(new BigDecimal(nb), DecimalUtils.HIGH_PRECISION).multiply(tauxTVA, DecimalUtils.HIGH_PRECISION);
424
            final BigDecimal multiply = article.getPriceWithoutTax().multiply(nb, DecimalUtils.HIGH_PRECISION).multiply(tauxTVA, DecimalUtils.HIGH_PRECISION);
401
 
425
 
402
            final String qtyString = DefaultTicketPrinter.formatRight(MAX_QTE_WIDTH, String.valueOf(nb));
426
            String qtyString = DefaultTicketPrinter.formatRight(MAX_QTE_WIDTH, String.valueOf(nb));
403
            final String priceString = DefaultTicketPrinter.formatRight(MAX_PRICE_WIDTH, TicketCellRenderer.centsToString(multiply.movePointRight(2).setScale(0, RoundingMode.HALF_UP).intValue()));
427
            final String priceUnformated = TicketCellRenderer.centsToString(multiply.movePointRight(2).setScale(0, RoundingMode.HALF_UP).intValue());
-
 
428
            final String priceString = DefaultTicketPrinter.formatRight(MAX_PRICE_WIDTH, priceUnformated);
404
            String unitPriceString = "";
429
            String unitPriceString = "";
-
 
430
            if (article.getSalesUnit() == null) {
405
            if (nb != 1) {
431
                if (nb.intValue() != 1) {
406
                unitPriceString = DefaultTicketPrinter.formatRight(MAX_PRICE_WIDTH, TicketCellRenderer.centsToString(unitPrice.movePointRight(2).setScale(0, RoundingMode.HALF_UP).intValue()));
432
                    unitPriceString = DefaultTicketPrinter.formatRight(MAX_PRICE_WIDTH, TicketCellRenderer.centsToString(unitPrice.movePointRight(2).setScale(0, RoundingMode.HALF_UP).intValue()));
407
            }
433
                }
-
 
434
            } else {
-
 
435
                unitPriceString = DefaultTicketPrinter.formatRight(MAX_PRICE_WIDTH, "");
-
 
436
                if (nb.signum() >= 0) {
-
 
437
                    qtyString = DefaultTicketPrinter.formatRight(MAX_QTE_WIDTH, "1");
-
 
438
                } else {
-
 
439
                    qtyString = DefaultTicketPrinter.formatRight(MAX_QTE_WIDTH, "-1");
-
 
440
                }
408
 
441
            }
409
            if (article.getCode() != null && !article.getCode().isEmpty()) {
442
            if (article.getCode() != null && !article.getCode().isEmpty() && !article.getCode().equalsIgnoreCase(article.getName())) {
410
                // 2 lines
443
                // 2 lines
411
                final String codeString = DefaultTicketPrinter.formatLeft(maxWidth - 2 - MAX_PRICE_WIDTH - MAX_QTE_WIDTH - 1 - unitPriceString.length(), article.getCode());
444
                final String codeString = DefaultTicketPrinter.formatLeft(maxWidth - 2 - MAX_PRICE_WIDTH - MAX_QTE_WIDTH - 1 - unitPriceString.length(), article.getCode());
412
                prt.addToBuffer(qtyString + " " + codeString + " " + unitPriceString + " " + priceString);
445
                prt.addToBuffer(qtyString + " " + codeString + " " + unitPriceString + " " + priceString);
413
                final String nameString = DefaultTicketPrinter.formatLeft(maxWidth - MAX_QTE_WIDTH - 1, article.getName());
446
                final String nameString = DefaultTicketPrinter.formatLeft(maxWidth - MAX_QTE_WIDTH - 1, article.getName());
414
                prt.addToBuffer("      " + nameString);
447
                prt.addToBuffer("      " + nameString);
415
            } else {
448
            } else {
416
                // 1 line
449
                // 1 line
417
                final String nameString = DefaultTicketPrinter.formatLeft(maxWidth - 2 - MAX_PRICE_WIDTH - MAX_QTE_WIDTH - 1 - unitPriceString.length(), article.getName());
450
                final String nameString = DefaultTicketPrinter.formatLeft(maxWidth - 2 - MAX_PRICE_WIDTH - MAX_QTE_WIDTH - 1 - unitPriceString.length(), article.getName());
418
                prt.addToBuffer(qtyString + " " + nameString + " " + unitPriceString + " " + priceString);
451
                prt.addToBuffer(qtyString + " " + nameString + " " + unitPriceString + " " + priceString);
419
            }
452
            }
-
 
453
            if (article.getSalesUnit() != null) {
-
 
454
                prt.addToBuffer(
-
 
455
                        "      (" + nb.abs() + " " + article.getSalesUnit() + " x " + TicketCellRenderer.centsToString(unitPrice.movePointRight(2).setScale(0, RoundingMode.HALF_UP).intValue()) + ")");
420
 
456
            }
421
        }
457
        }
422
 
458
 
423
        final StringBuilder spacer = new StringBuilder();
459
        final StringBuilder spacer = new StringBuilder();
424
        for (int i = 0; i <= MAX_QTE_WIDTH; i++) {
460
        for (int i = 0; i <= MAX_QTE_WIDTH; i++) {
425
            spacer.append(' ');
461
            spacer.append(' ');
426
        }
462
        }
427
        for (int i = 0; i < maxWidth - MAX_QTE_WIDTH - 1; i++) {
463
        for (int i = 0; i < maxWidth - MAX_QTE_WIDTH - 1; i++) {
428
            spacer.append('=');
464
            spacer.append('=');
429
        }
465
        }
430
        prt.addToBuffer(spacer.toString());
466
        prt.addToBuffer(spacer.toString());
431
 
467
 
432
        final TotalCalculator calc = getTotalCalculator();
468
        final TotalCalculator calc = getTotalCalculator();
433
        final int totalTTCInCents = calc.getTotalTTC().movePointRight(2).setScale(0, RoundingMode.HALF_UP).intValue();
469
        final int totalTTCInCents = calc.getTotalTTC().movePointRight(2).setScale(0, RoundingMode.HALF_UP).intValue();
434
 
470
 
435
        prt.addToBuffer(DefaultTicketPrinter.formatRight(maxWidth - MAX_PRICE_WIDTH, "MONTANT TOTAL TTC (Euros) : ")
471
        prt.addToBuffer(DefaultTicketPrinter.formatRight(maxWidth - MAX_PRICE_WIDTH, "MONTANT TOTAL TTC (Euros) : ")
436
                + DefaultTicketPrinter.formatRight(MAX_PRICE_WIDTH, TicketCellRenderer.centsToString(totalTTCInCents)), TicketPrinter.BOLD);
472
                + DefaultTicketPrinter.formatRight(MAX_PRICE_WIDTH, TicketCellRenderer.centsToString(totalTTCInCents)), TicketPrinter.BOLD);
437
 
473
 
438
        final Map<SQLRowAccessor, Tuple2<BigDecimal, BigDecimal>> mapHtTVARowTaux = calc.getMapHtTVARowTaux();
474
        final Map<SQLRowAccessor, Tuple2<BigDecimal, BigDecimal>> mapHtTVARowTaux = calc.getMapHtTVARowTaux();
439
        for (final SQLRowAccessor row : mapHtTVARowTaux.keySet()) {
475
        for (final SQLRowAccessor row : mapHtTVARowTaux.keySet()) {
440
            final Tuple2<BigDecimal, BigDecimal> htTVA = mapHtTVARowTaux.get(row);
476
            final Tuple2<BigDecimal, BigDecimal> htTVA = mapHtTVARowTaux.get(row);
441
            final float tvaTaux = TaxeCache.getCache().getTauxFromId(row.getID());
477
            final float tvaTaux = TaxeCache.getCache().getTauxFromId(row.getID());
442
            final BigDecimal montantTVA = htTVA.get1();
478
            final BigDecimal montantTVA = htTVA.get1();
443
            if (montantTVA != null && montantTVA.signum() != 0) {
479
            if (montantTVA != null && montantTVA.signum() != 0) {
444
                prt.addToBuffer(
480
                prt.addToBuffer(
445
                        DefaultTicketPrinter.formatRight(maxWidth - MAX_PRICE_WIDTH, "Dont TVA " + tvaTaux + "% : ")
481
                        DefaultTicketPrinter.formatRight(maxWidth - MAX_PRICE_WIDTH, "Dont TVA " + tvaTaux + "% : ")
446
                                + DefaultTicketPrinter.formatRight(MAX_PRICE_WIDTH, TicketCellRenderer.centsToString(montantTVA.movePointRight(2).setScale(0, RoundingMode.HALF_UP).intValue())),
482
                                + DefaultTicketPrinter.formatRight(MAX_PRICE_WIDTH, TicketCellRenderer.centsToString(montantTVA.movePointRight(2).setScale(0, RoundingMode.HALF_UP).intValue())),
447
                        TicketPrinter.NORMAL);
483
                        TicketPrinter.NORMAL);
448
            }
484
            }
449
        }
485
        }
450
        prt.addToBuffer("");
486
        prt.addToBuffer("");
451
        //
487
        //
452
        for (final Paiement paiement : this.paiements) {
488
        for (final Paiement paiement : this.paiements) {
453
 
489
 
454
            String type = "";
490
            String type = "";
455
            final int montantInCents = paiement.getMontantInCents();
491
            final int montantInCents = paiement.getMontantInCents();
456
            if (montantInCents != 0) {
492
            if (montantInCents != 0) {
457
                if (montantInCents > 0) {
493
                if (montantInCents > 0) {
458
                    type = "Paiement ";
494
                    type = "Paiement ";
459
                } else {
495
                } else {
460
                    type = "Remboursement ";
496
                    type = "Remboursement ";
461
                }
497
                }
462
                if (paiement.getType() == Paiement.CB) {
498
                if (paiement.getType() == Paiement.CB) {
463
                    type = "CB";
499
                    type += "CB";
464
                } else if (paiement.getType() == Paiement.CHEQUE) {
500
                } else if (paiement.getType() == Paiement.CHEQUE) {
465
                    type = "par chèque";
501
                    type += "par chèque";
466
                } else if (paiement.getType() == Paiement.ESPECES) {
502
                } else if (paiement.getType() == Paiement.ESPECES) {
467
                    type = "en espèces";
503
                    type += "en espèces";
468
                } else if (paiement.getType() == Paiement.SOLDE) {
504
                } else if (paiement.getType() == Paiement.SOLDE) {
469
                    type = "depuis solde";
505
                    type += "depuis solde";
470
                }
506
                }
-
 
507
                if (montantInCents > 0) {
471
                type += " de " + TicketCellRenderer.centsToString(montantInCents);
508
                    type += " de " + TicketCellRenderer.centsToString(montantInCents);
-
 
509
                } else {
-
 
510
                    type += " de " + TicketCellRenderer.centsToString(-montantInCents);
-
 
511
                }
472
                if (montantInCents > 100) {
512
                if (Math.abs(montantInCents) > 100) {
473
                    type += " euros";
513
                    type += " euros";
474
                } else {
514
                } else {
475
                    type += " euro";
515
                    type += " euro";
476
                }
516
                }
477
                prt.addToBuffer(type);
517
                prt.addToBuffer(type);
478
            }
518
            }
479
        }
519
        }
480
        // Montant Rendu
520
        // Montant Rendu
481
        if (getTotalInCents() < getPaidTotal()) {
521
        if (getTotalInCents() < getPaidTotal()) {
482
            final int montantInCents = getPaidTotal() - getTotalInCents();
522
            final int montantInCents = getPaidTotal() - getTotalInCents();
483
            String type = "Rendu : " + TicketCellRenderer.centsToString(montantInCents);
523
            String type = "Rendu : " + TicketCellRenderer.centsToString(montantInCents);
484
            if (montantInCents > 100) {
524
            if (Math.abs(montantInCents) > 100) {
485
                type += " euros";
525
                type += " euros";
486
            } else {
526
            } else {
487
                type += " euro";
527
                type += " euro";
488
            }
528
            }
489
            prt.addToBuffer(type);
529
            prt.addToBuffer(type);
490
        }
530
        }
491
        prt.addToBuffer("");
531
        prt.addToBuffer("");
492
        // Footer
532
        // Footer
493
        final List<TicketLine> footers = POSConfiguration.getInstance().getFooterLines();
533
        final List<TicketLine> footers = POSConfiguration.getInstance().getFooterLines();
494
        for (final TicketLine line : footers) {
534
        for (final TicketLine line : footers) {
495
            prt.addToBuffer(line);
535
            prt.addToBuffer(line);
496
        }
536
        }
497
        prt.addToBuffer("");
537
        prt.addToBuffer("");
498
        prt.addToBuffer(getCode(), TicketPrinter.BARCODE);
538
        prt.addToBuffer(getCode(), TicketPrinter.BARCODE);
499
        prt.addToBuffer("");
539
        prt.addToBuffer("");
500
        prt.addToBuffer("Ticket créé par l'ERP OpenConcerto.");
540
        prt.addToBuffer("Ticket créé par l'ERP OpenConcerto.");
501
 
541
 
502
        try {
542
        try {
503
            prt.printBuffer();
543
            prt.printBuffer();
504
        } catch (final Exception e) {
544
        } catch (final Exception e) {
505
            e.printStackTrace();
545
            e.printStackTrace();
506
        }
546
        }
507
    }
547
    }
508
 
548
 
509
    public Date getCreationDate() {
549
    public Date getCreationDate() {
510
        return this.getCreationCal().getTime();
550
        return this.getCreationCal().getTime();
511
    }
551
    }
512
 
552
 
513
    public Calendar getCreationCal() {
553
    public Calendar getCreationCal() {
514
        return this.creationCal;
554
        return this.creationCal;
515
    }
555
    }
516
 
556
 
517
    public void setCreationCal(final Calendar cal) {
557
    public void setCreationCal(final Calendar cal) {
518
        // FIXME date mismatch when ticket created one day and saved the next one
558
        // FIXME date mismatch when ticket created one day and saved the next one
519
        this.creationCal = cal == null ? null : (Calendar) cal.clone();
559
        this.creationCal = cal == null ? null : (Calendar) cal.clone();
520
    }
560
    }
521
 
561
 
522
    public void addPaiement(final Paiement p1) {
562
    public void addPaiement(final Paiement p1) {
523
        this.paiements.add(p1);
563
        this.paiements.add(p1);
524
 
564
 
525
    }
565
    }
526
 
566
 
527
    public boolean isAdditionnalCopyRequested() {
567
    public boolean isAdditionnalCopyRequested() {
528
        return additionnalCopyRequested;
568
        return this.additionnalCopyRequested;
529
    }
569
    }
530
 
570
 
531
    public void addArticle(final Article a) {
571
    public void addArticle(final Article a) {
-
 
572
        System.err.println("Ticket.addArticle()" + a);
532
        boolean alreadyExist = false;
573
        boolean alreadyExist = false;
533
        if (a.isAdditionalCopyRequested()) {
574
        if (a.isAdditionalCopyRequested()) {
534
            this.additionnalCopyRequested = true;
575
            this.additionnalCopyRequested = true;
535
        }
576
        }
-
 
577
        if (a.getSalesUnit() == null) {
536
        for (final Pair<Article, Integer> line : this.items) {
578
            for (final TicketItem line : this.items) {
537
            if (line.getFirst().equals(a)) {
579
                if (line.getArticle().equals(a)) {
538
                alreadyExist = true;
580
                    alreadyExist = true;
539
                break;
581
                    break;
540
            }
582
                }
541
        }
583
            }
542
 
584
        }
543
        if (!alreadyExist) {
585
        if (!alreadyExist) {
544
            final Pair<Article, Integer> line = new Pair<Article, Integer>(new Article(a), 1);
586
            final TicketItem line = new TicketItem(new Article(a), BigDecimal.ONE);
545
            this.items.add(line);
587
            this.items.add(line);
546
        }
588
        }
547
 
589
 
548
    }
590
    }
549
 
591
 
550
    public void incrementArticle(final Article a) {
592
    public void incrementArticle(final Article a) {
-
 
593
        System.err.println("Ticket.incrementArticle()" + a.getName());
-
 
594
 
551
        boolean alreadyExist = false;
595
        boolean alreadyExist = false;
-
 
596
        if (a.getSalesUnit() == null) {
552
        for (final Pair<Article, Integer> line : this.items) {
597
            for (final TicketItem line : this.items) {
553
            if (line.getFirst().equals(a)) {
598
                if (line.getArticle().equals(a)) {
554
                alreadyExist = true;
599
                    alreadyExist = true;
555
                line.setSecond(line.getSecond() + 1);
600
                    line.setQty(line.getQty().add(BigDecimal.ONE));
556
                break;
601
                    break;
557
            }
602
                }
558
        }
603
            }
-
 
604
        }
559
        if (!alreadyExist) {
605
        if (!alreadyExist) {
560
            final Pair<Article, Integer> line = new Pair<Article, Integer>(a, 1);
606
            final TicketItem line = new TicketItem(a, BigDecimal.ONE);
561
            this.items.add(line);
607
            this.items.add(line);
562
        }
608
        }
563
 
609
 
564
    }
610
    }
565
 
611
 
-
 
612
    public void addItem(TicketItem item) {
-
 
613
        this.items.add(item);
-
 
614
    }
-
 
615
 
566
    public List<Paiement> getPaiements() {
616
    public List<Paiement> getPaiements() {
567
        return this.paiements;
617
        return this.paiements;
568
    }
618
    }
569
 
619
 
570
    public int getTotalInCents() {
620
    public int getTotalInCents() {
571
        final TotalCalculator calc = getTotalCalculator();
621
        final TotalCalculator calc = getTotalCalculator();
572
        final BigDecimal totalTTC = calc.getTotalTTC();
622
        final BigDecimal totalTTC = calc.getTotalTTC();
573
        return totalTTC.movePointRight(2).setScale(0, RoundingMode.HALF_UP).intValue();
623
        return totalTTC.movePointRight(2).setScale(0, RoundingMode.HALF_UP).intValue();
574
    }
624
    }
575
 
625
 
576
    public TotalCalculator getTotalCalculator() {
626
    public TotalCalculator getTotalCalculator() {
577
        final SQLTable tableElt = ((ComptaPropsConfiguration) Configuration.getInstance()).getRootSociete().findTable("SAISIE_VENTE_FACTURE_ELEMENT");
627
        final SQLTable tableElt = ((ComptaPropsConfiguration) Configuration.getInstance()).getRootSociete().findTable("SAISIE_VENTE_FACTURE_ELEMENT");
578
        final TotalCalculator calc = new TotalCalculator("T_PA_HT", "T_PV_HT", null, null);
628
        final TotalCalculator calc = new TotalCalculator("T_PA_HT", "T_PV_HT", null, null);
579
        final String val = DefaultNXProps.getInstance().getStringProperty("ArticleService");
629
        final String val = DefaultNXProps.getInstance().getStringProperty("ArticleService");
580
        final Boolean bServiceActive = Boolean.valueOf(val);
630
        final Boolean bServiceActive = Boolean.valueOf(val);
581
        calc.setServiceActive(bServiceActive != null && bServiceActive);
631
        calc.setServiceActive(bServiceActive != null && bServiceActive);
582
        final int size = this.items.size();
632
        final int size = this.items.size();
583
        for (int i = 0; i < size; i++) {
633
        for (int i = 0; i < size; i++) {
584
            final Pair<Article, Integer> line = this.items.get(i);
634
            final TicketItem line = this.items.get(i);
585
            final int count = line.getSecond();
635
            final BigDecimal count = line.getQty();
586
            final Article art = line.getFirst();
636
            final Article art = line.getArticle();
587
            final SQLRowValues rowVals = new SQLRowValues(tableElt);
637
            final SQLRowValues rowVals = new SQLRowValues(tableElt);
588
            rowVals.put("T_PV_HT", art.getPriceWithoutTax().multiply(new BigDecimal(count)));
638
            rowVals.put("T_PV_HT", art.getPriceWithoutTax().multiply(count));
-
 
639
            if (art.getSalesUnit() != null) {
589
            rowVals.put("QTE", count);
640
                rowVals.put("QTE_UNITAIRE", count);
-
 
641
                rowVals.put("QTE", BigDecimal.ONE);
-
 
642
            } else {
-
 
643
                rowVals.put("QTE", count.intValue());
-
 
644
            }
590
            rowVals.put("ID_TAXE", art.getIdTaxe());
645
            rowVals.put("ID_TAXE", art.getIdTaxe());
591
            calc.addLine(rowVals, tableArticle.getRow(art.getId()), i, false);
646
            calc.addLine(rowVals, CaissePanel.getArticleRowValuesFromCache(art.getId()), i, false);
592
 
647
 
593
        }
648
        }
594
        calc.checkResult();
649
        calc.checkResult();
595
        return calc;
650
        return calc;
596
    }
651
    }
597
 
652
 
598
    public List<Pair<Article, Integer>> getArticles() {
653
    public List<TicketItem> getItems() {
599
        return this.items;
654
        return this.items;
600
    }
655
    }
601
 
656
 
602
    public void clearArticle(final Article article) {
657
    public void clearArticle(final Article article) {
603
        Pair<Article, Integer> toRemove = null;
658
        TicketItem toRemove = null;
604
        for (final Pair<Article, Integer> line : this.items) {
659
        for (final TicketItem line : this.items) {
605
            if (line.getFirst().equals(article)) {
660
            if (line.getArticle().equals(article)) {
-
 
661
                toRemove = line;
-
 
662
                break;
-
 
663
            }
-
 
664
        }
-
 
665
        if (toRemove != null) {
-
 
666
            this.items.remove(toRemove);
-
 
667
        }
-
 
668
    }
-
 
669
 
-
 
670
    public void removeTicketItem(TicketItem item) {
-
 
671
        TicketItem toRemove = null;
-
 
672
        for (final TicketItem line : this.items) {
-
 
673
            if (line.equals(item)) {
606
                toRemove = line;
674
                toRemove = line;
607
                break;
675
                break;
608
            }
676
            }
609
        }
677
        }
610
        if (toRemove != null) {
678
        if (toRemove != null) {
611
            this.items.remove(toRemove);
679
            this.items.remove(toRemove);
612
        }
680
        }
-
 
681
 
613
    }
682
    }
614
 
683
 
615
    public void setArticleCount(final Article article, final int count) {
684
    public void setArticleCount(final Article article, final BigDecimal count) {
616
        // TODO Allow only if annulation?
685
        // TODO Allow only if annulation?
617
        // if (count <= 0) {
686
        // if (count <= 0) {
618
        // this.clearArticle(article);
687
        // this.clearArticle(article);
619
        // return;
688
        // return;
620
        // }
689
        // }
621
        Pair<Article, Integer> toModify = null;
690
        TicketItem toModify = null;
622
        for (final Pair<Article, Integer> line : this.items) {
691
        for (final TicketItem line : this.items) {
623
            if (line.getFirst().equals(article)) {
692
            if (line.getArticle().equals(article)) {
624
                toModify = line;
693
                toModify = line;
625
                break;
694
                break;
626
            }
695
            }
627
        }
696
        }
628
        if (toModify != null) {
697
        if (toModify != null) {
629
            toModify.setSecond(count);
698
            toModify.setQty(count);
630
        }
699
        }
631
 
700
 
632
    }
701
    }
633
 
702
 
634
    public int getItemCount(final Article article) {
703
    public BigDecimal getItemCount(final Article article) {
635
        for (final Pair<Article, Integer> line : this.items) {
704
        for (final TicketItem line : this.items) {
636
            if (line.getFirst().equals(article)) {
705
            if (line.getArticle().equals(article)) {
637
                return line.getSecond();
706
                return line.getQty();
638
            }
707
            }
639
        }
708
        }
640
        return 0;
709
        return BigDecimal.ZERO;
641
    }
710
    }
642
 
711
 
643
    public int getPaidTotal() {
712
    public int getPaidTotal() {
644
        int paid = 0;
713
        int paid = 0;
645
        for (final Paiement p : this.paiements) {
714
        for (final Paiement p : this.paiements) {
646
            paid += p.getMontantInCents();
715
            paid += p.getMontantInCents();
647
        }
716
        }
648
        return paid;
717
        return paid;
649
    }
718
    }
650
 
719
 
651
    public void removeArticle(final Article a) {
720
    public void removeArticle(final Article a) {
652
        Pair<Article, Integer> lineToDelete = null;
721
        TicketItem lineToDelete = null;
653
        for (final Pair<Article, Integer> line : this.items) {
722
        for (final TicketItem line : this.items) {
654
            if (line.getFirst().equals(a)) {
723
            if (line.getArticle().equals(a)) {
655
                final int count = line.getSecond() + 1;
724
                final BigDecimal count = line.getQty().add(BigDecimal.ONE);
656
                if (count <= 0) {
725
                if (count.signum() <= 0) {
657
                    lineToDelete = line;
726
                    lineToDelete = line;
658
                }
727
                }
659
                line.setSecond(count);
728
                line.setQty(count);
660
                break;
729
                break;
661
            }
730
            }
662
        }
731
        }
663
        if (lineToDelete != null) {
732
        if (lineToDelete != null) {
664
            this.items.remove(lineToDelete);
733
            this.items.remove(lineToDelete);
665
        }
734
        }
666
 
735
 
667
    }
736
    }
668
 
737
 
669
    @Override
738
    @Override
670
    public String toString() {
739
    public String toString() {
671
        return "Ticket " + getCode();
740
        return "Ticket " + getCode();
672
    }
741
    }
673
 
742
 
674
    @Override
743
    @Override
675
    public boolean equals(final Object obj) {
744
    public boolean equals(final Object obj) {
676
        if (this == obj) {
745
        if (this == obj) {
677
            return true;
746
            return true;
678
        } else if (obj instanceof Ticket) {
747
        } else if (obj instanceof Ticket) {
679
            final Ticket t = (Ticket) obj;
748
            final Ticket t = (Ticket) obj;
680
            return t.getCode().equals(getCode());
749
            return t.getCode().equals(getCode());
681
        }
750
        }
682
        return false;
751
        return false;
683
    }
752
    }
684
 
753
 
685
    @Override
754
    @Override
686
    public int hashCode() {
755
    public int hashCode() {
687
        return getCode().hashCode();
756
        return getCode().hashCode();
688
    }
757
    }
689
 
758
 
690
    public void deleteTicket(final SQLElementDirectory dir) throws IOException {
759
    public void deleteTicket(final SQLElementDirectory dir) throws IOException {
691
        final SQLTable table = dir.getElement(CompteClientTransactionSQLELement.class).getTable();
760
        final SQLTable table = dir.getElement(CompteClientTransactionSQLELement.class).getTable();
692
 
761
 
693
        for (final Paiement paiement : this.paiements) {
762
        for (final Paiement paiement : this.paiements) {
694
            final int montantInCents = paiement.getMontantInCents();
763
            final int montantInCents = paiement.getMontantInCents();
695
            if (montantInCents > 0 && paiement.getType() == Paiement.SOLDE) {
764
            if (montantInCents > 0 && paiement.getType() == Paiement.SOLDE) {
696
                try {
765
                try {
697
                    SQLUtils.executeAtomic(table.getDBSystemRoot().getDataSource(), new SQLUtils.SQLFactory<Object>() {
766
                    SQLUtils.executeAtomic(table.getDBSystemRoot().getDataSource(), new SQLUtils.SQLFactory<Object>() {
698
                        @Override
767
                        @Override
699
                        public Object create() throws SQLException {
768
                        public Object create() throws SQLException {
700
                            final SQLTable tablePrefCompte = table.getDBRoot().findTable("PREFS_COMPTE");
769
                            final SQLTable tablePrefCompte = table.getDBRoot().findTable("PREFS_COMPTE");
701
                            final SQLRow rowPrefsCompte = tablePrefCompte.getRow(2);
770
                            final SQLRow rowPrefsCompte = tablePrefCompte.getRow(2);
702
                            final SQLRowValues rowValsTransact = new SQLRowValues(table);
771
                            final SQLRowValues rowValsTransact = new SQLRowValues(table);
703
                            rowValsTransact.put("ID_CLIENT", Ticket.this.client.getId());
772
                            rowValsTransact.put("ID_CLIENT", Ticket.this.client.getId());
704
 
773
 
705
                            rowValsTransact.put("DATE", getCreationCal().getTime());
774
                            rowValsTransact.put("DATE", getCreationCal().getTime());
706
                            final BigDecimal amountTransaction = new BigDecimal(montantInCents).movePointLeft(2);
775
                            final BigDecimal amountTransaction = new BigDecimal(montantInCents).movePointLeft(2);
707
                            rowValsTransact.put("MONTANT", amountTransaction);
776
                            rowValsTransact.put("MONTANT", amountTransaction);
708
 
777
 
709
                            SQLRow rowTransact = rowValsTransact.commit();
778
                            SQLRow rowTransact = rowValsTransact.commit();
710
                            final GenerationEcritures ecr = new GenerationEcritures();
779
                            final GenerationEcritures ecr = new GenerationEcritures();
711
                            final int idMvt = ecr.getNewMouvement(table.getName(), rowTransact.getID(), 1, "Annule Transact. " + Ticket.this.client.getFullName() + " Ticket " + getCode());
780
                            final int idMvt = ecr.getNewMouvement(table.getName(), rowTransact.getID(), 1, "Annule Transact. " + Ticket.this.client.getFullName() + " Ticket " + getCode());
712
                            rowTransact = rowTransact.createEmptyUpdateRow().put("ID_MOUVEMENT", idMvt).commit();
781
                            rowTransact = rowTransact.createEmptyUpdateRow().put("ID_MOUVEMENT", idMvt).commit();
713
 
782
 
714
                            // mise à jour du solde
783
                            // mise à jour du solde
715
                            final SQLTable tableClient = table.getForeignTable("ID_CLIENT");
784
                            final SQLTable tableClient = table.getForeignTable("ID_CLIENT");
716
                            final SQLRow row = tableClient.getRow(Ticket.this.client.getId());
785
                            final SQLRow row = tableClient.getRow(Ticket.this.client.getId());
717
                            final BigDecimal solde = row.getBigDecimal("SOLDE_COMPTE");
786
                            final BigDecimal solde = row.getBigDecimal("SOLDE_COMPTE");
718
                            final BigDecimal nouveauSolde = solde.add(amountTransaction);
787
                            final BigDecimal nouveauSolde = solde.add(amountTransaction);
719
                            row.createEmptyUpdateRow().put("SOLDE_COMPTE", nouveauSolde).commit();
788
                            row.createEmptyUpdateRow().put("SOLDE_COMPTE", nouveauSolde).commit();
720
 
789
 
721
                            // Créeation des réglements et écritures
790
                            // Créeation des réglements et écritures
722
 
791
 
723
                            int idCompteAvanceClient = rowPrefsCompte.getInt("ID_COMPTE_PCE_AVANCE_CLIENT");
792
                            int idCompteAvanceClient = rowPrefsCompte.getInt("ID_COMPTE_PCE_AVANCE_CLIENT");
724
                            int idCompteClient = row.getInt("ID_COMPTE_PCE");
793
                            int idCompteClient = row.getInt("ID_COMPTE_PCE");
725
                            try {
794
                            try {
726
                                if (idCompteAvanceClient <= 1) {
795
                                if (idCompteAvanceClient <= 1) {
727
                                    idCompteAvanceClient = ComptePCESQLElement.getIdComptePceDefault("AvanceClients");
796
                                    idCompteAvanceClient = ComptePCESQLElement.getIdComptePceDefault("AvanceClients");
728
                                }
797
                                }
729
 
798
 
730
                                // compte Clients
799
                                // compte Clients
731
                                if (idCompteClient <= 1) {
800
                                if (idCompteClient <= 1) {
732
                                    idCompteClient = rowPrefsCompte.getInt("ID_COMPTE_PCE_CLIENT");
801
                                    idCompteClient = rowPrefsCompte.getInt("ID_COMPTE_PCE_CLIENT");
733
                                    if (idCompteClient <= 1) {
802
                                    if (idCompteClient <= 1) {
734
                                        idCompteClient = ComptePCESQLElement.getIdComptePceDefault("Clients");
803
                                        idCompteClient = ComptePCESQLElement.getIdComptePceDefault("Clients");
735
                                    }
804
                                    }
736
                                }
805
                                }
737
                            } catch (final Exception e) {
806
                            } catch (final Exception e) {
738
                                e.printStackTrace();
807
                                e.printStackTrace();
739
                                throw new SQLException(e);
808
                                throw new SQLException(e);
740
                            }
809
                            }
741
                            new GenerationMvtVirement(idCompteAvanceClient, idCompteClient, montantInCents, 0L, "Annulation transaction compte client", getCreationCal().getTime(),
810
                            new GenerationMvtVirement(idCompteAvanceClient, idCompteClient, montantInCents, 0L, "Annulation transaction compte client", getCreationCal().getTime(),
742
                                    JournalSQLElement.VENTES, "Ticket N°" + getCode()).genereMouvement();
811
                                    JournalSQLElement.VENTES, "Ticket N°" + getCode()).genereMouvement();
743
                            return null;
812
                            return null;
744
                        }
813
                        }
745
                    });
814
                    });
746
                } catch (final SQLException e) {
815
                } catch (final SQLException e) {
747
                    e.printStackTrace();
816
                    e.printStackTrace();
748
                }
817
                }
749
            }
818
            }
750
        }
819
        }
751
 
820
 
752
        getReceiptCode().markDeleted();
821
        getReceiptCode().markDeleted();
753
    }
822
    }
-
 
823
 
754
}
824
}