Páginas

MATERIAL CFOP + CST

Bom Dia a todos,

Nas ultimas semanas tenho demonstrado este material a muitos consultores que questionam o uso da CFOP + CST no AX, O mesmo é bem simples mas demonstra como utilizarmos estas caracteristicas. Aproveito e faço minha primeira Publicação no site.

TABELA II
CÓDIGO DA SITUAÇÃO TRIBUTÁRIA –CST
(Códigos a que se refere o art.230 deste regulamento)

AS OPÇÕES SÃO:



Poderemos cadastrar de 2 formas:

1) Caso o Item sempre ter uma compra em 1(uma) determinada situação acima demonstrada, este poderá ser fixado no cadastro de itens :

CAMINHO AX: Gerenciamento de estoque > Detalhes do item > Informações Fiscais:



2) Caso o Item ter mais de uma origem das situações acima demonstradas, este poderá ser identificado no cadastro de informações fiscais da Ordem de Venda :

CAMINHO AX: Contas a receber > Detalhe da Ordem de Venda > Itens > Informações Fiscais:



1) Grupo de Impostos Sobre Vendas do Item:

CAMINHO AX: Contabilidade > Configuração > Imposto sobre vendas > Grupo de impostos sobre venda do item:




Para impostos que existir mais de um Valor fiscal ou código de Tributação, o mesmo deverá ser cadastrado separado em:

CAMINHO AX: Contabilidade > Configuração > Imposto sobre vendas > Código de imposto sobre vendas

E identificado através da regra da matriz de impostos em qual momento deverá ser utilizado cada código de tributação nas notas fiscais de vendas. Exemplo:


Espero que seja de grande utílidade.

Nelson Romero

Como enviar e-mail pelo AX sem configurar o Outlook

Essa semana precisei fazer o AX enviar e-mails direto, sem precisar configurar o Outlook.

Para isso verifiquei em alguns blogs de referência e no final criei um código simples e com algumas configurações do sistema fiz o envio diretamente pelo AX.

Antes de alterar qualquer código, vamos parametrizar a conta que o AX utiliza para fazer o envio, para isso vamos acessar o módulo Administração > Configuração > Parâmetros de email.
 

Nessa tela vamos configurar o servidor de saída, computador local, porta SMTP, tamanho do anexo e outras configurações como nome do usuário, senha e se iremos utilizar autenticação NTLM (que é um protocolo de autenticação para transações entre dois computadores em que um ou ambos estejam executando o Windows NT 4.0 ou anterior).

Ao enviar os e-mail eu não quero que apareça a conta que configuramos como remetente para executar o envio, para isso o usuário que está logado no sistema precisa ter a sua conta configurada nas opções de usuário.

Para configurar vamos no Painel de Navegação do Microsoft Dynamics AX > Ferramentas > Opções e vamos configurar a conta de email do usuário no campo Email:
 

Feito isso vamos alterar o código reportSendMail() da classe Info:
  1. void reportSendMail(PrintJobSettings p1)
  2. {
  3.     System.Net.Mail.MailMessage myMailMessage;
  4.     System.Net.Mail.Attachment attachment;
  5.     System.Net.Mail.AttachmentCollection attachementCollection;
  6.     System.Net.Mail.SmtpClient myMail;
  7.     System.Net.NetworkCredential myNC;
  8.     //Atribui o nome de usuário e senha dos parâmetros para as variáveis 
  9.     str myLogin = SysEmailParameters::find(true).SMTPUserName;
  10.     str myPassword = SysEmailParameters::password();
  11.     str userMailAddress; 
  12.     str receiverMailAddress;
  13.     str mailBody;
  14.     str smtpServer;
  15.     str mail;
  16.     str fileName = 'axaptareport';
  17.     FileNameOpen    fileNameForEmail; 
  18.     FileIOPermission perm;
  19.     ;
  20.     //Verifica o tipo do Anexo 
  21.     if (p1.format() == PrintFormat::ASCII)
  22.     {
  23.         fileNameForEmail = subStr(p1.fileName(),strLen(p1.fileName())-3,-999)+'TXT'; 
  24.     }
  25.     else if (p1.format() == PrintFormat::RTF)
  26.     {
  27.         fileNameForEmail = subStr(p1.fileName(),strLen(p1.fileName())-3,-999)+'RTF';
  28.     }
  29.     else if (p1.format() == PrintFormat::HTML)
  30.     {
  31.         fileNameForEmail = subStr(p1.fileName(),strLen(p1.fileName())-3,-999)+'HTM';
  32.     }
  33.     else if (p1.format() == PrintFormat::PDF || p1.format() == PrintFormat::PDF_EMBED_FONTS) 
  34.     {
  35.         fileNameForEmail = subStr(p1.fileName(),strLen(p1.fileName())-3,-999)+'PDF';
  36.     }
  37.     mail = subStr(fileNameforEmail,(strlen(fileNameforEmail)-8),9); 
  38.     fileNameforEmail = winApi::getTempPath() + mail;
  39.     perm = new FileIOPermission(fileNameforEmail,'w');
  40.     //Verifica se o usuário tem permissão 
  41.     if (!perm)
  42.     {
  43.         throw error("Não é possível mover o anexo para a pasta Temp.");
  44.         return;
  45.     }
  46.     else
  47.     {
  48.         try
  49.         {
  50.             perm.assert();
  51.         }
  52.         catch
  53.         {
  54.             throw error("Não é possível acessar a pasta Temp.");
  55.             return;
  56.         }
  57.         userMailAddress = SysUserInfo::find().Email;
  58.         receiverMailAddress = p1.mailTo() + "," + p1.mailCc();
  59.         mailBody = "E-mail enviado a partir da " + CompanyInfo::name() + ", pelo Microsoft Dynamics AX";
  60.         smtpServer = SysEmaiLParameters::find(false).SMTPRelayServerName;
  61.         myMailMessage = new System.Net.Mail.MailMessage(userMailAddress,receiverMailAddress);
  62.         myMailmessage.set_Subject(p1.mailSubject());
  63.         myMailmessage.set_Body(mailBody);
  64.         winapi::moveFile(p1.fileName(), fileNameforEmail);
  65.         attachementCollection = myMailMessage.get_Attachments();
  66.         attachment = new System.Net.Mail.Attachment(fileNameforEmail);
  67.         attachementCollection.Add(attachment);
  68.         myMail = new System.Net.Mail.SmtpClient(smtpServer);
  69.         myNC= new System.Net.NetworkCredential(mylogin,mypassword);
  70.         myMail.set_Credentials(myNC);
  71.         myMail.Send(myMailmessage);
  72.         Box::info("E-mail enviado com sucesso!");
  73.     }
  74. }
Para testar, vamos realizar o envio do e-mail de um relatório de clientes no módulo Contas a receber > Relatórios > Dados Básicos > Cliente


Filtrei apenas alguns clientes e agora vamos no botão Opções, selecionar a opção Destinatário do email, Preencher o assunto, destinatário, formato do anexo e depois Ok:


Você terá uma mensagem informando que o e-mail foi enviado com sucesso e receberá o e-mail com o relatório.
Note que o e-mail do remetente é o e-mail que configuramos nas opções do usuário.
E por fim temos o relatório do cliente em anexo.



Fiz um código meio que as pressas para isso e tenho certeza que dá para melhorar, cheguei a ver até que você pode configurar um template do corpo do email, por isso aceito sugestões e dúvidas.

Quando tiver um tempo vou dar uma olhada com calma nessa parte dos templates e crio um novo post futuramente.

[]'s
Alexssander

Como criar uma conexão entre o SQL e o Dynamics AX

Eu estou trabalhando em uma migração de dados um tanto extensa, mas ao invés de trabalhar exportando dados do antigo sistema para um arquivo e importando o mesmo para o AX, decidimos criar uma conexão direta com o SQL, ler as informações e importá-las para o AX. Meu amigo ucraniano que trabalha comigo Kirill Val me deu as instruções e depois da primeira classe o resto é brincadeira de criança. Gostaria de que caso alguém tenha alguma sugestão de melhoria, por favor envie.

Criei uma classe chamada AXImport e no método classDeclaration() eu declaro duas variáveis, uma do tipo LoginProperty e outra do tipo ODBCConnection. Essa classe específica é usada também para update, por isso, para executá-la em batch, eu a fiz extendendo a classe RunBaseBatch, mas não é uma regra.
  1. public class AXImport extends RunBaseBatch
  2. {
  3.     LoginProperty         loginProperty;
  4.     ODBCConnection  connection;
Depois crie um método connect() que faça a conexão com o banco:
  1. void connect()
  2. {
  3.     ;
  4.     loginProperty = new LoginProperty();
  5.     loginProperty.setServer('localhost');//Endereço do server, no caso era local
  6.     loginProperty.setDatabase('DATABASE');//Nome da base, na dúvida, cheque no SQL
  7.  
  8.     connection = new ODBCConnection(loginProperty);
  9. }
Crie os métodos pack() e unpack():
  1. public container pack()
  2. {
  3.     container ret;
  4.     return ret;
  5. }

  1. public boolean unpack(container packedClass)
  2. {
  3.     boolean ret = true;
  4.     return ret;
  5. }
Agora crie um método que leia os dados do banco e os insira no AX. Só vamos criar um método que vai inserir alguns fornecedores. Como é um exemplo, só vou mandar buscar o id, nome e grupo de fornecedores. Você pode colocar quais campos você quer no select, ou usar o SELECT * FROM, mas neste caso, você vai precisar ver no SQL qual vai ser a ordem em que os campos aparecem, enquanto na primeira opção você escolhe a ordem dos campos. Saber a ordem dos campos é importante na hora de determinar qual campo do banco preencherá o campo da tabela no AX.
  1. void TransferData()
  2. {
  3.     Statement statement;
  4.     ResultSet  resultSet;
  5.     str            sql;
  6.     str            description;
  7.     SqlStatementExecutePermission perm;
  8.     VendTable      vendTable;
  9.     AxVendTable axVendTable;
  10.     VendGroupId vendGroup;
  11.     VendAccount vendAccount;
  12.     VendName    vendName;
  13.     ;
  14.     //Deve ser utilizado a sintaxe do SQL, não a do AX.
  15.     sql = "SELECT NANUM, NANAME, NAVENDG FROM TABELA_EXEMPLO";
  16.     perm = new SqlStatementExecutePermission(sql);
  17.     perm.assert();
  18.  
  19.     statement = connection.createStatement();
  20.     resultSet  = statement.executeQuery(sql);
  21.  
  22.     while (resultSet.next())
  23.     {
  24.         //Na mesma ordem do select ou, se usado o select * from, na que está no SQL
  25.         vendAccount = strrtrim(resultSet.getString(1));
  26.         vendName = strrtrim(resultSet.getString(2));
  27.         vendGroup = strrtrim(resultSet.getString(3));
  28.         vendTable = VendTable::find(vendAccount);
  29.  
  30.         if (!vendTable)
  31.         {
  32.             axVendTable = new AxVendTable();
  33.             axVendTable.parmAccountNum(vendAccount);
  34.             axVendTable.parmVendGroup(vendGroup);
  35.             axVendTable.parmName(vendName);
  36.             axVendTable.save();
  37.             info("Inserido Fornecedor: " + vendAccount);
  38.         }
  39.     }
  40.     resultSet.close();
  41.     statement.close();
  42. }
Crie o método run() que vai chamar primeiro o método da conexão e depois o da transferência de dados.
  1. public void run()
  2. {
  3.     this.connect();
  4.     this.TransferData();
  5. }
Crie o método main():
  1. static void main(Args args)
  2. {
  3.     AXImport axImport = new AXImport();
  4.     ;
  5.     if (axImport.prompt())
  6.     {
  7.         axImport.run();
  8.         info("Importação concluída");
  9.     }
  10. }
Bom, essa é a classe de exemplo, qualquer sugestão de melhoria ou críticas são bem-vindas.