001: /*
002: * Created on 03/11/2004
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: package br.com.gfp.features;
023:
024: import java.sql.Date;
025: import java.sql.SQLException;
026: import java.util.Calendar;
027:
028: import br.com.gfp.dao.AccountTypeDAO;
029: import br.com.gfp.dao.GFPController;
030: import br.com.gfp.dao.TransactionDAO;
031: import br.com.gfp.dao.TransactionTypeDAO;
032: import br.com.gfp.data.AccountType;
033: import br.com.gfp.data.ConfigPrevisao;
034: import br.com.gfp.data.ProjecaoFinanceira;
035: import br.com.gfp.data.Transaction;
036: import br.com.gfp.data.TransactionType;
037: import br.com.gfp.internationalization.TipoDeLancamentosMessages;
038: import br.com.gfp.util.SimpleLog;
039: import br.com.gfpshare.config.Propriedades;
040: import br.com.gfpshare.controllers.PropriedadesController;
041: import br.com.gfpshare.db.DAOEvent;
042: import br.com.gfpshare.db.DAOListener;
043: import br.com.gfpshare.db.SQLCondition;
044: import br.com.gfpshare.db.SQLCondition.Condicao;
045:
046: /**
047: * Esta classe é responsável por controlar a previsão de rendimentos para as aplicações
048: * financeiras. <br>
049: * Sempre que houver movimentação nas contas de aplicação financeira, esta classe será notificada
050: * e reagirá, fazendo os recalculos e lançamentos de acordo com o novo cenário
051: * <br>
052: * @author Igor Regis da Silva Simoes
053: */
054: public class PreverMovimentoAplicacao implements
055: DAOListener<Transaction> {
056: private Integer aplicacao = Integer.valueOf("-1");
057:
058: private Integer resgate = Integer.valueOf("-1");
059:
060: private String tipoContaAplicacao = null;
061:
062: private final PropriedadesController propriedadesController = new PropriedadesController();
063:
064: /**
065: * Constrrói uma instancia desta classe que irá monitorar as aplicações e resgates
066: */
067: public PreverMovimentoAplicacao() {
068: getAplicacao();
069: getResgate();
070: }
071:
072: /**
073: * Código do tipo de conta referente a aplicações financeiras
074: * @return Integer
075: */
076: private String getTipoContaAplicacao() {
077: if (tipoContaAplicacao == null)
078: try {
079: tipoContaAplicacao = new AccountTypeDAO().getBy(
080: new AccountType("aplicacao")).getId()
081: .toString();
082: } catch (Exception e) {
083: tipoContaAplicacao = "-1";
084: }
085: return tipoContaAplicacao;
086: }
087:
088: /**
089: * Código do tipo de lançamento que representa uma aplicação
090: * @return Integer
091: */
092: private Integer getAplicacao() {
093: if (aplicacao.intValue() == -1)
094: try {
095: aplicacao = new TransactionTypeDAO().getBy(
096: new TransactionType(TipoDeLancamentosMessages
097: .getMessages().getString("Aplicacao")))
098: .getId();
099: } catch (Exception e) {
100: aplicacao = Integer.valueOf("-1");
101: }
102: return aplicacao;
103: }
104:
105: /**
106: * Código do tipo de lançamento que representa um resgate
107: * @return Integer
108: */
109: private Integer getResgate() {
110: if (resgate.intValue() == -1)
111: try {
112: resgate = new TransactionTypeDAO().getBy(
113: new TransactionType(TipoDeLancamentosMessages
114: .getMessages().getString("Resgate")))
115: .getId();
116: } catch (Exception e) {
117: resgate = Integer.valueOf("-1");
118: }
119: return resgate;
120: }
121:
122: /**
123: *
124: * @param conta Account cuje o movimento será previsto
125: * @param tempoPraDormir Tempo que a thread vai esperar antes de começar o processamento
126: */
127: private void preverMovimentoAplicacao(final Integer conta,
128: final int tempoPraDormir) {
129: (new Thread() {
130: {
131: setPriority(Thread.MIN_PRIORITY);
132: setName("PreverMovimentoAplicacao");
133: }
134:
135: @Override
136: public void run() {
137: try {
138: sleep(1 + tempoPraDormir * 100);
139:
140: TransactionDAO<Transaction> lancamentoController = new TransactionDAO<Transaction>();
141:
142: //Até quando vamos fazer previsões
143: Calendar dataMaxina = Calendar.getInstance();
144:
145: //Montamos a condição que restringe nossa busca aos últimos 12 meses
146: Calendar inicio = Calendar.getInstance();
147: Calendar fim = Calendar.getInstance();
148:
149: inicio.add(Calendar.MONTH, -12);
150: inicio.set(Calendar.DAY_OF_MONTH, 1);
151: fim.add(Calendar.MONTH, 1);
152: fim.set(Calendar.DAY_OF_MONTH, 0);
153:
154: SQLCondition<Date> condicao = new SQLCondition<Date>(
155: "Dia", new java.sql.Date(inicio.getTime()
156: .getTime()), new java.sql.Date(fim
157: .getTime().getTime()),
158: Condicao.BETWEEN);
159: Transaction transaction = new Transaction();
160: transaction.addCondicaoExtra(condicao);
161: transaction.setConta(conta);
162: transaction.setTipoConta(getTipoContaAplicacao());
163:
164: //Agora vamos pegar a média das aplicações
165: transaction.setTipo(getAplicacao());
166: ProjecaoFinanceira projecaoAplicacao = lancamentoController
167: .calculaMediana(transaction, 12);
168:
169: //Agora pegamos a média dos resgates
170: transaction.setTipo(getResgate());
171: ProjecaoFinanceira projecaoResgate = lancamentoController
172: .calculaMediana(transaction, 12);
173:
174: //System.out.println(projecaoAplicacao + "\n" + projecaoResgate);
175: if (((int) (projecaoAplicacao.getValor() + projecaoResgate
176: .getValor())) == 0)
177: return;
178:
179: //Esta é nossa previão
180: Double valor = projecaoAplicacao.getValor()
181: + projecaoResgate.getValor();
182: ProjecaoFinanceira projecao = valor.doubleValue() > 0 ? projecaoAplicacao
183: : projecaoResgate;
184: projecao.setValor(valor.doubleValue());
185: //TODO Remvoer log de projeção
186: ((SimpleLog) GFPController.getGFPController()
187: .getContexto().get(GFPController.LOG))
188: .log(projecao.toString());
189: //Descobrimos até quando vamos fazer previões
190: ConfigPrevisao configPrevisao = (ConfigPrevisao) Propriedades
191: .loadPropiedades(ConfigPrevisao.class);
192: try {
193: propriedadesController.getBy(configPrevisao
194: .getPersistentObject());
195: } catch (SQLException e2) {
196: //Não fazemos nada
197: }
198: dataMaxina.setTime(configPrevisao
199: .getPreverAteQueAno());
200:
201: transaction.setIncluirSubtipos(false);
202: //Calculamos o dia em que devemos fazer as previsões deste lancamento
203: int diaLancamento = lancamentoController
204: .getDiaComumParaLancamento(transaction);
205: //Montamos o tipo de lancamento que queremos alterar...
206: Calendar dia = Calendar.getInstance();
207: dia.set(Calendar.DATE, diaLancamento);
208:
209: transaction = new Transaction();
210: transaction.setConta(conta);
211: transaction.setTipoConta(getTipoContaAplicacao());
212: transaction.setEhDeSistema(true);
213: transaction.setEhPrevisao(true);
214:
215: //deletamos os antigos
216: deletarPrevisoes(conta);
217:
218: transaction.setValor(valor);
219: if (valor < 0)
220: transaction.setTipo(getResgate());
221: else
222: transaction.setTipo(getAplicacao());
223:
224: // ...e realizamos as novas previsões mes a mês
225: Transaction filtro = new Transaction();
226: filtro.setConta(conta);
227: filtro.setTipoConta(getTipoContaAplicacao());
228: filtro.setIncluirSubtipos(true);
229: boolean ehResgate = transaction.getTipo().equals(
230: getResgate());
231: while (dia.get(Calendar.YEAR) != dataMaxina
232: .get(Calendar.YEAR)
233: || dia.get(Calendar.MONTH) != dataMaxina
234: .get(Calendar.MONTH)) {
235: //Se a previsão futura for de resgates, então vamos ver a cada lançamento se já não atingimos o saldo zero (0).
236: if (ehResgate) {
237: condicao = new SQLCondition<Date>("Dia",
238: new java.sql.Date(dia.getTime()
239: .getTime()),
240: Condicao.MENOR_IGUAL);
241: filtro.addCondicaoExtra(condicao);
242: double saldo = lancamentoController
243: .getTotalNoPeriodo(filtro);
244: if (saldo < 0) {
245: return;
246: } else if (saldo < valor) {
247: transaction.setValor(saldo);
248: }
249: filtro.removeCondicaoExtra(condicao);
250: }
251: dia.add(Calendar.MONTH, 1);
252: transaction.setDia(dia.getTime());
253:
254: if ((projecao.getValor() < 0 && transaction
255: .getValor() < -1d)
256: || projecao.getValor() > 0
257: && transaction.getValor() > 1d) {
258: lancamentoController
259: .adicionarNovo(transaction);
260: }
261:
262: if ((projecao.getTendencia() == ProjecaoFinanceira.ALTA && projecao
263: .getValor() > 0)
264: || (projecao.getTendencia() == ProjecaoFinanceira.QUEDA && projecao
265: .getValor() < 0)) {
266: if (dia.get(Calendar.MONTH) % 2 != 0) {
267: transaction.setValor(transaction
268: .getValor()
269: + transaction.getValor()
270: * projecao.getVariacao());
271: } else {
272: transaction
273: .setValor(transaction
274: .getValor()
275: - (transaction
276: .getValor()
277: * projecao
278: .getVariacao() * 1.2));
279: }
280: } else if ((projecao.getTendencia() == ProjecaoFinanceira.QUEDA && projecao
281: .getValor() > 0)
282: || (projecao.getTendencia() == ProjecaoFinanceira.ALTA && projecao
283: .getValor() < 0)) {
284: if (dia.get(Calendar.MONTH) % 2 != 0) {
285: transaction
286: .setValor(transaction
287: .getValor()
288: - (transaction
289: .getValor() * projecao
290: .getVariacao()));
291: } else {
292: transaction.setValor(transaction
293: .getValor()
294: + transaction.getValor()
295: * projecao.getVariacao() * 1.2);
296: }
297: }
298: }
299: } catch (SQLException sqle) {
300: sqle.printStackTrace();
301: } catch (InterruptedException e) {
302: e.printStackTrace();
303: }
304: }
305: }).start();
306: }
307:
308: /**
309: * Deleta as previcões para a aplicação especificada pelo ID de conta passado
310: * @param conta Id da conta de aplicação
311: * @throws SQLException
312: */
313: private void deletarPrevisoes(Integer conta) throws SQLException {
314: Transaction transaction = new Transaction();
315: transaction.setConta(conta);
316: transaction.setTipoConta(getTipoContaAplicacao());
317: transaction.setEhDeSistema(Boolean.valueOf(true));
318: transaction.setEhPrevisao(Boolean.valueOf(true));
319:
320: //deletamos os antigos
321: TransactionDAO<Transaction> lancamentoController = new TransactionDAO<Transaction>();
322: lancamentoController.setCheckIntegridade(false);
323: lancamentoController.deletar(transaction);
324: lancamentoController.setCheckIntegridade(true);
325: }
326:
327: /**
328: * @see br.com.gfpshare.db.DAOListener#adicionadoNovo(br.com.gfpshare.db.DAOEvent)
329: */
330: public void adicionadoNovo(DAOEvent<Transaction> e) {
331: verSeVaiPreverMovimento(e);
332: }
333:
334: /**
335: * @see br.com.gfpshare.db.DAOListener#atualizado(br.com.gfpshare.db.DAOEvent)
336: */
337: public void atualizado(DAOEvent<Transaction> e) {
338: verSeVaiPreverMovimento(e);
339: }
340:
341: /**
342: * @see br.com.gfpshare.db.DAOListener#deletado(br.com.gfpshare.db.DAOEvent)
343: */
344: public void deletado(DAOEvent<Transaction> e) {
345: verSeVaiPreverMovimento(e);
346: }
347:
348: /**
349: * @see br.com.gfpshare.db.DAOListener#selecionado(br.com.gfpshare.db.DAOEvent)
350: */
351: public void selecionado(DAOEvent<Transaction> e) {
352: // Este evento não nos interessa
353: }
354:
355: /**
356: * @see br.com.gfpshare.db.DAOListener#filtrado(br.com.gfpshare.db.DAOEvent)
357: */
358: public void filtrado(DAOEvent<Transaction> e) {
359: // Este evento não nos interessa
360: }
361:
362: /**
363: * Verificamos se o evento gerado realmente dispara uma previsão de movimento futuro de contas de aplicação
364: * @param e
365: */
366: private void verSeVaiPreverMovimento(DAOEvent<Transaction> e) {
367: if ((e.getPersistentObject().getEhPrevisao() == null || !e
368: .getPersistentObject().getEhPrevisao())
369: && (e.getPersistentObject().getEhDeSistema() == null || !e
370: .getPersistentObject().getEhDeSistema())) {
371: Integer tipo = e.getPersistentObject().getTipo();
372: if (tipo != null
373: && (tipo.equals(getAplicacao()) || tipo
374: .equals(getResgate()))) {
375: //Aqui veremos se o GFP esta configurado para realizar previsões
376: ConfigPrevisao configPrevisao = (ConfigPrevisao) Propriedades
377: .loadPropiedades(ConfigPrevisao.class);
378: try {
379: propriedadesController.getBy(configPrevisao
380: .getPersistentObject());
381: } catch (SQLException e2) {
382: //Não fazemos nada
383: }
384: if (!configPrevisao.getRealizarPrevisoes()
385: || !configPrevisao.getPreverRendimentos()) {
386: try {
387: deletarPrevisoes(e.getPersistentObject()
388: .getConta());
389: } catch (SQLException e1) {
390: ((SimpleLog) GFPController.getGFPController()
391: .getContexto().get(GFPController.LOG))
392: .log("Erro ao remover previões de lançamentos para aplicação "
393: + e.getPersistentObject());
394: ((SimpleLog) GFPController.getGFPController()
395: .getContexto().get(GFPController.LOG))
396: .log(e1.getLocalizedMessage());
397: ((SimpleLog) GFPController.getGFPController()
398: .getContexto().get(GFPController.LOG))
399: .log(e1);
400: }
401: return;
402: }
403:
404: preverMovimentoAplicacao(e.getPersistentObject()
405: .getConta(), e.getPersistentObject()
406: .getVezesPraRealizar());
407: }
408: }
409: }
410: }
|