OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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

Rev Author Line No. Line
67 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.common.ui;
15
 
16
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement;
17
import org.openconcerto.erp.core.finance.tax.model.TaxeCache;
18
import org.openconcerto.sql.Configuration;
19
import org.openconcerto.sql.model.SQLRow;
20
import org.openconcerto.sql.model.SQLRowAccessor;
21
import org.openconcerto.sql.model.SQLRowValues;
22
import org.openconcerto.sql.model.SQLRowValuesListFetcher;
23
import org.openconcerto.sql.model.SQLTable;
24
 
25
import java.math.BigDecimal;
26
import java.math.MathContext;
27
import java.math.RoundingMode;
28
import java.util.HashMap;
73 ilm 29
import java.util.HashSet;
67 ilm 30
import java.util.List;
31
import java.util.Map;
73 ilm 32
import java.util.Set;
67 ilm 33
 
34
public class TotalCalculator {
35
 
36
    private static String FIELD_SERVICE = "SERVICE";
73 ilm 37
    private static String FIELD_POIDS = "T_POIDS";
67 ilm 38
    private final String fieldHT, fieldHA, fieldDevise;
39
 
80 ilm 40
    private SQLRowAccessor rowDefaultCptProduit, rowDefaultCptService, rowDefaultCptTVACollecte, rowDefaultCptTVADeductible, rowDefaultCptAchat;
67 ilm 41
    private static final SQLTable tablePrefCompte = Configuration.getInstance().getRoot().findTable("PREFS_COMPTE");
42
    private static final SQLRow rowPrefsCompte = tablePrefCompte.getRow(2);
43
 
73 ilm 44
    private double totalPoids;
67 ilm 45
 
46
    private BigDecimal totalDevise, totalDeviseSel;
47
    private BigDecimal totalHA, totalHASel;
48
    private BigDecimal totalService, totalServiceSel;
49
    private BigDecimal totalTTC, totalTTCSel;
50
    private long remiseHT, remiseRestante;
80 ilm 51
    private final boolean achat;
67 ilm 52
 
53
    // Total des HT par comptes
54
    private Map<SQLRowAccessor, BigDecimal> mapHt = new HashMap<SQLRowAccessor, BigDecimal>();
55
    private Map<SQLRowAccessor, BigDecimal> mapHtSel = new HashMap<SQLRowAccessor, BigDecimal>();
56
 
57
    // Total des TVA par comptes
58
    private Map<SQLRowAccessor, BigDecimal> mapHtTVA = new HashMap<SQLRowAccessor, BigDecimal>();
59
    private Map<SQLRowAccessor, BigDecimal> mapHtTVASel = new HashMap<SQLRowAccessor, BigDecimal>();
73 ilm 60
    private int[] selectedRows;
67 ilm 61
 
62
    private Boolean bServiceActive;
63
    private BigDecimal totalHTAvantRemise;
64
 
65
    public TotalCalculator(String fieldHA, String fieldHT, String fieldDeviseTotal) {
80 ilm 66
        this(fieldHA, fieldHT, fieldDeviseTotal, false, null);
67
    }
67 ilm 68
 
80 ilm 69
    public TotalCalculator(String fieldHA, String fieldHT, String fieldDeviseTotal, boolean achat, SQLRowAccessor defaultCompte) {
70
 
71
        this.achat = achat;
67 ilm 72
        initValues();
73
 
74
        this.fieldDevise = fieldDeviseTotal;
75
        this.fieldHA = fieldHA;
76
        this.fieldHT = fieldHT;
77
 
78
        // Comptes par défaut
79
        this.rowDefaultCptService = rowPrefsCompte.getForeign("ID_COMPTE_PCE_VENTE_SERVICE");
80
        if (this.rowDefaultCptService == null || this.rowDefaultCptService.isUndefined()) {
81
            try {
82
                this.rowDefaultCptService = ComptePCESQLElement.getRowComptePceDefault("VentesServices");
83
            } catch (Exception e) {
84
                e.printStackTrace();
85
            }
86
        }
87
 
88
        this.rowDefaultCptProduit = rowPrefsCompte.getForeign("ID_COMPTE_PCE_VENTE_PRODUIT");
89
        if (this.rowDefaultCptProduit == null || this.rowDefaultCptProduit.isUndefined()) {
90
            try {
91
                this.rowDefaultCptProduit = ComptePCESQLElement.getRowComptePceDefault("VentesProduits");
92
            } catch (Exception e) {
93
                e.printStackTrace();
94
            }
95
        }
96
 
80 ilm 97
        this.rowDefaultCptTVACollecte = rowPrefsCompte.getForeign("ID_COMPTE_PCE_TVA_VENTE");
98
        if (this.rowDefaultCptTVACollecte == null || this.rowDefaultCptTVACollecte.isUndefined()) {
67 ilm 99
            try {
80 ilm 100
                this.rowDefaultCptTVACollecte = ComptePCESQLElement.getRowComptePceDefault("TVACollectee");
67 ilm 101
            } catch (Exception e) {
102
                e.printStackTrace();
103
            }
104
        }
105
 
80 ilm 106
        this.rowDefaultCptTVADeductible = rowPrefsCompte.getForeign("ID_COMPTE_PCE_TVA_ACHAT");
107
        if (this.rowDefaultCptTVADeductible == null || this.rowDefaultCptTVADeductible.isUndefined()) {
108
            try {
109
                this.rowDefaultCptTVADeductible = ComptePCESQLElement.getRowComptePceDefault("TVADeductible");
110
            } catch (Exception e) {
111
                e.printStackTrace();
112
            }
113
        }
114
 
115
        if (defaultCompte == null || defaultCompte.isUndefined()) {
116
            this.rowDefaultCptAchat = rowPrefsCompte.getForeign("ID_COMPTE_PCE_ACHAT");
117
            if (this.rowDefaultCptAchat == null || this.rowDefaultCptAchat.isUndefined()) {
118
                try {
119
                    this.rowDefaultCptAchat = ComptePCESQLElement.getRowComptePceDefault("Achats");
120
                } catch (Exception e) {
121
                    e.printStackTrace();
122
                }
123
            }
124
        } else {
125
            this.rowDefaultCptAchat = defaultCompte;
126
        }
127
 
67 ilm 128
    }
129
 
130
    /**
131
     * Définition d'une remise HT à appliquer
132
     *
133
     * @param remiseHT montant de la remise en cents
134
     * @param totalHTAvantRemise montant de la facture avant remise
135
     */
136
    public void setRemise(long remiseHT, BigDecimal totalHTAvantRemise) {
137
        this.remiseHT = remiseHT;
138
        this.remiseRestante = remiseHT;
139
        this.totalHTAvantRemise = totalHTAvantRemise;
140
    }
141
 
142
    /**
143
     * Gestion de la vente de service
144
     *
145
     * @param b
146
     */
147
    public void setServiceActive(boolean b) {
148
        this.bServiceActive = b;
149
    }
150
 
151
    /**
152
     * Remise à zéro des valeurs de calcul
153
     */
154
    public void initValues() {
155
        this.remiseHT = 0;
156
        this.remiseRestante = 0;
157
        this.totalHTAvantRemise = BigDecimal.ZERO;
158
 
159
        this.selectedRows = null;
160
 
161
        this.totalTTC = BigDecimal.ZERO;
162
        this.totalTTCSel = BigDecimal.ZERO;
163
 
164
        this.totalHA = BigDecimal.ZERO;
165
        this.totalHASel = BigDecimal.ZERO;
166
 
167
        this.totalService = BigDecimal.ZERO;
168
        this.totalServiceSel = BigDecimal.ZERO;
169
 
170
        this.totalDeviseSel = BigDecimal.ZERO;
171
        this.totalDevise = BigDecimal.ZERO;
172
 
173
        this.totalPoids = 0;
174
 
175
        // Total des HT par comptes
176
        this.mapHt.clear();
177
        this.mapHtSel.clear();
178
 
179
        // Total des TVA par comptes
180
        this.mapHtTVA.clear();
181
        this.mapHtTVASel.clear();
182
 
183
    }
184
 
185
    public void setSelectedRows(int[] selectedRows) {
186
        this.selectedRows = selectedRows;
187
    }
188
 
189
    public void addEchantillon(BigDecimal ht, SQLRowAccessor tva) {
190
        addHT(ht, tva, this.rowDefaultCptProduit, false);
191
    }
192
 
193
    private Map<Integer, SQLRowAccessor> mapTVA;
194
    final SQLTable tvaTable = Configuration.getInstance().getRoot().findTable("TAXE");
195
    final SQLTable compteTable = Configuration.getInstance().getRoot().findTable("COMPTE_PCE");
196
 
197
    /**
198
     * Mise en cache des comptes de TVA
199
     */
200
    private void fetchTVA() {
201
        mapTVA = new HashMap<Integer, SQLRowAccessor>();
202
        SQLRowValues rowVals = new SQLRowValues(tvaTable);
203
        SQLRowValues rowValsC1 = new SQLRowValues(compteTable);
204
        rowValsC1.put("NUMERO", null);
205
        rowValsC1.put("ID", null);
206
 
80 ilm 207
        SQLRowValues rowValsC2 = new SQLRowValues(compteTable);
208
        rowValsC2.put("NUMERO", null);
209
        rowValsC2.put("ID", null);
210
 
67 ilm 211
        rowVals.put(tvaTable.getKey().getName(), null);
83 ilm 212
        rowVals.put("ID_COMPTE_PCE_COLLECTE", rowValsC1);
80 ilm 213
        rowVals.put("ID_COMPTE_PCE_DED", rowValsC2);
67 ilm 214
 
215
        SQLRowValuesListFetcher fetch = SQLRowValuesListFetcher.create(rowVals);
216
        List<SQLRowValues> rowValsList = fetch.fetch();
217
 
218
        for (SQLRowValues sqlRowValues : rowValsList) {
219
            mapTVA.put(sqlRowValues.getID(), sqlRowValues);
220
        }
221
    }
222
 
223
    private void addHT(BigDecimal ht, SQLRowAccessor tva, SQLRowAccessor cptArticle, boolean selection) {
224
 
225
        BigDecimal ttc;
226
        BigDecimal totalTVA;
227
 
228
        if (tva == null || tva.isUndefined()) {
229
            ttc = ht;
230
            totalTVA = BigDecimal.ZERO;
231
        } else {
232
            BigDecimal tauxTVA = BigDecimal.valueOf(TaxeCache.getCache().getTauxFromId(tva.getID())).movePointLeft(2);
233
            ttc = tauxTVA.add(BigDecimal.ONE).multiply(ht, MathContext.DECIMAL128);
234
            totalTVA = ttc.subtract(ht);
235
        }
236
 
237
        if (tva != null && !tva.isUndefined()) {
80 ilm 238
            SQLRowAccessor rowCptTva;
239
            if (this.achat) {
240
                rowCptTva = tva.getForeign("ID_COMPTE_PCE_DED");
241
                if (rowCptTva == null || rowCptTva.isUndefined()) {
242
                    rowCptTva = this.rowDefaultCptTVADeductible;
243
                }
244
            } else {
83 ilm 245
                rowCptTva = tva.getForeign("ID_COMPTE_PCE_COLLECTE");
80 ilm 246
                if (rowCptTva == null || rowCptTva.isUndefined()) {
247
                    rowCptTva = this.rowDefaultCptTVACollecte;
248
                }
67 ilm 249
            }
250
            if (mapHtTVA.get(rowCptTva) == null) {
251
                mapHtTVA.put(rowCptTva, totalTVA);
252
            } else {
253
                BigDecimal l = mapHtTVA.get(rowCptTva);
254
                mapHtTVA.put(rowCptTva, l.add(totalTVA));
255
            }
256
            if (selection) {
257
                if (mapHtTVASel.get(rowCptTva) == null) {
258
                    mapHtTVASel.put(rowCptTva, totalTVA);
259
                } else {
260
                    BigDecimal l = mapHtTVASel.get(rowCptTva);
261
                    mapHtTVASel.put(rowCptTva, l.add(totalTVA));
262
                }
263
            }
264
        }
265
 
266
        if (mapHt.get(cptArticle) == null) {
267
            mapHt.put(cptArticle, ht);
268
        } else {
269
            BigDecimal l = mapHt.get(cptArticle);
270
            mapHt.put(cptArticle, l.add(ht));
271
        }
272
 
273
        this.totalTTC = this.totalTTC.add(ttc);
274
 
275
        if (selection) {
276
 
277
            if (mapHtSel.get(cptArticle) == null) {
278
                mapHtSel.put(cptArticle, ht);
279
            } else {
280
                BigDecimal l = mapHtSel.get(cptArticle);
281
                mapHtSel.put(cptArticle, l.add(ht));
282
            }
283
            this.totalTTCSel = this.totalTTCSel.add(ttc);
284
        }
285
    }
286
 
287
    private static boolean containsInt(int[] tab, int i) {
288
        if (tab == null) {
289
            return false;
290
        }
291
 
292
        for (int j = 0; j < tab.length; j++) {
293
            if (tab[j] == i) {
294
                return true;
295
            }
296
        }
297
        return false;
298
    }
299
 
300
    public void addLine(SQLRowAccessor rowAccessorLine, SQLRowAccessor article, int lineNumber, boolean last) {
301
 
302
        // Total HT de la ligne
303
        BigDecimal totalLineHT = rowAccessorLine.getObject(fieldHT) == null ? BigDecimal.ZERO : (BigDecimal) rowAccessorLine.getObject(fieldHT);
304
 
305
        // Prix Unitaire de la ligne
306
        // TODO voir pour passer le prix total et non le prix unitaire
307
        BigDecimal totalHALigne = rowAccessorLine.getObject(fieldHA) == null ? BigDecimal.ZERO : (BigDecimal) rowAccessorLine.getObject(fieldHA);
308
 
309
        Boolean service = rowAccessorLine.getBoolean(FIELD_SERVICE);
310
 
311
        BigDecimal totalLineDevise = (fieldDevise == null || rowAccessorLine.getObject(fieldDevise) == null) ? BigDecimal.ZERO : (BigDecimal) rowAccessorLine.getObject(fieldDevise);
312
 
313
        Number nPoids = (Number) rowAccessorLine.getObject(FIELD_POIDS);
314
 
315
        // Si il y a une remise à appliquer
83 ilm 316
        if (this.remiseHT != 0 && this.remiseRestante > 0 && this.totalHTAvantRemise != null && this.totalHTAvantRemise.signum() != 0) {
67 ilm 317
 
318
            // Si c'est la derniere ligne, on applique le restant de la remise
319
            if (last) {
320
                totalLineHT = totalLineHT.subtract(new BigDecimal(this.remiseRestante).movePointLeft(2));
321
                this.remiseRestante = 0;
322
            } else {
323
                BigDecimal percent = totalLineHT.divide(this.totalHTAvantRemise, MathContext.DECIMAL128);
324
 
325
                BigDecimal remiseApply = percent.multiply(new BigDecimal(this.remiseHT), MathContext.DECIMAL128).setScale(0, RoundingMode.HALF_UP);
326
                totalLineHT = totalLineHT.subtract(remiseApply.movePointLeft(2));
327
                this.remiseRestante -= remiseApply.longValue();
328
            }
329
        }
330
 
80 ilm 331
        SQLRowAccessor cpt = (achat ? this.rowDefaultCptAchat : this.rowDefaultCptProduit);
67 ilm 332
        if (article != null && !article.isUndefined()) {
80 ilm 333
            String suffix = (this.achat ? "_ACHAT" : "");
334
            SQLRowAccessor compteArticle = article.getForeign("ID_COMPTE_PCE" + suffix);
67 ilm 335
            if (compteArticle != null && !compteArticle.isUndefined()) {
336
                cpt = compteArticle;
337
            } else {
338
                SQLRowAccessor familleArticle = article.getForeign("ID_FAMILLE_ARTICLE");
73 ilm 339
                Set<SQLRowAccessor> unique = new HashSet<SQLRowAccessor>();
340
                while (familleArticle != null && !familleArticle.isUndefined() && !unique.contains(familleArticle)) {
341
 
342
                    unique.add(familleArticle);
80 ilm 343
                    SQLRowAccessor compteFamilleArticle = familleArticle.getForeign("ID_COMPTE_PCE" + suffix);
67 ilm 344
                    if (compteFamilleArticle != null && !compteFamilleArticle.isUndefined()) {
345
                        cpt = compteFamilleArticle;
73 ilm 346
                        break;
67 ilm 347
                    }
73 ilm 348
 
349
                    familleArticle = familleArticle.getForeign("ID_FAMILLE_ARTICLE_PERE");
67 ilm 350
                }
351
            }
352
        }
353
 
354
        // Total Service
355
        if (bServiceActive != null && bServiceActive) {
356
            if (service != null && service.booleanValue()) {
357
                totalService = totalService.add(totalLineHT);
358
                cpt = this.rowDefaultCptService;
359
            }
360
        }
361
 
362
        // Total HA
363
        this.totalHA = this.totalHA.add(totalHALigne);
364
 
365
        // Total Devise
366
        if (totalLineDevise != null) {
367
            totalDevise = totalDevise.add(totalLineDevise);
368
        }
369
 
370
        // Total Poids
371
 
372
        totalPoids += nPoids == null ? 0 : nPoids.doubleValue();
373
 
374
        // Calcul total sélectionné
375
        boolean selection = containsInt(selectedRows, lineNumber);
376
        if (selection) {
377
 
378
            totalHASel = totalHASel.add(totalHALigne);
379
 
380
            if (bServiceActive != null && bServiceActive) {
73 ilm 381
                if (service != null && service.booleanValue()) {
67 ilm 382
                    totalServiceSel = totalServiceSel.add(totalLineHT);
383
                }
384
            }
385
 
386
            if (totalLineDevise != null) {
387
                totalDeviseSel = totalDeviseSel.add(totalLineDevise);
388
            }
389
        }
390
 
73 ilm 391
        // TODO Ne pas fetcher la TVA pour chaque instance de TotalCalculator utiliser un cache
67 ilm 392
        if (mapTVA == null) {
393
            fetchTVA();
394
        }
73 ilm 395
        final SQLRowAccessor foreignTVA = rowAccessorLine.getForeign("ID_TAXE");
396
        Integer idTVA = null;
397
        if (foreignTVA != null) {
398
            idTVA = foreignTVA.getID();
399
        }
400
        addHT(totalLineHT, mapTVA.get(idTVA), cpt, selection);
67 ilm 401
    }
402
 
403
    /**
404
     * Vérifie si ht + tva = ttc
405
     */
406
    public void checkResult() {
407
        BigDecimal ht = getTotalHT();
408
        BigDecimal tva = getTotalTVA();
409
        BigDecimal totalTTC2 = getTotalTTC();
410
        BigDecimal reste = totalTTC2.subtract(ht.add(tva));
411
        if (reste.compareTo(BigDecimal.ZERO) != 0) {
73 ilm 412
            System.err.print("Ecarts: " + reste + "(HT:" + ht);
413
            System.err.print(" TVA:" + tva);
414
            System.err.println(" TTC:" + totalTTC2);
67 ilm 415
            SQLRow row = ComptePCESQLElement.getRow("758", "Ecarts arrondis");
416
            // TODO Check if row already exist in MAP ??
417
            this.mapHt.put(row, reste);
418
        }
419
    }
420
 
421
    public BigDecimal getTotalDevise() {
422
        return totalDevise;
423
    }
424
 
425
    public BigDecimal getTotalDeviseSel() {
426
        return totalDeviseSel;
427
    }
428
 
429
    public BigDecimal getTotalHA() {
430
        return totalHA;
431
    }
432
 
433
    public BigDecimal getTotalHASel() {
434
        return totalHASel;
435
    }
436
 
437
    public double getTotalPoids() {
438
        return totalPoids;
439
    }
440
 
441
    public BigDecimal getTotalService() {
442
        return totalService;
443
    }
444
 
445
    public BigDecimal getTotalServiceSel() {
446
        return totalServiceSel;
447
    }
448
 
449
    public BigDecimal getTotalHT() {
450
        BigDecimal ht = BigDecimal.ZERO;
451
        for (SQLRowAccessor row : this.mapHt.keySet()) {
452
            ht = ht.add(this.mapHt.get(row).setScale(2, RoundingMode.HALF_UP));
453
        }
454
 
455
        return ht;
456
    }
457
 
458
    public BigDecimal getTotalTVA() {
459
        BigDecimal tva = BigDecimal.ZERO;
460
        for (SQLRowAccessor row : this.mapHtTVA.keySet()) {
461
            tva = tva.add(this.mapHtTVA.get(row).setScale(2, RoundingMode.HALF_UP));
462
        }
463
        return tva;
464
    }
465
 
466
    public BigDecimal getTotalTTC() {
467
        return this.totalTTC.setScale(2, RoundingMode.HALF_UP);
468
    }
469
 
470
    public BigDecimal getTotalHTSel() {
471
        BigDecimal ht = BigDecimal.ZERO;
472
        for (SQLRowAccessor row : this.mapHtSel.keySet()) {
473
            ht = ht.add(this.mapHtSel.get(row).setScale(2, RoundingMode.HALF_UP));
474
        }
475
 
476
        return ht;
477
    }
478
 
479
    public BigDecimal getTotalTVASel() {
480
        BigDecimal tva = BigDecimal.ZERO;
481
        for (SQLRowAccessor row : this.mapHtTVASel.keySet()) {
482
            tva = tva.add(this.mapHtTVASel.get(row).setScale(2, RoundingMode.HALF_UP));
483
        }
484
        return tva;
485
    }
486
 
487
    public BigDecimal getTotalTTCSel() {
488
 
489
        return this.totalTTCSel.setScale(2, RoundingMode.HALF_UP);
490
    }
491
 
492
    public Map<SQLRowAccessor, BigDecimal> getMapHt() {
493
        return mapHt;
494
    }
495
 
496
    public Map<SQLRowAccessor, BigDecimal> getMapHtTVA() {
497
        return mapHtTVA;
498
    }
499
}