001: /*
002: * Created on 03/06/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.Date;
026: import java.sql.ResultSet;
027: import java.sql.SQLException;
028: import java.util.Arrays;
029: import java.util.Calendar;
030:
031: import javax.swing.event.EventListenerList;
032:
033: import br.com.gfp.data.AccountSaving;
034: import br.com.gfp.data.IncomePrediction;
035: import br.com.gfpshare.db.AbstractDAO;
036: import br.com.gfpshare.db.SQLCondition;
037: import br.com.gfpshare.db.SQLParser;
038: import br.com.gfpshare.db.SQLCondition.Condicao;
039:
040: /**
041: * @author Igor Regis da Silva Simoes
042: */
043: public class IncomePredictionDAO extends AbstractDAO<IncomePrediction> {
044: public IncomePredictionDAO() {
045: //------------------------------------------------
046: }
047:
048: /**
049: * Seta uma nova data para uma previsão, considernado o proximo periodo de rendimento
050: * @param previsao
051: *
052: */
053: private synchronized void setNovaData(IncomePrediction previsao) {
054: Calendar data = Calendar.getInstance();
055: data.setTime(previsao.getDataRendimento());
056:
057: switch (previsao.getTipoRendimento()) {
058: case 1:
059: data.add(Calendar.DAY_OF_MONTH, 1);
060: break;
061: case 2:
062: data.add(Calendar.MONTH, 1);
063: break;
064: case 3:
065: data.add(Calendar.YEAR, 1);
066: break;
067: }
068:
069: if (data.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)
070: data.add(Calendar.DATE, 1);
071: else if (data.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY)
072: data.add(Calendar.DATE, 2);
073:
074: //Estipulamos a data do próximo lançamento
075: previsao.setDataRendimento(data.getTime());
076: }
077:
078: /**
079: * Este método recebe como parâmetro o numero de repetições que ele terá que fazer do laçamentos
080: * @param novoRegistro registro a ser adicionado
081: * @return Retorna true se todos os dados forem inseridos com sucesso
082: * @throws SQLException Caso ocorra algum erro irrecuparável na inserção dos dados
083: *
084: * @see br.com.gfpshare.db.AbstractDAO#adicionarNovo(br.com.gfpshare.db.PersistentObject)
085: */
086: @Override
087: public synchronized boolean adicionarNovo(
088: IncomePrediction novoRegistro) throws SQLException {
089: //Lancamento a ser realizado
090: IncomePrediction incomePrediction = novoRegistro;
091:
092: Float valor = incomePrediction.getValorRendimento();
093:
094: if (incomePrediction.getTipoRendimento() == AccountSaving.MENSAL
095: || incomePrediction.getTipoRendimento() == AccountSaving.ANUAL) {
096: Calendar dia = Calendar.getInstance();
097: dia.setTime(incomePrediction.getDataRendimento());
098: dia.set(Calendar.DATE, 1);
099: incomePrediction.setDataRendimento(dia.getTime());
100: }
101:
102: atualizaPrevisao(incomePrediction);
103:
104: //Vamos repetir o lançamento conforme solicitado
105: for (int i = 0; i < incomePrediction.getVezesPraRealizar(); i++) {
106:
107: setNovaData(incomePrediction);
108: incomePrediction.setValorRendimento(valor);
109: atualizaPrevisao(incomePrediction);
110: }
111: return true;
112: }
113:
114: /**
115: * Tenta adicionar a previsão e se não der cero assume que ela já existe então tenta atualiza-la
116: * se ocorrer erro mesmo assim, será entãolançada uma SQLException
117: * @param previsao
118: * @throws SQLException
119: */
120: private synchronized void atualizaPrevisao(IncomePrediction previsao)
121: throws SQLException {
122: try {
123: //Tentamos adicionar o novo lançamento
124: super .adicionarNovo(previsao);
125: } catch (SQLException sqle) {
126: try {
127: //se já existe uma lancamento com essas características então atualizamos seus valores
128: super .atualizar(previsao);
129: } catch (SQLException sqle2) {
130: sqle2.printStackTrace();
131: throw sqle2;
132: }
133:
134: }
135: }
136:
137: /**
138: * Este método recebe como parâmetro o numero de repetições que ele terá que fazer do laçamento
139: *
140: * @see br.com.gfpshare.db.AbstractDAO#atualizar(br.com.gfpshare.db.PersistentObject)
141: */
142: @Override
143: public boolean atualizar(IncomePrediction atualizacao)
144: throws SQLException {
145: return adicionarNovo(atualizacao);
146: }
147:
148: /**
149: * Lista de listeners de eventos do controller
150: */
151: private static final EventListenerList listeners = new EventListenerList();
152:
153: /**
154: * @see br.com.gfpshare.db.AbstractDAO#getListeners()
155: */
156: @Override
157: protected EventListenerList getListeners() {
158: return listeners;
159: }
160:
161: /**
162: * Retorna o valor total dos lançamentos em um do período.
163: * Através desse cálculo podemos chegar ao saldo atual da conta.
164: * Por exemplo:
165: * Somando-se o total de lancamentos de uma conta desde a data de sua abertura até
166: * a dia atual teremos o saldo atual desta conta.
167: * @param argunento Lancamento que pode restringir até que data queremos que a soma seja feita
168: * @return Valor indicando o total calculado
169: * @throws SQLException
170: */
171: public synchronized double getMediaNoPeriodo(
172: IncomePrediction argunento) throws SQLException {
173: argunento.setResultadoDesejado("sum("
174: + SQLParser.ENVOLVE_COLUNA + "ValorRendimento"
175: + SQLParser.ENVOLVE_COLUNA + ")");
176: ResultSet rs = null;
177: double total = 0;
178: double media = 0;
179: try {
180: rs = filterBy(rs, argunento);
181: argunento.setResultadoDesejado(null);
182: rs.first();
183: total = rs.getDouble(1);
184: } catch (SQLException e) {
185: e.printStackTrace();
186: throw e;
187: } finally {
188: //freeResource(rs);
189: }
190:
191: argunento.setResultadoDesejado("count("
192: + SQLParser.ENVOLVE_COLUNA + "ValorRendimento"
193: + SQLParser.ENVOLVE_COLUNA + ")");
194: try {
195: rs = filterBy(rs, argunento);
196: argunento.setResultadoDesejado(null);
197: rs.first();
198: media = total / rs.getDouble(1);
199: } catch (SQLException e) {
200: e.printStackTrace();
201: throw e;
202: } finally {
203: //freeResource(rs);
204: }
205:
206: return media;
207: }
208:
209: /**
210: * Calcula a mediana dos lancamentos do tipo solicitado insidentes nos ultimos N meses
211: * onde N é igual ao segunto parametro deste método
212: * @param lancamentoOriginal LAncamento com as definições do tipo de lancamento a ter a mediana calculada
213: * @param meses Numero de meses retroativos a serem considerados no calculo
214: * @return Meidana
215: * @throws NumberFormatException
216: * @throws SQLException
217: */
218: public synchronized Double calculaMediana(
219: IncomePrediction lancamentoOriginal, int meses)
220: throws NumberFormatException, SQLException {
221: //Os totais de lancamento de determinado tipo mes a mes
222: double lancamentosMensais[] = new double[12];
223:
224: //Montamos a condição que restringe nossa busca aos últimos 12 meses
225: Calendar inicio = Calendar.getInstance();
226: Calendar fim = Calendar.getInstance();
227:
228: IncomePrediction incomePrediction = new IncomePrediction();
229: for (int i = -1; i >= -1 * meses; i--) {
230: inicio.add(Calendar.MONTH, -1);
231: inicio.set(Calendar.DAY_OF_MONTH, 1);
232: fim.setTimeInMillis(inicio.getTimeInMillis());
233: fim.add(Calendar.MONTH, +1);
234: fim.set(Calendar.DAY_OF_MONTH, 0);
235:
236: SQLCondition<Date> condicaoExtra = new SQLCondition<java.sql.Date>(
237: "DataRendimento", new java.sql.Date(inicio
238: .getTime().getTime()), new java.sql.Date(
239: fim.getTime().getTime()), Condicao.BETWEEN);
240: incomePrediction.addCondicaoExtra(condicaoExtra);
241: incomePrediction.setId(lancamentoOriginal.getId());
242: incomePrediction.setTipoConta(lancamentoOriginal
243: .getTipoConta());
244:
245: //Agora vamos pegar a soma dos lancamentos desse tipo para este mes
246: lancamentosMensais[(i + 1) * -1] = getMediaNoPeriodo(incomePrediction);
247: //Pra quem quiser ver os valores que foram capturados por periodo:
248: //System.out.println("Mes " + new java.sql.Date(inicio.getTime().getTime()) + " a " + new java.sql.Date(fim.getTime().getTime()) + " = " +lancamentosMensais[(i+1)*-1]);
249: incomePrediction.removeCondicaoExtra(condicaoExtra);
250: }
251:
252: Arrays.sort(lancamentosMensais);
253: return Double
254: .valueOf(""
255: + (lancamentosMensais.length % 2 == 0 ? (lancamentosMensais[lancamentosMensais.length / 2] + lancamentosMensais[lancamentosMensais.length / 2 - 1]) / 2
256: : lancamentosMensais[lancamentosMensais.length] / 2));
257: }
258: }
|