OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

Rev 73 | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 73 Rev 156
Line 14... Line 14...
14
 package org.openconcerto.erp.core.finance.accounting.model;
14
 package org.openconcerto.erp.core.finance.accounting.model;
15
 
15
 
16
import org.openconcerto.erp.config.ComptaPropsConfiguration;
16
import org.openconcerto.erp.config.ComptaPropsConfiguration;
17
import org.openconcerto.sql.Configuration;
17
import org.openconcerto.sql.Configuration;
18
import org.openconcerto.sql.model.SQLBase;
18
import org.openconcerto.sql.model.SQLBase;
-
 
19
import org.openconcerto.sql.model.SQLField;
19
import org.openconcerto.sql.model.SQLRow;
20
import org.openconcerto.sql.model.SQLRow;
20
import org.openconcerto.sql.model.SQLSelect;
21
import org.openconcerto.sql.model.SQLSelect;
21
import org.openconcerto.sql.model.SQLTable;
22
import org.openconcerto.sql.model.SQLTable;
22
import org.openconcerto.sql.model.Where;
23
import org.openconcerto.sql.model.Where;
23
 
24
 
-
 
25
import java.util.ArrayList;
24
import java.util.Date;
26
import java.util.Date;
25
import java.util.List;
27
import java.util.List;
26
 
28
 
27
import org.apache.commons.dbutils.handlers.ArrayListHandler;
29
import org.apache.commons.dbutils.handlers.ArrayListHandler;
28
 
30
 
Line 30... Line 32...
30
 
32
 
31
    private static final SQLBase base = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete();
33
    private static final SQLBase base = ((ComptaPropsConfiguration) Configuration.getInstance()).getSQLBaseSociete();
32
 
34
 
33
    private SQLRow rowAnalytique = null;
35
    private SQLRow rowAnalytique = null;
34
 
36
 
-
 
37
    private boolean removeClotureCompte = false;
-
 
38
 
-
 
39
    private List<String> compteUsed = new ArrayList<String>();
-
 
40
 
35
    public SommeCompte() {
41
    public SommeCompte() {
36
        this(null);
42
        this(null);
37
    }
43
    }
38
 
44
 
39
    public SommeCompte(SQLRow rowAnalytique) {
45
    public SommeCompte(SQLRow rowAnalytique) {
40
        this.rowAnalytique = rowAnalytique;
46
        this.rowAnalytique = rowAnalytique;
41
    }
47
    }
42
 
48
 
-
 
49
    public void setRemoveClotureCompte(boolean removeClotureCompte) {
-
 
50
        this.removeClotureCompte = removeClotureCompte;
-
 
51
    }
-
 
52
 
43
    SQLTable ecritureTable = base.getTable("ECRITURE");
53
    SQLTable ecritureTable = base.getTable("ECRITURE");
44
    SQLTable compteTable = base.getTable("COMPTE_PCE");
54
    SQLTable compteTable = base.getTable("COMPTE_PCE");
45
 
55
 
46
    private void addAnalytiqueJoin(SQLSelect sel) {
56
    private void addAnalytiqueJoin(SQLSelect sel) {
47
        if (this.rowAnalytique != null) {
57
        if (this.rowAnalytique != null) {
Line 59... Line 69...
59
     * @param dateDebut Date de début de la période prise en compte
69
     * @param dateDebut Date de début de la période prise en compte
60
     * @param dateFin Date de la fin de la période prise en compte
70
     * @param dateFin Date de la fin de la période prise en compte
61
     * @return le solde debiteur
71
     * @return le solde debiteur
62
     **********************************************************************************************/
72
     **********************************************************************************************/
63
    public long sommeCompteFils(String numero, Date dateDebut, Date dateFin) {
73
    public long sommeCompteFils(String numero, Date dateDebut, Date dateFin) {
-
 
74
 
-
 
75
        this.compteUsed.add(numero.trim() + "%");
64
        long sommeDebit = 0;
76
        long sommeDebit = 0;
65
        long sommeCredit = 0;
77
        long sommeCredit = 0;
66
 
78
 
67
        SQLSelect sel = new SQLSelect(base);
79
        SQLSelect sel = new SQLSelect();
68
 
80
 
69
        sel.addSelect(ecritureTable.getField("DEBIT"), "SUM");
81
        sel.addSelect(ecritureTable.getField("DEBIT"), "SUM");
70
        sel.addSelect(ecritureTable.getField("CREDIT"), "SUM");
82
        sel.addSelect(ecritureTable.getField("CREDIT"), "SUM");
71
        // sel.addSelect(compteTable.getField("ID"));
83
        // sel.addSelect(compteTable.getField("ID"));
72
        // sel.addSelect(compteTable.getField("NUMERO"));
84
        // sel.addSelect(compteTable.getField("NUMERO"));
Line 74... Line 86...
74
        // Where w = new Where(ecritureTable.getField("ID_COMPTE_PCE"), "=",
86
        // Where w = new Where(ecritureTable.getField("ID_COMPTE_PCE"), "=",
75
        // compteTable.getField("ID"));
87
        // compteTable.getField("ID"));
76
        sel.addJoin("LEFT", ecritureTable.getField("ID_COMPTE_PCE"));
88
        sel.addJoin("LEFT", ecritureTable.getField("ID_COMPTE_PCE"));
77
        Where w2 = new Where(compteTable.getField("NUMERO"), "LIKE", numero.trim() + "%");
89
        Where w2 = new Where(compteTable.getField("NUMERO"), "LIKE", numero.trim() + "%");
78
        Where w3 = new Where(ecritureTable.getField("DATE"), dateDebut, dateFin);
90
        Where w3 = new Where(ecritureTable.getField("DATE"), dateDebut, dateFin);
-
 
91
        if (this.removeClotureCompte) {
-
 
92
            Where w4 = new Where(ecritureTable.getField("NOM"), "NOT LIKE", "Fermeture du compte %");
-
 
93
            sel.setWhere(w2.and(w3).and(w4));
-
 
94
        } else {
79
        sel.setWhere(w2.and(w3));
95
            sel.setWhere(w2.and(w3));
-
 
96
        }
80
        addAnalytiqueJoin(sel);
97
        addAnalytiqueJoin(sel);
81
 
98
 
82
        // String req = sel.asString() +
99
        // String req = sel.asString() +
83
        // " GROUP BY \"COMPTE_PCE\".\"ID\",\"COMPTE_PCE\".\"NUMERO\" ORDER BY \"COMPTE_PCE\".\"NUMERO\"";
100
        // " GROUP BY \"COMPTE_PCE\".\"ID\",\"COMPTE_PCE\".\"NUMERO\" ORDER BY
-
 
101
        // \"COMPTE_PCE\".\"NUMERO\"";
84
        String req = sel.asString();
102
        String req = sel.asString();
85
        // System.out.println(req);
103
        // System.out.println(req);
86
 
104
 
87
        Object ob = base.getDataSource().execute(req, new ArrayListHandler());
105
        Object ob = base.getDataSource().execute(req, new ArrayListHandler());
88
 
106
 
Line 120... Line 138...
120
        long sommeDebit = 0;
138
        long sommeDebit = 0;
121
        long sommeCredit = 0;
139
        long sommeCredit = 0;
122
 
140
 
123
        SQLTable ecritureTable = base.getTable("ECRITURE");
141
        SQLTable ecritureTable = base.getTable("ECRITURE");
124
        SQLTable compteTable = base.getTable("COMPTE_PCE");
142
        SQLTable compteTable = base.getTable("COMPTE_PCE");
125
        SQLSelect sel = new SQLSelect(base);
143
        SQLSelect sel = new SQLSelect();
126
 
144
 
127
        sel.addSelect(ecritureTable.getField("DEBIT"), "SUM");
145
        sel.addSelect(ecritureTable.getField("DEBIT"), "SUM");
128
        sel.addSelect(ecritureTable.getField("CREDIT"), "SUM");
146
        sel.addSelect(ecritureTable.getField("CREDIT"), "SUM");
129
        // sel.addSelect(compteTable.getField("ID"));
147
        // sel.addSelect(compteTable.getField("ID"));
130
        // sel.addSelect(compteTable.getField("NUMERO"));
148
        // sel.addSelect(compteTable.getField("NUMERO"));
131
 
149
 
132
        // Where w = new Where(ecritureTable.getField("ID_COMPTE_PCE"), "=",
150
        // Where w = new Where(ecritureTable.getField("ID_COMPTE_PCE"), "=",
133
        // compteTable.getField("ID"));
151
        // compteTable.getField("ID"));
134
        sel.addJoin("LEFT", ecritureTable.getField("ID_COMPTE_PCE"));
152
        sel.addJoin("LEFT", ecritureTable.getField("ID_COMPTE_PCE"));
135
        Where w2 = new Where(compteTable.getField("NUMERO"), "LIKE", String.valueOf(numeroStart) + "%");
153
        Where w2 = new Where(compteTable.getField("NUMERO"), "LIKE", String.valueOf(numeroStart) + "%");
-
 
154
        this.compteUsed.add(String.valueOf(numeroStart) + "%");
136
        Where w4 = new Where(ecritureTable.getField("DATE"), dateDebut, dateFin);
155
        Where w4 = new Where(ecritureTable.getField("DATE"), dateDebut, dateFin);
137
 
156
 
138
        for (int i = numeroStart + 1; i < numeroEnd + 1; i++) {
157
        for (int i = numeroStart + 1; i < numeroEnd + 1; i++) {
139
            Where w3;
158
            Where w3;
140
            if ((i == numeroEnd) && (!includeAllEnd)) {
159
            if ((i == numeroEnd) && (!includeAllEnd)) {
141
                w3 = new Where(compteTable.getField("NUMERO"), "=", String.valueOf(i));
160
                w3 = new Where(compteTable.getField("NUMERO"), "=", String.valueOf(i));
-
 
161
                this.compteUsed.add(String.valueOf(i));
142
            } else {
162
            } else {
143
                w3 = new Where(compteTable.getField("NUMERO"), "LIKE", String.valueOf(i) + "%");
163
                w3 = new Where(compteTable.getField("NUMERO"), "LIKE", String.valueOf(i) + "%");
-
 
164
                this.compteUsed.add(String.valueOf(i) + "%");
144
            }
165
            }
145
            w2 = w2.or(w3);
166
            w2 = w2.or(w3);
146
        }
167
        }
-
 
168
        if (this.removeClotureCompte) {
147
 
169
 
-
 
170
            Where w5 = new Where(ecritureTable.getField("NOM"), "NOT LIKE", "Fermeture du compte %");
-
 
171
            sel.setWhere(w2.and(w4).and(w5));
-
 
172
        } else {
148
        sel.setWhere(w2.and(w4));
173
            sel.setWhere(w2.and(w4));
-
 
174
        }
149
        addAnalytiqueJoin(sel);
175
        addAnalytiqueJoin(sel);
150
 
176
 
151
        // String req = sel.asString() +
177
        // String req = sel.asString() +
152
        // " GROUP BY \"COMPTE_PCE\".\"ID\",\"COMPTE_PCE\".\"NUMERO\" ORDER BY \"COMPTE_PCE\".\"NUMERO\"";
178
        // " GROUP BY \"COMPTE_PCE\".\"ID\",\"COMPTE_PCE\".\"NUMERO\" ORDER BY
-
 
179
        // \"COMPTE_PCE\".\"NUMERO\"";
153
        String req = sel.asString();
180
        String req = sel.asString();
154
 
181
 
155
        Object ob = base.getDataSource().execute(req, new ArrayListHandler());
182
        Object ob = base.getDataSource().execute(req, new ArrayListHandler());
156
 
183
 
157
        List myList = (List) ob;
184
        List myList = (List) ob;
Line 175... Line 202...
175
 
202
 
176
    public long soldeCompteDebiteur(int numeroStart, int numeroEnd, boolean includeAllEnd, Date dateDebut, Date dateFin) {
203
    public long soldeCompteDebiteur(int numeroStart, int numeroEnd, boolean includeAllEnd, Date dateDebut, Date dateFin) {
177
 
204
 
178
        SQLTable ecritureTable = base.getTable("ECRITURE");
205
        SQLTable ecritureTable = base.getTable("ECRITURE");
179
        SQLTable compteTable = base.getTable("COMPTE_PCE");
206
        SQLTable compteTable = base.getTable("COMPTE_PCE");
180
        SQLSelect sel = new SQLSelect(base);
207
        SQLSelect sel = new SQLSelect();
181
 
208
 
182
        sel.addSelect(ecritureTable.getField("DEBIT"), "SUM");
209
        sel.addSelect(ecritureTable.getField("DEBIT"), "SUM");
183
        sel.addSelect(ecritureTable.getField("CREDIT"), "SUM");
210
        sel.addSelect(ecritureTable.getField("CREDIT"), "SUM");
184
 
211
 
185
        sel.addJoin("LEFT", ecritureTable.getField("ID_COMPTE_PCE"));
212
        sel.addJoin("LEFT", ecritureTable.getField("ID_COMPTE_PCE"));
Line 188... Line 215...
188
 
215
 
189
        // Where w = new Where(ecritureTable.getField("ID_COMPTE_PCE"), "=",
216
        // Where w = new Where(ecritureTable.getField("ID_COMPTE_PCE"), "=",
190
        // compteTable.getField("ID"));
217
        // compteTable.getField("ID"));
191
 
218
 
192
        Where w2 = new Where(sel.getAlias(compteTable).getField("NUMERO"), "LIKE", String.valueOf(numeroStart) + "%");
219
        Where w2 = new Where(sel.getAlias(compteTable).getField("NUMERO"), "LIKE", String.valueOf(numeroStart) + "%");
-
 
220
        this.compteUsed.add(String.valueOf(numeroStart) + "%");
193
        Where w4 = new Where(ecritureTable.getField("DATE"), dateDebut, dateFin);
221
        Where w4 = new Where(ecritureTable.getField("DATE"), dateDebut, dateFin);
194
 
222
 
195
        for (int i = numeroStart + 1; i < numeroEnd + 1; i++) {
223
        for (int i = numeroStart + 1; i < numeroEnd + 1; i++) {
196
            Where w3;
224
            Where w3;
197
            if ((i == numeroEnd) && (!includeAllEnd)) {
225
            if ((i == numeroEnd) && (!includeAllEnd)) {
198
                w3 = new Where(sel.getAlias(compteTable).getField("NUMERO"), "=", String.valueOf(i));
226
                w3 = new Where(sel.getAlias(compteTable).getField("NUMERO"), "=", String.valueOf(i));
-
 
227
                this.compteUsed.add(String.valueOf(i));
199
            } else {
228
            } else {
200
                w3 = new Where(sel.getAlias(compteTable).getField("NUMERO"), "LIKE", String.valueOf(i) + "%");
229
                w3 = new Where(sel.getAlias(compteTable).getField("NUMERO"), "LIKE", String.valueOf(i) + "%");
-
 
230
                this.compteUsed.add(String.valueOf(i) + "%");
201
            }
231
            }
202
            w2 = w2.or(w3);
232
            w2 = w2.or(w3);
203
        }
233
        }
204
 
234
 
-
 
235
        if (this.removeClotureCompte) {
-
 
236
 
-
 
237
            Where w5 = new Where(ecritureTable.getField("NOM"), "NOT LIKE", "Fermeture du compte %");
-
 
238
 
-
 
239
            sel.setWhere(w2.and(w4).and(w5));
-
 
240
        } else {
205
        sel.setWhere(w2.and(w4));
241
            sel.setWhere(w2.and(w4));
-
 
242
        }
206
        addAnalytiqueJoin(sel);
243
        addAnalytiqueJoin(sel);
207
        String req = sel.asString() + " GROUP BY \"COMPTE_PCE\".\"ID\",\"COMPTE_PCE\".\"NUMERO\" ORDER BY \"COMPTE_PCE\".\"NUMERO\"";
244
        String req = sel.asString() + " GROUP BY \"COMPTE_PCE\".\"ID\",\"COMPTE_PCE\".\"NUMERO\" ORDER BY \"COMPTE_PCE\".\"NUMERO\"";
208
 
245
 
209
        Object ob = base.getDataSource().execute(req, new ArrayListHandler());
246
        Object ob = base.getDataSource().execute(req, new ArrayListHandler());
210
 
247
 
Line 231... Line 268...
231
    // 474, 475
268
    // 474, 475
232
    public long soldeCompteCrediteur(int numeroStart, int numeroEnd, boolean includeAllEnd, Date dateDebut, Date dateFin) {
269
    public long soldeCompteCrediteur(int numeroStart, int numeroEnd, boolean includeAllEnd, Date dateDebut, Date dateFin) {
233
 
270
 
234
        SQLTable ecritureTable = base.getTable("ECRITURE");
271
        SQLTable ecritureTable = base.getTable("ECRITURE");
235
        SQLTable compteTable = base.getTable("COMPTE_PCE");
272
        SQLTable compteTable = base.getTable("COMPTE_PCE");
236
        SQLSelect sel = new SQLSelect(base);
273
        SQLSelect sel = new SQLSelect();
237
 
274
 
238
        sel.addSelect(ecritureTable.getField("DEBIT"), "SUM");
275
        sel.addSelect(ecritureTable.getField("DEBIT"), "SUM");
239
        sel.addSelect(ecritureTable.getField("CREDIT"), "SUM");
276
        sel.addSelect(ecritureTable.getField("CREDIT"), "SUM");
240
        sel.addJoin("LEFT", ecritureTable.getField("ID_COMPTE_PCE"));
277
        sel.addJoin("LEFT", ecritureTable.getField("ID_COMPTE_PCE"));
241
        sel.addSelect(sel.getAlias(compteTable).getField("ID"));
278
        sel.addSelect(sel.getAlias(compteTable).getField("ID"));
Line 243... Line 280...
243
 
280
 
244
        // Where w = new Where(ecritureTable.getField("ID_COMPTE_PCE"), "=",
281
        // Where w = new Where(ecritureTable.getField("ID_COMPTE_PCE"), "=",
245
        // compteTable.getField("ID"));
282
        // compteTable.getField("ID"));
246
 
283
 
247
        Where w2 = new Where(sel.getAlias(compteTable).getField("NUMERO"), "LIKE", String.valueOf(numeroStart) + "%");
284
        Where w2 = new Where(sel.getAlias(compteTable).getField("NUMERO"), "LIKE", String.valueOf(numeroStart) + "%");
-
 
285
        this.compteUsed.add(String.valueOf(numeroStart) + "%");
248
        Where w4 = new Where(ecritureTable.getField("DATE"), dateDebut, dateFin);
286
        Where w4 = new Where(ecritureTable.getField("DATE"), dateDebut, dateFin);
249
 
287
 
250
        for (int i = numeroStart + 1; i < numeroEnd + 1; i++) {
288
        for (int i = numeroStart + 1; i < numeroEnd + 1; i++) {
251
            Where w3;
289
            Where w3;
252
            if ((i == numeroEnd) && (!includeAllEnd)) {
290
            if ((i == numeroEnd) && (!includeAllEnd)) {
253
                w3 = new Where(sel.getAlias(compteTable).getField("NUMERO"), "=", String.valueOf(i));
291
                w3 = new Where(sel.getAlias(compteTable).getField("NUMERO"), "=", String.valueOf(i));
-
 
292
                this.compteUsed.add(String.valueOf(i));
254
            } else {
293
            } else {
255
                w3 = new Where(sel.getAlias(compteTable).getField("NUMERO"), "LIKE", String.valueOf(i) + "%");
294
                w3 = new Where(sel.getAlias(compteTable).getField("NUMERO"), "LIKE", String.valueOf(i) + "%");
-
 
295
                this.compteUsed.add(String.valueOf(i) + "%");
256
            }
296
            }
257
            w2 = w2.or(w3);
297
            w2 = w2.or(w3);
258
        }
298
        }
-
 
299
        if (this.removeClotureCompte) {
-
 
300
            Where w5 = new Where(ecritureTable.getField("NOM"), "NOT LIKE", "Fermeture du compte %");
259
 
301
 
-
 
302
            sel.setWhere(w2.and(w4).and(w5));
-
 
303
        } else {
260
        sel.setWhere(w2.and(w4));
304
            sel.setWhere(w2.and(w4));
-
 
305
        }
261
        addAnalytiqueJoin(sel);
306
        addAnalytiqueJoin(sel);
262
        String req = sel.asString();
307
        String req = sel.asString();
263
 
308
 
264
        req += " GROUP BY \"COMPTE_PCE\".\"ID\",\"COMPTE_PCE\".\"NUMERO\" ORDER BY \"COMPTE_PCE\".\"NUMERO\"";
309
        req += " GROUP BY \"COMPTE_PCE\".\"ID\",\"COMPTE_PCE\".\"NUMERO\" ORDER BY \"COMPTE_PCE\".\"NUMERO\"";
265
 
310
 
Line 301... Line 346...
301
        sel.addSelect(ecritureTable.getField("DEBIT"), "SUM");
346
        sel.addSelect(ecritureTable.getField("DEBIT"), "SUM");
302
        sel.addSelect(ecritureTable.getField("CREDIT"), "SUM");
347
        sel.addSelect(ecritureTable.getField("CREDIT"), "SUM");
303
 
348
 
304
        Where w = new Where(ecritureTable.getField("ID_COMPTE_PCE"), "=", compteTable.getField("ID"));
349
        Where w = new Where(ecritureTable.getField("ID_COMPTE_PCE"), "=", compteTable.getField("ID"));
305
        Where w2 = new Where(compteTable.getField("NUMERO"), "=", numero.trim());
350
        Where w2 = new Where(compteTable.getField("NUMERO"), "=", numero.trim());
-
 
351
        this.compteUsed.add(numero.trim());
-
 
352
 
-
 
353
        if (this.removeClotureCompte) {
-
 
354
            Where w5 = new Where(ecritureTable.getField("NOM"), "NOT LIKE", "Fermeture du compte %");
-
 
355
 
-
 
356
            sel.setWhere(w.and(w2).and(w5));
-
 
357
        } else {
306
        sel.setWhere(w.and(w2));
358
            sel.setWhere(w.and(w2));
-
 
359
        }
307
        addAnalytiqueJoin(sel);
360
        addAnalytiqueJoin(sel);
308
        String req = sel.asString() + " GROUP BY \"COMPTE_PCE\".\"ID\",\"COMPTE_PCE\".\"NUMERO\" ORDER BY \"COMPTE_PCE\".\"NUMERO\"";
361
        String req = sel.asString() + " GROUP BY \"COMPTE_PCE\".\"ID\",\"COMPTE_PCE\".\"NUMERO\" ORDER BY \"COMPTE_PCE\".\"NUMERO\"";
309
        // System.out.println(req);
362
        // System.out.println(req);
310
 
363
 
311
        Object ob = base.getDataSource().execute(req, new ArrayListHandler());
364
        Object ob = base.getDataSource().execute(req, new ArrayListHandler());
Line 320... Line 373...
320
            sommeCredit += ((Number) objTmp[1]).longValue();
373
            sommeCredit += ((Number) objTmp[1]).longValue();
321
        }
374
        }
322
 
375
 
323
        return sommeDebit - sommeCredit;
376
        return sommeDebit - sommeCredit;
324
    }
377
    }
-
 
378
 
-
 
379
    public void clearUsedCompte() {
-
 
380
        this.compteUsed.clear();
-
 
381
    }
-
 
382
 
-
 
383
    public void getNonUsedCompte(Where where, Date dateDebut, Date dateFin) {
-
 
384
 
-
 
385
        SQLSelect sel = new SQLSelect();
-
 
386
        final SQLTable table = base.getTable("COMPTE_PCE");
-
 
387
        final SQLTable tableEcr = base.getTable("ECRITURE");
-
 
388
        final SQLField field = table.getField("NUMERO");
-
 
389
        sel.addSelect(field);
-
 
390
 
-
 
391
        for (String cpt : this.compteUsed) {
-
 
392
            where = where.and(new Where(field, "NOT LIKE", cpt));
-
 
393
        }
-
 
394
 
-
 
395
        Where w2 = new Where(tableEcr.getField("ID_COMPTE_PCE"), "=", table.getKey());
-
 
396
        w2 = w2.and(new Where(tableEcr.getField("DATE"), dateDebut, dateFin));
-
 
397
        where = where.and(w2);
-
 
398
        sel.setWhere(where);
-
 
399
        sel.addGroupBy(field);
-
 
400
        List<String> s = tableEcr.getBase().getDataSource().executeCol(sel.asString());
-
 
401
        System.err.println("COMPTE NOT USED");
-
 
402
        for (String string : s) {
-
 
403
            System.err.println("Compte " + s);
-
 
404
        }
-
 
405
 
-
 
406
    }
325
}
407
}