[Resolvido] Calculo total de linhas


#1

Tenho uma aba Pedido e uma Aba Itens.
Vou inserindo os itens que tem quantidade, valor unitário e valor total.
Na aba Pedido tenho dois valores totais, ai vem minha duvida:
Como posso fazer o total de linhas na aba Pedido? Os campos que receberão o total são: GrandTotal e TotalLines.

Alguma dica?
Tenho que fazer um CallOut?
Ou um processo?

Obrigada :smiley:


#2

Neste caso se for uma tabela totalmente nova, o ideal é você criar um modelo para esta tabela. Use o GenerateModel, e crie uma classe Model que extende a classe gerada pelo GenerateModel. Olhe os exemplos das classes do Adempiere (MOrder, MInvoice, etc) ai você faz um override do método beforeSave para popular os valores que precisa na aba de cima.

Outra opção é usando os ModelValidator. Há exemplos de como usar os ModelValidators no código-fonte do LBR.

Att.


#3

Na verdade, eu ja tenho duas Model, uma pra cada tabela (cada aba é uma tabela). Até tinha pensado em fazer no beforeSave, mas não consegui colocar em código a minha idéia.

Obrigada :smiley:


#4

o primeiro código que fiz foi esse:

[code] protected String beforeSave (String VlrTotal, String ValorLinha, Double TotalGeral)
{
VlrTotal = “GrandTotal”;
ValorLinha = “LineNetAmt”;

    while (m_item != null); {            
        TotalGeral =  Double.parseDouble(ValorLinha)+Double.parseDouble(ValorLinha);
        VlrTotal = TotalGeral.toString();
    }            
        
    return VlrTotal;
}    //    beforeSave[/code]

mas nem deu certo XD

vou continuar tentando…

mudei um pouco:

[code] protected BigDecimal beforeSave (BigDecimal VlrTotal, BigDecimal ValorLinha, BigDecimal TotalGeral, BigDecimal TotalLinha)
{
VlrTotal = getGrandTotal();
TotalLinha = getTotalLines();
//ValorLinha = getLineNetAmt;

    while (m_item != null); {            
        TotalGeral =  ValorLinha.add(ValorLinha);
        VlrTotal = TotalGeral;
        TotalLinha = TotalGeral;
    }            
        
    return VlrTotal;
}    //    beforeSave[/code]

mas não consigo pegar o valor da outra tabela (getLineNetAmt)

continuar tentando…
idéias são bem vindas!

Obrigada :smiley:


#5

Olá Cátia,

Eu não consegui entender direito o seu código, mas da pra ver que tem um erro aqui:

while (m_item != null);

Note que há um ; no final, e não há como sair do looping.

Minha sugestão seria usar o método afterSave da sua classe referente a Aba Linhas. Você também não pode mudar a assinatura do método beforeSave/afterSave senão não funciona.

protected boolean afterSave (boolean newRecord) { String sql = "UPDATE C_Order i" + " SET TotalLines=" + "(SELECT COALESCE(SUM(LineNetAmt),0) FROM C_OrderLine il WHERE i.C_Order_ID=il.C_Order_ID) " + "WHERE C_Order_ID=" + getC_Order_ID(); int no = DB.executeUpdate(sql, get_TrxName()); }

Dessa forma toda vez que alguém salvar algum registro na Aba Itens, o sistema irá preencher o valor na Aba pedido. Note que você pode usar o método afterDelete para fazer essa atualização também.

Att.


#6

Obrigada.
Não havia percebido meu erro ^^
sou nova no uso do ADempiere, comecei na semana passada. To aprendendo como funciona, e nada melhor do que praticando.
Criei as telas de cadastro, já fiz relatórios e essa agora é praticamente como a Ordem de Compra. Apenas com menos dados.
Adaptei o código que me passou e ficou assim:

[code]protected boolean afterSave (boolean newRecord)
{
String sql = “UPDATE FRK_Venda_livros vl”
+ " SET TotalLines="
+ "(SELECT COALESCE(SUM(LineNetAmt),0) FROM FRK_VendaLivros_Item vi WHERE vl.FRK_Venda_Livros_ID=vi.FRK_Venda_Livros_ID) "
+ “WHERE FRK_Venda_Livros_ID=” + getFRK_Venda_Livros_ID();
int no = DB.executeUpdate(sql, get_TrxName());

          return true;
       }[/code]

Apenas não entendi o que é o “COALESCE”, os outros campos eu coloquei de acordo com minhas tabelas.
Ainda não mostrou resultado. Acho que faltou o retorno correto ali.
Obrigada :smiley:


#7

O COALESCE é equivalente ao NVL do Oracle, quando o primeiro parâmetro é NULL ele usa o segundo, neste caso se o LineNetAmt for NULL ele somará ZERO.

Confira se o campo que tem o valor é o campo LineNetAmt na FRK_VendaLivros_Item mesmo. Também confira se a sua classe extende a super-classe X_FRK_VendaLivros_Item.

Você pode colocar um breakpoint dentro do método afterSave pra debugar, o sistema deve entrar neste método toda vez que salva alguma coisa na tabela FRK_VendaLivros_Item.
Att.


#8

Realmente ele não entra no método quando salvo.
Percebi uma coisa olhando no banco, os campos de valor são numéricos, mas eles salvam algo como “5.000000000000” o valor e “2.000000000000” a quantidade, dando um total “10.000000000000”.
Isso é normal?
Não tem como mudar a quantidade de números?
Pode interferir em alguma coisa??

A classe está estendida corretamente.

ta dando essa mensagem:

Obrigada :slight_smile:


#9

Bom, descobri vários erros…

Resolvi fazer no Validator, depois de corrigir os erros da Model, creio que dará certo.

Obrigada pela ajuda. :slight_smile:


#10

Catia, uma dica importante é sempre fazer os cálculos usando BigDecimal, pois o double pode causar muitos problemas com relação a casas decimais…

Outra coisa é vc fazer um arredondamento antes de fazer o update no banco de dados… assim vc garante que a informação inseriada no seu banco é da forma que vc quer…

ex.

taxTotalAmt.setScale(TaxBR.SCALE, TaxBR.ROUND);

sobre o erro, na tabela FRK_Venda_Livros, marque o FRK_Venda_Livros_ID como identificador, dai este erro provavelmente não vai mais ocorrer.

sds, Mario


#11

UPDATE FRK_Venda_Livros vl
SET TotalLines=
(SELECT COALESCE(SUM(LineNetAmt),0) FROM FRK_VendaLivros_Item vi WHERE vl.FRK_Venda_Livros_ID=vi.FRK_Venda_Livros_ID) and
SET GrandTotal=
(SELECT COALESCE(SUM(LineNetAmt),0) FROM FRK_VendaLivros_Item vi WHERE vl.FRK_Venda_Livros_ID=vi.FRK_Venda_Livros_ID)

WHERE FRK_Venda_Livros_ID=1000000000;

Eu queria fazer algo assim, mas esse código não da certo. Tem como fazer o update dos dois campos juntos? Porque eles recebem o mesmo valor.

Obrigada :slight_smile:


#12

UPDATE FRK_Venda_Livros vl SET TotalLines= (SELECT COALESCE(SUM(LineNetAmt),0) FROM FRK_VendaLivros_Item vi WHERE vl.FRK_Venda_Livros_ID=vi.FRK_Venda_Livros_ID), GrandTotal= (SELECT COALESCE(SUM(LineNetAmt),0) FROM FRK_VendaLivros_Item vi WHERE vl.FRK_Venda_Livros_ID=vi.FRK_Venda_Livros_ID) WHERE FRK_Venda_Livros_ID=1000000000;

A sintaxe não tem o segundo SET, os valores devem ser separados por vírgula.

Att.


#13

Ahhh

Muito Obrigada!


#14

Hehe

voltei, vou abusar mais um pouco da vossa ajuda.

Alguem sabe me dizer porque motivo pode dar o seguinte erro:

GridTable.saveWarning: Error - org.adempiere.model.GenericPO cannot be cast to org.adempiere_fricke.model.MVendaLivrosItem [12]
GenericPO.save: Validation failed - org.adempiere.model.GenericPO cannot be cast to org.adempiere_fricke.model.MVendaLivrosItem [12]
GenericPO.saveError: Error - org.adempiere.model.GenericPO cannot be cast to org.adempiere_fricke.model.MVendaLivrosItem [12]

Aparentemente esta tudo correto em meu Validator. Pelo menos o que implementei.

Agradeço a ajuda :slight_smile:


#15

Este erro é pq ou vc está usando o EntityType ‘User maintained’ ou se vc criou algum entitypetype e não definiu o Model Package…

Na classe MTable, o adempiere pega a tabela e tenta achar a sua model class para instanciar o objeto, no seu caso a table FRK_Venda_Livros, porém ele por padrão nunca vai buscar no package org.adempiere_fricke.model, pois ele não sabe que a classe está lá… então o seu PO na verdade vai ser uma instancia do org.compiere.model.X_FRK_Venda_Livros, que é a classe que foi gerado pelo seu generate model…

Solução, ou vc cria um entitytype para sua empresa e define o model package (igual é no adempierelbr), ou adiciona na MTable o package hardcoded (dê uma olhada no svn do adempierelbr, no RC110 ou Stable tem um exemplo…) ou nos validators utilize sempre o cast do PO para as classes X_??? que foram geradas pelo GenerateModel


#16

Referenciei minha Model na MTable, e funcionou.

Obrigado à todos pela ajuda.

Meu código está funcionando certinho agora, inclusive as alterações de valores pelo Validator.

:stuck_out_tongue: