quarta-feira, 30 de janeiro de 2008

Impostos no AX - Visão Geral parte 2

Decidi retomar esse post, porém de uma forma um pouco mais didatica e um pouco menos técnica.

A partir do AX 4.0, existem 2 tipos de impostos que podem ser calulados no sistema:
1. Impostos sobre vendas - Sales Tax
2. Impostos retidos - Withholding Taxes (erroneamente traduzido para Retenção de Impostos)

Os impostos sobre são venda podem ser calculados nos pedidos de venda, pedidos de compra, notas fiscais de fornecedores e diários da contabilidade (a partir do SP2)

Os impostos que devem retidos quando há pagamento são calculados SOMENTE nos diários de pagamentos (fornecedor e cliente) - com o detalhe que, para o Brasil, somente são calculados caso um produto do tipo serviço tenha sido utilizado no registro do pedido e para os casos em que a nota fiscal e registrada a partir do diário de notas fiscais, a opção Nota Fiscal de serviços tenha sido marcada na aba Nota Fiscal.


Impostos sobre vendas (Contabilidade/Configuração/Impostos sobre Vendas)

Os impostos são calculados da junção de 2 grupos - grupos de impostos de venda e grupos de impostos de venda do item.

Os impostos cadastrados par ao Brasil devem seguir uma configuração: impostos retidos no reistro da nota fiscal devem ser configurados como "Retidos", exemplos de impostos retidos: IRRF, INSS, ISS para alguns municípios.

Os impostos configurados como impostos retidos, quando registrados na compra, são registrado como impostos a pagar, e o seu valor é deduzido do valor a ser pago ao fornecedor. Nos pedidos de venda, o Ax segue o mesmo funcionamento, porém, o valor a receber registrado é deduzido dos impostos.





Um erro comum de configuração que leva o Ax a fazer coisas "estranhas" é configurar o imposto da seguinte maneira:

Percebam que o campo Base Marginal esta configurado como: Valor líquido do saldo de nota fiscal, esse é valor padrão do Ax quando se cadastra um novo imposto. A consequência para essa configuração é o registro errado da nota fiscal, consequentemente dos impostos retidos.
Na figura abaixo a contabilização da nota fiscal, uma nota fiscal de R$3.000,00, deveria gera um valor a pagar R$2.955,00 porém gerou um valor a pagar de R$3.045,00.

O correto é seria:


O PIS, COFINS e CSLL (sobre serviços)podem ser configurados aqui, mas isso depende mais de uma decisão do contador da empresa do que do sistema. Legalmente eu também não saberia dizer se existe algum problema em reter ja na nota fiscal.


Impostos que ja estão incluídos nos preços de compra e venda devem ser configurados como "Incluidos", os exemplos clássicos são: ICMS, PIS e COFINS. Sendo essa a única solução par ao calculo correto dos impostos, fica como efeito colateral no sistema uma margem de venda bruta, com impostos, ja que normalmente as empresas trabalham com tabelas de preços ou preços padrão ja com esse impostos embutidos no preço, ou mesmo mantém tabelas de preços distintas para regiões diferentes do Brasil. (A venda para nordeste, a partir de são paulo por exemplo, tem um ICMS de 7% enquanto vendas para dentro de são paulo, tem 18%, impactando diretamente no preço).

No próximo post vou retomar com os impostos retidos a partir dos diário de pagamentos(withholding taxes).

Abs,






quinta-feira, 10 de janeiro de 2008

Interface com Cobre Bem para o AX

Cobre bem é uma DLL (paga) que cria arquivos de cobrança (CNAB) e emite boletos bancários. Muito facil de utilizar.



Criei uma interface para esse DLL que esta no link http://www.axaptapedia.com/Cobre_Bem, a ideia é mante-la como um projeto.



Postei uma versão 0.0b, portanto, usem por conta sua conta e risco, mas a ideia é implementar todas as funcionalidades disponiveis na versão.


A DLL é de propriedade da Cobre Bem Tecnologia http://www.cobrebem.com.br/


* Mais informações sobre a DLL em http://www.cobrebem.com.br/testecbx.html

* Download da versão de testes em http://www.cobrebem.com.br/downloads.html

* Informações sobre licenciamento em http://www.cobrebem.com.br/modelolicenciamento.html

* Gerar licença demo http://www.cobrebem.com/cgi-bin/GeraArquivoLicencaTeste/

quinta-feira, 27 de dezembro de 2007

Blog sobre AX

Alguns blog que frequento, são atualizados com alguma frequência:

http://axaptafreak.blogspot.com/ blog mais antigo que eu frequento
http://axaptabuilder.blogspot.com/ esse blog não é atualizado a 1 ano, mas tem ótimas informações sobre AX + VSS
http://blogs.msdn.com/dpokluda/ ótimos posts sobre Test Units ultimamente
http://blogs.msdn.com/palle_agermark/ também frquento a tempos.

Um recado para quem frequenta o blog: deixem coments nos posts para sabermos quem são vocês!!! - ja que no Brasil não somos muitos.

Abs,
Matiazo

Job para migração de produtos utilizando ADO

Feliz natal a todos (e talvez poucos!) que frequentam o blog. Esse ano completou 4 anos que eu trabalho com Ax (antigo Axapta) e é claro que nesse tempo todo trabalhando com o sistema, a cabeça ferve de ideias e soluções para todos os problemas encontrados no dia dia.

Um dos que mais me incomodavam, era a falta de uma maneira simples de carregar uma tabela de produtos, seja no começo da implantação, ou para uma demo mais aprofundada. A algum tempo escrevi um job que se utiliza das classes .Net para fazer um select num excel e importar os produtos de forma infinitamente mais rápida que a ferramenta de importação de tabelas do Ax.
Essa importação tem a vantagem de poermos trabalhar com tabela simples com todos os campos em colunas, não do conjuntos de tabelas: inventtable + InventItemLocaltion + inventTableModule para Estoque, Compras e Vendas, que são necessárias serem criadas/importadas para que o produto apareça no form de produto, uma conta simples, par aimportar um produto voce precisaria criar um excel contendo essas 3 tabelas e criar:
1. Um linha de produto na pasta InventTable
2. 3 Linhas para o mesmo produto criado na pasta 1 para preços (e todos campos que estão na aba Preço e Quantidade) de compra, venda e estoque na pasta InventTableModule
3. Uma linha ligada ao produto 1 na pasta InventItemLocation.

Para construir o job eu utilizei a classe AxInventTable, ela encapsula toda a logica para criação de produtos, as classes Ax são as classes que devem ser utilizadas quando se deseja criar alguma integração com o Ax ja que esse encapsulamento garante a criação correta das entidades. No caso dos produtos, para cada produto que é gravado, através do .save() ela ja cria os registros respectivos nas tabelas mostradas acima.

Para manter o job simples de ler, acabei trabalhando com comandos de macros definido constantes para cada indice de coluna que eu gostaria de trabalhar, assim o código fica mais legível e facil de manter.

No exemplo, o job cria o produto com as seguintes características:
1. Item id
2. Name
3. Item group
4. Item Type
5. Inventory Model group
6. Dimension group
7. Packing Quantity (quantidade de unidades por embalagem)
8. Net Weight (peso liquido)
9. Tara (o peso bruto é dado pral tara + peso liquido)
10. Classificação fiscal
11. Coluna com % de IPI

Para o IPI eu segui uma lógica simples, para cada porcentagem de IPI, foi criado um grupo correspondente dentro do Ax, no caso do exemplo somente 10%, mas isso poderia ser expandido para os IPI utilizados pelo cliente.

Utilizando deste tipo de importação (e das classes Ax), é possível configurar uma empresa com produtos, clientes e fornecedores para fazer workshops, demos, ou mesmo carga inicial de implantação de uma maneira simples e rápida com um pouco esforço de programação.

Ultimamente, todos os workshops (tanto em pre-venda ou início de implantação) que eu ja faço com meus clientes, ja trabalho com os dados reais, mesmo que básicos, falando a lingua do cliente fazendo com que a comunicação com os usuários e o entendimento do sistema seja feito de uma maneira simples para quem não conhece o sistema fazendo inclusive o usuário ir se acostumando com o sistema desde o início.


O job segue abaixo:

static void migrarProdutos(Args _args)
{
#define.ItemId (0) // A
#define.ItemName (1) // B
#define.ItemGroupId (2) // C
#define.ItemType (3) // D
#define.ModelGroupId (4) // E
#define.DimGroupId (5) // F
#define.TaxPackagingQty (6) // G
#define.NetWeight (7) // H
#define.TaraWeight (8) // I
#define.TaxFiscalClassificationId (9) // J
#define.PctIPI (10)// L


CCADOConnection adoexcel = new CCADOConnection();
CCAdoxCatalog adoCatalog = new CCAdoxCatalog();
COM adoxCatalog = new COM('ADOX.Catalog');
CCADORecordSet adoRecordSet = new CCADORecordSet();
CCADOFields adoFields;
int i;
int j;

// ------ Objetos usados importação
AxInventTable axInventTable;

InventItemGroup inventItemGroup;
TaxFiscalClassification_BR fiscalClassification;

ItemId itemId;
TaxItemGroup salesIaxItemGroup;
// ------ Objetos usados importação
;

adoexcel.connectionString("Provider=Microsoft.Jet.OLEDB.4.0;Data Source="+
"D:\\Documentos\\rm\\Projetos\\\\MigraProdutos.xlsx ;Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'");
adoexcel.open();
adoxCatalog.activeConnection(adoexcel.connection());
adoCatalog.adoxCatalog(adoxCatalog);
adoRecordSet.open(@"SELECT * FROM [Plan1$]", adoexcel);
adoFields = adoRecordSet.fields();

ttsbegin;

while (! adoRecordSet.EOF())
{
if(adoFields.itemIdx(#ItemId).value())
{
itemId = adoFields.itemIdx(#ItemId).value();
if(!InventTable::find(itemId))
{
axInventTable = new AxInventTable();

axInventTable.parmItemId (adoFields.itemIdx(#ItemId) .value());
axInventTable.parmItemName (adoFields.itemIdx(#ItemName) .value());
axInventTable.parmTaxPackagingQty (adoFields.itemIdx(#TaxPackagingQty) .value());
axInventTable.parmNetWeight (adoFields.itemIdx(#NetWeight) .value());
axInventTable.parmTaraWeight (adoFields.itemIdx(#TaraWeight) .value());
axInventTable.parmTaxFiscalClassificationId(adoFields.itemIdx(#TaxFiscalClassificationId).value());

axInventTable.axInventTableModule_Sales().parmPrice(100.00);

if(adoFields.itemIdx(#PctIPI).value() == 10)
{
if(adoFields.itemIdx(#ItemType).value() == 'BOM')
{
salesIaxItemGroup = 'V-PA10'; // Venda produto acabado IPI 10%
}
else if (adoFields.itemIdx(#ItemType).value() == 'Item')
{
salesIaxItemGroup = 'V-MP10'; // Venda materia prima IPI 10%
}
else// if (adoFields.itemIdx(#ItemType).value() == 'Service') ou em branco
{
salesIaxItemGroup = "";
}
}

axInventTable.axInventTableModule_Sales().parmTaxItemGroupId(salesIaxItemGroup);

if(adoFields.itemIdx(#ItemType).value() == 'BOM')
{
axInventTable.parmItemType(ItemType::BOM);
}
else if (adoFields.itemIdx(#ItemType).value() == 'Item')
{
axInventTable.parmItemType(ItemType::Item);
}
else if (adoFields.itemIdx(#ItemType).value() == 'Service')
{
axInventTable.parmItemType(ItemType::Service);
}
else // se nada é especificado, cria o produto como ITEM
{
axInventTable.parmItemType(ItemType::Item);
}

// Cria o grupo de produto caso não exista
inventItemGroup = inventItemGroup::find(adoFields.itemIdx(#ItemGroupId).value());
if(!inventItemGroup)
{
inventItemGroup.ItemGroupId = adoFields.itemIdx(#ItemGroupId).value();
inventItemGroup.insert();
}

// Cria a classificação fiscal caso não exista
select fiscalClassification
where fiscalClassification.FiscalClassificationId == adoFields.itemIdx(#TaxFiscalClassificationId).value();

if(!fiscalClassification)
{
fiscalClassification.FiscalClassificationId = adoFields.itemIdx(#TaxFiscalClassificationId).value();
fiscalClassification.insert();
}

axInventTable.parmItemGroupId(adoFields.itemIdx(#ItemGroupId).value());
axInventTable.parmModelGroupId("CUSMED"); // Grupo de modelo de estoque fixo
axInventTable.parmDimGroupId("Std-Dim"); // Grupo de dimensões de estoque fixo
axInventTable.save();
j++;
}
}
adoRecordSet.moveNext();
}
ttscommit;

info(strfmt('Items criados %1',j));
}


quinta-feira, 20 de dezembro de 2007

X++ - Excel via OleDB direto no AX

Saudações a todos!

O Microsoft Dynamics AX dispõe de várias formas de integração.

Entre elas, existe a opção de utilizar o . NET Framework diretamente no código X++, instanciando objetos dos namespaces desejados para ler os dados diretamente da base através do ADO.Net.

A discussão sobre integração surgiu originalmente no fórum MSDN, onde existe um tópico aberto sobre importação de dados para o DAX pelos variados meios, seja AIF, Excel table (que não é recomendável para Itens, vide tópico).
Vale lembrar que a participação de todos os profissionais do ramo nesse fórum é essencial para que possamos construir uma base de conhecimento, com uma "cara" mais prática, fortalecendo nossas referências no mercado.

Voltando ao assunto principal:

O método de acesso é realizado através do .Net framework.

As referências devem ser adicionadas no node
References do AOT.
Ex. System.Data / System.Data.resources / System.Data.SqlXml e assim por diante.

static
void MeuJob(Args _args)

{

System.Data.OleDb.OleDbConnection connection;
System.Data.OleDb.OleDbCommand command;
System.Data.OleDb.OleDbDataReader dr;
str id;
str nome;
str c;
str strSql;

c = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Dados.xls;Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\";";

// O parametro HDR determina se a primeira linha contem os nomes de colunas

// "IMEX=1;" lê os dados como texto.


connection = new System.Data.OleDb.OleDbConnection();
connection.set_ConnectionString(c);
connection.Open();

strSql = "SELECT * FROM [MinhaTabela$]";

//MinhaTabela corresponde ao nome da Planilha seguido por $ e entre []s.

command = new System.Data.OleDb.OleDbCommand(strSql, connection);
dr = command.ExecuteReader();


while (dr.Read())
{
id = dr.get_Item(0);
nome = dr.get_Item(1);
info(strfmt("%1 - %2",id,nome));
}
dr.Close();
}

Caso haja qualquer outra fonte de dados suportada pelos NameSpaces System.Data.* , seja Sql, OleDB ou ODBC, é só procurar o meio de conectar.

Uma fonte interessante é o site www.connectionstrings.com que comporta uma lista com as strings de conexão, bem como suas variações para quase todos os SGBDs disponíveis no mercado.

Aproveitando a época, eu gostaria de deixar um Feliz Natal e um Ótimo 2008 a todos que prestigiam nossa casa e compartilham as idéias.

Um abraço!

Nota Fiscal Eletrônica - função de quebra de nota fiscal por linhas do pedido de venda

A nota fiscal eletrônica traz uma funcionalidade interessante de que faz a quebra dos pedidos de venda por informações contidas nas linhas.

A princípio essa quebra esta apenas disponível quando o parametro de quebra por código de serviço esta ativo.





















Porém, com uma pequena alteração, é possível fazer com que o sistema quebre uma nota fiscal por qualquer campo disponível na linha do pedido de venda mesmo que a empresa não vena serviços.

Basta localizar o grupo chamado InvoiceSplit e adicionar o campo, por exemplo PackingUnit, que é a unidade da embalagem, fazendo isso, o sistema vai quebrar as notas fiscais quando houver diferentes tipos de embalagens para as linhas do pedido de venda.

Até a proxima,

Dynamics AX SP2 para o Brasil

Em novembro foi lançado o SP2 para a localização do AX, esse service pack tras novas funcionalidades localizadas para o AX que não estavam disponíveis anteriormente:

  • Diários de Notas Fiscais (Vendor invoice jourals) agora estão localizados, isto significa que é possivel entrar com notas fiscais e ter os impostos contabilizados e registrados corretamente dentro da lei brasileira.
  • Summary Update agora agrupa corretamente tanto pedidos de compra como pedidos de venda levando em considesções fiscais importantes como CFOP, Tipo de Documento Fiscal, etc..

Também contém 2 novas funcionalidades que cobrem mudanças recentes da lei ou mudanças que estão para entrar em vigor:

  • Nota Fiscal Eletrônica para cidade de São Paulo
  • Campos e formatação da imformatação requeria pelo Ato Cotepe/SPED Fiscal

Sobre a arquitetura de software e como tornar-se um arquiteto.

Recebi uma boa indicação sobre a profissão de arquiteto de software, para que esta nessa área ou gostaria de saber mais, segue o link.

http://www.microsoft.com/brasil/msdn/arquitetura/journal/Profile_Pat_Helland.mspx

quinta-feira, 18 de outubro de 2007

Impostos no AX - Class Tax - Parte 1

Como foi dito no post anterior a classe Tax é o motor de impostos do sistema, sendo uma das mais importantes se tratando de localização brasileira.

Alguns métodos importantes, por ordem de execução (macro) e alguns comentários para cada método:

protected void insertIntersection(TaxGroup _taxGroup,
Neste método, primeiro a ser chamado quando se trata de calcular impostos, nenhum valor é tratado e sim é feita a interseção dos dois grupos de impostos (TaxGroupData e TaxOnItem) e inicializada a tabela temporária tmpTaxWorkTrans, esta tabela tem extrema importancia no manuseio dos impostos no AX, e dela que se deve extrair as imformações enquanto a nota fiscal não é efetivamente registrada, como ela é temporaria e esta dentro da classe tax, deve ser tomado um cuidado especial quando tentar usala em um escopo fora desta classe, sempre acessando o método tmpTaxWorkTrans(), que retorna a tabela.


protected void insertLineInInternal(TaxBase _baseAmount,
Ao meu ver, o melhor lugar para se "trabalhar" com as bases dos impostos, é o primeiro lugar em que se pode alterar de qualquer maneira a base dos impostos sem que haja consequencias para o post dos impostos, da nota fiscal ou que quebre o método de calculo, calculo do limite mínimo ou máximo, etc... do imposto.


TaxAmount calcTax()
Método que efetivamente faz os impostos serem calculados, a principio tem uma maniera um pouco estranha de trabalhar ja que a tabela que é utilizada nesse escopo é a TmpTax e não a TmpTaxWorkTrans, o método organiza a sequencia de calculo, isto é, impostos que tem usa base de cálculo baseada no valor "net" são calculados primeiro que impostos que tem a base baseada no "gross", em outro momento posto sobre meu entendimento de "net" e "gross" aplicado as bases de impostos aqui no Brasil.
Quem efetivamente calcula os impostos é a propria tabela de imposto através do método TaxTable.calcTaxSimple e .calcTax, um ponto importante para a localização brasileira é que regras de negócio importantes estão definidas dentro desses métodos como a redução na ase de impostos e aumento da base de impostos, aplicada a substituição tributária.


public void saveAndPost()
Método que cria as transações de impostos e registra os lançamentos contábeis relativos aos impostos.


protected void post(TaxDirection _taxDirection,
Chamado pelo método saveAndPost, contém a lógica do registro no objeto LedgerVoucher.

Impostos no AX - Visão geral

O termo Imposto é usado em 10 de 10 conversas sobre ERPs no Brasil, e claro, é foco de preocupações quando se fala de ERPs internacionais.

Tecnicamente falando, os impostos no AX são dividos em 2 classes básicas:
1. Tax
2. TaxWithhold

class Tax
A classe Tax é a base do potente motor de impostos do AX ela é responsável por descobrir que impostos devem ser calculados, trabalhar em cima das bases dos impostos até chegar na base final, que vai ser usada para efetivamente o calculo dos impostos e finalmente e registrar-los contabilmente.
Essa classe é utilizada em todos os lugares do sistema onde se vê Impostos sobre Vendas (Sales Tax), isto é, atua no momento que uma nota fiscal (seja ela se vendas, compras, projetos) é postada no sistema.


class TaxWithhold
Esta classe trabalha no famigerado calculo de impostos retidos no pagamento (seja ele de clientes ou fornecedores). Diferente dos impostos sobre vendas, os impostos aqui são calculados com base em um único grupo de impostos e não a interseção (união de 2 grupos) de grupos de impostos. A classe cumpre a tarefa de descobrir a base do imposto, calculá-la e registra-la contabilmente.
Um detalhe importante é que diferente da classe Tax. a classe TaxWithhold não é uma super classe totalmente genérica, criada para a retenção de impostos (ou um único imposto) no pagamento a fornecedores para a Itália, foi estendida para o Brasil para também tratar pagamentos recebidos de clientes, para isso, temos a classe:
TaxWithhold_CustPaym extends TaxWithhold, onde os métodos mais importantes da classe TaxWithhold são sobrescritos para tratar os impostos com base na tabela CustTrans e não VendTrans.

Histórico sobre retenção no pagamento:
Criada pela lei 10.833 de 2003 que diz que para uma serie de serviços, quem contrata o serviço é obrigado a reter, no ato do pagamento (e não do faturamento) o imposto, com o detalhe que ele so começa a ser retido após após o pagamento a partir 5000,00 e pior ainda, cumulativo, isto é, para um pagamento de 3000,00, não há impostos, para outro pagamento, no mesmo mes de 3000,00, deve ser retido os impostos com base em 6000,00 e a partir daí, todos os pagamentos devem ter o imposto retido.