001: /*
002: * Created on 14/01/2005
003: *
004: * Swing Components - visit http://sf.net/projects/gfd
005: *
006: * Copyright (C) 2004 Igor Regis da Silva Simões
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License
010: * as published by the Free Software Foundation; either version 2
011: * of the License, or (at your option) any later version.
012: *
013: * This program is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: * GNU General Public License for more details.
017: *
018: * You should have received a copy of the GNU General Public License
019: * along with this program; if not, write to the Free Software
020: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
021: *
022: */
023: package br.com.gfp.features;
024:
025: import java.sql.SQLException;
026: import java.text.DateFormat;
027: import java.text.ParseException;
028: import java.util.Calendar;
029: import java.util.Date;
030: import java.util.HashMap;
031: import java.util.Map;
032:
033: import javax.swing.text.DateFormatter;
034:
035: import br.com.gfp.dao.AccountSavingDAO;
036: import br.com.gfp.dao.AccountTypeDAO;
037: import br.com.gfp.dao.GFPController;
038: import br.com.gfp.dao.IncomePredictionDAO;
039: import br.com.gfp.dao.TransactionDAO;
040: import br.com.gfp.dao.TransactionTypeDAO;
041: import br.com.gfp.data.AccountSaving;
042: import br.com.gfp.data.AccountType;
043: import br.com.gfp.data.ConfigPrevisao;
044: import br.com.gfp.data.IncomePrediction;
045: import br.com.gfp.data.Transaction;
046: import br.com.gfp.data.TransactionType;
047: import br.com.gfp.internationalization.FeaturesMessages;
048: import br.com.gfp.internationalization.TipoDeLancamentosMessages;
049: import br.com.gfp.util.SimpleLog;
050: import br.com.gfp.util.ThreadUtil;
051: import br.com.gfpshare.beans.MessageView;
052: import br.com.gfpshare.config.Propriedades;
053: import br.com.gfpshare.controllers.PropriedadesController;
054: import br.com.gfpshare.db.DAOEvent;
055: import br.com.gfpshare.db.DAOListener;
056: import br.com.gfpshare.db.SQLCondition;
057: import br.com.gfpshare.db.SQLCondition.Condicao;
058:
059: /**
060: * @author Igor Regis da Silva Simões
061: * @since 14/01/2005 18:29:54
062: *
063: */
064: public class AtualizaRendimentoAplicacao implements DAOListener {
065: /**
066: * Quanto evento nós vamos ignorar e não vamos responder a eles
067: * Isso é necessário pois o uusário pode solicitar que o programa
068: * realize uma sequencia de lançamento repetidos em um determinado
069: * perído. Portanto verificamos se o lançamento será repetido, caso seja
070: * então ignoraremos X eventos * quantas vezes o lancamento se repetirá
071: */
072: private int quantosEventosIgnorar = 0;
073:
074: /**
075: * Tipo de conta aplicação
076: */
077: private String tipoContaAplicacao = null;
078:
079: /**
080: * Indice geral de Id de Thread
081: */
082: private static int nn = 0;
083:
084: /**
085: * Registro das Threads em execução no momento
086: */
087: private Map<Integer, Thread> threadsMap = new HashMap<Integer, Thread>();
088:
089: /**
090: * Código do tipo de conta referente a aplicações financeiras
091: * @return Integer
092: */
093: private String getTipoContaAplicacao() {
094: if (tipoContaAplicacao == null)
095: try {
096: tipoContaAplicacao = new AccountTypeDAO().getBy(
097: new AccountType("aplicacao")).getId()
098: .toString();
099: } catch (Exception e) {
100: tipoContaAplicacao = "-1";
101: }
102: return tipoContaAplicacao;
103: }
104:
105: /**
106: *
107: * @see br.com.gfpshare.db.DAOListener#adicionadoNovo(br.com.gfpshare.db.DAOEvent)
108: */
109: public void adicionadoNovo(DAOEvent e) {
110: verSePrecisaPrever(e);
111: }
112:
113: /**
114: *
115: * @see br.com.gfpshare.db.DAOListener#atualizado(br.com.gfpshare.db.DAOEvent)
116: */
117: public void atualizado(DAOEvent e) {
118: verSePrecisaPrever(e);
119: }
120:
121: /**
122: *
123: * @see br.com.gfpshare.db.DAOListener#deletado(br.com.gfpshare.db.DAOEvent)
124: */
125: public void deletado(DAOEvent e) {
126: verSePrecisaPrever(e);
127: }
128:
129: /**
130: *
131: * @see br.com.gfpshare.db.DAOListener#selecionado(br.com.gfpshare.db.DAOEvent)
132: */
133: public void selecionado(DAOEvent e) {
134: // Não fazemos nada
135: }
136:
137: /**
138: *
139: * @see br.com.gfpshare.db.DAOListener#filtrado(br.com.gfpshare.db.DAOEvent)
140: */
141: public void filtrado(DAOEvent e) {
142: //Não fazemos nada
143: }
144:
145: private void verSePrecisaPrever(DAOEvent e) {
146: quantosEventosIgnorar--;//Um evento a menos pra ignorar
147: if (quantosEventosIgnorar >= 0)
148: return;
149: if (e.getPersistentObject() instanceof Transaction) {
150: Transaction transaction = (Transaction) e
151: .getPersistentObject();
152: if (transaction.getTipoConta() != null
153: && transaction.getTipoConta().equalsIgnoreCase(
154: getTipoContaAplicacao())
155: && (transaction.getEhPrevisao() == null || !transaction
156: .getEhPrevisao().booleanValue())
157: && (transaction.getEhDeSistema() == null || !transaction
158: .getEhDeSistema().booleanValue())) {
159: quantosEventosIgnorar = transaction
160: .getVezesPraRealizar();
161: atualizaRendimentos(new IncomePrediction(transaction
162: .getTipoConta(), transaction.getDia(),
163: transaction.getConta()), transaction
164: .getVezesPraRealizar());
165: }
166: } else if (e.getPersistentObject() instanceof IncomePrediction) {
167: IncomePrediction previsao = (IncomePrediction) e
168: .getPersistentObject();
169: quantosEventosIgnorar = previsao.getVezesPraRealizar();
170: atualizaRendimentos(previsao, previsao
171: .getVezesPraRealizar());
172: }
173: }
174:
175: /**
176: * Atualizamos os rendimentos de uma determinada aplicação, para isso usamos um objeto PervisaoRendimento, do qual extraímos
177: * a data a partir da qual os rendimentos serão alterados o tipo da conta (aplicacao) e a conta a ser afatada pelas alterações
178: * @param incomePrediction
179: * @param listener
180: * @param tempoPraDormir Tempo que a thread vai dormir antes de exectuar as atualizações
181: */
182: private void atualizaRendimentos(
183: final IncomePrediction incomePrediction,
184: final int tempoPraDormir) {
185: if (threadsMap.get(incomePrediction.getId()) != null)
186: ThreadUtil.interrupt(threadsMap.get(
187: incomePrediction.getId()).getName());
188: final Integer tipoLancamento;
189: final int tipoRendimento;
190: final AccountSaving accountSaving;
191:
192: //Vemos +/- até quando vamos fazer lancamentos
193: PropriedadesController propriedadesController = new PropriedadesController();
194: final ConfigPrevisao configPrevisao = (ConfigPrevisao) Propriedades
195: .loadPropiedades(ConfigPrevisao.class);
196: try {
197: propriedadesController.getBy(configPrevisao
198: .getPersistentObject());
199: } catch (SQLException e2) {
200: //Não fazemos nada
201: }
202:
203: try {
204: tipoLancamento = new TransactionTypeDAO().getBy(
205: new TransactionType(TipoDeLancamentosMessages
206: .getMessages().getString("Rendimentos")))
207: .getId();
208: accountSaving = new AccountSavingDAO()
209: .getBy(new AccountSaving(incomePrediction.getId()));
210: tipoRendimento = accountSaving.getTipoRendimento()
211: .intValue();
212: } catch (SQLException e2) {
213: e2.printStackTrace();
214: return;
215: }
216:
217: (new Thread() {
218: {
219: setDaemon(true);
220: setPriority(Thread.MIN_PRIORITY);
221: setName("AtualizaRendimentoAplicacao " + (nn++));
222: }
223:
224: @Override
225: public void run() {
226: //Registramos esta thread como ativa
227: threadsMap.put(incomePrediction.getId(), this );
228: MessageView messages = null;
229: try {
230: Thread
231: .sleep(incomePrediction
232: .getVezesPraRealizar() * 3);
233: ThreadUtil.waitFor("PreverMovimentoAplicacao");
234:
235: messages = (MessageView) GFPController
236: .getGFPController().getContexto().get(
237: GFPController.RODAPE_MESSAGER);
238: messages = messages.showMessage(FeaturesMessages
239: .getMessages().getString(
240: "AtualizandoRendimentosTitle")
241: + " " + accountSaving.getDescricao(),
242: FeaturesMessages.getMessages().getString(
243: "AtualizandoRendimentosTitle"),
244: true);
245:
246: final Date hoje = new Date();
247: long dias = configPrevisao.getPreverAteQueAno()
248: .getTime()
249: - hoje.getTime();
250: dias = dias / 1000 / 60 / 60 / 24;
251: messages.getMessagePanel().getProgressBar()
252: .setMinimum(0);
253: messages.getMessagePanel().getProgressBar()
254: .setMaximum((int) dias);
255:
256: TransactionDAO<Transaction> lancamentoController = new TransactionDAO<Transaction>();
257: IncomePredictionDAO incomePredictionDAO = new IncomePredictionDAO();
258: Transaction transaction = new Transaction();
259:
260: Calendar dia = Calendar.getInstance();
261: dia.setTime(incomePrediction.getDataRendimento());
262:
263: DateFormat format = DateFormat
264: .getDateInstance(DateFormat.MEDIUM);
265: format.setCalendar(dia);
266: DateFormatter formatoDataExibicao = new DateFormatter(
267: format);
268:
269: switch (tipoRendimento) {
270: case AccountSaving.DIARIO:
271: dia.add(Calendar.DATE, 1);
272: if (dia.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)
273: dia.add(Calendar.DATE, 1);
274: else if (dia.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY)
275: dia.add(Calendar.DATE, 2);
276: break;
277: case AccountSaving.MENSAL:
278: case AccountSaving.ANUAL:
279: dia.set(Calendar.DATE, 1);
280: break;
281: }
282:
283: transaction.setConta(incomePrediction.getId());
284: transaction.setTipoConta(incomePrediction
285: .getTipoConta());
286: transaction.setTipo(tipoLancamento);
287: transaction.setEhDeSistema(Boolean.valueOf(true));
288:
289: if (Thread.currentThread().isInterrupted())
290: return;
291: SQLCondition<java.sql.Date> condicao = new SQLCondition<java.sql.Date>(
292: "Dia", new java.sql.Date(dia.getTime()
293: .getTime()), Condicao.MAIOR_IGUAL);
294: transaction.addCondicaoExtra(condicao);
295:
296: try {
297: //Deletamos o lançamento de rendimento antigo se existir
298: lancamentoController.setCheckIntegridade(false);
299: lancamentoController.deletar(transaction);
300: lancamentoController.setCheckIntegridade(true);
301: } catch (SQLException e) {
302: ((SimpleLog) GFPController.getGFPController()
303: .getContexto().get(GFPController.LOG))
304: .log("Erro ao deletar rendimentos anteriores");
305: ((SimpleLog) GFPController.getGFPController()
306: .getContexto().get(GFPController.LOG))
307: .log(e.getLocalizedMessage());
308: ((SimpleLog) GFPController.getGFPController()
309: .getContexto().get(GFPController.LOG))
310: .log(e);
311: }
312: transaction.removeCondicaoExtra(condicao);
313:
314: int counter = 0;
315:
316: messages.getMessagePanel().getProgressBar()
317: .setIndeterminate(false);
318: while (true) {
319: counter++;
320: if (counter % 10 == 0)
321: Thread.yield();
322: try {
323: messages
324: .getMessagePanel()
325: .setMessage(
326: accountSaving
327: .getDescricao()
328: + " - "
329: + FeaturesMessages
330: .getMessages()
331: .getString(
332: "AtualizandoRendimentos")
333: + formatoDataExibicao
334: .valueToString(dia
335: .getTime()),
336: counter == 1);
337: dias = dia.getTime().getTime()
338: - hoje.getTime();
339: dias = dias / 1000 / 60 / 60 / 24;
340: messages.getMessagePanel().getProgressBar()
341: .setValue((int) dias);
342: } catch (ParseException e) {
343: messages.getMessagePanel().setMessage("",
344: false);
345: }
346:
347: condicao = new SQLCondition<java.sql.Date>(
348: "Dia", new java.sql.Date(dia.getTime()
349: .getTime()), Condicao.MENOR);
350: transaction.addCondicaoExtra(condicao);
351: transaction.setDia(null);
352: transaction.setTipo(null);
353: transaction.setValor(null);
354: transaction.setId(null);
355: transaction.setEhDeSistema(null);
356: transaction.setConta(incomePrediction.getId());
357: transaction.setTipoConta(incomePrediction
358: .getTipoConta());
359: transaction.setIncluirSubtipos(false);
360:
361: if (Thread.currentThread().isInterrupted())
362: return;
363:
364: //Pegamos o saldo da aplicacao, até aquela data
365: double saldo = lancamentoController
366: .getTotalNoPeriodo(transaction);
367:
368: if (saldo < 0)
369: return;
370: transaction.setTipo(tipoLancamento);
371: transaction.removeCondicaoExtra(condicao);
372:
373: //Calculamos o juro
374: incomePrediction.setDataRendimento(dia
375: .getTime());
376: incomePrediction.setValorRendimento(null);
377: //Quando der uma SQL exception é que não há previsões de % de rendimento para esta conta
378: //então paramos de fazer os lançamentos (é aqui que o loop eterno termina)
379: double rendimento = incomePredictionDAO.getBy(
380: incomePrediction).getValorRendimento()
381: .doubleValue();
382: transaction.setValor(new Double(saldo
383: * rendimento / 100));
384:
385: //Realizamos novo lançamento com o novo valor de rendimento
386: transaction.setDia(dia.getTime());
387: transaction.setEhDeSistema(Boolean
388: .valueOf(true));
389: lancamentoController.setCheckIntegridade(false);
390: lancamentoController.adicionarNovo(transaction);
391: lancamentoController.setCheckIntegridade(true);
392: transaction.setEhDeSistema(null);
393: //Pegamos a data do proximo lancamento
394: switch (tipoRendimento) {
395: case AccountSaving.DIARIO:
396: dia.add(Calendar.DATE, 1);
397: if (dia.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)
398: dia.add(Calendar.DATE, 1);
399: else if (dia.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY)
400: dia.add(Calendar.DATE, 2);
401: break;
402: case AccountSaving.MENSAL:
403: dia.add(Calendar.MONTH, 1);
404: break;
405: case AccountSaving.ANUAL:
406: dia.add(Calendar.YEAR, 1);
407: break;
408: }
409: if (Thread.currentThread().isInterrupted())
410: return;
411: }
412: } catch (SQLException e) {
413: ((SimpleLog) GFPController.getGFPController()
414: .getContexto().get(GFPController.LOG))
415: .log("Atualização parou em: "
416: + incomePrediction
417: .getDataRendimento());
418: ((SimpleLog) GFPController.getGFPController()
419: .getContexto().get(GFPController.LOG))
420: .log(e.getLocalizedMessage());
421: ((SimpleLog) GFPController.getGFPController()
422: .getContexto().get(GFPController.LOG))
423: .log(e);
424: } catch (Throwable t) {
425: if (t instanceof InterruptedException)
426: return;
427: ((SimpleLog) GFPController.getGFPController()
428: .getContexto().get(GFPController.LOG))
429: .log("Erro na Thread AtualizaRendimentos");
430: ((SimpleLog) GFPController.getGFPController()
431: .getContexto().get(GFPController.LOG))
432: .log(t.getLocalizedMessage());
433: ((SimpleLog) GFPController.getGFPController()
434: .getContexto().get(GFPController.LOG))
435: .log(t);
436: } finally {
437: //Removemos esta Thread do Registro pois ela já parou de executar
438: threadsMap.remove(incomePrediction.getId());
439:
440: if (messages != null
441: && messages.getMessagePanel() != null) {
442: messages.getMessagePanel()
443: .setMessage("", false);
444: messages.getMessagePanel().getProgressBar()
445: .setValue(0);
446: messages.finishUse(5);
447: }
448: }
449: }
450: }).start();
451: }
452: }
|