Elaboração de contas a receber

Bom dia a todos do fórum, estou com um problema a mais de um ano, estou precisando muito da ajuda de vocês, vou tentar simplificar o máximo possível.
Objetivo: Elaborar um conta a receber.

Vou tentar descrever o que eu desejo:
Eu vou efetuar varias vendas no crediário, estas vendas vai para contas a receber de um determinado cliente, quando este cliente comparecer para efetuar o pagamento, eu quero fazer um sistema que coloque apenas um valor, ai o sistema vai dando baixa em todas as venda para aquele cliente.

Exemplo:
Venda 1 = 100,00
Venda 2 = 50,00
Venda 3 = 80,00
Venda 4 = 150,00

O valor total de todas as venda é 380,00
O cliente vai efetuar o pagamento de apenas 350,00
Vai ficar faltando 30,00
Então o sistema terá de fazer o seguinte:
Venda 1 = 100,00 - pg
Venda 2 = 50,00 - pg
Venda 3 = 80,00 - pg
Venda 4 = 150,00 - Obs: 120 - valor pago e falta pagar 30,00 reais da venda 4

depois, em outra data o cliente farar a efetuação do pagamento de 30,00,
Venda 4 = 150,00 - pg

valos lá, eu já estou trabalhando com as seguintes tabelas:

tb.vendas
idVenda, cdgCliente, dtVenda, hrVenda, status

tb.vendas.pagamentos
idPagamento, cdgVenda, valorDoPagamento

tb.vendas.pagamentos.credito
idPagamentoCredito, cdgPagamento, valorTotalDoPagamento, qtdParcelas, valorDasParcelas

Esta funcionando da seguinte forma.
toda venda é armazenada na tabela tb.vendas
quando a venda for efetuada a vista, o valor vai para a tabela tb.vendas.pagamentos
quando a venda for efetuada no crediário, o valor vai para a tabela tb.vendas.pagamentos.credito
dependendo da quantidade de parcelas o valor é calculado altomaticamente

O que devo fazer para que o sistema funcione do jeito que desejo?
fazendo o calculo automaticamente.

Qual é sua dúvida exatamente? Modelar o banco de dados para o sistema trabalhar desse jeito?

O que você descreveu parece um sistema de cartao de crédito, quando você pode pagar parcialmente, pagar o mínimo, etc.
Se você pode pagar parcialmente, para que quer controlar quais vendas foram totalmente pagas ou nao? Nao te ajuda manter apenas o saldo do cliente?

Se for pra realmente resolver desse jeito, você pode criar uma tabela para vendas “fechadas” e inserir novos registros lá a cada vez que o cliente efetuar pagamentos.
Geralmente em sistemas financeiros você quer evitar fazer updates ou deletes, entao é melhor registrar essas operaçoes como eventos que ocorreram, sempre inserindo novos registros.

Muito obrigado pela a sua atenção amigo.
eu já tenho o PDV funcionando, quero implementar um contas à receber a partir das vendas efetuada no credito.
Desejo modelar o banco de dados para depois começar a criar as telas no sistema “uso o Netbeans”. Eu quero montar uma forma que informe quanto o cliente esta devendo e mostre o que já foi pago.

Como ficaria a relação desta tabela vendas.fechadas com as tabelas tb.vendas, tb.vendas.pagamentos, tb.vendas.pagamentos.credito e o caixa?

Estou quebrando a cabeça com a elaboração deste banco de dados, pensando como vai ser montado o sistema.

Bom dia a todos do grupo, peço desculpas pois o meu conhecimento na programação é muito pouco, por isso a dificuldade, caso não tenha sido muito claro no que desejo, peço para deixarem o comentário e tentarei esclarecer, se alguém poder mim ajudar ficarem muito grato.

Mas em qual linguagem pretende fazer isso ?

Muito obrigado por sua atenção, eu uso a Linguagem Java, trabalho com o NetBeans!

Esta’ fazendo em swing ou em javafx e qual banco de dados esta’ usando ?

swing e o banco é mysql.

Bom !!! depois de definida todas as telas de entradas, processamento e as saidas

O esqueleto do controle de recebimento seria mais ou menos assim .

arquivo fatura // indice = (chave cpf + codigo_fatura)
codigo_fatura, // chave primaria
cpf
valor // o total da compra
data_hora_compra

arquivo duplicatas // indice (codigo_duplicata + parcela + vencimento)
codigo_duplicata (usando a chave estrangeira codigo_fatura)
parcela
vencimento
valor_total_parcela
valor_total_parcela_pagamento_recebido
forma_pagamento // 1-avista chegue, 2-cheque pre, 3-avista dinheiro, 4-cc 5-cartao debito

// na hora de dar a baixa, você começa baixando da primeira a ultima, se faltar dinheiro o campo
valor_total_parcela_pagamento_recebido sera’ menor que o valor_total_parcela.

E tambem voce podera criar outros indices diante da necessidade de exibição ou processamento.

Ainda se seus clientes costumam pagar as parcelas em pedaços, voce pode criar um terceiro arquivo e nele colocar o valor recebido a data e o tipo de recebimento tendo como chave estrangeira o arquivo de duplicatas.

Uma dica : por causa da integração com a contabilidade Eu não gosto de ir diminuindo o valor total_parcela a medida que o cliente vai pagando,mas isso e’ de cada um.

Obrigado amigo, vou tentar estruturar minha tabela e depois comunico como ficou!

Bom dia a todos, amigo j-menezes desculpa a demora, estou montando a minha estrutura do banco de dado.
A duplicata é lançada quando for gerada a fatura ou quando o cliente efetuar o pagamento da fatura?

Ela e’ lançada quando for gerada a fatura ( porque isso te dá a possibilidade de controlar as duplicatas em aberto e paga )

Amigo, quais colunas devem ter na tabela duplicata
idDuplicata,
codigoFatura,
dataEmissao,
horaEmissao,
dataVencimento,
qtdParcela,
valorParcela,
tipoPagamento,
dataPagamento,
horaPagamento,
juros,
multa,
descontos,
status

na sua visão teria que acrescenta alguma coluna?

Veja bem caro ismaelmartinsds,

Como mencionado antes, na tabela “titulo” você coloca tudo que pertence a nota fiscal fatura, já no arquivo “duplicatas” você coloca tudo que se refere as parcelas. Veja com calma o que postei anteriormente e confronta com o que você tem em mente. Você pode colocar dentro da tabela “titulo” uma matriz com as parcelas[], vencimentos[], etc[]…, mas Eu não gosto de usar assim, prefiro criar uma tabela separada de “duplicatas”.Mas isso e’ de cada um.

idDuplicata,
codigoFatura,
dataEmissao, // essa não precisa porque a emissao da duplicata e’ a mesma do titulo
horaEmissao, // nao precisa tambem

dataVencimento,
qtdParcela, // correto e’ o nroParcela

valorParcela,
tipoPagamento,
dataPagamento, // coloca num mesmo campo a data e hora
horaPagamento, // nao precisa

juros,
multa,
descontos,

status

E’ por ai mesmo

Teria mais alguma coluna para ser criado?

Talvez os detalhes do tipo de pagamento.
As vezes você quer guardar em um campo o numero do recibo do CC, do cheque , enfim…
nesse caso pode criar um campo tipo texto

O bom é que a table poderá ser modificada se preciso for no futuro.

Bom amigo, é o seguinte, eu criei a tabela Duplicata e nela como citada acima foi criada o campo dataPagameto, agora o que devo fazer se a Duplicata for paga em mais de uma vez?
ex:
o valor da duplicata é R$ 200,00 e foi gerada em uma parcela
na hora do pagamento foi paga da seguinte forma:
R$ 60,00
R$ 20,00
R$ 40,50
R$ 60,00
R$ 19,50
vejamos que vai ter vários pagamento com data diferente

é melhor criar uma tabela DuplicataArquivo?

em cima do exemplo sitado vou tentar demostrar outro problema.

o valor da duplicata é R$ 200,00 e foi gerada em uma parcela
na hora do pagamento foi paga da seguinte forma:
R$ 60,00
R$ 20,00

os valores de 60,00 e 20,00 foi pagos, agora falta o restante.
será bom criar um campo valor residual onde quando cada pagamento for feito eu var alterando este valor ate ele zerar?
ou será melhor efetuar a soma até chegar o valor da parcela de 200,00?

Nesse caso Eu prefiro criar um terceiro arquivo, apenas para controlar os recebimentos quebrados da duplicata.

Volto a mencionar que isso e’ de cada um, apenas estou dando a minha opinião. No entanto prefiro gerar esse terceiro arquivo e deixar tudo o que for pago da duplicata nele e por causa da integração com a contabilidade não gosto de ir zerando o campo.

Resumindo table duplicataParcelada

codigo // chave primaria
codigoDuplicata // chave estrangeira codigo duplicata
data_recebimento
valor
tipo_pagamento
detalhe_pagamento
juros,
multa
desconto

Observaçao, se usar esse terceiro arquivo, os campos tipo_pagamento, juros, multa, desconto podem sair da table duplicatas e ir para duplicataParcelada

Acho que a parte do banco esta ok, agora vamos aumenta o nível de dificuldade vamos passar para a criação do formulário:
tenho duas tabela
1 - pega todas as duplicatas
2 - pega todas as duplicatas recebidas

tenho cinco campos para lança os valores
1 - Total a receber - recebe o calcula de todas as duplicatas
2 - Valor pagamento - onde lanço o valor que o cliente vai efetuar o pagamento
3 - Juros - onde lanço o valor do juros
4 - Multas - onde lanço o valor do multas
5 - Descontos - onde lanço o valor do descontos

1- Pergunta. de que forma devo fazer a logica para receber o pagamento das duplicatas?

este é botão que clico para adicionar a duplicatarecebida

private void bt_adicionarActionPerformed(java.awt.event.ActionEvent evt) {

        for (int i = 0; i < tabela_despesa.getRowCount(); i++) { 
        Boolean ck = (Boolean)tabela_despesa.getValueAt(i, 5);
        if (ck == null){
            ck = false; 
            }else if((Boolean) tabela_despesa.getValueAt(i, 5)==true) {  
        bdr.codigoDuplicata = Integer.parseInt(String.valueOf(tabela_despesa.getValueAt(i, 0)));  
        bdr.juros                 = Double.parseDouble(parametrosNS.TransStrDou.TransformaValorStringeDouble(txt_valorJuro.getText(), 1));
        bdr.multas                = Double.parseDouble(parametrosNS.TransStrDou.TransformaValorStringeDouble(txt_valorMulta.getText(), 1));
        bdr.desconto              = Double.parseDouble(parametrosNS.TransStrDou.TransformaValorStringeDouble(txt_valorDesconto.getText(), 1));
        
        PegaDuplicataRecebida();
             
        IncluirDuplicataRecebida();
                
        mensagem = "Pagamento da duplitada finalizada com êxito!";
        mostraMensagem();

            } 
          }
}    

private void PegaDuplicataRecebida(){

    sql = "select \n"
        + "   tb_duplicata_recebidas.idDuplicataRecebidas, \n" 
        + "   tb_duplicata_recebidas.idEmpresa, \n"
        + "   tb_duplicata_recebidas.codigoGrupo, \n"
        + "   tb_duplicata_recebidas.codigoEmpresa, \n"
        + "   tb_duplicata_recebidas.codigoDuplicata, \n"
        + "   tb_duplicata_recebidas.dataRecebimento, \n"
        + "   tb_duplicata_recebidas.valorRecebimento, \n"
        + "   tb_duplicata_recebidas.tipoPagamento, \n"
        + "   tb_duplicata_recebidas.detalhePagamento, \n" 
        + "   tb_duplicata_recebidas.juros, \n"  
        + "   tb_duplicata_recebidas.multas, \n"
        + "   tb_duplicata_recebidas.descontos \n"                
          
        + "from tb_duplicata_recebidas "
        + "where tb_duplicata_recebidas.codigoDuplicata = " + bdr.codigoDuplicata + " and tb_duplicata_recebidas.idEmpresa = " + parametrosNS.be.IdEmpresa + "\n" 
        + preenchimento
        + "   order by dataRecebimento asc;";

    dadosContaRecebida.clear();
    dadosContaRecebida = parametrosNS.dao.Consulta(sql);
    PegaDadosDuplicataRecebida();
}

private void PegaDadosDuplicataRecebida(){

    tabela_recebida.getColumnModel().getColumn(0).setPreferredWidth(0);  
    tabela_recebida.getColumnModel().getColumn(0).setMaxWidth(0);  
    tabela_recebida.getColumnModel().getColumn(0).setMinWidth(0);  
    tabela_recebida.getTableHeader().getColumnModel().getColumn(0).setMaxWidth(0);  
    tabela_recebida.getTableHeader().getColumnModel().getColumn(0).setMinWidth(0); 
    
    TableContaRecebida.setNumRows(0);
    
    SomaValorContaReceberdr    = 0;
    SomaValorPagodr       = 0;
    SomaValorRecebidodr     = 0;
            
    String valorDespesa         = "";
   
    for(int i = 0; i < dadosContaRecebida.size(); i++){
        bdur = new BeanDuplicataReceber();
        
        bdur.idDuplicataReceber     = Integer.parseInt  ((String) dadosContaRecebida.get(i).get(0));
        bdur.idEmpresa              = Integer.parseInt  ((String) dadosContaRecebida.get(i).get(2));
        bdur.codigoGrupo            = Integer.parseInt  ((String) dadosContaRecebida.get(i).get(3));
        bdur.codigoEmpresa          = Integer.parseInt  ((String) dadosContaRecebida.get(i).get(4));
        bdur.codigoDuplicata        = Integer.parseInt  ((String) dadosContaRecebida.get(i).get(1));
        bdur.detalheRecebimento     =                    (String) dadosContaRecebida.get(i).get(8);
       

            bdur.valorRecebimento     = Double.parseDouble((String) dadosContaRecebida.get(i).get(6));
            bdur.dataRecebimento   =                    (String) dadosContaRecebida.get(i).get(5);
            valorDespesa    = TransStrDou.TransformaValorStringeDouble(String.valueOf(bdur.valorRecebimento), 0);

            bdur.juros              = Double.parseDouble((String) dadosContaRecebida.get(i).get(9));
            bdur.multas             = Double.parseDouble((String) dadosContaRecebida.get(i).get(10));
            bdur.desconto           = Double.parseDouble((String) dadosContaRecebida.get(i).get(11));

        SomaValorContaReceberdr       += bdur.valorRecebimento;
        SomaValorPagodr               = bdur.valorRecebimento + bdur.juros + bdur.multas - bdur.desconto;
        SomaValorRecebidodr           += SomaValorPagodr;
        
        
        bdur.dataRecebimento        = invdata.inverterData(bdur.dataRecebimento, 1);
        

        TableContaRecebida.addRow(new Object[] {fc.FormataCampo(String.valueOf(bdur.idDuplicataReceber), 6, 0), fc.FormataCampo(String.valueOf(bdur.idDuplicataReceber), 6, 0), bdur.detalheRecebimento, bdur.dataRecebimento,valorDespesa,TransStrDou.TransformaValorStringeDouble(String.valueOf(bdur.juros), 0),TransStrDou.TransformaValorStringeDouble(String.valueOf(bdur.multas), 0),TransStrDou.TransformaValorStringeDouble(String.valueOf(bdur.desconto), 0),TransStrDou.TransformaValorStringeDouble(String.valueOf(SomaValorPagodr), 0)

        });
    
     }
       new AjustarLarguraColunasBoolean(tabela_recebida);
}

private void IncluirDuplicataRecebida(){
bdr.idEmpresa = parametrosNS.be.IdEmpresa;
bdr.codigoGrupo = parametrosNS.bge.CodigoGrupo;
bdr.codigoEmpresa = parametrosNS.be.CodigoEmpresa;
bdr.dataRecebimento = invdata.inverterData(cdh.CapturarData(), 2);
bdr.valorRecebimento = SomaValorRecebidodr; //Ismael Martins: tenho que ver este calculo para tentar da baixa
bdr.tipoPagamento = 1;
bdr.detalheRecebimento = "Ref. ao Pagamento da Duplicata de Nº: “+bdr.codigoDuplicata+” ";

    sql = "insert into tb_duplicata_recebidas (idEmpresa, codigoGrupo, codigoEmpresa, codigoDuplicata, dataRecebimento, valorRecebimento, tipoPagamento, detalhePagamento, juros, multas, descontos) "
        + "values (" + bdr.idEmpresa + ", " + bdr.codigoGrupo + ", " + bdr.codigoEmpresa + ", " + bdr.codigoDuplicata + ", '" + bdr.dataRecebimento + "', " + bdr.valorRecebimento + ", " + bdr.tipoPagamento + ", '" + bdr.detalheRecebimento + "', " + bdr.juros + ", " + bdr.multas + ", " + bdr.desconto + ");";

    sqlstate = parametrosNS.dao.incluirRegistro(sql);
    if(!sqlstate.equals("00000")){
        mensagem = "Erro ao incluir duplicatas recebidas!";
        mostraMensagem();
    }
      
}

Com estes códigos, o sistema já insere os dados no banco, só falta a parte de cálculos.
Estou com problema nos cálculos para inserir os valores no banco de dados.
quem puder mim ajudar, pode manisfesta-se que eu passo todos os detalhes.

ficarem muito grato se alguém poder ajudar.