Open main menu

Changes

19,742 bytes added ,  10:41, 7 February 2017
m
{{Not free|CiviCRM}} [http://en.wikipedia.org/wiki/Sugarcrm SugarCRM] is the world's leading Customer Relationship Management (CRM) software available with complete freedom under the GPL license. For companies that want more than freedom, SugarCRM Inc, fully backs the product with expert support, service, training and customization. SugarCRM offers several deployment options, including on-demand, on-premise and appliance-based solutions to suit customers' security, integration and configuration needs. Because CRM software captures the varied relationships between a company and it's sources of revenue, most businesses really stand to benefit from the intelligence provided by a CRM system. All companies already have 'ad-hoc' methods to track leads, contacts, customer accounts and the company interactions with these (e.g. spreadsheets, lists and email records). They may even have organized CRM solutions in place. Either way, once you decide to adopt an open and standards-based solution like SugarCRM, your first order of business will be to load it with your existing data. SugarCRM has importing (and exporting) utilities that make it easy to do this, so these wizards will not be the focus of this article. Instead, we'll focus on programmatic interaction with the system. <!--{{Infobox Company|company_name=SugarCRM|company_type=Private|foundation=[[California]] 2004|location=[[Cupertino, California]]|industry=CRM Software|products= Sugar Community Edition, Sugar Professional, Sugar Enterprise|num_employees=150+|parent=|subsid=|homepage=[http://www.sugarcrm.com/ www.sugarcrm.com]}} -->{{Infobox|name = SugarCRM|bodystyle = |title = Company Info|titlestyle = |above = |abovestyle = |image = |imagestyle = |caption = |captionstyle = |headerstyle = |labelstyle = |datastyle =  |header1 = |label1 = Company Name|data1 = SugarCRM|header2 = |label2 = Company Type|data2 = private|header3 = |label3 = Founded|data3 = California 2004|header4 = |label4 = Industry|data4 = CRM Software|header5 = |label5 = Products|data5 = Sugar Community Edition, Sugar Professional, Sugar Enterprise|header6 = |label6 = Employees|data6 = 150+|header7 = |label7 = Website|data7 = [http://www.sugarcrm.com/ www.sugarcrm.com]|header8 = |label8 = |data8 = |header9 = |label9 = |data9 =|header10 =First I downloaded the source |label10 = |data10 = }}== Introduction ==# I went Typically a company will deploy the CRM system and will also create one or more pipelines which act as conduits to capture new account, and contact information. This article will show how to establish a web service, using [http://en.wikipedia.org/wiki/SOAP SOAP] to add contacts and accounts to your [[Installing SugarCRM|SugarCRM installation]]. As an example scenario, let's suppose that a conference organizer wants to offer a sign-up sheet on their existing website. The existing website could be a [http://drupal.org Drupal] content management system (CMS) which not only manages the SugarCRM homepageconference, but also adds company and clicked individual contact details to the SugarCRM system via the web service. The details on creating the form for the capture are beyond the scope of this article but the capture routines could easily handle a form input (HTTP POST) just as easily as we read input from a file . Again our focus for today will be on the plumbing of the top navbar link interaction with the SOAP server. == Goal ==Import records into SugarCRM without using existing import wizards but rather by writing a tool in [http://en.wikipedia.org/wiki/PHP PHP] to "Sugar Open Source"do the work. Records should go into Accounts and Contacts, while creating a relationship between the two. == Requirements ==# Assume that we start with a spreadsheet that has column headings matching the 17 fields shown below. Assume too that we want to capture all of the data in the sample. (The owner of the data collected it for a reason and they wouldn't be too happy with a loss of data in a migration to a new application!) I skipped did not define new fields in the "Wizard" and went right database, but I did correlate my data source to the "Download Page" because Accounts and Contacts tables. Because I know what had parsed the data source (spreadsheet or CSV file) for column headings, I'm doing simply exported that variable and also have then used it as a comment right in my code workup as I went. What I mean is that I created a pre-existing setup PHP (array) variable of Linuxthe 17 field names, Apache MySQL and PHP - then used the [http://php.net/var_export|var_export]() function to print it and copy/paste into a comment block so that I only want could mark up a plan for mapping those fields into fields in SugarCRM. <source lang="php">print '<pre>'; var_export ($arrFields); print '</pre>';// copy and paste that output; then add comments about which fields go into which table// comment the whole block so that it remains as a reference in the apptoolarray ( 0 => 'Company Name',// a:name 1 => 'Industry', // a:industry # I downloaded SugarCE- 2 => 'First Name', // c:first_name 3 => 'Last Name', // c:last_name 4 => 'Fax', // a:phone_fax c:phone_fax 5=> 'Address', // a:billing_address_street c:primary_address_street 6 => 'City', // a:billing_address_city c:primary_address_city 7 => 'State', // a:billing_address_state c:primary_address_state 8 => 'Zip Code', // a:billing_address_postalcode c:primary_address_postalcode 9 => 'Country', // a:billing_address_country c:primary_address_country 10 => 'Notes', // a:description 11 => 'Work Phone', // a:phone_office c:phone_work 12 => 'Other Phone',// a:phone_alternate c:phone_other 13 => 'Email', // a:email c:email1 14 => 'website', // a:website 15 => 'employees', // a:employees 16 => 'ticker_symbol'// a:ticker_symbol )</source> === Using a Form ===The [http://www.0sugarcrm.com/wiki/index.0ephp?title=SOAP_Intro_and_Practical_Examples SOAP Intro and Practical Examples], shows a simple form-based processing script for leads.zip (production release)# I visited The form can be found in the recommended "Installationexamples" instructions page directory in the source. Note: the example did not work as an application entry point (because even though it defined ('sugarEntry', true); there was also an IF that pre-empted that definition -- because requests inside the SugarCRM install directory will automatically bootstrap the SugarCRM system). To work around this, either put the example form outside the application directory or define sugarEntry as true ''without'' the 'if' conditional. Using the lead capture form is illustrated at http://www.sugarforgesugarcrm.orgcom/content/installationwiki/index.php?title=Creating_a_lead_capture_form_for_your_website# Then I installed it according to If your needs are more complex, you can learn more by looking at the instructionsmodules dealing with Import (dataMaps), however I immediately ran into trouble because the instructions did say database abstraction layer (SugarBeans and VarDefs) or the database directly to chmod 766 all files that needed to be writable by get a clearer picture of everything going on in the web_userSugarCRM system. # This command renders === Use the Source Luke ===Answers are always found in the source, with the directories noncaveat that it can be confusing and/or time-executable which manifests in include errors because consuming to find those answers. Looking at the full application import routines and the four-step forms for importing leads, there is a lot of example machinery that you could use to create a sophisticated web user (wwwfront-data) end using SugarCRM internals. For this exercise, I want to assume that we'll be operating between two websites, and so I will simply insert records into the database communicating with SugarCRM's SOAP server. ; Tip: You can not see peer into those directories the SugarCRM environment with a call to PHP's 'get_defined_vars(to find includes)'. This will give you some information about field maps etc.<source lang="bashphp"># find directories temp.php to show a concise view of the variables defined in the config scriptdefine('sugarEntry', true);include ('./modules/Import/config.php');print "Defined variables: <br /crm path and change the mode on them so that all users can execute >\n<pre>"; print_r (get_defined_vars(see into) the directory ); print "\n</pre>\n";# end temp.php# partial output: [salesforce_contacts_field_map] => Array ( [Salutation] => salutation [Description] => description [First Name] => first_name [Last Name] => last_name [Title] => title [Department] => department [Birthdate] => birthdate [Lead Source] => lead_source [Assistant] => assistantfind [Asst.Phone] => assistant_phone [Contact ID] => id [Mailing Street] => primary_address_street [Mailing Address Line1] => primary_address_street_2 [Mailing Address Line2] => primary_address_street_3 [Mailing Address Line3] => primary_address_street_4 [Mailing City] => primary_address_city [Mailing State] => primary_address_state [Mailing Zip/Postal Code] => primary_address_postalcode [Mailing Country] => primary_address_country [Other Street] => alt_address_street [Other Address Line 1] => alt_address_street_2 [Other Address Line 2] => alt_address_street_3 [Other Address Line 3] => alt_address_street_4 [Other City] => alt_address_city [Other State] => alt_address_state [Other Zip/Postal Code] => alt_address_postalcode [Other Country] => alt_address_country [Phone] => phone_work [Mobile] => phone_mobile [Home Phone] => phone_home [Other Phone] => phone_other [Fax] => phone_fax [Email] => email1 [Email Opt Out] => email_opt_out [Do Not Call] => do_not_call [Account Name] => account_name [Account ID] => account_id )  [salesforce_accounts_field_map] => Array ( [Account Name] => name [Annual Revenue] => annual_revenue [Type] => account_type [Ticker Symbol] => ticker_symbol [Rating] => rating [Industry] => industry [SIC Code] => sic_code [Ownership] => ownership [Employees] => employees [Description] => description [Account ID] => id [Billing Street] => billing_address_street [Billing Address Line1] => billing_address_street_2 [Billing Address Line2] => billing_address_street_3 [Billing City] => billing_address_city [Billing State] => billing_address_state [Billing Zip/crmPostal Code] => billing_address_postalcode [Billing Country] => billing_address_country [Shipping Street] => shipping_address_street [Shipping Address Line1] => shipping_address_street_2 [Shipping Address Line2] => shipping_address_street_3 [Shipping City] => shipping_address_city [Shipping State] => shipping_address_state [Shipping Zip/ -type d |xargs chmod a+x Postal Code] => shipping_address_postalcode [Shipping Country] => shipping_address_country [Phone] => phone_office [Fax] => phone_fax [Website] => website )
</source>
resolved the include errors
== Ideas on How to do the import ==
=== Existing Work ===
My first instinct was to find info about somebody doing this before (e.g. APIs, Documentation, forum questions, Wikis)
I searched the wiki for importing or APIs and quickly found the SOAP Intro and Practical Examples, so I figured I was onto a fast track.
However, the soap example worked with a frontend form which wasn't explained much and so I looked more into what was required.
When I found the form in "examples", it did not work as an application entry point (because even though it defined ('sugarEntry', true); there was also an IF that pre-empted that definition)
Not immediately seeing this cause for the example failure, I put the example form outside the application directory and then used the form to insert a single lead http://www.sugarcrm.com/wiki/index.php?title=Creating_a_lead_capture_form_for_your_website
Seeing that the example worked, but did not capture all the details provided in the data exercise, I knew I should look at the existing functionality of modules/Lead and/or the database to get a clear picture of what I needed to label everything.
==Using SOAP = Use = Note: SOAP examples can obviously change slightly over time with SugarCRM, so you must be careful about what example you use, and generally rely on the source to be the definitive source ;-)* soap/SoapPortalUsers.php* soap/SoapSugarUsers.php* soap/SoapData.php* soap/SoapDeprecated.php Getting on with the soap service, it is easy to discover the service profile and import the data From the [http://freephile.com/crm/soap.php soap.php] page (which shows the WSDL), we can get a definition of the available SOAP calls. For example, here is the definition of the 'create_account' method <pre>Name: create_accountBinding: sugarsoapBindingEndpoint: http://freephile.com/crm/soap.phpSoapAction: http://freephile.com/crm/soap.php/create_accountStyle: rpcInput: use: encoded namespace: http://www.sugarcrm.com/sugarcrm encodingStyle: http://schemas.xmlsoap.org/soap/encoding/ message: create_accountRequest parts: user_name: xsd:string password: xsd:string name: xsd:string phone: xsd:string website: xsd:stringOutput: use: encoded namespace: http://www.sugarcrm.com/sugarcrm encodingStyle: http://schemas.xmlsoap.org/soap/encoding/ message: create_accountResponse parts: return: xsd:stringNamespace: http://www.sugarcrm.com/sugarcrmTransport: http://schemas.xmlsoap.org/soap/httpDocumentation: </pre>And the create_contact method:<pre>Name: create_contactBinding: sugarsoapBindingEndpoint: http://freephile.com/crm/soap.phpSoapAction: http://freephile.com/crm/soap.php/create_contactStyle: rpcInput: use: encoded namespace: http://www.sugarcrm.com/sugarcrm encodingStyle: http://schemas.xmlsoap.org/soap/encoding/ message: create_contactRequest parts: user_name: xsd:string password: xsd:string first_name: xsd:string last_name: xsd:string email_address: xsd:stringOutput: use: encoded namespace: http://www.sugarcrm.com/sugarcrm encodingStyle: http://schemas.xmlsoap.org/soap/encoding/ message: create_contactResponse parts: return: xsd:stringNamespace: http://www.sugarcrm.com/sugarcrmTransport: http://schemas.xmlsoap.org/soap/httpDocumentation: </pre> Even more detail can be had by inspecting the Source Luke service.<source lang="php">$get_available_modules_params = array ( 'session' => $session_id,);$result = $soapclient->call('get_available_modules', $get_available_modules_params);print '<pre>'; var_export ($result); print '</pre>'; // output:</source>See [[Importing_contacts/sugar_modules]] <source lang="php">$interestedModules = array('Accounts', 'Contacts'); foreach ($interestedModules as $module_name) { $get_module_fields_params = array ( 'session' => $session_id, 'module_name' => $module_name ); $result = $soapclient->call('get_module_fields', $get_module_fields_params); print "\n $module_name fields:<br />\n<pre>\n"; var_export ($result); print "\n</pre>\n";}</source> ===Accounts fields: ===[[Importing_contacts/Accounts|See the SOAP profile for Accounts]]  My second instinct was to look at === Contacts fields: ===[[Importing_contacts/Contacts|See the SOAP profile for Contacts]]  == Setting Records ==<source lang="php">// read in our data from sourceCSV file format$arrData = file('./account_contact_list. Answers are always found csv');$separator = ',';// initialize an array to hold structured data; we'll determine what columns we want and map our data$leadData = array();// take the first (header) row off the CSV file$arrFields = explode($separator, array_shift($arrData));// flipping the array gives us the integer value we need defined by it's name// in other words, we now have an associative array of integers$fieldKeys = array_flip($arrFields); // break up our recordsforeach ($arrData as $k => $v) { $arrData[$k] = explode($separator, $v);} foreach ($arrData as $record) { // Accounts $set_entry_params = array( 'session' => $session_id, 'module_name' => 'Accounts', 'name_value_list'=>array( array('name'=>'name', 'value'=>$record[$fieldKeys['Company Name']]), // required array('name'=>'industry', 'value'=>$record[$fieldKeys['last_name']]), array('name'=>'phone_fax', 'value'=>$record[$fieldKeys['Fax']]), array('name'=>'billing_address_street', 'value'=>$record[$fieldKeys['Address']]), array('name'=>'billing_address_city', 'value'=>$record[$fieldKeys['City']]), array('name'=>'billing_address_state', 'value'=>$record[$fieldKeys['State']]), array('name'=>'billing_address_postalcode', 'value'=>$record[$fieldKeys['Zip Code']]), array('name'=>'billing_address_country', 'value'=>$record[$fieldKeys['Country']]), array('name'=>'description', 'value'=>$record[$fieldKeys['Notes']]), array('name'=>'phone_office', 'value'=>$record[$fieldKeys['Work Phone']]), array('name'=>'phone_alternate', 'value'=>$record[$fieldKeys['Other Phone']]), array('name'=>'email', 'value'=>$record[$fieldKeys['Email']]), array('name'=>'website', 'value'=>$record[$fieldKeys['website']]), array('name'=>'employees', 'value'=>$record[$fieldKeys['employees']]), array('name'=>'ticker_symbol', 'value'=>$record[$fieldKeys['ticker_symbol']]), array('name'=>'assigned_user_id', 'value'=>$user_guid) ) ); // make the soap call $result = $soapclient->call('set_entry',$set_entry_params); // print "\n <br />Entry results:<br />\n<pre>\n"; var_export ($result); print "\n</pre>\n"; // the return value will give us the unique identifier for the Account record, which we // then use to create a relationship entry when creating the Contact $accountId = $result['id'];  // Contacts $set_entry_params = array( 'session' => $session_id, 'module_name' => 'Contacts', 'name_value_list'=>array( array('name'=>'first_name', 'value'=>$record[$fieldKeys['First Name']]), array('name'=>'last_name', 'value'=>$record[$fieldKeys['Last Name']]), array('name'=>'phone_fax', 'value'=>$record[$fieldKeys['Fax']]), array('name'=>'primary_address_street', 'value'=>$record[$fieldKeys['Address']]), array('name'=>'primary_address_city', 'value'=>$record[$fieldKeys['City']]), array('name'=>'primary_address_state', 'value'=>$record[$fieldKeys['State']]), array('name'=>'primary_address_postalcode', 'value'=>$record[$fieldKeys['Zip Code']]), array('name'=>'primary_address_country', 'value'=>$record[$fieldKeys['Country']]), array('name'=>'phone_office', 'value'=>$record[$fieldKeys['Work Phone']]), array('name'=>'phone_other', 'value'=>$record[$fieldKeys['Other Phone']]), array('name'=>'email', 'value'=>$record[$fieldKeys['Email']]), array('name'=>'account_name', 'value'=>$record[$fieldKeys['Company Name']]), // relation array('name'=>'account_id', 'value'=>$accountId), // relation array('name'=>'assigned_user_id', 'value'=>$user_guid) ) ); // make the soap call to create the (related) Contact entry $result = $soapclient->call('set_entry',$set_entry_params); print "\n <br />Contact Entry results:<br />\n<pre>\n"; var_export ($result); print "\n</pre>\n"; $contactId = $result['id']; /** // alternately, if you have both ids, you can use set_relationship $set_relationship_params = array( 'session' => $session_id, 'set_relationship_value' => array( 'module1' => 'Contacts', 'module1_id' => $contactId, 'module2' => 'Accounts', 'module2_id' => $accountId ) ); $result = $soapclient->call('set_relationship', $set_relationship_params); print "\n <br />Relationship results:<br />\n<pre>\n"; var_export ($result); print "\n</pre>\n";  */}</source, with > == Conclusion ==In this article we've shown how the caveat SugarCRM system is enterprise-ready in that it has a fully built SOAP service that can be confusing and/used to integrate the system with one or timemore 'front-consuming end' websites or applications for data capture. With important information easily added to the system, it allows the company to focus resources on managing the most valuable assets. Due to SugarCRM's open source nature and standards support, it's easy to find those answersextend and integrate the system with other existing or new infrastructure components.Looking In future articles, we'll take a look at the full application import routines still more interesting integrations with SugarCRM such as collaboration, document management and knowledge management.  <table class="toc"><tr><td>-- Greg Rundlett<br />Greg Rundlett is an open source technologist. He currently manages the fourTechnology Services team at [http://www.oasis-open.org OASIS]. <br />''This website is not affiliated nor endorsed by any third-step forms party .''</td></tr></table>  == Postscript: Some Improvements for importing leadsSugarCRM == As with any software, it was clear there is always room for improvement. Here are some minor issues that there was I noted in the course of writing this article.# "Import Step 2: Upload Export File" is a lot confusing title on the second step of machinery the "Import Contacts" wizard. How can one use the words 'import', 'upload', 'export' all at once? It could read "Import Step 2: Select Data File to load"# Typographical bug: I saw that I didnthe term "custom_delimeted" in the language files. It doesn't need actually cause any errors, but b/c the term is used elsewhere (spelled correctly), this typo could potentially lead to a real bug down the line.## ./modules/Import/language/en_us.lang.php## ./modules/Import/ImportStep1.html## ./modules/Import/ImportStep2.php# The source is formatted poorly, or want practically not at all in some cases, due to get involved with to simply import recordsvarious editors using different space and tab settings, and line endings. [http://pear.php.net/package/PHP_Beautifier PHP Beautifier] used in a commit hook would solve this in the version control system. Coding standards and configuration files like vim modelines would solve this on the developer desktop. Being open source, I decided can pass this information on to go back the developers (or even get involved myself by posting articles like this to [http://www.sugarcrm.com/wiki/index.php?title=Main_Page the SOAP example wiki]) and write will likely see a scipt positive response to read the exercise data and create full records for the 50 provided leadsthese suggested fixes. Note too - SugarCRM fosters an extended community of value-add partners through it's [http://www.sugarforge.org/ forge site]. == Further Resources ==* http://www.sugarcrm.com/wiki/index.php?title=SOAP_Intro_and_Practical_Examples* http://freephile.com/crm/index.php?module=Home&action=TrainingPortal* http://freephile.com/crm/soap.php* http://www.sugarcrm.com/wiki/index.php?title=SOAP_in_PHP* http://dietrich.ganx4.com/nusoap/* http://www.beanizer.org/site/index.php/en/Articles/Sugar-CRM-integration-with-custom-PHP-applications-I.html
I looked at the config.php to get Soap examples seemed to have changed with the addition of a version number [[Category:CRM]] "Import Step 2[[Category: Upload Export File" is a confusing title on the second step of the "Import Contacts" wizard. It could read "Import Step 2: Specify Data File to load"Code]] Typographical bug[[Category: I saw that the term "custom_delimeted" is used in a self-contained way in ./modules/Import/language/en_us.lang.php ./modules/Import/ImportStep1.html ./modules/Import/ImportStep2.phpThis term is used elsewhere spelled correctly, and thus could potentially lead to a bug down the line.Software]]
4,558

edits