001: /*
002: * Created on 15/02/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:
023: package br.com.gfp.dao;
024:
025: import java.sql.ResultSet;
026: import java.sql.SQLException;
027: import java.util.ArrayList;
028: import java.util.Arrays;
029: import java.util.Calendar;
030:
031: import javax.swing.event.EventListenerList;
032:
033: import br.com.gfp.data.ProjecaoFinanceira;
034: import br.com.gfp.data.Transaction;
035: import br.com.gfp.util.SimpleLog;
036: import br.com.gfpshare.db.AbstractDAO;
037: import br.com.gfpshare.db.DataBaseManager;
038: import br.com.gfpshare.db.SQLCondition;
039: import br.com.gfpshare.db.SQLParser;
040: import br.com.gfpshare.db.SQLCondition.Condicao;
041:
042: /**
043: * Controler para os lançamentos
044: * A idéia é que esta classe realize a formulação de relatórios.
045: * @author Igor Regis da Silva Simoes
046: * @param <A> Este controller ira trabalhar apenas com tipo de dados subclasses de Lancamento
047: */
048: @SuppressWarnings("unchecked")
049: public class TransactionDAO<A extends Transaction> extends
050: AbstractDAO<A> {
051: /**
052: * Cada operação de lançamento passa por uma verificação para garantir que
053: * a operação é valida (adição, alteração e remoção) quando esta propriedade
054: * está em false, essa verificação não é realizada
055: */
056: boolean checkIntegridade = true;
057:
058: /**
059: * Lista de listeners de eventos do controller
060: */
061: private static final EventListenerList listeners = new EventListenerList();
062:
063: public TransactionDAO() {
064: //------------------------------------------------
065: }
066:
067: /**
068: * @see br.com.gfpshare.db.AbstractDAO#getListeners()
069: */
070: @Override
071: protected EventListenerList getListeners() {
072: return listeners;
073: }
074:
075: /**
076: * Este método recebe como parâmetro o numero de repetições que ele terá que fazer do laçamentos
077: * @see br.com.gfpshare.db.AbstractDAO#adicionarNovo(br.com.gfpshare.db.PersistentObject)
078: */
079: @Override
080: public boolean adicionarNovo(A novoRegistro) throws SQLException {
081: //Lancamento a ser realizado
082: Transaction transaction = novoRegistro;
083:
084: boolean sucesso = false;
085:
086: sucesso = super .adicionarNovo(novoRegistro);
087:
088: Calendar dia = Calendar.getInstance();
089: for (int i = 0; i < transaction.getVezesPraRealizar(); i++) {
090: dia.setTime(transaction.getDia());
091:
092: switch (transaction.getTipoIntervaloRepeticao().intValue()) {
093: case Transaction.DIAS:
094: dia.add(Calendar.DAY_OF_MONTH, transaction
095: .getIntervaloRepeticao().intValue());
096: break;
097: case Transaction.SEMANDAS:
098: dia.add(Calendar.WEEK_OF_MONTH, transaction
099: .getIntervaloRepeticao().intValue());
100: break;
101: case Transaction.MESES:
102: dia.add(Calendar.MONTH, transaction
103: .getIntervaloRepeticao().intValue());
104: break;
105: case Transaction.ANOS:
106: dia.add(Calendar.YEAR, transaction
107: .getIntervaloRepeticao().intValue());
108: break;
109: }
110: transaction.setDia(dia.getTime());
111:
112: try {
113: boolean retorno = super .adicionarNovo((A) transaction);
114: sucesso = sucesso == true ? sucesso && retorno
115: : sucesso;
116: } catch (SQLException e1) {
117: ((SimpleLog) GFPController.getGFPController()
118: .getContexto().get(GFPController.LOG))
119: .log("Erro ao adicionar novo lancamento: "
120: + transaction);
121: ((SimpleLog) GFPController.getGFPController()
122: .getContexto().get(GFPController.LOG)).log(e1
123: .getLocalizedMessage());
124: ((SimpleLog) GFPController.getGFPController()
125: .getContexto().get(GFPController.LOG)).log(e1);
126: }
127: }
128: return sucesso;
129: }
130:
131: /**
132: * Realizamos a sobrecarga deste método para impedir a alteração de lançamentos que sejam de sistema. <br>
133: *
134: * @see br.com.gfpshare.db.AbstractDAO#atualizar(br.com.gfpshare.db.PersistentObject)
135: */
136: @Override
137: public boolean atualizar(A atualizacao) throws SQLException {
138: if (checkIntegridade && atualizacao.getEhDeSistema() != null
139: && atualizacao.getEhDeSistema().booleanValue())
140: throw new SQLException(
141: "Este tipo de lançamento não pode ser modificado.",
142: "", -9645);
143: return super .atualizar(atualizacao);
144: }
145:
146: /**
147: * Realizamos a sobrecarga deste método para impedir a deleção de lançamentos que sejam de sistema. <br>
148: *
149: * @see br.com.gfpshare.db.DAO#deletar(br.com.gfpshare.db.PersistentObject)
150: */
151: @Override
152: public boolean deletar(A aSerDeletado) throws SQLException {
153: if (checkIntegridade && aSerDeletado.getEhDeSistema() != null
154: && aSerDeletado.getEhDeSistema().booleanValue())
155: throw new SQLException(
156: "Este tipo de lançamento não pode ser deletado.",
157: "", -9645);
158: return super .deletar(aSerDeletado);
159: }
160:
161: /**
162: * Fazemos o a sobrecarga deste método pra podermos adicionar a fiuncionalidade de um filtro recursivo no que
163: * se refere ao tipo do lançamento.<br>
164: * Por exemplo:<br>
165: * Ao selecionarmos o tipo de laçamento Despesas pegaremos também todos seus subtipos<br><br>
166: *
167: * @see br.com.gfpshare.db.AbstractDAO#filterBy(java.sql.ResultSet, br.com.gfpshare.db.PersistentObject)
168: */
169: @Override
170: public synchronized ResultSet filterBy(ResultSet old, A argumento)
171: throws SQLException {
172: try {
173: if (argumento.isIncluirSubtipos()) {
174: Integer tipo = argumento.getTipo();
175: if (tipo != null) {
176: String sql = "select ST2.*";
177: boolean incluirOrderBy = true;
178: if (argumento.getResultadoDesejado() != null) {
179: incluirOrderBy = false;
180: sql = "select "
181: + argumento.getResultadoDesejado();
182: }
183: sql = sql + getFromSQLFiltroPorTipo(tipo);
184: argumento.setTipo(null);
185: if (old != null)
186: DataBaseManager.getDataBaseManager()
187: .fecharConexao(old);
188: old = executarSQL(argumento, sql, true,
189: incluirOrderBy);
190: argumento.setTipo(tipo);
191: } else {
192: old = super .filterBy(old, argumento);
193: }
194: } else {
195: old = super .filterBy(old, argumento);
196: }
197: return old;
198: } catch (SQLException e) {
199: e.printStackTrace();
200: throw e;
201: }
202: }
203:
204: /**
205: * Este sql pega todos os lançamentos de um tipo e de seus subtipos
206: *
207: * select ST2.* from (select distinct t3."Id" from (select * from "TipoLancamento" where "SuperTipo" = 0 or "Id" = 0) t1
208: * join "TipoLancamento" t2 on t2."SuperTipo" = t1."Id" or t1."Id" = t2."Id"
209: * join "TipoLancamento" t3 on t3."SuperTipo" = t2."Id" or t2."Id" = t3."Id") ST1 join "Lancamento" ST2 on ST2."Tipo" = ST1."Id"
210: *
211: * @param tipo Tipo do lancamento
212: * @return SQL
213: */
214: private String getFromSQLFiltroPorTipo(Integer tipo) {
215: return " from " + "(select distinct t3."
216: + SQLParser.ENVOLVE_COLUNA + "Id"
217: + SQLParser.ENVOLVE_COLUNA + " from "
218: + "(select * from " + SQLParser.ENVOLVE_NOME_TABELA
219: + "TipoLancamento" + SQLParser.ENVOLVE_NOME_TABELA
220: + " where " + SQLParser.ENVOLVE_COLUNA + "SuperTipo"
221: + SQLParser.ENVOLVE_COLUNA + " = " + tipo + " or "
222: + SQLParser.ENVOLVE_COLUNA + "Id"
223: + SQLParser.ENVOLVE_COLUNA + " = " + tipo + ") t1 "
224: + " join " + SQLParser.ENVOLVE_NOME_TABELA
225: + "TipoLancamento" + SQLParser.ENVOLVE_NOME_TABELA
226: + " t2 " + " on t2." + SQLParser.ENVOLVE_COLUNA
227: + "SuperTipo" + SQLParser.ENVOLVE_COLUNA + " = t1."
228: + SQLParser.ENVOLVE_COLUNA + "Id"
229: + SQLParser.ENVOLVE_COLUNA + " or t1."
230: + SQLParser.ENVOLVE_COLUNA + "Id"
231: + SQLParser.ENVOLVE_COLUNA + " = t2."
232: + SQLParser.ENVOLVE_COLUNA + "Id"
233: + SQLParser.ENVOLVE_COLUNA + " join "
234: + SQLParser.ENVOLVE_NOME_TABELA + "TipoLancamento"
235: + SQLParser.ENVOLVE_NOME_TABELA + " t3 " + " on t3."
236: + SQLParser.ENVOLVE_COLUNA + "SuperTipo"
237: + SQLParser.ENVOLVE_COLUNA + " = t2."
238: + SQLParser.ENVOLVE_COLUNA + "Id"
239: + SQLParser.ENVOLVE_COLUNA + " or t2."
240: + SQLParser.ENVOLVE_COLUNA + "Id"
241: + SQLParser.ENVOLVE_COLUNA + " = t3."
242: + SQLParser.ENVOLVE_COLUNA + "Id"
243: + SQLParser.ENVOLVE_COLUNA + ") ST1" + " join "
244: + SQLParser.ENVOLVE_NOME_TABELA + "Lancamento"
245: + SQLParser.ENVOLVE_NOME_TABELA + " ST2 " + " on ST2."
246: + SQLParser.ENVOLVE_COLUNA + "Tipo"
247: + SQLParser.ENVOLVE_COLUNA + " = ST1."
248: + SQLParser.ENVOLVE_COLUNA + "Id"
249: + SQLParser.ENVOLVE_COLUNA + " ";
250: }
251:
252: /**
253: * Retorna o valor total dos lançamentos em um do período.
254: * Através desse cálculo podemos chegar ao saldo atual da conta.
255: * Por exemplo:
256: * Somando-se o total de lancamentos de uma conta desde a data de sua abertura até
257: * a dia atual teremos o saldo atual desta conta.
258: * @param argumento Lancamento que pode restringir até que data queremos que a soma seja feita
259: * @return Valor indicando o total calculado
260: * @throws SQLException
261: */
262: public synchronized double getTotalNoPeriodo(A argumento)
263: throws SQLException {
264: argumento.setResultadoDesejado("sum("
265: + SQLParser.ENVOLVE_COLUNA + "Valor"
266: + SQLParser.ENVOLVE_COLUNA + ")");
267:
268: ResultSet rs = null;
269: try {
270: rs = filterBy(rs, argumento);
271: argumento.setResultadoDesejado(null);
272: rs.first();
273: return rs.getDouble(1);
274: } catch (SQLException e) {
275: e.printStackTrace();
276: throw e;
277: } finally {
278: //freeResource(rs);
279: }
280: }
281:
282: /**
283: * Retorna o valor total dos lançamentos em um do período.
284: * Através desse cálculo podemos chegar ao saldo atual da conta.
285: * Por exemplo:
286: * Somando-se o total de lancamentos de uma conta desde a data de sua abertura até
287: * a dia atual teremos o saldo atual desta conta.
288: * Ex.: mesIni = 12 e mesFim = 0
289: * Significa 12 meses atráz até o mes atual
290: * mesIni = 6 e mesFim = 1
291: * Significa 6 meses atráz até o mes anterior
292: * @param argumento Lancamento que pode restringir até que data queremos que a soma seja feita
293: * @param mesIni Quantos meses atraz devem estar no intervalo inicial de pesquisa
294: * @param mesFim Quantos meses atraz devem estar no intervalo final de pesquisa
295: * @return Valor indicando o total calculado
296: * @throws SQLException
297: */
298: public synchronized double getTotalNoPeriodo(A argumento,
299: int mesIni, int mesFim) throws SQLException {
300:
301: Transaction transaction = new Transaction();
302: transaction.setConta(argumento.getConta());
303: transaction.setTipoConta(argumento.getTipoConta());
304: transaction.setTipo(argumento.getTipo());
305:
306: transaction.setResultadoDesejado("sum("
307: + SQLParser.ENVOLVE_COLUNA + "Valor"
308: + SQLParser.ENVOLVE_COLUNA + ")");
309:
310: Calendar inicio = Calendar.getInstance();
311: Calendar fim = Calendar.getInstance();
312:
313: inicio.add(Calendar.MONTH, -1 * mesIni);
314: inicio.set(Calendar.DAY_OF_MONTH, 1);
315: fim.add(Calendar.MONTH, -1 * mesFim + 1);
316: fim.set(Calendar.DAY_OF_MONTH, 0);
317:
318: transaction.addCondicaoExtra(new SQLCondition<java.sql.Date>(
319: "Dia", new java.sql.Date(inicio.getTime().getTime()),
320: new java.sql.Date(fim.getTime().getTime()),
321: Condicao.BETWEEN));
322:
323: ResultSet rs = null;
324: try {
325: rs = filterBy(rs, (A) transaction);
326: rs.first();
327: return rs.getDouble(1);
328: } catch (SQLException e) {
329: e.printStackTrace();
330: throw e;
331: } finally {
332: //argumento.removeCondicaoExtra(condicao);
333: //freeResource(rs);
334: }
335: }
336:
337: /**
338: * Este metodo informa qual dia geralmente inside este tipo de lançamento, ou seja, se é mais comum o pagamento
339: * de contas de luz no dia 10 ou no dia 30 de cada mes.
340: * @param argumento Lancamento que pode restringir até que data queremos que a soma seja feita
341: * @return Valor indicando o total calculado
342: * @throws SQLException
343: */
344: public synchronized int getDiaComumParaLancamento(A argumento)
345: throws SQLException {
346:
347: Transaction transaction = new Transaction();
348: transaction.setConta(argumento.getConta());
349: transaction.setTipoConta(argumento.getTipoConta());
350: transaction.setTipo(argumento.getTipo());
351: transaction.setEhPrevisao(Boolean.FALSE);
352:
353: transaction.setResultadoDesejado("avg(dayofmonth("
354: + SQLParser.ENVOLVE_COLUNA + "Dia"
355: + SQLParser.ENVOLVE_COLUNA + "))");
356:
357: ResultSet rs = null;
358: try {
359: rs = filterBy(rs, (A) transaction);
360: rs.first();
361: return rs.getInt(1);
362: } catch (SQLException e) {
363: e.printStackTrace();
364: throw e;
365: } finally {
366: //argumento.removeCondicaoExtra(condicao);
367: //freeResource(rs);
368: }
369: }
370:
371: /**
372: * Retornamos um ResultSet com o total dos lançamentos para cada tipo de lançamento e seu respectivo subtipo
373: * Ex.:
374: * Se Despesas com Gasolina = 100.00
375: * e Despesas com Mecânico = 300.00
376: * e Despeas com automóvel = 0.0
377: * então Despesas com Automável = 0.00
378: * @param argumento
379: * @return ResultSet
380: * @throws SQLException
381: */
382: public synchronized ResultSet getTotalPorTipo(A argumento)
383: throws SQLException {
384: if (argumento.getTipo() == null)
385: throw new SQLException("O campo tipo não pode estar nulo!");
386:
387: String sql = "select " + SQLParser.ENVOLVE_COLUNA + "Tipo"
388: + SQLParser.ENVOLVE_COLUNA + ", " + "SUM("
389: + SQLParser.ENVOLVE_COLUNA + "Valor"
390: + SQLParser.ENVOLVE_COLUNA + ") "
391: + getFromSQLFiltroPorTipo(argumento.getTipo());
392:
393: argumento.setTipo(null);
394:
395: sql = argumento.getSQL(sql, true, false);
396:
397: sql = sql + " group by " + SQLParser.ENVOLVE_COLUNA + "Tipo"
398: + SQLParser.ENVOLVE_COLUNA;
399:
400: return executarSQL(argumento, sql, false, false);
401: }
402:
403: /**
404: * Cada operação de lançamento passa por uma verificação para garantir que
405: * a operação é valida (adição, alteração e remoção) quando esta propriedade
406: * está em false, essa verificação não é realizada
407: * @return boolean
408: */
409: public boolean isCheckIntegridade() {
410: return checkIntegridade;
411: }
412:
413: /**
414: * Cada operação de lançamento passa por uma verificação para garantir que
415: * a operação é valida (adição, alteração e remoção) quando esta propriedade
416: * está em false, essa verificação não é realizada
417: * @param checkIntegridade Novo valor da propriedade
418: */
419: public void setCheckIntegridade(boolean checkIntegridade) {
420: this .checkIntegridade = checkIntegridade;
421: }
422:
423: /**
424: * Verifica se existem lancamento do tipo especificado no mes atual
425: * @param lancamento
426: * @return boolean
427: */
428: public synchronized boolean existeLancamentoDesseTipoNoMes(
429: A lancamento) {
430: //Montamos a condição que restringe nossa busca aos últimos 12 meses
431: Calendar inicio = Calendar.getInstance();
432: Calendar fim = Calendar.getInstance();
433:
434: inicio.setTime(lancamento.getDia());
435: fim.setTime(lancamento.getDia());
436: fim.add(Calendar.MONTH, 1);
437: fim.set(Calendar.DAY_OF_MONTH, 0);
438:
439: try {
440:
441: Transaction filtro = new Transaction();
442: filtro.setConta(lancamento.getConta());
443: filtro.setTipoConta(lancamento.getTipoConta());
444: filtro.setTipo(lancamento.getTipo());
445:
446: filtro.addCondicaoExtra(new SQLCondition<java.sql.Date>(
447: "Dia",
448: new java.sql.Date(inicio.getTime().getTime()),
449: new java.sql.Date(fim.getTime().getTime()),
450: Condicao.BETWEEN));
451: getBy((A) filtro);
452: } catch (SQLException sqle) {
453: return false;
454: }
455: return true;
456: }
457:
458: /**
459: * Calcula a mediana dos lancamentos do tipo solicitado insidentes nos ultimos N meses
460: * onde N é igual ao segunto parametro deste método
461: * @param lancamentoOriginal LAncamento com as definições do tipo de lancamento a ter a mediana calculada
462: * @param meses Numero de meses retroativos a serem considerados no calculo
463: * @return Meidana
464: * @throws NumberFormatException
465: * @throws SQLException
466: * @throws InterruptedException
467: */
468: public synchronized ProjecaoFinanceira calculaMediana(
469: A lancamentoOriginal, int meses)
470: throws NumberFormatException, SQLException,
471: InterruptedException {
472: //Os totais de lancamento de determinado tipo mes a mes
473: double lancamentosMensais[] = new double[12];
474:
475: Transaction lancamento = new Transaction();
476: for (int i = -1; i >= -1 * meses; i--) {
477: if (Thread.interrupted())
478: throw new InterruptedException();
479: lancamento.setConta(lancamentoOriginal.getConta());
480: lancamento.setTipoConta(lancamentoOriginal.getTipoConta());
481: lancamento.setTipo(lancamentoOriginal.getTipo());
482: lancamento.setIncluirSubtipos(false);
483:
484: //Agora vamos pegar a soma dos lancamentos desse tipo para este mes
485: lancamentosMensais[(i + 1) * -1] = getTotalNoPeriodo(
486: (A) lancamento, -1 + i * -1, -1 + i * -1);
487: //Pra quem quiser ver os valores que foram capturados por periodo:
488: //TODO Remover
489: // ((SimpleLog)GFPController.getGFPController().getContexto().get(GFPController.LOG)).log("Mes " + (-1+i*-1) + " a " + (-1+i*-1) + " = " +lancamentosMensais[(i+1)*-1]);
490: }
491:
492: //Vamos descartar a primeira sequencia de zeros que aparecer, pois indicam o inicio da
493: //incidencia deste tipo de lancamento
494: int valoresZero = 0;
495: for (int i = lancamentosMensais.length - 1; i >= 0; i--) {
496: if (lancamentosMensais[i] == 0)
497: valoresZero++;
498: else
499: break;
500: }
501:
502: //Agora descartamos os zeros conforme comentado acima
503: double[] resultado = new double[lancamentosMensais.length
504: - valoresZero];
505: for (int i = 0; i < resultado.length; i++) {
506: resultado[i] = lancamentosMensais[i];
507: }
508:
509: //Agora vamos verificar se a tendencia é de queda, alta ou estável
510: int crescente = 0, decescente = 0;
511: ArrayList<Double> quantoCresce = new ArrayList<Double>();
512: ArrayList<Double> quantoDecresce = new ArrayList<Double>();
513:
514: for (int i = resultado.length - 1, j = resultado.length - 2; i >= 0
515: && j >= 0; i--, j--) {
516: if (resultado[i] < resultado[j] && resultado[j] != 0) {
517: crescente++;
518: quantoCresce.add(Double.valueOf(""
519: + (1 - resultado[i] / resultado[j])));
520: } else if (resultado[i] > resultado[j] && resultado[i] != 0) {
521: decescente++;
522: quantoDecresce.add(Double.valueOf(""
523: + (1 - resultado[j] / resultado[i])));
524: }
525: }
526:
527: ProjecaoFinanceira projecao = new ProjecaoFinanceira();
528:
529: double ajuste = 1;
530: if (crescente > decescente) {
531: Object[] temp = quantoCresce.toArray();
532:
533: Arrays.sort(temp);
534: //Vamos ignorar o maior e o menor valor
535: if (temp.length >= 3) {
536: for (int i = 1; i < temp.length - 1; i++) {
537: ajuste += ((Double) temp[i]);
538: }
539: } else {
540: for (int i = 0; i < temp.length; i++) {
541: ajuste += ((Double) temp[i]);
542: }
543: }
544: ajuste /= (quantoCresce.size() + quantoDecresce.size() * 2);
545: projecao.setTendencia(ProjecaoFinanceira.ALTA);
546: } else if (crescente < decescente) {
547: Object[] temp = quantoDecresce.toArray();
548: Arrays.sort(temp);
549: //Vamos ignorar o maior e o menor valor
550: if (temp.length >= 3) {
551: for (int i = 1; i < temp.length - 1; i++) {
552: ajuste += ((Double) temp[i]);
553: }
554: } else {
555: for (int i = 0; i < temp.length; i++) {
556: ajuste += ((Double) temp[i]);
557: }
558: }
559:
560: ajuste /= (quantoDecresce.size() + quantoCresce.size() * 2);
561: projecao.setTendencia(ProjecaoFinanceira.QUEDA);
562: } else {
563: projecao.setTendencia(ProjecaoFinanceira.ESTAVEL);
564: }
565:
566: //Aqui nós ignoramos as variações absurdas, ou seja, superiores a 100%
567: projecao.setVariacao(ajuste > 1 ? ajuste - (int) ajuste
568: : ajuste < -1 ? ajuste - (int) ajuste : ajuste);
569:
570: Arrays.sort(resultado);
571:
572: if (resultado.length < 2) {
573: projecao.setValor(0);
574: projecao.setTendencia(ProjecaoFinanceira.ESTAVEL);
575: } else {
576: projecao
577: .setValor((resultado.length % 2 == 0 ? (resultado[resultado.length / 2] + resultado[resultado.length / 2 - 1]) / 2
578: : (resultado[resultado.length / 2] == 0 ? resultado[resultado.length / 2 - 1]
579: : resultado[resultado.length / 2])));
580: }
581:
582: return projecao;
583: }
584:
585: /**
586: * Calcula a media dos ultimos N meses onde N = ao segundo parametro deste metodo
587: * @param lancamentoOriginal Lancamnto com os parametros para se calcular a média
588: * @param meses Ultimos meses sobre os quais se deseja calcular a média
589: * @return A média dos lancamentos do tipo solicitado incidentes nos ultimos meses
590: * @throws NumberFormatException
591: * @throws SQLException
592: */
593: public synchronized Double calculaMedia(A lancamentoOriginal,
594: int meses) throws NumberFormatException, SQLException {
595: //Os totais de lancamento de determinado tipo mes a mes
596: Transaction transaction = new Transaction();
597: transaction.setConta(lancamentoOriginal.getConta());
598: transaction.setTipoConta(lancamentoOriginal.getTipoConta());
599: transaction.setTipo(lancamentoOriginal.getTipo());
600: transaction.setIncluirSubtipos(false);
601:
602: return Double.valueOf(""
603: + getTotalNoPeriodo((A) transaction, meses, 0) / meses);
604: }
605: }
|