OpenConcerto

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

svn://code.openconcerto.org/openconcerto

Rev

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

Rev Author Line No. Line
104 ilm 1
package org.openconcerto.modules.finance.accounting.exchangerates;
2
 
147 ilm 3
import java.awt.GraphicsEnvironment;
104 ilm 4
import java.io.File;
5
import java.io.IOException;
6
import java.math.BigDecimal;
7
import java.sql.ResultSet;
8
import java.sql.SQLException;
9
import java.util.ArrayList;
10
import java.util.Arrays;
11
import java.util.Calendar;
12
import java.util.Date;
13
import java.util.HashSet;
14
import java.util.List;
15
import java.util.Set;
16
import java.util.TimeZone;
17
 
18
import javax.swing.JOptionPane;
19
 
20
import org.apache.commons.dbutils.ResultSetHandler;
21
import org.openconcerto.erp.config.ComptaPropsConfiguration;
22
import org.openconcerto.erp.config.Gestion;
23
import org.openconcerto.erp.core.finance.accounting.model.CurrencyConverter;
24
import org.openconcerto.erp.modules.AbstractModule;
25
import org.openconcerto.erp.modules.DBContext;
26
import org.openconcerto.erp.modules.ModuleFactory;
27
import org.openconcerto.erp.modules.ModuleManager;
28
import org.openconcerto.erp.modules.ModulePackager;
29
import org.openconcerto.erp.modules.ModulePreferencePanel;
30
import org.openconcerto.erp.modules.ModulePreferencePanelDesc;
31
import org.openconcerto.erp.modules.ModuleVersion;
32
import org.openconcerto.erp.modules.RuntimeModuleFactory;
33
import org.openconcerto.sql.model.DBRoot;
34
import org.openconcerto.sql.model.SQLBase;
35
import org.openconcerto.sql.model.SQLRequestLog;
36
import org.openconcerto.sql.model.SQLRow;
37
import org.openconcerto.sql.model.SQLRowListRSH;
38
import org.openconcerto.sql.model.SQLSelect;
39
import org.openconcerto.sql.model.SQLTable;
40
import org.openconcerto.sql.model.Where;
41
import org.openconcerto.sql.ui.ConnexionPanel;
42
import org.openconcerto.sql.utils.SQLUtils;
43
import org.openconcerto.utils.PrefType;
44
 
45
public final class Module extends AbstractModule {
46
 
47
    public static final String TABLE_EXPENSE = "EXPENSE";
48
    public static final String TABLE_EXPENSE_STATE = "EXPENSE_STATE";
49
    public static final String EXPENSE_RATE_NOT_DOWNLOAD_PREF = "EXPENSE_RATE_NOT_DOWNLOAD_PREF";
50
    public static ModuleVersion MODULE_VERSION = new ModuleVersion(1, 0);
51
    private CurrencyConverter commercialConverter = null;
52
 
53
    public Module(ModuleFactory f) throws IOException {
54
        super(f);
55
    }
56
 
57
    @Override
58
    protected void install(DBContext ctxt) {
59
 
60
    }
61
 
62
    public void setCommercialConverter(CurrencyConverter commercialConverter) {
63
        this.commercialConverter = commercialConverter;
64
    }
65
 
66
    @Override
67
    protected void start() {
68
        final DBRoot root = ComptaPropsConfiguration.getInstanceCompta().getRootSociete();
69
        Boolean b = ModuleManager.getInstance().getFactories().get("org.openconcerto.modules.finance.accounting.exchangerates").get(Module.MODULE_VERSION).getSQLPreferences(root)
70
                .getBoolean(EXPENSE_RATE_NOT_DOWNLOAD_PREF, false);
71
        if (!b) {
72
            final Thread t = new Thread() {
73
                public void run() {
74
                    // Wait 1s to prevent too many internet access at startup
75
                    try {
76
                        Thread.sleep(1000);
77
                    } catch (InterruptedException e1) {
78
                        e1.printStackTrace();
79
                    }
80
                    updateRates(root, ComptaPropsConfiguration.getInstanceCompta().getRowSociete().getForeign("ID_DEVISE").getString("CODE"));
81
                };
82
            };
83
            t.setPriority(Thread.MIN_PRIORITY);
84
            t.setDaemon(true);
85
            t.start();
86
        }
87
 
88
    }
89
 
90
    public void updateRates(DBRoot root, String companyCurrencyCode) {
91
        // Check if update need to be done
92
        final Calendar c = Calendar.getInstance();
93
        c.set(Calendar.HOUR_OF_DAY, 0);
94
        c.set(Calendar.MINUTE, 0);
95
        c.set(Calendar.SECOND, 0);
96
        c.set(Calendar.MILLISECOND, 0);
97
 
98
        if (c.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
99
            c.set(Calendar.HOUR, -72);
100
        } else {
101
            c.add(Calendar.HOUR, -24);
102
        }
103
        final Date yesterday = c.getTime();
104
 
105
        final CurrencyConverter converter = new CurrencyConverter(root, companyCurrencyCode, "EUR");
106
        final SQLSelect select = new SQLSelect();
107
        final SQLTable t = root.getTable("DEVISE_HISTORIQUE");
108
        select.addAllSelect(t, Arrays.asList("DATE", "SRC", "ID"));
109
        Where w = new Where(t.getField("SRC"), "=", "EUR");
110
        w = w.and(new Where(t.getField("DATE"), "=", yesterday));
111
        select.setWhere(w);
112
        select.setLimit(1);
113
        final List<SQLRow> rows = SQLRowListRSH.execute(select);
114
        if (!rows.isEmpty()) {
115
            // Nothing to update
116
            System.out.println("No exchange rates to download");
117
            return;
118
        }
119
        // Get conversion info
120
        final ExchangeRatesDownloader d = new ExchangeRatesDownloader();
121
        try {
122
            d.downloadAndParse();
123
            Set<Date> dates = getMissingDates(converter, root);
124
            System.out.println("Missing date:" + dates);
125
            List<Report> reports = d.getReports();
126
 
127
            for (Report report : reports) {
128
                if (dates.contains(report.getDate())) {
129
                    importReport(d, report, converter, root);
130
                }
131
            }
132
        } catch (Exception e) {
133
            e.printStackTrace();
147 ilm 134
            if (!GraphicsEnvironment.isHeadless()) {
135
                JOptionPane.showMessageDialog(null, "Impossible de mettre à jour les taux de change");
136
            }
104 ilm 137
        }
138
    }
139
 
140
    @Override
141
    public List<ModulePreferencePanelDesc> getPrefDescriptors() {
142
        return Arrays.<ModulePreferencePanelDesc> asList(new ModulePreferencePanelDesc("Gestion des devises") {
143
            @Override
144
            protected ModulePreferencePanel createPanel() {
145
                return new ModulePreferencePanel("Gestion des devises") {
146
                    @Override
147
                    protected void addViews() {
148
 
149
                        final SQLPrefView<Boolean> view = new SQLPrefView<Boolean>(PrefType.BOOLEAN_TYPE, "Ne pas télécharger les nouveaux taux au lancement du logiciel",
150
                                EXPENSE_RATE_NOT_DOWNLOAD_PREF);
151
                        this.addView(view);
152
                    }
153
                };
154
            }
155
        }.setLocal(false).setKeywords("devise"));
156
    }
157
 
158
    protected void importReport(ExchangeRatesDownloader d, Report report, CurrencyConverter converter, DBRoot root) {
159
 
160
        System.out.println("Module.importReport() " + report.getDate());
161
 
162
        SQLTable tDeviseHisto = root.getTable("DEVISE_HISTORIQUE");
163
 
164
        final List<String> queries = new ArrayList<String>();
165
        final List<ResultSetHandler> handlers = new ArrayList<ResultSetHandler>();
166
        final ResultSetHandler handler = new ResultSetHandler() {
167
 
168
            @Override
169
            public Object handle(ResultSet rs) throws SQLException {
170
                if (rs.next()) {
171
                    return rs.getObject(1);
172
                }
173
                return null;
174
            }
175
        };
176
        Date date = Calendar.getInstance().getTime();
177
        final int size = ExchangeRatesDownloader.supportedCurrencyCodes.size();
178
        for (int i = 0; i < size; i++) {
179
            String code = ExchangeRatesDownloader.supportedCurrencyCodes.get(i);
180
            BigDecimal tauxCommercial;
181
            if (this.commercialConverter != null) {
182
                tauxCommercial = commercialConverter.convert(BigDecimal.ONE, report.getMainCurrencyCode(), code, date, true);
183
            } else {
147 ilm 184
                try {
185
                    tauxCommercial = converter.convert(BigDecimal.ONE, report.getMainCurrencyCode(), code, date, true);
186
                } catch (IllegalStateException e) {
187
                    // Aucun taux n'existe encore dans la base.
188
                    tauxCommercial = null;
189
                }
104 ilm 190
            }
191
            if (tauxCommercial == null) {
192
                tauxCommercial = BigDecimal.ONE;
193
            }
194
            tauxCommercial = tauxCommercial.setScale(4, BigDecimal.ROUND_HALF_UP);
195
            String query = "INSERT INTO " + tDeviseHisto.getSQLName().quote();
196
            final BigDecimal rate = report.getRate(code);
197
            if (rate == null) {
198
                System.err.println("RATE " + code + " NOT Supported");
199
                // Thread.dumpStack();
200
            } else {
201
                final BigDecimal taux = rate.setScale(4, BigDecimal.ROUND_HALF_UP);
202
 
203
                final java.sql.Date date2 = new java.sql.Date(report.getDate().getTime());
204
                query += " (\"DATE\", \"SRC\", \"DST\", \"TAUX\", \"TAUX_COMMERCIAL\", \"ORDRE\") select " + SQLBase.quoteStringStd(date2.toString()) + ", "
205
                        + SQLBase.quoteStringStd(report.getMainCurrencyCode()) + ", " + SQLBase.quoteStringStd(code) + ", " + taux + ", " + tauxCommercial + ", COALESCE(MAX(\"ORDRE\"), 0) + 1 ";
206
                query += "FROM " + tDeviseHisto.getSQLName().quote() + " RETURNING \"ID\"";
207
 
208
                queries.add(query);
209
                handlers.add(handler);
210
            }
211
        }
212
 
213
        try {
214
            SQLUtils.executeMultiple(tDeviseHisto.getDBSystemRoot(), queries, handlers);
215
 
216
        } catch (Exception e) {
217
            e.printStackTrace();
218
        }
219
 
220
    }
221
 
222
    protected Set<Date> getMissingDates(CurrencyConverter converter, DBRoot root) {
223
        final SQLSelect select = new SQLSelect();
224
 
225
        final SQLTable t = root.getTable("DEVISE_HISTORIQUE");
226
        select.addAllSelect(t, Arrays.asList("DATE"));
227
        Where w = new Where(t.getField("SRC"), "=", converter.getCompanyCurrencyCode());
228
        w = w.and(new Where(t.getField("DATE"), "<", new Date(System.currentTimeMillis())));
229
        select.setWhere(w);
230
        select.addGroupBy(t.getField("DATE"));
231
        select.setLimit(30);
232
        final List<Date> dates = t.getDBSystemRoot().getDataSource().executeCol(select.asString());
233
 
234
        final Set<Date> result = new HashSet<Date>();
235
        Calendar c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
236
        c.set(Calendar.HOUR_OF_DAY, 0);
237
        c.set(Calendar.MINUTE, 0);
238
        c.set(Calendar.SECOND, 0);
239
        c.set(Calendar.MILLISECOND, 0);
240
        for (int i = 0; i < 20; i++) {
241
            c.add(Calendar.HOUR_OF_DAY, -24);
242
            final Date time = c.getTime();
243
            System.out.println("::" + time);
244
            result.add(time);
245
        }
246
 
247
        for (Date date : dates) {
248
            Calendar c2 = Calendar.getInstance();
249
            c2.setTime(date);
250
            c = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
251
            c.set(Calendar.YEAR, c2.get(Calendar.YEAR));
252
            c.set(Calendar.DAY_OF_YEAR, c2.get(Calendar.DAY_OF_YEAR));
253
            c.set(Calendar.HOUR_OF_DAY, 0);
254
            c.set(Calendar.MINUTE, 0);
255
            c.set(Calendar.SECOND, 0);
256
            c.set(Calendar.MILLISECOND, 0);
257
            Date dd = c.getTime();
258
            result.remove(dd);
259
            System.out.println("--" + dd);
260
        }
261
        System.out.println(result.size());
262
 
263
        return result;
264
    }
265
 
266
    @Override
267
    protected void stop() {
268
    }
269
 
270
    public static void main(String[] args) throws IOException {
271
        System.setProperty(ConnexionPanel.QUICK_LOGIN, "true");
272
        final File propsFile = new File("module.properties");
273
        System.out.println(propsFile.getAbsolutePath());
274
        final ModuleFactory factory = new RuntimeModuleFactory(propsFile);
275
        SQLRequestLog.setEnabled(true);
276
        SQLRequestLog.showFrame();
277
        // uncomment to create and use the jar
278
        final ModulePackager modulePackager = new ModulePackager(propsFile, new File("bin/"));
279
        modulePackager.writeToDir(new File("../OpenConcerto/Modules"));
280
        // final ModuleFactory factory = new JarModuleFactory(jar);
281
        ModuleManager.getInstance().addFactories(new File("../OpenConcerto/Modules"));
282
        ModuleManager.getInstance().addFactoryAndStart(factory, false);
283
        Gestion.main(args);
284
    }
285
 
286
}