simple trigger for duplicate fullname not working, - salesforce

In student123__C detail page there are 3 fields: firstname__c. lastname__c, middlename__c. I need to write a trigger to check "if a person is entering the same values then, throw an error that "duplicate contact found".
Example: 1st record I entered as " Siva Naga Raju " so if am again entering this same name then it should throw an error.
For that i created a forumla field called TOTALNAME__C ( firstname__c + lastname__c + middlename__c). upto here ok. But trigger not firing, intially i worte bulk trigger, but its not firing, so i wrote a simple trigger then, it is also not firing, please some boby help me. thanks in advance.
trigger duplicatefullname on student123__c (before insert, before update) {
string name;
list<student123__c> databasenames;
for (student123__c stu : trigger.new) {
name = stu.firstname__c + stu.lastname__c + stu.middlename__c;
databasenames = [select totalname__C from student123__c where totalname__C = :name];
if (databasenames.size() > 0)
stu.adderror('another person with duplicate full name found');
}
}

Basically, formula doesn't store any value. Formula is executed only when you retrieve it.
A formula is similar to an equation that is executed at run time.

Related

How to update internal table without using MODIFY?

I have created internal tables where I want to update age of employee in one internal table by calculating it from another table, I have done arithmetic calculations to get age but now how can I update it by any alternate way instead of MODIFY?
WRITE : / 'FirstName','LastName', ' Age'.
LOOP AT gt_items1 INTO gwa_items1.
READ TABLE gt_header INTO gwa_header WITH KEY empid = gwa_items1-empid.
gwa_items1-age = gv_date+0(4) - gwa_header-bdate+0(4).
MODIFY gt_items1 from gwa_items1 TRANSPORTING age WHERE empid = gwa_items1-empid.
WRITE : / gwa_items1-fname , gwa_items1-lname , gwa_items1-age .
ENDLOOP.
Use field symbols (instead of work areas) by LOOPing over internal tables:
WRITE : / 'FirstName','LastName', ' Age'.
LOOP AT gt_items1
ASSIGNING FIELD-SYMBOL(<ls_item1>).
READ TABLE gt_header
ASSIGNING FIELD-SYMBOL(<ls_header>)
WITH KEY empid = <ls_item1>-empid.
IF sy-subrc EQ 0.
<ls_item1>-age = gv_date+0(4) - <ls_header>-bdate+0(4).
WRITE : / <ls_item1>-fname , <ls_item1>-lname , <ls_item1>-age .
ENDIF.
ENDLOOP.
Field symbols have two advantages:
They modify the internal table directly, no separate MODIFY is
necessary.
They are somewhat faster, than work areas.
Besides József Szikszai's answer you could also use references:
write : / 'FirstName','LastName', ' Age'.
sort gt_header by empid. " <------------- Sort for binary search
loop at gt_items1 reference into data(r_item1).
read table gt_header reference into data(r_header)
with key empid = r_item1->empid binary search. " <------------- Faster read
check sy-subrc eq 0.
r_item1->age = gv_date+0(4) - r_header->bdate+0(4).
write : / r_item1->fname , r_item1->lname , r_item1->age .
endloop.
I added some enhacements to your code also.
For more info check this link.

Sales force trigger INVALID_FIELD_FOR_INSERT_UPDATE

Below code works fine when updating/inserting on Visual Force Page one record at a time, receive error 'Insert failed....INVALID_FIELD_FOR_INSERT_UPDATE, cannot specify Id in an insert call' when using data loader (error pointing to code, 'insert amcRecord'). Would anyone know how to fix?
trigger Status on Cl__c (after insert, after update) 
{
List<AMC__c> amcRecord = new List<AMC__c>();
for (Cl__c cls: Trigger.new ) 
{
    Cl__c oldcls = Trigger.oldMap.get(cls.Id);
    if (cls.Status__c == 'Completed' && (oldcls.Status__c != 'Completed'  )) 
{
     AMC__c newAMC = new AMC__c();
     newAMC.Cl__c = cls.ID;
     newAMC.Default__c = true;  
     amcRecord.add(newAMC); 
     insert amcRecord;
}
  }
}
amcRecord is a list, not a single item, but you're calling insert for every item in the request [which would only be 1 for the UI, but upto 200 with the data loader. You need to move the insert amcRecord line to after the for (... Trigger.new) loop has finished, so that its only called once, e.g.
trigger Status on Cl__c (after insert, after update)
{
List<AMC__c> amcRecord = new List<AMC__c>();
for (Cl__c cls: Trigger.new )
{
Cl__c oldcls = Trigger.oldMap.get(cls.Id);
if (cls.Status__c == 'Completed' && (oldcls.Status__c != 'Completed' ))
{
AMC__c newAMC = new AMC__c();
newAMC.Cl__c = cls.ID;
newAMC.Default__c = true;
amcRecord.add(newAMC);
}
}
insert amcRecord;
}
You shouldn't be performing DML inside a loop.This exception comes if you try to insert already inserted record.
Account a =new Account();
a.name='Hello';
insert a;
insert a;
Changed
insert amcRecord;
to
upsert amcRecord;
It seems to be working now.

Oracle DB displays data

Having a hard time figuring this, how to display "name" using only like 3 letter string. example below.
$query = oci_parse($conn, "SELECT * FROM STAFF_DETAILS WHERE NAME = '$name' ");
if(oci_execute($query))
{
while(($row = oci_fetch_array($query, OCI_BOTH)) != false)
{
echo $row['NAME'];
}
}
the problem is you can display only the fullname (ex. Zach De La Rocha), what i want is to display all names begins "Zach" only.
Thanks
Not sure I understand your question, it would help if you could be a little clearer. Just guessing, if you are asking how you can select only the records where the name begins with 'Zach', the Oracle syntax is:
...where name like 'Zach%'
The % in the expression above means "anything may come after Zach". Since there is no % before Zach, that means Zach must be at the beginning of name.

How to avoid inserting duplicate contacts(using email check) in salesforce using apex batch?

I am trying to insert new contacts and leads in salesforce using external api call in apex batch. I am running once in a day and inserting 500 contacts or leads in salesfoce.
But my batch file is inserting duplicate contacts with same email address. I want to skip contact or lead records to insert when same email id already exists with another record.
If I check email address using query for each record then the SOQL query limit will be a problem.
How I can avoid duplicate insert in contacts or lead in salesforce.
Thanks in Advance
Rajendra J.
Apex code:
request.setMethod('GET');
request.setTimeout(120000);
request.setEndpoint('http://api.nurturehq.com/contacts/many?nurture_id='+last_insert_id+'&limit=10&auth_token='+obj_authentication.nurture_authentication_key__c);
request.setHeader('X-Api-Version', '2.0');
request.setHeader('X-Access-Id', 'APP_ID3MVG9A2kN3Bn17hvx6UytrOeZp67_J835ecdoZ5eJmyC_BQS227UFPVb5KgNJW7YpVd9oTA6sCJ19msqZQ9sY');
request.setHeader('X-Access-Secret', 'SECRET_KEY4317178691269588217');
JSONParser parser = JSON.createParser(response.getBody());
// system.debug('jsondataaaa'+parser);
NurtureSingleton__c nurSingle = [SELECT nurture_last_insert_contact_id__c FROM NurtureSingleton__c limit 1];
List listContacts = new List();
while (parser.nextToken() != null) {
if (parser.getCurrentToken() == JSONToken.START_ARRAY) {
while (parser.nextToken() != null) {
if (parser.getCurrentToken() == JSONToken.START_OBJECT){
Contacts cnts = (Contacts)parser.readValueAs(Contacts.class);
first_name=cnts.first_name;
last_name=cnts.last_name;
if(String.isEmpty(first_name)) {
first_name='-';
}
if(String.isEmpty(last_name)) {
last_name='-';
}
listContacts.add(new Contact(FirstName = first_name , LastName = last_name,Email=cnts.email,Title=cnts.title,Birthdate=cnts.birthdate,Phone=cnts.phone,
MobilePhone=cnts.mobile,Fax=cnts.fax,Description=cnts.description,LeadSource=cnts.lead_source,MailingCity=cnts.city,MailingState=cnts.state,
MailingPostalCode = cnts.zip, MailingCountry = cnts.country,Department=cnts.department,Salutation=cnts.Salutation,
MailingStreet=cnts.address,Nurture_contact_id__c=cnts.id,AccountId=cnts.salesforce_account_id));
nurSingle.nurture_last_insert_contact_id__c = cnts.id;
//insert listContacts;
}
}
}
}
insert listContacts;
you stated that
"But my batch file is inserting duplicate contacts with same email address."
Question here is , is it a duplicate or just the same email address?
You will need to compare the whole record or at least first name , last name email and phone
Enterprise businesses will have point of contact emails, meaning that Mr smith Mrs Yong and other can and will have an email like support#... or Info#..... and customer-care#..
So a simple validation on Email can't work if you have already one person in the list but another lead comes up.
Imaging a hospital that got AandE#xyzhospital.com , now you are selling health / hygiene products and selling direct to doctors, you are already selling to 2 doctors there and a 3rd ( a new lead joins) but you can only reach them under AandE#xyzhospital.com , the new lead would not be created as you only compare the email address

Weird SQL Error (Bug)

So this is really weird.
I run a sql command from .net on sqlserver with a 'Select Count(*)' and get a response like "Needs attention CA" (which is in a varchar of one field of one record of the inner joined tables).
Huh? How can Count(*) return a string? 999 out of 1000 times this code executes correctly. Just sometimes on some clients servers it will throw a string of errors for an hour or so only to miraculously stop again.
This is my sqlcommand:
SELECT Count(*)
FROM patientsappointments
INNER JOIN appointmenttypes
ON patientsappointments.appointmenttypeid =
appointmenttypes.appointmenttypeid
WHERE ( ( patientsappointments.date > #WeekStartDate
AND patientsappointments.date < #WeekFinishDate )
AND ( patientsappointments.status = 'Pending' )
AND ( patientsappointments.doctorid = #DoctorID )
AND ( appointmenttypes.appointmentname <> 'Note' ) )
And these are the parameters:
#WeekStartDate = 24/06/2013 12:00:00 AM (DateTime)
#WeekFinishDate = 1/07/2013 12:00:00 AM (DateTime)
#DoctorID = 53630c67-3a5a-406f-901c-dbf6b6d1b20f (UniqueIdentifier)
I do a sqlcmd.executescalar to get the result. Any ideas?
The actual executed code is:
SyncLock lockRefresh
Dim WeekFulfilled, WeekPending As Integer
Using conSLDB As New SqlConnection(modLocalSettings.conSLDBConnectionString)
Dim mySQL As SqlCommand
mySQL = New SqlCommand("SELECT COUNT(*) FROM PatientsAppointments INNER JOIN AppointmentTypes ON PatientsAppointments.AppointmentTypeID = AppointmentTypes.AppointmentTypeID " & _
"WHERE ((PatientsAppointments.Date > #WeekStartDate AND PatientsAppointments.Date < #WeekFinishDate) AND (PatientsAppointments.Status = 'Pending') " & _
"AND (PatientsAppointments.DoctorID = #DoctorID) AND (AppointmentTypes.AppointmentName <> 'Note'))", conSLDB)
Try
mySQL.Parameters.Add("#WeekStartDate", SqlDbType.DateTime).Value = MonthCalendar1.SelectionStart.Date.AddDays(-MonthCalendar1.SelectionStart.Date.DayOfWeek).AddDays(1)
mySQL.Parameters.Add("#WeekFinishDate", SqlDbType.DateTime).Value = MonthCalendar1.SelectionStart.Date.AddDays(-MonthCalendar1.SelectionStart.Date.DayOfWeek).AddDays(8)
mySQL.Parameters.Add("#DoctorID", SqlDbType.UniqueIdentifier).Value = cboDoctors.SelectedValue
conSLDB.Open()
'got errors here like "Conversion from string "R2/3" to type 'Integer' is not valid." Weird.
'failing on deadlock - maybe due to simultaneous updating from udp event. Try adding random delay to refresh
WeekPending = mySQL.ExecuteScalar
Catch ex As Exception
ErrorSender.SendError("frmAppointmentBook - RefreshHeader 1", ex, New String() {String.Format("mySQL.commandtext: {0}", mySQL.CommandText), _
String.Format("mySQL.Parameters: {0}", clsErrorSender.ParamsListToString(mySQL.Parameters))})
End Try
Me.lblPendingWeek.Text = WeekPending
Try
mySQL.CommandText = "SELECT COUNT(*) FROM PatientsAppointments INNER JOIN AppointmentTypes ON PatientsAppointments.AppointmentTypeID = AppointmentTypes.AppointmentTypeID WHERE " & _
"(PatientsAppointments.Date > #WeekStartDate AND PatientsAppointments.Date < #WeekFinishDate) AND (PatientsAppointments.Status = 'Fulfilled') AND " & _
"(PatientsAppointments.DoctorID = #DoctorID) AND (AppointmentTypes.AppointmentName <> 'Note')"
'didn't get the error here... but just in case...
WeekFulfilled = mySQL.ExecuteScalar
Catch ex As Exception
ErrorSender.SendError("frmAppointmentBook - RefreshHeader 2", ex, New String() {String.Format("mySQL.commandtext: {0}", mySQL.CommandText)})
End Try
conSLDB.Close()
End Using
End SyncLock
The exact error message is:
System.InvalidCastException
Conversion from string "Needs Attention DC" to type 'Integer' is not valid.
Your problem has nothing to do with the COUNT(*) portion of your code. The problem is somewhere else in your query. What that particular error is telling you is that at some point you are comparing a character field (it probably usually contains numbers) to an integer field. One of the values of the character field happens to be "Needs Attention DC". If I had to guess it is probably either patientsappointments.appointmenttypeid or appointmenttypes.appointmenttypeid. Double check the datatype of each of those columns to make sure they are in fact INT. If they are both INT then start checking the other explicitly named columns in your query to see if you have any surprises.
You must have an error somewhere in your implementation...
Per the documentation, count always returns an int data type value.
Since this doesn't always happen, it must be a result of one of the paramenter values that is sent in. This is one of the lbuiggest problems with using dynamic SQL. What I would do is create the dymanic SQl and then store it in a database logging table with the date and time and user who executed it. Then when you get the exception, you can find the exact SQL code that was sent. Most likely you need more controls on the input variables to ensure the data placed in them is of the correct data type.
I am going to make another guess. I am guessing that this is a multi threading issue. You probably are sharing the connection between multiple threads. Once in a while the thread will get that man from somewhere else and execute it. Make sure that the connection variable is local, and only one thread can access it at a time.
As Martin points out, the following answer is wrong. I'm keeping this here to show that this is wrong.
From what everyone has already said, there is a type mismatch on your columns. Since your where clause appears to be fine, and your join is fine, it must be elsewhere. I would check to see if patientsappointments or appointmenttypes are views. Maybe the view has a join that's throwing the exception. Check the schema definition of all your joins/where's. Somewhere in there you're storing integers in a character field. It's fine for most rows, but one of them has your string.
If it's not in your views, it may be a trigger somewhere. The point is that somewhere there is a schema mismatch. Once you find your schema mismatch, you can find the row by querying for that string.

Resources