Duvida sobre Arquitetura

E ai galera.

Estou desenvolvendo um controle financeiro onde [como não poderia deixar de ser] eu tenho a classe MovimentacaoFinanceira:

public class MovimentacaoFinanceira implements Serializable { private Long id; private BigDecimal valor; private Calendar data; private Character tipo; private Conta conta; //... }
Terei que disponibilizar uma funcionalidade de estorno da MovimentacaoFinanceira. Neste estorno devo excluir a movimentacaoFinanceira, reverter o valor debitado/creditado à conta e excluir os rateios da movimentacao. Onde eu devo fazer isto? Criar um metodo estornar() na classe MovimentacaoFinanceira? Criar uma classe apenas para a operacao de estorno com um metodo estornar(MovimentacaoFinanceira mov)? Alguma sugestão diferente? Lembrando que dentro da operacão de estorno terei que invocar metodos em DAOs, por isso não acho interessante criar uma dependencia da classe de modelo MovimentacaoFinanceira a DAOs.

Excluir uma MovimentacaoFinanceira é uma péssima ideia, você precisa manter esse histórico.

O ideal mesmo é criar uma movimentação inversa (invertendo quem paga e quem recebe), e marcar o tipo dela como “Estorno” de alguma forma.

[quote=Rodrigo Sasaki]Excluir uma MovimentacaoFinanceira é uma péssima ideia, você precisa manter esse histórico.

O ideal mesmo é criar uma movimentação inversa (invertendo quem paga e quem recebe), e marcar o tipo dela como “Estorno” de alguma forma.[/quote]
Ok Rodrigo. Excelente ideia de manter o historico de estornos, vou coloca-la em pratica, mas continuo na duvida sobre “onde” implementar o estorno.

Como assim onde? pode ser em alguma classe de service do seu sistema, talvez a mesma que usa para criar movimentações financeiras de outros tipos, porque um estorno é a mesma coisa.

Huuum, entendi.
Farei isso em uma classe Builder.
Obrigado Rodrigo Sasaki.

[quote=joparibeiro][quote=Rodrigo Sasaki]Excluir uma MovimentacaoFinanceira é uma péssima ideia, você precisa manter esse histórico.

O ideal mesmo é criar uma movimentação inversa (invertendo quem paga e quem recebe), e marcar o tipo dela como “Estorno” de alguma forma.[/quote]
Ok Rodrigo. Excelente ideia de manter o historico de estornos, vou coloca-la em pratica, mas continuo na duvida sobre “onde” implementar o estorno.

[/quote]

Primeiro que tudo, use os tipos certos para as coisas certas. Considere usar o padrão Money em vez de BigDecimal para valores e Date em vez de Calendar (Calendar é uma calculadora, não é um Value Object)

Segundo, como já foi dito, em finanças não se apaga nada. Se gerar movimentos inversos.

Terceiro, está faltando a movimentação casada.

Num sistema de contas (sejam financeiras ou contábeis) cada conta tem a sua movimentação ( que é a classe que vc fez) mas o sistema tem uma outra coisa chamada TransacaoFinanceira
A transação amarra duas movimentações (uma em cada conta). Na realidade, uma transação gera/é um conjunto de movimentações.

Por exemplo, um TED da conta A para B de 100 reais , gera duas movimentações na conta A e uma na conta B. Na conta A é removido 100 reais e mais o valor da taxa de ted ( que é outra movimentação), na B é lançado o deposito de 100.
É a transação que precisa ser estornada, não a movimentação.


       TransacaoFinanceira original = ... // otido de alguma forma

       TransacaoFinanceira  estorno = original.estorno();
        
       ServicoTransacaoFinanceira servico  = ..// injetado de alguma forma 

      servico.executa(estorno);

A classe TransacaoFinanceira sabe se inverter a si mesma e o serviço só trata com TransacaoFinanceira


    public class TransacaoFinanceira implements Serializable {  
        private Long id;  
       
        private Money valor;  
        private Money  taxaA;
        private Money taxaB;    
        private Date data;  
        private Tipo  tipo;  // enum DEBITO / CREDITO 
        private Conta origem;  
        private Conta destino
        //...  

        public  TransacaoFinanceira estorno () { // não é getEstorno porque não é uma propriedade

                    TransacaoFinanceira  estorno = new TransacaoFinanceira ();

                    estorno.origem = this.destino;
                    estorno.destino= this.origem;
                    estorno.valor= this.valor;
                    estorno.tipo= this.tipo;

                    return estorno;
        }
    }  

Tenha cuidado porque existem várias formas de inverter. Eu inverti as contas e assim o resto fica igual. Pode fazer ao contrário, manter as contas e inverter os dados. Não é a mesma coisa uma e outra embora o resultado final seja o mesmo. Aqui vai um pouco de regra de negocio.

[quote=sergiotaborda][quote=joparibeiro][quote=Rodrigo Sasaki]Excluir uma MovimentacaoFinanceira é uma péssima ideia, você precisa manter esse histórico.

O ideal mesmo é criar uma movimentação inversa (invertendo quem paga e quem recebe), e marcar o tipo dela como “Estorno” de alguma forma.[/quote]
Ok Rodrigo. Excelente ideia de manter o historico de estornos, vou coloca-la em pratica, mas continuo na duvida sobre “onde” implementar o estorno.

[/quote]

Primeiro que tudo, use os tipos certos para as coisas certas. Considere usar o padrão Money em vez de BigDecimal para valores e Date em vez de Calendar (Calendar é uma calculadora, não é um Value Object)

Segundo, como já foi dito, em finanças não se apaga nada. Se gerar movimentos inversos.

Terceiro, está faltando a movimentação casada.

Num sistema de contas (sejam financeiras ou contábeis) cada conta tem a sua movimentação ( que é a classe que vc fez) mas o sistema tem uma outra coisa chamada TransacaoFinanceira
A transação amarra duas movimentações (uma em cada conta). Na realidade, uma transação gera/é um conjunto de movimentações.

Por exemplo, um TED da conta A para B de 100 reais , gera duas movimentações na conta A e uma na conta B. Na conta A é removido 100 reais e mais o valor da taxa de ted ( que é outra movimentação), na B é lançado o deposito de 100.
É a transação que precisa ser estornada, não a movimentação.


       TransacaoFinanceira original = ... // otido de alguma forma

       TransacaoFinanceira  estorno = original.estorno();
        
       ServicoTransacaoFinanceira servico  = ..// injetado de alguma forma 

      servico.executa(estorno);

A classe TransacaoFinanceira sabe se inverter a si mesma e o serviço só trata com TransacaoFinanceira


    public class TransacaoFinanceira implements Serializable {  
        private Long id;  
       
        private Money valor;  
        private Money  taxaA;
        private Money taxaB;    
        private Date data;  
        private Tipo  tipo;  // enum DEBITO / CREDITO 
        private Conta origem;  
        private Conta destino
        //...  

        public  TransacaoFinanceira estorno () { // não é getEstorno porque não é uma propriedade

                    TransacaoFinanceira  estorno = new TransacaoFinanceira ();

                    estorno.origem = this.destino;
                    estorno.destino= this.origem;
                    estorno.valor= this.valor;
                    estorno.tipo= this.tipo;

                    return estorno;
        }
    }  

Tenha cuidado porque existem várias formas de inverter. Eu inverti as contas e assim o resto fica igual. Pode fazer ao contrário, manter as contas e inverter os dados. Não é a mesma coisa uma e outra embora o resultado final seja o mesmo. Aqui vai um pouco de regra de negocio.[/quote]
Muito obrigado Sergio.
Na verdade, acho que me expressei mal, o objetivo do sistema e um controle financeiro SIMPLES, não sendo necessario controle de TRANSACOES financeiras, implementacao de coisas como o metodo de partidas dobradas e outras, comuns nos ERPs da vida. O objetivo real e o desenvolvimento de um sistema de controle de financas pessoais com gerenciamento de entradas/saidas de forma categorizada (ex: alimentacao, transporte, educacao). Algo realmente simples.