quinta-feira, 18 de fevereiro de 2016

Apagando Campanhas no Salesforce

Recentemente estava realizando alguns testes e precisei apagar várias Campanhas que havia criado. Qual a forma mais rápida de apagar, pensei... Abri o Console do desenvolvedor, na janela de execução de código anônimo, escrevi o código a seguir e executei:

 List<Campaign> campanhas = [SELECT id FROM Campaign];  
 delete campanhas;  

Após tentar executar recebi a seguinte mensagem de erro:

DML operation DELETE not allowed on Campaign

Verifiquei se meu usuário possuía permissão no objeto e estava tudo certo. Então fui pesquisar o motivo. Descobri que o motivo era porque meu usuário não estava configurado como "Usuário do marketing". Então acessei o cadastro de usuários do SFDC e cliquei em Editar (o meu usuário). Em seguida marquei a opção "Usuário do marketing:



Pronto, executei novamente o código e consegui apagar as campanhas normalmente.

Finalizando... Com essa opção de  "Usuário do marketing" marcada você poderá:

- Criar uma nova campanha;
- Editar uma campanha existente;
- Apagar uma campanha;
- Atualizar estatísticas da campanha;
- Importar leads em uma campanha;
- Atualizar em massa, os status de membros de uma campanha;
- Alterar configurações avançadas de uma campanha;

- Rodar relatórios de campanhas por múltiplas campanhas.

domingo, 7 de fevereiro de 2016

Datetime no horário local em páginas Visualforce

Um problema comum entre os desenvolvedores de páginas Visualforce, é a exibição de dados Datetime no horário local (local time). O Salesforce armazena os dados de data e hora no padrão GMT. Dessa forma, ao realizar uma consulta SOQL no banco de dados do SFDC, em sua classe Controller, os dados de data e hora virão no padrão GMT. 

Bem, para exibir em sua Visualforce, os dados de data e hora no horário local da sua Org, use o método a seguir:

   public Datetime getLocalDateTime(Datetime z)  
   {    
     Datetime l = z.Date();  
     l = l.addHours(z.hour());  
     l = l.addMinutes(z.minute());  
     l = l.addSeconds(z.second());  
     return l;  
   }  

Com esse método, sua propriedade ou variável que estava sendo exibida no padrão GMT será exibido na hora local. Coloquei um System.Debug no código para verem o resultado:





sexta-feira, 5 de fevereiro de 2016

Inserindo referências de CSS e JS de recursos estáticos em páginas Visualforce

É comum encontrarmos alguma solução na Web, que gostaríamos de utilizar em nossas páginas Visualforce. Muitas dessas soluções incluem arquivos Javascript e CSS. Para usufruir de soluções como essa (que possuem referências JS e CSS) em nosso projeto, dentro do Salesforce, é necessário primeiramente fazer o upload desses arquivos (JS e CSS) para os recursos estáticos do SFDC. Os recursos estáticos se encontram em Configurações | Criar | Desenvolver | Recursos estáticos

Ao acessar o caminho acima, você deve dar um nome para seu recurso que está inserindo no SFDC. Esse recurso pode pode ser um arquivo .css ou um arquivo .zip com vários outros arquivos css e js, por exemplo.

Após inserir esses recursos estáticos, já podemos fazer uso deles, em nossa página Visualforce. Basta colocar os seguintes comandos em sua página Visualforce:

Para JS:

 <apex:includeScript value="{!URLFOR($Resource.NomeDoRecursoEstatico, 'arquivo.js')}"/>  

Para CSS:

 <apex:stylesheet value="{!URLFOR($Resource.NomeDoRecursoEstatico, 'arquivo.css')}" />    

Caso queira colocar a tag Media na sua referência ao CSS, use:


 <apex:stylesheet value="{!URLFOR($Resource.NomeDoRecursoEstatico, 'arquivo.css')}" html-media="print" />    

Se seu JS se encontrar dentro de um recurso estático em formato .zip e possua diretórios dentro desse zip, use:


 <apex:includeScript value="{!URLFOR($Resource.NomeDoRecursoEstatico, 'diretorio1/diretorio2/arquivo.js')}"/>  

Caso o seu CSS esteja em um zip e possua diretórios:

 <apex:stylesheet value="{!URLFOR($Resource.NomeDoRecursoEstatico, 'diretorio1/diretorio2/arquivo.css')}" />  


Por hora, é apenas isso! :)


segunda-feira, 1 de fevereiro de 2016

Relatório com diferença de vendas mês a mês

A Salesforce sempre me surpreende com sua flexibilidade, em diversas áreas. Dessa vez, destaco a facilidade que temos na ferramenta de relatórios, para gerar um relatório de avanço mês a mês (poderia ser ano a ano, trimestre a trimestre) das vendas.

Para iniciar, vamos criar um novo relatório de Oportunidades. Para tal, acesse a guia Relatórios e posteriormente clique em Novo relatório... Selecione o tipo de relatório como Oportunidades.


Após selecionar o tipo de relatório, clique em Criar. Em seguida selecione os campos desejados, entre eles, adicione o campo Valor e Mês de fechamento.


Agora faça o agrupamento pelo mês de fechamento. Para tal, passe o cursor sobre o título da coluna Mês de fechamento, clique na seta que aparecerá no canto direito e por fim, clique em Agrupar por esse campo.


Agora será necessário passar o cursor sobre o campo Valor, clicar na setinha no canto direito e clicar na opção Resumir este campo



Será exibido um pop-up para selecionar o tipo de resumo. Selecione Soma e clique em Aplicar.


Agora vamos fazer a parte mais interessante. Vamos em Adicionar fórmula...


E arraste essa opção para alguma posição do relatório. No meu caso, vou arrastar para ser a última coluna do relatório.


Após adicionar, será exibida uma tela para configuração da fórmula. Dê um nome para essa coluna. Eu vou chamar de Crescimento em relação ao mês anterior. Vou configurar para o formato ser Porcentagem, sem casas decimais (0). Também irei marcar a que a formula será exibida no agrupamento por mês de fechamento.


Agora vamos escrever a formula. Para se calcular o percentual de crescimento, precisamos escrever a seguinte fórmula:


Valor Final = Mês atual
Valor Inicial = Mês anterior

Transformando isso na formula do relatório, precisamos pegar os valores das oportunidades do mês atual e mês anterior. 

AMOUNT:SUM = Campo Amount, que é o valor da oportunidade. Porém, como se trata da somatória dos valores por mês, temos o SUM.

PREVGROUPVAL(AMOUNT:SUM, CLOSE_MONTH) = PREVGROUPVAL é uma função para se pegar o valor anterior em um relatório agrupado. Dessa forma, pegamos o valor anterior das somas de quantidades, do agrupamento por mês de fechamento (CLOSE_MONTH).

Ficando a fórmula assim:

(AMOUNT:SUM-PREVGROUPVAL(AMOUNT:SUM, CLOSE_MONTH))/PREVGROUPVAL(AMOUNT:SUM, CLOSE_MONTH)


Após a fórmula inserida, vamos executar o relatório e ver o resultado de crescimento (ou retração) mês a mês!




quinta-feira, 28 de janeiro de 2016

Relacionamento entre seus clientes - SFDC

Em um cenário que se deseja saber o nível de relacionamento entre seus clientes, o Salesforce possui uma funcionalidade para tal. Se trata da lista relacionada da Conta chamada "Partners" ou "Parceiros".


Através dela, é possível rastrear os fornecedores do seu cliente. Ou os distribuidores e revendedores dele... Enfim, conhecer estrategicamente quem relaciona com ele.

Bem, para associar um novo parceiro, selecione a conta desejada e clique no botão "Novo" na lista relacionada "Parceiros" para definir os parceiros dessa conta.


Selecione a conta do parceiro do seu cliente e defina o papel desse parceiro. Há algumas opções de papel, nativas da Salesforce, que vem em inglês. Você pode usá-las (traduzidas ou não). 
Ao selecionar os parceiros e respectivos papéis e clicar em salvar, eles ficarão disponíveis na lista relacionada de parceiros, tanto do cliente, como do parceiro selecionado.


Voltando nos papéis do Parceiro... Para adicionar novos papéis de parceiros, acesse as configurações do Salesforce, Criar | Personalização | Conta | Papéis do parceiro


A inserção, alteração ou remoção é bem simples e intuitiva. Semelhante a manipulação de um campo lista de opções (picklist).


Bem, basicamente é isso...


domingo, 27 de dezembro de 2015

Caputurando novos clientes em potencial com o Web-to-lead

Hoje conheci uma ferramenta bem interessante, da Salesforce, para capturar Leads, chamada "Web-to-lead". E é sobre ela que falaremos nesse post.

Para quem não está familiarizado com o termo, lead é o famoso "prospect", novo contato, cliente em prospecção ou cliente em potencial... Dentro da Salesforce, mesmo com a linguagem em português brasileiro, o termo não é traduzido. Sinal que o termo lead é conhecido e usado no meio do marketing e venda.

A ferramenta "Web-to-lead" da salesforce, permite integrar seu website com a plataforma SFDC, de forma simples e rápida. Através dela, além de capturar os leads diretamente para dentro da sua Org, é possível facilmente configurar respostas automáticas para o "cliente" e definir os campos que serão inseridos através do website. Tudo isso independente se seu site foi desenvolvimento em HTML, ASP.NET, JAVA, PHP, etc.

Iniciando os trabalhos, vamos criar um Modelo de e-mail para que, sempre que um lead, entre em contato comigo, pelo meu site, ele receba um e-mail automático. 



Agora que já temos o nosso e-mail padrão de auto-resposta, vamos configurar o Web-to-lead. Acesse Setup / Criar / Personalização / Leads / Web-to-lead



Caso a opção "Web-to-lead ativado" não esteja marcada, marque-a. Além disso, defina no campo "Modelo de resposta padrão", para definir o modelo de e-mail que criamos anteriormente para enviar uma resposta automática para o lead. Se não desejar enviar um e-mail automático para seu "cliente", basta não preencher o campo "Modelo de resposta padrão".

Vamos então criar o nosso formulário que será integrado ao nosso website. Ainda em Setup / Criar / Personalização / Leads / Web-to-lead acesse a opção "Criar formulário Web-to-lead". 



Nessa opção vamos definir quais campos (do objeto Lead) estarão disponíveis para o usuário preencher. Adicione os campos desejados na caixa "Campos selecionados". Você poderá também alterar a ordem desse campos através dos botões "Para cima" e "Para baixo". E por final, será necessário definir a "URL de retorno". Isto é, para qual página do seu site, o usuário será redirecionado após preencher e submeter o formulário. Creio ser importante criar uma página (pode ser HTML mesmo) no seu website, dizendo que o formulário de contato foi enviado com sucesso e setar nesse campo "URL de retorno". Mas caso não tenha interesse, coloque a página inicial do seu site ou outra que achar relevante.

Após realizar configurar o formulário, clique em "Gerar", para gerar um formulário HTML. Veja o resultado da geração:



Esses código gerados (HTML) deverá ser salvo em uma página HTML, PHP, ASPX, JSP ou qualquer outro formato web. E posteriormente enviado para o servidor que hospeda seu website. Importante ressaltar que o código gerado, não possui nenhuma formatação especial com CSS. Dessa forma, creio ser importante seu webdesigner trabalhar nesse código, caso você não tenha know-how para formatar.

Após a implantação da página no seu site, é só acessar o endereço, preencher os campos e clicar em "Enviar". E os dados, como mágica, irão aparecer entre seus Leads, no Salesforce. Simples, não acha?!

Regras de auto-resposta

As regras para resposta automática (ou auto-resposta) são importantes para enviar e-mails automáticos, diferenciados, de acordo com o preenchimento dos campos do formulário. Um exemplo seria enviar um e-mail específico, caso o usuário queira informações sobre um produto X. Porém se ele quiser mais detalhes sobre o produto Y, você poderá enviar automaticamente outro e-mail.

No nosso modelo de e-mail, que criamos no início desse post, se tratava de uma mensagem totalmente em português, certo? Mas se alguém acessar o formulário de contato do nosso site e disser que mora fora do Brasil? Ele irá receber uma resposta automática em português, certo? Errado... porque vamos criar uma regra para enviar um e-mail em inglês para o lead!

Primeiramente, vamos criar novamente um novo modelo de e-mail, porém com o texto em inglês. O segundo passo, será definir (caso não tenha feito isso ainda em sua Org), um e-mail padrão para envio da mensagem automática. Isso será possível através de: Setup / Administrar / Administração de email / Endereços de toda a organização. Nessa opção, clique em "Adicionar".


Preencha os campos "Exibir nome" e "Endereço de email". Posteriormente, marque uma das opções de utilização do e-mail (nesse caso, optei pela opção que permite todos os perfis utilizarem o endereço) e por fim, clique em salvar. É importante destacar que você receberá uma mensagem no e-mail cadastrado, para que você possa confirmar a autenticidade dessa conta.

Até então, estavamos apenas pré-configurando alguns itens para criar a a regra de resposta automática. Agora vamos de fato, criar a regra. Acesse: Setup / Criar / Personalização / Leads /Regras de resposta automática de lead. Em seguida, clique em "Novo". Digite um nome para regra e marque a opção "Ativado":


Após salvar, você será direcionado para a lista de regras de auto-resposta. Clique sobre o nome da regra para configurá-la. 
Na lista "Entrada de regras" clique em "Novo".



Nessa tela, é necessário preencher a ordem de classificação da regra. Isso significa que você poderá ter várias "entradas" para essa regra. 
Em seguida, preencher o critério para que seja enviado o modelo de e-mail que selecionaremos a seguir (e não o padrão). Nesse caso, colocamos que o campo "País" do objeto Lead, não pode ser (não igual) a "Brasil". Isto é, se o usuário, preencher no formulário, algo diferente de "Brasil", ele irá receber o e-mail do modelo que selecionaremos a seguir. 
Logo após, precisamos preencher os campos "Nome" e "Endereço de e-mail". É importante destacar que o endereço de e-mail preenchido deve ser um e-mail válido, cadastrado na opção "Endereços de toda organização", que vimos acima.
E por fim o modelo de e-mail em inglês, que criamos anteriormente. 
Agora é somente Salvar e testar. 

Veja que, caso preencha no formulário do site, o campo País: Brasil, receberá um e-mail em português. Caso não preencha, receberá em inglês.

Para finalizar, é importante fazer as seguintes ressalvas:

- Você não poderá selecionar campos de relacionamento do objeto lead, para serem inseridos no formulário, exceto Campanha.
- Você somente poderá receber 500 leads por dia. Caso precise receber mais, entre em contato com a Salesforce.
- Caso deseje validar os campos do formulário gerado para seu site, você deverá fazer por conta própria usando javascript. Regras de validação criadas no SFDC serão inválidas para o formulário web do seu site.

Bem, acho que já me alonguei demais. Até mais e bons leads :)

quarta-feira, 23 de dezembro de 2015

Problemas com Update em Custom Settings, no Salesforce.com

Estava trabalhando recentemente em uma demanda, em que eu deveria alterar, via código Apex, o valor de alguns campos de uma Custom Settings. Como já havia feito a operação de consulta de dados de uma Custom Settings com certa facilidade anteriormente, imaginei ser bem tranquila também a atualização. E realmente é! A questão é que tive alguns problemas para realizar essa operação de Update.

Caso tenha chegado até aqui, sem muito conhecimento do que são as Custom Settings, acesse o link abaixo para maiores informações:
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_custom_settings.htm

Inicialmente, antes de resolver o problema, precisamos de ter ciência da hierarquia das Custom Settings:
- Geral de toda Org;
- Específica de um Perfil de Usuário;
- Específica de um Usuário;

Bem, conhecendo a hierarquia, realizei alguns teste e verifiquei as formas de buscar os dados das Custom Settings:

MinhaCustomSetting__c settings = MinhaCustomSetting__c.getInstance();
Dessa forma eu buscava o valor padrão para o meu usuário, sempre respeitando a hierarquia. Isto é, se houvesse um valor para meu usuário, este seria retornado. Caso não, retornaria do perfil do meu usuário. Caso não, retornaria o valor geral da Org.


MinhaCustomSetting__c settings = MinhaCustomSetting__c.getInstance('IdDoUsuario');
Dessa forma eu recebia o valor padrão de Custom Setting para o usuário indicado, sempre respeitando a hierarquia.

MinhaCustomSetting__c settings = MinhaCustomSetting__c.getInstance('IdDoPerfil');
Busca os valores padrões para o perfil, se existir, caso não, retornará os valores padrões da Org;

MinhaCustomSetting__c settings = MinhaCustomSetting__c.getOrgDefaults();
Busca os valores padrões da Org, independente de usuário ou perfil;

MinhaCustomSetting__c settings = MinhaCustomSetting__c.getValues('IdDoUsuario');
Busca os valores do usuário como um todo. A diferença para o getInstance('IdDoUsuario') é que se houver (no getInstance) 2 campos, 1 preenchido e o outro não, será feita uma busca, para cima na hierarquia até encontrar um valor para a variável não preenchida. Já para o getValues('IdDoUsuario') irá retornar os valores do usuário, independente do preenchimento;

MinhaCustomSetting__c settings = MinhaCustomSetting__c.getValues('IdDoPerfil');
Busca os valores do por perfil, com a mesma lógica do getValues('IdDoUsuario');

Com essas informações, comecei a escrever o código para buscar os dados relacionados ao meu usuário, na Custom Settings:


           MinhaCustomSetting__c settings = MinhaCustomSetting__c.getInstance();  
           settings.Campo__c = 'Novo valor';  
           update settings;  

Porém, ao executar esse código, percebi que o valor do campo "Campo__c" não era atualizado. Após realizar diversos testes, percebi que ao fazer acessar os dados com o getInstance() sem parâmetro, o objeto settings, instancia o MinhaCustomSetting__c com o campo ID nulo. E por esse motivo o Update não funcionava. Afinal, é impossível atualizar algo, sem seu respectivo ID. 
Diante dessa situação, resolvi realizar outros testes e ficou claro que somente seria instanciado o objeto com o ID, quando houvesse a referência hierárquica criada. Por exemplo: 

- Geral de toda Org: Referenciado;
- Específica de um Perfil de Usuário: Referenciado;

- Específica de um Usuário: Não referenciado;

Com o cenário acima, qual dos abaixo, retornaria o ID?


 MinhaCustomSetting__c setting1 = MinhaCustomSetting__c.getInstance();  
 System.debug('setting1: ' + setting1.id);  
 //Não retorna ID pois pega os valores pela hierarquia  
   
 MinhaCustomSetting__c setting2 = MinhaCustomSetting__c.getInstance(UserInfo.getUserId());  
 System.debug('setting2: ' + setting2.id);  
 //Não retorna ID pois não criei uma referencia direta por usuário  
   
 MinhaCustomSetting__c setting3 = MinhaCustomSetting__c.getInstance(UserInfo.getProfileId());  
 System.debug('setting3: ' + setting3.id);  
 //Retorna o ID pois criei uma referência para o perfil  
   
 MinhaCustomSetting__c setting4 = MinhaCustomSetting__c.getOrgDefaults();  
 System.debug('setting4: ' + setting4.id);  
 //Retorna o ID, pois há uma referência para toda ORG  
   
 MinhaCustomSetting__c setting5 = MinhaCustomSetting__c.getValues(UserInfo.getUserId());  
 System.debug('setting5: ' + setting5.id);  
 //Exceção é levantada, pois não há referência para o usuário e o settings5 é null;  
   
 MinhaCustomSetting__c setting6 = MinhaCustomSetting__c.getValues(UserInfo.getProfileId());  
 System.debug('setting6: ' + setting6.id);  
 //Retorna o ID, pois criei uma referência por perfil  


Isto é, quando há uma referência completa, o ID é retornado e é possível realizar o Update. No meu exemplo inicial, alterei a utilização do getInstance() para getOrgDefaults(), pois me atenderia melhor.
Para finalizar, é importante ressaltar que são coisas diferentes o fato de retornar o ID e o procedimento de retornar os valores hierarquicamente. 

Caso ainda tenha dúvidas, é só postar nos comentários que tentarei responder.