Регистрация  |  Вход

Как правильно использовать Rec Type как условие в тригере?

Всем привет!

Столкнулся с ситуацией, которую раньше не вопринимал как потенциально-проблемную, а сейчас мне кажется, что в ней еще есть над чем подумать.

в тригере на апдейт заложена какая-то логика, которая выполняется только если у пришедшей записи нужный Record Type. Думаю, что это типичный случай.

чтобы сравнить РТайп я сначал выквериваю ID нужного РТ. и кверю так как ранее объяснял Дмитрий:

List<RecordType> RTypeList = [SELECT Id FROM RecordType 
WHERE Name = 'My record type' // или developerName
AND SobjectType = :MyObject__c.SObjectType.getDescribe().getName()
AND IsActive = true];

ID rtID;

if (RTypeList.size()>0) rtId = RTypeList[0].id;

for (MyObject__c mo : trigger.new) {

if(mo.RecordTypeId==rtID) {

//здесь логика, или только сбор в лист id записей, а логика вне цикла (если нужно кверить-дмлить)

}

}

ну так вот, а что если в какой-то момент, первый селект перестанет выбирать record type ID???
и rtID останется нулевым? ведь тригер не упадет, просто перестанет выполнятся условие, и как следствие логика. Что делать?

а что если сделать так:

List<RecordType> RTypeList =....


if (RTypeList.size()>0) {
ID rtId = RTypeList[0].id;

и пошла логика
}else{
как-то сообщить пользователю, что требуемый для условия РТ вообще не найден!!!
}

Я даже не уверен, что в правильном направлении веду размышления и код.

Спасибо

Всем привет!

Столкнулся с ситуацией, которую раньше не вопринимал как потенциально-проблемную, а сейчас мне кажется, что в ней еще есть над чем подумать.

в тригере на апдейт заложена какая-то логика, которая выполняется только если у пришедшей записи нужный Record Type. Думаю, что это типичный случай.

чтобы сравнить РТайп я сначал выквериваю ID нужного РТ. и кверю так как ранее объяснял Дмитрий:
	
[code]List<RecordType> RTypeList = [SELECT Id FROM RecordType 
									WHERE Name = 'My record type' // или developerName
									AND SobjectType = :MyObject__c.SObjectType.getDescribe().getName() 
									AND IsActive = true];
 
ID rtID;	
							
if (RTypeList.size()>0)  rtId = RTypeList[0].id;
	   
for (MyObject__c mo : trigger.new) {
	
			if(mo.RecordTypeId==rtID) 	{

//здесь логика, или только сбор в лист id записей, а логика вне цикла (если нужно кверить-дмлить)
		
	   }

}[/code]

ну так вот, а что если в какой-то момент, первый селект перестанет выбирать record type ID???
и rtID останется нулевым? ведь тригер не упадет, просто перестанет выполнятся условие, и как следствие логика. Что делать?

а что если сделать так:
[code]List<RecordType> RTypeList =....
 

							
if (RTypeList.size()>0) {
ID  rtId = RTypeList[0].id;

и пошла логика
}else{
как-то сообщить пользователю, что требуемый для условия РТ вообще не найден!!!
}
[/code]

Я даже не уверен, что в правильном направлении веду размышления и код.

Спасибо

Ну как бы тут нет технической проблемы. Тут больше логическая задача.

Ты в триггере используешь RecordType чтобы отобрать записи и что-то с ними сделать. Если таких записей нет, то и делать получается нечего. Значит если нет RecordType, значит и записей нет, значит делать ничего в триггере не надо.

твой второй вариант очень даже правильно реализует эту логику. Вот только else тебе не нужен. Триггер не должен сообщать пользователю ничего кроме ошибок (например валидация данных), которые не позволяют сохранить запись в базу данных. А то что есть какие-то записи или их нет и, это не влияет на сам факт сохранения записи в базу, не должно волновать триггер.

Есть записи - сделал что-то
Нет записей (нет recordType) - просто продолжил дальше.

Ну как бы тут нет технической проблемы. Тут больше логическая задача.

Ты в триггере используешь RecordType чтобы отобрать записи и что-то с ними сделать. Если таких записей нет, то и делать получается нечего. Значит если нет  RecordType, значит и записей нет, значит делать ничего в триггере не надо.

твой второй вариант очень даже правильно реализует эту логику. Вот только else тебе не нужен. Триггер не должен сообщать пользователю ничего кроме ошибок (например валидация данных), которые не позволяют сохранить запись в базу данных. А то что есть какие-то записи или их нет и, это не влияет на сам факт сохранения записи в базу, не должно волновать триггер. 

Есть записи - сделал что-то
Нет записей (нет recordType) - просто продолжил дальше.

Спасибо.

наверное я зря запаниковал.

Вот Прод. Вот запись с РТ "А", и удалить этот РТ с объекта неполучится, пока есть записи у которых есть такой РТ. Или может и получится - но тогда и у записей больше не будет такого РТ. Нет проблем.

Другой вариант. В коде РТ ищется по обычному имени. Кто-то в Проде менят имя "А" на "А1". В таком случае код не найдет РТ и не обработает записи. Но при этом упадет тест для данного тригера, так как в них ищется РТ "А", передается во вновь создаваемые записи. Получается, что или тест вообще упадет или упадет покрытие.

Ну ладно, наверное, об этом не стоит много думать. все будет норм с нашими РТами.

Спасибо.

наверное я зря запаниковал.

Вот Прод. Вот запись с РТ "А", и удалить этот РТ с объекта неполучится, пока есть записи у которых есть такой РТ. Или может и получится - но тогда и у записей больше не будет такого РТ. Нет проблем.

Другой вариант. В коде РТ ищется по обычному имени. Кто-то в Проде менят имя "А" на "А1". В таком случае код не найдет РТ и не обработает записи. Но при этом упадет тест для данного тригера, так как в них ищется РТ "А", передается во вновь создаваемые записи. Получается, что или тест вообще упадет или упадет покрытие.

Ну ладно, наверное, об этом не стоит много думать. все будет норм с нашими РТами.

RT могут не только удалить, но и деактивировать это надо в коде предусматривать. В твоем запросе RT это предусмотрено.

На счет изменят имя - для этого предназначено поле DeveloperName, оно в отличии от Name не меняется после создания. Это как API name для объекта

FROM RecordType WHERE DeveloperName = 'My_record_type'

RT могут не только удалить, но и деактивировать :) это надо в коде предусматривать. В твоем запросе RT это предусмотрено.

На счет изменят имя - для этого предназначено поле DeveloperName, оно в отличии от Name не меняется после создания. Это как API name для объекта

FROM RecordType WHERE DeveloperName = 'My_record_type'