001: /*
002: * Created on 08/08/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: package br.com.gfp.features;
023:
024: import java.sql.SQLException;
025: import java.util.Calendar;
026:
027: import br.com.gfp.dao.AccountTypeDAO;
028: import br.com.gfp.dao.CreditCardDAO;
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.CheckingAccount;
034: import br.com.gfp.data.ConfigPrevisao;
035: import br.com.gfp.data.CreditCard;
036: import br.com.gfp.data.Transaction;
037: import br.com.gfp.data.TransactionType;
038: import br.com.gfp.internationalization.TipoDeLancamentosMessages;
039: import br.com.gfp.util.SimpleLog;
040: import br.com.gfpshare.config.Propriedades;
041: import br.com.gfpshare.controllers.PropriedadesController;
042: import br.com.gfpshare.db.DAOEvent;
043: import br.com.gfpshare.db.DAOListener;
044:
045: /**
046: * Esta classe é responsável por controlar o valor e a previsão de valor da fatura do cartão de crédito.
047: * <br>
048: * Sempre que houver movimentação nas contas de cartaão de crédito, esta classe será notificada
049: * e reagirá, fazendo os recalculos e lançamentos de acordo com o novo cenário
050: * <br>
051: * @author Igor Regis da Silva Simoes
052: */
053: public class CalcularValorFaturaCartao implements
054: DAOListener<Transaction> {
055: private String tipoContaCartaoCredito = null;
056:
057: /**
058: * Usado para consultar as configurações do GFP
059: */
060: private PropriedadesController propriedadesController = new PropriedadesController();
061:
062: /**
063: * Usado para consultar as características do cartão de crédito
064: */
065: private CreditCardDAO creditCardDAO = new CreditCardDAO();
066:
067: /**
068: * Contador de Threads - indica quantas threads já fpra disparadas por esta classe
069: */
070: private int counter = 0;
071:
072: /**
073: * Constrrói uma instancia desta classe que irá monitorar as aplicações e resgates
074: */
075: public CalcularValorFaturaCartao() {
076: //Não fazemos nada
077: }
078:
079: /**
080: * Código do tipo de conta referente a aplicações financeiras
081: * @return Integer
082: */
083: private String getTipoContaCartaoCredito() {
084: if (tipoContaCartaoCredito == null)
085: try {
086: tipoContaCartaoCredito = new AccountTypeDAO().getBy(
087: new AccountType("cartaoCredito")).getId()
088: .toString();
089: } catch (Exception e) {
090: tipoContaCartaoCredito = "-1";
091: }
092: return tipoContaCartaoCredito;
093: }
094:
095: /**
096: *
097: * @param lancamentoOriginal
098: */
099: private void preverMovimento(final Transaction lancamentoOriginal) {
100: (new Thread("PrevendoFaturaCartao" + (counter++)) {
101: {
102: setPriority(Thread.MIN_PRIORITY);
103: }
104:
105: @Override
106: public void run() {
107: //Este algoritmo serve para caso já exista uma thread desta rodando nos a derrubamos para que possamos continuar.
108: Thread[] t = new Thread[Thread.activeCount()];
109: Thread.currentThread().getThreadGroup().enumerate(t);
110: for (int i = 0; i < t.length; i++) {
111: if (t[i] != null
112: && t[i].getName().indexOf(
113: "PrevendoFaturaCartao") != -1
114: && !t[i].getName().equals(
115: Thread.currentThread().getName())
116: && t[i].getName().compareTo(
117: Thread.currentThread().getName()) <= -1) {
118: t[i].interrupt();
119: try {
120: Thread.sleep(100);
121: } catch (InterruptedException e1) {
122: // Não precisamos fazer nada
123: }
124: }
125: }
126:
127: try {
128: TransactionDAO<Transaction> lancamentoController = new TransactionDAO<Transaction>();
129:
130: CreditCard creditCard = new CreditCard(
131: lancamentoOriginal.getConta());
132: creditCard = creditCardDAO.getBy(creditCard);
133: Calendar dia = Calendar.getInstance();
134: Calendar hoje = Calendar.getInstance();
135: dia.set(Calendar.DATE, creditCard
136: .getDataPagamento().intValue());
137:
138: Transaction lancamentoPagamentoCartao = null;
139: //Se este cartão NÃO possui uma conta para débito automático...
140: if (creditCard.getContaDebito() == null)
141: return;//não faremos previsões
142:
143: //Deletamos os antigos lançamentos da conta de débito automatico...
144: lancamentoPagamentoCartao = deletarDebitosAutomaticos(
145: lancamentoController, creditCard);
146:
147: //Montamos o tipo de lancamento que queremos deletar...
148: Transaction transaction = deletarPrevisoesNaContaCartao(
149: lancamentoOriginal, lancamentoController);
150: transaction.setDia(dia.getTime());
151: do {
152: if (Thread.interrupted())
153: return;
154: Thread.yield();
155: Thread.sleep(10);
156: if (hoje.get(Calendar.DAY_OF_MONTH) >= creditCard
157: .getDataPagamento().intValue()
158: && hoje.get(Calendar.MONTH) == dia
159: .get(Calendar.MONTH)
160: && hoje.get(Calendar.YEAR) == dia
161: .get(Calendar.YEAR)) {
162: transaction.setEhPrevisao(Boolean.FALSE);
163: lancamentoPagamentoCartao
164: .setEhPrevisao(Boolean.FALSE);
165: try {//Se o lançamento já existir nós vamos um mes pra frente e
166: //deixamos o lançamento atual intocado (o usuário é que deve atualiza-lo
167: //se necessasio, pois o mesmo não é mais uma previsao
168: if (lancamentoController
169: .getBy(transaction) != null) {
170: dia.add(Calendar.MONTH, 1);
171: transaction
172: .setEhPrevisao(Boolean.TRUE);
173: //Se este cartão possui uma conta para débito automático...
174: if (creditCard.getContaDebito() != null) {
175: lancamentoPagamentoCartao
176: .setEhPrevisao(Boolean.TRUE);
177: }
178: }
179: } catch (SQLException sqle) {
180: //Não fazemos nada
181: }
182: } else {
183: transaction.setEhPrevisao(Boolean.TRUE);
184: lancamentoPagamentoCartao
185: .setEhPrevisao(Boolean.TRUE);
186: }
187: // somamos o valor da fatura
188: Double valor = creditCardDAO
189: .getValorFaturaNoMes(dia
190: .get(Calendar.MONTH), dia
191: .get(Calendar.YEAR),
192: lancamentoOriginal.getConta());
193: fazerPrevisaoDePagamento(lancamentoController,
194: dia, lancamentoPagamentoCartao,
195: transaction, valor);
196:
197: dia.add(Calendar.MONTH, 1);
198:
199: } while (transaction.getValor().intValue() != 0);
200: } catch (SQLException sqle) {
201: sqle.printStackTrace();
202: } catch (InterruptedException e) {
203: return;
204: }
205: }
206: }).start();
207: }
208:
209: /**
210: * @see br.com.gfpshare.db.DAOListener#adicionadoNovo(br.com.gfpshare.db.DAOEvent)
211: */
212: public void adicionadoNovo(DAOEvent<Transaction> e) {
213: verSeVaiPreverMovimento(e);
214: }
215:
216: /**
217: * @see br.com.gfpshare.db.DAOListener#atualizado(br.com.gfpshare.db.DAOEvent)
218: */
219: public void atualizado(DAOEvent<Transaction> e) {
220: verSeVaiPreverMovimento(e);
221: }
222:
223: /**
224: * @see br.com.gfpshare.db.DAOListener#deletado(br.com.gfpshare.db.DAOEvent)
225: */
226: public void deletado(DAOEvent<Transaction> e) {
227: verSeVaiPreverMovimento(e);
228: }
229:
230: /**
231: * @see br.com.gfpshare.db.DAOListener#selecionado(br.com.gfpshare.db.DAOEvent)
232: */
233: public void selecionado(DAOEvent<Transaction> e) {
234: // Este evento não nos interessa
235: }
236:
237: /**
238: * @see br.com.gfpshare.db.DAOListener#filtrado(br.com.gfpshare.db.DAOEvent)
239: */
240: public void filtrado(DAOEvent<Transaction> e) {
241: // Este evento não nos interessa
242: }
243:
244: /**
245: * Verificamos se o evento gerado realmente dispara uma previsão de movimento futuro de contas de aplicação
246: * @param e
247: */
248: private void verSeVaiPreverMovimento(DAOEvent<Transaction> e) {
249: if ((e.getPersistentObject().getEhPrevisao() == null || !e
250: .getPersistentObject().getEhPrevisao().booleanValue())
251: && (e.getPersistentObject().getEhDeSistema() == null || !e
252: .getPersistentObject().getEhDeSistema()
253: .booleanValue())) {
254: Integer tipo = e.getPersistentObject().getTipo();
255: String tipoConta = e.getPersistentObject().getTipoConta();
256: if (tipo != null
257: && tipoConta.equals(getTipoContaCartaoCredito())) {
258: //Aqui veremos se o GFP esta configurado para realizar previsões
259: ConfigPrevisao configPrevisao = (ConfigPrevisao) Propriedades
260: .loadPropiedades(ConfigPrevisao.class);
261: try {
262: propriedadesController.getBy(configPrevisao
263: .getPersistentObject());
264: } catch (SQLException e2) {//Não fazemos nada
265: }
266: if (!configPrevisao.getRealizarPrevisoes()
267: || !configPrevisao.getPreverGastosEReceitas())
268: return;
269:
270: try {
271: //Se o tipo de lançamento estiver configurado para não realizar previsão então agente ignora
272: //getRealizarPrevisao() == false ou == null (caindo no NullPointerException)
273: try {
274: TransactionType transactionType = new TransactionTypeDAO()
275: .getBy(new TransactionType(
276: TipoDeLancamentosMessages
277: .getMessages()
278: .getString(
279: "CreditoPagamentoCartao")));
280: if (!transactionType.getRealizarPrevisao()
281: || transactionType.getId().equals(tipo))
282: return;
283: } catch (NullPointerException npe) {
284: return;
285: }
286: } catch (SQLException e1) {
287: ((SimpleLog) GFPController.getGFPController()
288: .getContexto().get(GFPController.LOG))
289: .log("Erro já previsto possivelmente sem IMPACTO");
290: ((SimpleLog) GFPController.getGFPController()
291: .getContexto().get(GFPController.LOG))
292: .log(e1.getLocalizedMessage());
293: ((SimpleLog) GFPController.getGFPController()
294: .getContexto().get(GFPController.LOG))
295: .log(e1);
296: return;
297: }
298:
299: preverMovimento(e.getPersistentObject());
300: }
301: }
302: }
303:
304: /**
305: * Here we remove the old credit card bill value predictions
306: * @param lancamentoController
307: * @param creditCard
308: * @return
309: * @throws SQLException
310: */
311: private Transaction deletarDebitosAutomaticos(
312: TransactionDAO<Transaction> lancamentoController,
313: CreditCard creditCard) throws SQLException {
314: Transaction lancamentoPagamentoCartao;
315: lancamentoPagamentoCartao = new Transaction();
316: lancamentoPagamentoCartao.setConta(creditCard.getContaDebito());
317: lancamentoPagamentoCartao.setTipoConta(new CheckingAccount()
318: .getTipoConta());
319: lancamentoPagamentoCartao.setEntidadeEnvolvida(creditCard
320: .getBanco() == null ? creditCard.getOperadora()
321: : creditCard.getBanco());
322: lancamentoPagamentoCartao.setTipo(new TransactionTypeDAO()
323: .getBy(
324: new TransactionType(TipoDeLancamentosMessages
325: .getMessages().getString(
326: "PagamentoCartao"))).getId());
327: lancamentoPagamentoCartao.setEhPrevisao(true);
328:
329: //deletamos os antigos
330: lancamentoController.setCheckIntegridade(false);
331: lancamentoController.deletar(lancamentoPagamentoCartao);
332: lancamentoController.setCheckIntegridade(true);
333: return lancamentoPagamentoCartao;
334: }
335:
336: /**
337: * @param lancamentoOriginal
338: * @param lancamentoController
339: * @return
340: * @throws SQLException
341: */
342: private Transaction deletarPrevisoesNaContaCartao(
343: final Transaction lancamentoOriginal,
344: TransactionDAO<Transaction> lancamentoController)
345: throws SQLException {
346: Transaction transaction = new Transaction();
347: transaction.setConta(lancamentoOriginal.getConta());
348: transaction.setTipoConta(lancamentoOriginal.getTipoConta());
349: transaction.setTipo(new TransactionTypeDAO().getBy(
350: new TransactionType(TipoDeLancamentosMessages
351: .getMessages().getString(
352: "CreditoPagamentoCartao"))).getId());
353: transaction.setEhPrevisao(true);
354:
355: //deletamos os antigos
356: lancamentoController.setCheckIntegridade(false);
357: lancamentoController.deletar(transaction);
358: lancamentoController.setCheckIntegridade(true);
359: return transaction;
360: }
361:
362: /**
363: * @param lancamentoController
364: * @param dia
365: * @param lancamentoPagamentoCartao
366: * @param transaction
367: * @param valor
368: * @throws SQLException
369: */
370: private void fazerPrevisaoDePagamento(
371: TransactionDAO<Transaction> lancamentoController,
372: Calendar dia, Transaction lancamentoPagamentoCartao,
373: Transaction transaction, Double valor) throws SQLException {
374: transaction.setValor(valor);
375: transaction.setDia(dia.getTime());
376: transaction.setTransferencia(new Double(System
377: .currentTimeMillis() / 1000d));
378: transaction
379: .setContaTransf(lancamentoPagamentoCartao.getConta());
380: transaction.setTipoContaTransf(lancamentoPagamentoCartao
381: .getTipoConta());
382: lancamentoController.adicionarNovo(transaction);
383:
384: //Lançamos o débito em outra conta
385: lancamentoPagamentoCartao.setDia(dia.getTime());
386: lancamentoPagamentoCartao.setValor(Double.valueOf(""
387: + (valor.doubleValue() * -1)));
388: lancamentoPagamentoCartao.setTransferencia(transaction
389: .getTransferencia());
390: lancamentoPagamentoCartao
391: .setContaTransf(transaction.getConta());
392: lancamentoPagamentoCartao.setTipoContaTransf(transaction
393: .getTipoConta());
394: lancamentoController.adicionarNovo(lancamentoPagamentoCartao);
395: }
396: }
|