Desenvolvimento de plugin

Quanto ao git acredito que será tranquilo, mexo com git há um bom tempo.

Mas tenho uma dúvida. vou versionar apenas o conteúdo da pasta Custom ou adiciono todo o projeto do SuiteCRM no repositório e versiono a pasta custom a partir daí?

Digo, versionar a pasta Custom.

Acho que se pode versionar tudo. O projecto quando se faz “clone” do GitHub já traz um .gitignore com as opções adequadas.

Normalmente só se muda coisas em “custom”, mas se se mudar em algum outro sítio, é melhor que também fique registado.

Entendi.
Me surgiu uma dúvida aqui.

Criei um Entrypoint, fui na administração do CRM e reparei pra que meu entrypoint pudesse ser executado.
Depois disso executei a url correspondente ao meu entrypoint e deu certo, apareceu o que deveria aparecer.

Em seguida criei outro entrypoint (em outro arquivo) e refiz o processo acima. Quando executei esse segundo entrypoint, o código do primeiro também foi executado.

Após procurar encontrei um arquivo que contém todos os pontos de entrada criado. Esse arquivo é o: entry_point_registry.ext.php

Lá está o código dos dois entrypoint que criei. Cada Url não deveria executar apenas o código que refere a si? Tipo, se eu executar o segundo entrypoint, não deveria executar apenas o código referente a ele?

Meus Entrypoinit coloquei aqui: C:\xampp\htdocs\crmAlpha\custom\Extension\application\Ext\EntryPointRegistry

O arquivo que falei acima (entry_point_registry.ext.php) se encontra aqui: C:\xampp\htdocs\crmAlpha\custom\application\Ext\EntryPointRegistry

Estou fazendo algo errado?

Qual é o conteúdo dos ficheiros em custom\Extension\application\Ext\EntryPointRegistry ?

Dois arquivos, cada um é um Entrypoint que criei.

Eu pedi o conteúdo deles pois nestas questões de código não é possível ajudar sem ver exactamente como as coisas estão definidas. Pode ser apenas um ponto e víguel a mais ou a menos…

Me desculpa, estava na correria e não li direito.

O primeiro faz a captura de informação do RD quando ocorre algum evento no RD.

Segue o código

$entry_point_registry[‘MyTimeEntryPoint’] = array(
‘file’ => ‘custom/Extension/application/Ext/EntryPointRegistry/MyTimeEntryPoint.php’,
‘auth’ => false,
);

header("Content-Type: application/json");
$dadosRd = json_decode(stripslashes(file_get_contents("php://input")));



$accountBean = BeanFactory::newBean('Accounts');

//$accountBean->name = $dadosRd->leads[0]->custom_fields->Vendedor;
$accountBean->name = $dadosRd->leads[0]->name;
//$accountBean->description = json_encode($dadosRd->leads[0]);
$accountBean->email1 = $dadosRd->leads[0]->email;
$accountBean->billing_address_postalcode = 12345;
$accountBean->save();

O segundo faz a leitura de algum dado do SuiteCrm utilizando Beans e os envia ao RD Station…
Segue o código

$entry_point_registry[‘UpdateRdEntryPoint’] = array(
‘file’ => ‘custom/Extension/application/Ext/EntryPointRegistry/UpdateRdEntryPoint.php’,
‘auth’ => false,
);

class UpdateRdEntryPoint
{
	private $publicToken;
	private $privateToken;
	private $rdAPI;
	
	public function __construct()
	{
		$this->publicToken = "";
		$this->privateToken = "";
		$this->rdAPI = new RDStationAPI($this->privateToken, $this->publicToken);
	}
	/*
	*
	*	RESPONSÁVEL POR RETORNAR UMA LISTA CONTENDO TODAS AS OPORTUNIDADES ORIGINADAS DO RD STATION.
	*/
	public function GetListOpportunitySourceRd()
	{
		$bean = BeanFactory::newBean('Opportunities');
		$a = $bean->get_list('name', "opportunities.date_entered = '2017-03-14 14:03:39'");
		$a = $this->RemoveFieldNameMap($a);
		
		return $a;
	}
	/*
	*	RESPONSÁVEL POR REMOVER O ESQUEMA MOSTRA OS DETALHES DE TODOS OS ATRIBUTOS REFERENTE AO OBJETO.
	*
	*	$opportunities -> Lista de oportunidades carregadas.
	*/
	public function RemoveFieldNameMap($opportunities)
	{
		for($i = 0; $i < count($opportunities['list']); $i++)
			unset($opportunities['list'][$i]->field_name_map);
		return $opportunities;
	}
	
	public function SendSaleToRdStation($opportunity = null)
	{
		if($opportunity != null)
			$return = $this->rdAPI->updateLeadStageAndOpportunity(contato@company.com.br", 'won', 20);
	}
}

$up = new UpdateRdEntryPoint();
$up->SendSaleToRdStation();

São apenas testes, o primeiro, como pode ver é executado apenas quando ocorre algum evento no RD e o segundo eu executo manualmente para enviar
dados ao RD Station. (obs.: Removi os tokens para postar aqui)

Os códigos estão funcionando, a questão é que quando executo um entrypoint, o outro também é executado.

Outra coisa que também observei foi que quando eu acesso a página inicial do SuiteCRM com login de administrador (fiz esse teste só com usuário de administrador) os dois entrypoint são executados também.

Só os ficheiros de definição devem estar em custom/Extension/application/Ext/EntryPointRegistry (os que preenchem o array $entry_point_registry).

Os outros ficheiros com as funções para executar, devem estar noutro lugar (por exemplo, apenas “custom/”). Naturalmente que tem de ajustar as definições de $entry_point_registry para buscar na nova localização.

Isto porque todos os ficheiros PHP em custom/Extension/application/Ext/EntryPointRegistry são executados automaticamente em várias ocasiões para aplicar as definições. Se têm apenas definições, não tem problema de aplicar mais de uma vez. Mas não deve ter ali outro código.

Bem, consegui. Agora deu certo.

Nisso me surgiu outra dúvida. Supomos que eu queira marcar como venda um determinado lead no RD (Tem a API do RD pra isso e já estou conseguindo fazer a comunicação). Mas o que quero fazer é: quando o campo chamado Fase da venda no formulário de criar oportunidade estiver com o status Pedido recebido e o usuário clicar em salvar, então enviar ao RD uma venda para aquele lead em questão. Como posso fazer isso? Há alguma forma de programar ações com base em determinados eventos a partir do CRM? Há uma outra maneira de fazer?

Sim, isso é uma after_save Logic Hook

https://docs.suitecrm.com/developer/logic-hooks/

Trabalhando mais com beans aqui no CRM, me surgiu um problema e não consigo resolver.

Acompanhei a documentação tentando reproduzir o seguinte exemplo:

$accountBean = BeanFactory::newBean('Contacts');

$beanList = $accountBean->get_linked_beans(
'contacts',
'Contacts',
array(),
0,
10,
0,
"contacts.primary_address_country = 'Brasil'");

print_r($beanList);

O problema é que quando executo isso, volta um arrary vazio. Já verifiquei no banco de dados e existe primary_address_country com o valor Brasil cadastrado. O último parâmetro eu tentei passar em branco tambem, mas permaneceu vazio o array de resultado do mesmo jeito.

O que estou fazendo de errado?

Tente usar ‘Contact’ em lugar de ‘Contacts’

get_linked_beans('contacts', 'Contact' ...

Essa questão de quando usar singular ou plural é muito sensível. O melhor é procurar no código existente instruções semelhantes e fazer igual.

Essa linha aí também não me parece bem:

$accountBean = BeanFactory::newBean('Contacts');

Se chama à variável $accountBean não faz sentido colocar nela um bean de contactos…

Certo.

A integração que eu queria fazer entre o RD e o SuiteCRM está funcionando. Graças as dúvidas que você me foi tirando eu pude implementar essa integração.

Porém está ocorrendo um problema que não sentido nenhum.

Vou tentar ser o mais claro possível

No RD há uma página web que permite com que eu configure o webhook para fazer a integração. Eu fui e coloquei a URL do entrypoint do CRM, especifiquei o gatilho de disparo como Conversão. Isto é, toda vez que alguém preencher um formulário os dados serão enviados para o RD, é claro, e em seguida serão enviados para o CRM.
Até aqui tudo bem. Nessa mesma tela, ao criar o webhook há a opçao de fazer um teste para verificar se a comunicação com o SuiteCRM está correta. Eu clico nesse botão e escolho um lead qualquer na lista para fazer o envio dos dados. Fazendo isso, os dados são enviados e ao olhar no CRM eu vejo que os dados chegaram e a oportunidade foi criada com sucesso. Perfeito, integração funcionando.

O problema começa aqui. Quando eu criei o webhook eu tive que especificar também qual seria o formulário que teria seus dados enviados para o CRM. Sendo assim, eu acesso esse fomulário pelo meu navegador e preencho-o, em seguida eu envio os dados. Se tudo estiver ok, esses dados informados, ou seja, essa conversão, deverão ser enviados para o CRM. Então eu vou no SuiteCRM novamente para conferir se a oportunidade foi inserida, quando carrego a página, está la a oportunidade inserida, porém passa 1 ou dois minutos, mais ou menos, outra oportunidade aparece, sendo que eu enviei o formulário uma vez só. Parece que o RD está enviando mais de uma vez para o CRM. E toda vez que tento, chega uma quantidade diferente de oportunidades, não tem padrão.

Resumindo, pra cada vez que eu preencher o formulário deveria enviar uma vez só, para inserir apenas uma oportunidade e não duas ou três. Já comparei os dados dessas oportunidades, são todos exatamente iguais. Parece que duplicou.

Ao meu ver não parece ser problema do CRM, pois no início eu te expliquei que fiz um teste no webhook criado antes de preencher o formulário. Se fosse problema do CRM, teria que duplicar em ambos os casos, certo?

O que será que está ocorrendo? Será problema no envio feito pelo RD?

Não sei, parece ser problema do envio do RD.

Talvez haja algo na resposta do SuiteCRM que ele entenda como “não foi criada a oportunidade”, e tem lá código para fazer “retry” após um pouco.

Outra hipótese a verificar é se você não tem nenhuma “logic hook” ou “workflow” esquecidos, correndo quando cria a oportunidade, e que estejam duplicando por algum motivo.

Eu também penso que é problema no RD.

Bem, eu tinha um work flow lá sim e para oportunidades. Imaginei que ele pudesse ser o problema então eu o desativei, mas não resolveu nada.

O engraçado é que há momentos raros que esse problema para ocorrer.

Eu decidi fazer um teste, em vez de enviar para uma url do SuiteCRM eu coloquei uma outra url. Na verdade eu apenas criei um diretório na pasta raiz do CRM e lá dentro coloquei um arquivo php para receber os dados que seriam enviados pelo RD. Bem, aqui imagino eu que o CRM não poderá influenciar em nada nesse teste.

O conteúdo desse php simplesmente pegava os dados quando o RD enviasse e os escrevia em um arquivo de log que eu criei. Então se entrasse mais de uma vez estaria duplicando da mesma forma.

O engraçado é que ao fazer esse teste não duplicou e se eu voltasse para a url do CRM começava a duplicar novamente.

Observando isso dá pra perceber que é um problema no CRM. Mas mesmo assim não entendo, porque quando eu faço o envio de verificação através da tela de configuração de webhook que eu mencionei, não duplica no CRM. Duplica apenas quando vem de conversão de formulário.

Você disse que tem também a possibilidade de fazer retry após passar um tempo caso ele entenda que falhou a inserção da oportunidade né?. Bem, eu notei que demora um pouco sim para entrar novamente, é variável o tempo. As vezes entra uma 1 oportunidade aí passa uns 2 minutos entra outra. E fica assim.

Estou desconfiado que seja a última atualização do CRM que apliquei…

Enfim, esse meu último cenário de teste torna mais difícil entender o problema.

Outro teste:

Experimente fazer o cron do SuiteCRM correr só de 5 em 5 minutos, em vez de ser todos os minutos.

Para ver se o tempo de repetição fica igual (e então não pode ser dos Schedulers, que correm os Workflows), ou se muda (e então o problema vêm mesmo daí).

pgr, muito obrigado pela ajuda. A integração do RD Station com o SuiteCRM está 100%.

Boa B-) ! Fico contente por saber.