quinta-feira, 27 de abril de 2017

Exibindo corretamente Data/Hora em páginas Visualforce do Salesforce

Você que desenvolve páginas Visualforce no Salesforce, provavelmente já enfrentou dificuldades ao exibir data e hora em páginas Visualforce - VF. Como já expliquei em um post anterior (com título Datetime no horário local em páginas Visualforce), o Salesforce armazena as informações de Data/Hora no GMT 0. Portanto, se não for feito nada, essas informações serão exibidas na VF no GMT 0, o que irá confundir o usuário.

Além da sugestão de resolução que dei no post supracitado, encontrei duas outras formas. Veja quais são:

1) Utilizar <apex:OutputField />

Veja que quando se utiliza o <apex:OutputField /> diferente do <apex:OutputText /> a hora já vem formatada no GMT padrão.

Controller:


  
public class TesteController {
    public MeuObjeto__c obj { get; set; }
    
    public TesteController() {
        this.obj = new MeuObjeto__c();
        this.obj.DataHoraOcorrido__c = DateTime.Now();
    }
}


Visualforce:


 
<apex:page controller="TesteController" >

 <apex:outputText value="{!Obj.DataHoraOcorrido__c}" />
 <br/><br/>
 <apex:outputField value="{!Obj.DataHoraOcorrido__c}" />

</apex:page>


Resultado:




2) Utilizar o fuso horário através do Apex


Dessa forma, crio uma propriedade no Apex que retorna um cálculo em cima do Timezone (fuso horário) do Usuário, que deve ser adicionado à Data/Hora.


Controller:


public class TesteController {
    public MeuObjeto__c obj { get; set; }
    
    public TesteController() {
        this.obj = new MeuObjeto__c();
        this.obj.DataHoraOcorrido__c = DateTime.Now();
    }
    
    public Double Timezone {
        get {
            return UserInfo.getTimeZone().getOffset(DateTime.now()) / (1000 * 3600 * 24.0);
        }
    }
}


Visualforce:


 
<apex:page controller="TesteController" >

 Não formatado: <br/>
 <apex:outputText value="{!Obj.DataHoraOcorrido__c + timezone}" />

 <br/><br/>

 Formatado: <br/>
 <apex:outputText value="{0,date,dd/MM/yyyy HH:mm:ss}">
  <apex:param value="{!Obj.DataHoraOcorrido__c + timezone}"/>
 </apex:outputText>

</apex:page>


Resultado:





Por hoje é só! Até a próxima...



* Está precisando de um suporte ou uma consultoria formatações de Data e Hora nas Visualforce dentro da sua plataforma Salesforce? Entre em contato conosco - CbCloud: http://www.cbcloud.com.br/ Somos parceiros Salesforce

sexta-feira, 21 de abril de 2017

Alterando Membros do time da Oportunidade em massa - Salesforce

Hoje me deparei com uma situação em que alterar um Membro do Time da Oportunidade, em massa, por outro. A princípio pensei: "Simples! Vou no Objeto OpportunityTeamMember e altero o UserId de um usuário para outro.". Cheguei até a criar um rápido script Apex para executar essa mudança. Porém esbarrei na situação que o UserId não pode ser alterado, conforme descrito na documentação do Objeto: ID of the User who is a member of the opportunity team. This field can’t be updated.!

Bem, diante dessa situação, me restou inserir o novo usuário, Membro do Time da Oportunidade e remover o anterior. Fiz o código Apex para isso, porém esbarrei na situação das divisões da Oportunidade (apesar de não trabalhar com elas nessa Org, haviam divisões) e em situações em que o único participante do Time da Oportunidade era o próprio Owner da Oportunidade (que era o usuário que eu iria remover). Para resolver essas situações, criei um código que apaga o usuário antigo do Time da Oportunidade, apenas quando ele não fosse o Owner da Oportunidade. Veja:


List<opportunityteammember> oppTeam = [SELECT id, OpportunityId, Opportunity.OwnerId, UserId, TeamMemberRole FROM OpportunityTeamMember WHERE TeamMemberRole = 'Gerente de Canais'];
List<opportunityteammember> oppTeamNew = new List<opportunityteammember>();
List<opportunityteammember> oppTeamOld = new List<opportunityteammember>();

for (OpportunityTeamMember otm : oppTeam){
    OpportunityTeamMember otmNew = new OpportunityTeamMember();
    otmNew.OpportunityId = otm.OpportunityId;
    otmNew.TeamMemberRole = otm.TeamMemberRole;    
    otmNew.UserId = '00540000001AY11'; //ID do Novo Gerente de Canais
    oppTeamNew.add(otmNew);
    if (otm.UserId != otm.Opportunity.OwnerId)
        oppTeamOld.add(otm);
}

delete oppTeamOld;
insert oppTeamNew;

No código acima, faço uma busca pelos Membros do Time da Oportunidade que possuam o papel "Gerente de Canais". Nas Oportunidade que possuierem esse papel, eu crio um novo Membro passando o ID e removo o ID antigo, caso ele não seja o Proprietário da Oportunidade.

Caso precise manipular também a divisão da Oportunidade, terá que incluir um tratamento no Objeto OpportunitySplit.

É isso por hoje...


* Precisa de um suporte ou consultoria para manipular os Membros do Time da Oportunidade em sua Org Salesforce? Entre em contato conosco - CbCloud: http://www.cbcloud.com.br/

sábado, 15 de abril de 2017

Editando layout de tela de Aprovação/Rejeição do Processo de Aprovação

Hoje vamos ver como inserir, remover ou alterar a ordem de campos, no layout de tela, da página de aprovação ou rejeição do Processo de Aprovação no Salesforce. Isto é, editar a tela a seguir:




A princípio, é necessário ter em mente que não temos muita liberdade para alterar essa tela. O que é possível fazer é:

- Remover campos;
- Inserir campos;
- Alterar a ordem dos campos.

Diante disso, acesse a configuração do seu processo de aprovação:
- Menu Criar / Fluxo de trabalho e Aprovações / Processos de aprovação.
- Selecione o processo desejado. 
- Ao abrir a tela do processo (como essa a seguir), clique na setinha ao lado de Editar. 
- No menu que se abrir, selecione "Layout de página de aprovação".





Na tela seguinte, é exibido 2 caixas com campos do objeto relacionado ao processo de aprovação. A caixa da esquerda são os campos disponíveis para seleção. Os da direita os campos selecionados, que serão exibidos na página de aprovação. Dessa forma, selecione ou remova os campos de sua preferencia com os botões de Adicionar/Remover. Caso queira alterar a ordem dos campos da caixa da direita (os que serão exibidos), selecione-os, e clique nos botões Para cima/Para baixo.




Para finalizar, clique em Salvar e acesse a página de aprovação para ver o resultado.

Por hoje é isso... até a próxima!


* Está precisando de um suporte ou uma consultoria nos processos de aprovação dentro da sua plataforma Salesforce? Entre em contato conosco - CbCloud: http://www.cbcloud.com.br/ Somos parceiros Salesforce!






sábado, 8 de abril de 2017

Trabalhando com SObject no Apex - Salesforce

Um das coisas mais interessantes de se trabalhar com linguagens de programação Orientadas a Objeto é a possibilidade de se trabalhar com Abstração. No Salesforce, mais especificamente no plataforma Force.com, todos os objetos abstraem de sObject, sendo assim possível, trabalhar de forma genérica com todos os Objetos da Plataforma, sejam eles nativos ou personalizados.

Vamos ao primeiro exemplo de como isso funciona:


    
SObject sObj1 = new Account();
SObject sObj2 = new MeuObjeto__c();


Veja que instanciei um objeto Account e (personalizado) MeuObjeto__c como um sObject sem problemas. Assumindo esse conceito de abstração, consigo, por exemplo atualizar atualizar registros de um Objeto Account ou Personalizado com o mesmo código:


  
    public void Main() {
        Account conta = [SELECT id, name, OwnerId FROM Account LIMIT 1];
        MeuObjeto__c meuObj = [SELECT id, name, OwnerId FROM MeuObjeto__c LIMIT 1];
        
        this.atualizaProprietario(conta, UserInfo.getUserId());
        this.atualizaProprietario(meuObj, UserInfo.getUserId());
    }
    
    public void atualizaProprietario(SObject sObj, id idNovoProprietario){
        sObj.put('OwnerId', idNovoProprietario);
        update sObj;
    }

No método Main, eu busco os dados de objetos diferente (Account e MeuObjeto__c) e chamo um método genérico, chamado atualizaProprietário que tem o poder de atualizar qualquer objeto da plataforma Force.com, afinal todos abstraem de sObject (por isso uso o sObject como parâmetro desse método). No método atualizaProprietário, veja que uso o método put do SObject (que é um Key/Value) para dizer qual campo desejo atualizar (OwnerId) e qual o novo valor (passado por parâmetro).

Bem, vamos ver agora como faço para buscar, de forma genérica, dados de um sObject:


 
    public void Main() {
        Account conta = [SELECT id, name, OwnerId FROM Account LIMIT 1];
        MeuObjeto__c meuObj = [SELECT id, name, OwnerId FROM MeuObjeto__c LIMIT 1];
        
        String nomeConta = this.buscaNome(conta);
        String nomeMeuObj = this.buscaNome(meuObj);
        
        System.debug('Nome da conta: ' + nomeConta);
        System.debug('Nome do meuObj: ' + nomeMeuObj);
    }
    
    public String buscaNome(SObject sObj){
        Object nome = sObj.get('name');
        return String.valueOf(nome);
    }


Observe que, criei um método buscaNome, que utiliza o método get do sObject para buscar o valor de um campo no objeto. O resultado dos System.Debug são:





Por fim, vamos fazer um método que retorne uma String com o tipo do Objeto que foi passado como parâmetro:


 
    public void Main() {
        Account conta = [SELECT id, name, OwnerId FROM Account LIMIT 1];
        MeuObjeto__c meuObj = [SELECT id, name, OwnerId FROM MeuObjeto__c LIMIT 1];
        
        String tipoConta = this.buscaTipo(conta);
        String tipoMeuObj = this.buscaTipo(meuObj);
        
        System.debug('Tipo da conta: ' + tipoConta);
        System.debug('Tipo do meuObj: ' + tipoMeuObj);
    }
    
    public String buscaTipo(SObject sObj){
        Schema.DescribeSObjectResult result = sObj.getSObjectType().getDescribe();
        return result.getName();
    }

Para buscarmos o tipo do Objeto, usamos o método getSObjectType, que retorna um SObjectType e neste usamos o método getDescribe. O describe nos retorna informações informações básicas através do DescribeSObjectResult. No result temos um método getName que nos trás o tipo do Objeto, no caso Account e MeuObjeto__c:





Bem, por hoje é somente isso! :)





* Está precisando de um suporte ou uma consultoria nos desenvolvimentos Apex dentro da sua plataforma Salesforce? Entre em contato conosco - CbCloud: http://www.cbcloud.com.br/