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

Наивные вопросы от новичков

Тема для "наивных" вопросов от новичков.

Иногда бывает, что сталкиваешься с ситуацией, и даже не можешь правильно сформулировать вопрос.
Или вопросы слишком простые, чтобы выводить их в отдельную тему, но тем не менее требуют ответа.

На русском Убунту форуме есть раздел только для навичков. И если там задать какой-то вопрос, всегда ответят и ответят вежливо. Мне очень понравилось, это очень помогло перевести домашний комп на линукс без лишних фрустраций.

Вопрос:
Можно ли использовать физический адрес, например для картинки.

Ситуация:
делаю "шапку" на стандартном лэйауте для Дом страницы портала. там можно посадить либо лого-картинку, либо всю шапку в виде html фрагмента. Выбираю второе (так как при этом можно занять всю ширину шапки) и в разметку вставляю картинку с лого. НО этот html фрагмент не запускает APEX код, то есть не получается дать виртуальный адрес для картинки через {! URLFOR}. Поэтому я загрузил картинку не в Стат Ресурсы, а в Документы, нашел физический адрес и захардкодил в html-шапки. При переносе на продакшин, как я понимаю, придется переписывать адрес на новый. Но другого решения пока не вижу.

Тема для "наивных" вопросов от новичков. 

Иногда бывает, что сталкиваешься с ситуацией, и даже не можешь правильно сформулировать вопрос. 
Или вопросы слишком простые, чтобы выводить их в отдельную тему, но тем не менее требуют ответа.

На русском Убунту форуме есть раздел только для навичков. И если там задать какой-то вопрос, всегда ответят и ответят вежливо. Мне очень понравилось, это очень помогло перевести домашний комп на линукс без лишних фрустраций.

[b]Вопрос:[/b]
Можно ли использовать [b]физический адрес[/b], например для картинки.

[b]Ситуация:[/b]
делаю "шапку" на стандартном лэйауте для Дом страницы портала. там можно посадить либо лого-картинку, либо всю шапку в виде html фрагмента. Выбираю второе (так как при этом можно занять всю ширину шапки) и в разметку вставляю картинку с лого. НО этот html фрагмент не запускает APEX код, то есть не получается дать виртуальный адрес для картинки через {! URLFOR}. Поэтому я загрузил картинку не в Стат Ресурсы, а в Документы, нашел физический адрес и захардкодил в html-шапки. При переносе на продакшин, как я понимаю, придется переписывать адрес на новый. Но другого решения пока не вижу.

Еще наивный вопрос:

вижу код

IF (AND(Payment_Due_Date__c < Today(), Payment_Sataus__c = "unpaid"), "Где деньги?", null)
все просто.

Но как запускать этот код. Триггер на апдейт и пр. записи здесь не пойдет. С записью ничего не происходит. Просто меняется текущее время.
Получается, что нужно выставить таймер, который запускает раз в день код, который перебирает все записи и выполняет фрагмент выше.
Но как это все организовать в salesforce? уверен, что там уже есть решение...
Спасибо

Еще наивный вопрос:

вижу код

IF (AND(Payment_Due_Date__c < Today(), Payment_Sataus__c = "unpaid"), "Где деньги?", null)
все просто.

Но как запускать этот код. Триггер на апдейт и пр. записи здесь не пойдет. С записью ничего не происходит. Просто меняется текущее время.
Получается, что нужно выставить таймер, который запускает раз в день код, который перебирает все записи и выполняет фрагмент выше.
Но как это все организовать в salesforce? уверен, что там уже есть решение...
Спасибо

"Наивные вопросы от новичков" - тут нет ничего страшного. Наверное я из таких динозавров, которые помнят золотое время, когда интернет был роскошью, а знания и опыт передавались непосредственно прямым общением. Сам не понимаю модераторов на форумах, которые отсылают читать документацию и гуглить. Так что пиши вопросы любые, постараюсь ответить.

Небольшое замечание каждый вопрос ложи лучше в отдельную ветку. Сам понимаешь так получается каша.

Ответы смотри ниже.

"Наивные вопросы от новичков" - тут нет ничего страшного. Наверное я из таких динозавров, которые помнят золотое время, когда интернет был роскошью, а знания и опыт передавались непосредственно прямым общением. Сам не понимаю модераторов на форумах, которые отсылают читать документацию и гуглить. Так что пиши вопросы любые, постараюсь ответить.

Небольшое замечание :) каждый вопрос ложи лучше в отдельную ветку. Сам понимаешь так получается каша.

Ответы смотри ниже.

Вопрос:
Можно ли использовать физический адрес, например для картинки.

Физические адреса лучше не использовать. Все сломается при переносе на другой орг.

Ситуация:
делаю "шапку" на стандартном лэйауте для Дом страницы портала. там можно посадить либо лого-картинку, либо всю шапку в виде html фрагмента. Выбираю второе (так как при этом можно занять всю ширину шапки) и в разметку вставляю картинку с лого. НО этот html фрагмент не запускает APEX код, то есть не получается дать виртуальный адрес для картинки через {! URLFOR}. Поэтому я загрузил картинку не в Стат Ресурсы, а в Документы, нашел физический адрес и захардкодил в html-шапки. При переносе на продакшин, как я понимаю, придется переписывать адрес на новый. Но другого решения пока не вижу.

Все правильно. "шапка на home page" - это чистый html, который просто вставляется в home. Никакой обработки в стиле Visualforce тут нет. Поэтому естественно что получить адрес картинки из static resources не получится. В документации так и сказано что контент для шапки это или картинка logo, которая лежит в documents или файл содержащий статический html, который тоже лежит в documents. Если ты хочешь вставить в html картинку, то тут либо хардкодная ссылки на документ или небольшой хак.

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

[quote]Вопрос:
Можно ли использовать физический адрес, например для картинки.
[/quote]

Физические адреса лучше не использовать. Все сломается при переносе на другой орг.

[quote]Ситуация:
делаю "шапку" на стандартном лэйауте для Дом страницы портала. там можно посадить либо лого-картинку, либо всю шапку в виде html фрагмента. Выбираю второе (так как при этом можно занять всю ширину шапки) и в разметку вставляю картинку с лого. НО этот html фрагмент не запускает APEX код, то есть не получается дать виртуальный адрес для картинки через {! URLFOR}. Поэтому я загрузил картинку не в Стат Ресурсы, а в Документы, нашел физический адрес и захардкодил в html-шапки. При переносе на продакшин, как я понимаю, придется переписывать адрес на новый. Но другого решения пока не вижу.[/quote]

Все правильно. "шапка на home page" - это чистый html, который просто вставляется в home. Никакой обработки в стиле Visualforce тут нет. Поэтому естественно что получить адрес картинки из static resources не получится. В документации так и сказано что контент для шапки это или картинка logo, которая лежит в documents или файл содержащий статический html, который тоже лежит в documents. Если ты хочешь вставить в html картинку, то тут либо хардкодная ссылки на документ или небольшой хак.

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

вижу код

IF (AND(Payment_Due_Date__c < Today(), Payment_Sataus__c = "unpaid"), "Где деньги?", null)
все просто.

Тут нужно точно сказать где видишь. То что ты видишь это так называемая в Salesforce FORMULA. Они могут применяться в разных местах: formula field, validation rule, visualforce page.

Но как запускать этот код. Триггер на апдейт и пр. записи здесь не пойдет. С записью ничего не происходит. Просто меняется текущее время.
Получается, что нужно выставить таймер, который запускает раз в день код, который перебирает все записи и выполняет фрагмент выше.
Но как это все организовать в salesforce? уверен, что там уже есть решение...

Как запустить тоже зависит от того, откуда ты взял эту FORMULA.

[quote]вижу код

IF (AND(Payment_Due_Date__c < Today(), Payment_Sataus__c = "unpaid"), "Где деньги?", null)
все просто.[/quote]

Тут нужно точно сказать где видишь. То что ты видишь это так называемая в Salesforce FORMULA. Они могут применяться в разных местах: formula field, validation rule, visualforce page.

[quote]Но как запускать этот код. Триггер на апдейт и пр. записи здесь не пойдет. С записью ничего не происходит. Просто меняется текущее время.
Получается, что нужно выставить таймер, который запускает раз в день код, который перебирает все записи и выполняет фрагмент выше.
Но как это все организовать в salesforce? уверен, что там уже есть решение...[/quote]

Как запустить тоже зависит от того, откуда ты взял эту FORMULA.

спасибо огромное.

Dmitry Shnyrev
Небольшое замечание каждый вопрос ложи лучше в отдельную ветку. Сам понимаешь так получается каша.

Ответы смотри ниже.

открыл такую тему именно потому, что не смог сфорулировать вопрос по второй ситуации (с формулой) и сделать ясное заглавие у темы.
может модератору дать право редактировать неопределенные заглавия у тем, так что бы стороннему читателю (да автору темы тоже) стало понятно, о чем тема.

Dmitry Shnyrev
хак - размести картинку где-нибудь на внешнем ресурсе, желательно своем и ставь ссылку на эту картинку. Сам понимаешь это не самый лучший выход, но лучше не придумаешь, если собираешься активно распространять свое приложение.
)

вот это первое что я сделал, так как не был уверен что SF даст подтянуть что-нибудь с внешнего ресурса. Но лого - клиенто-зависимая вещь, у всех - разная, поэтому придется хардкодить...

Dmitry Shnyrev
Как запустить тоже зависит от того, откуда ты взял эту FORMULA.

эта формула в данном случае - просто описание идеи. А что если я хочу, чтобы в объекте "Машины" КОД ежедневно проверял поле "Дата сл замены масла", и если дата совпадает с сегодня или меньше, то менять статус в другом поле этого же объекта на "пора что-то делать с машиной", после чего сработает тригер и т.д. В этом непонятно только вот эта часть "КОД ежедневно самостоятельно проверял дата-поле в объекте Машины ". Как это организовать?

спасибо огромное.

[quote="Dmitry Shnyrev"]

Небольшое замечание :) каждый вопрос ложи лучше в отдельную ветку. Сам понимаешь так получается каша.

Ответы смотри ниже.[/quote]

открыл такую тему именно потому, что не смог сфорулировать вопрос по второй ситуации (с формулой) и сделать ясное заглавие у темы.
может модератору дать право редактировать неопределенные заглавия у тем, так что бы стороннему читателю (да автору темы тоже) стало понятно, о чем тема.

[quote="Dmitry Shnyrev"]
хак - размести картинку где-нибудь на внешнем ресурсе, желательно своем и ставь ссылку на эту картинку. Сам понимаешь это не самый лучший выход, но лучше не придумаешь, если собираешься активно распространять свое приложение.[/quote]) 

вот это первое что я сделал, так как не был уверен что SF даст подтянуть что-нибудь с внешнего ресурса. Но лого - клиенто-зависимая вещь, у всех - разная, поэтому придется хардкодить...

[quote="Dmitry Shnyrev"]Как запустить тоже зависит от того, откуда ты взял эту FORMULA.[/quote]
эта формула в данном случае - просто описание идеи. А что если я хочу, чтобы в объекте "Машины" КОД ежедневно проверял поле "Дата сл замены масла", и если дата совпадает с сегодня или меньше, то  менять статус в другом поле этого же объекта на "пора что-то делать с машиной", после чего сработает тригер и т.д. В этом непонятно только вот эта часть "КОД ежедневно самостоятельно проверял дата-поле в объекте Машины ". Как это организовать?

может модератору дать право редактировать неопределенные заглавия у тем

Ну пока я и модератор и админ и владелец :). Так что все заботы ложатся на мои плечи. Еще активно мне помогает Sergey Prichepo, так что если не я, то Сергей точно сможет помочь.

Но лого - клиенто-зависимая вещь, у всех - разная, поэтому придется хардкодить...

Ну тогда тут даже думать не надо - ложишь в documents лого и хардкодишь ссылку.

эта формула в данном случае - просто описание идеи. А что если я хочу, чтобы в объекте "Машины" КОД ежедневно проверял поле "Дата сл замены масла", и если дата совпадает с сегодня или меньше, то менять статус в другом поле этого же объекта на "пора что-то делать с машиной", после чего сработает тригер и т.д. В этом непонятно только вот эта часть "КОД ежедневно самостоятельно проверял дата-поле в объекте Машины ". Как это организовать?

Есть два способа. Один мне нравится, другой нет.

Начну с того, который мне не нравится. Не нравится потому что очень сложно контролировать и отлаживать.
Time-based workflow. Подробно не буду рассказывать. Но суть в том что заставить срабатывать workflow относительно даты записаной в одном из полей объекта.

Второй способ более интересный, потому что все находится в коде. Надо запусти scheduled job, который будет срабатывать каждый день в определенное время и обрабатывать все записи, которые удовлетворяют определенному условию. В твоем случае выбирать все машины, у которых дата замены масла сегодня или прошла.

Попробуй почитай про оба способа доках Salesforce. Если будут вопросы пиши.

[quote]может модератору дать право редактировать неопределенные заглавия у тем[/quote]

Ну пока я и модератор и админ и владелец :). Так что все заботы ложатся на мои плечи. Еще активно мне помогает Sergey Prichepo, так что если не я, то Сергей точно сможет помочь.

[quote]Но лого - клиенто-зависимая вещь, у всех - разная, поэтому придется хардкодить...[/quote]
Ну тогда тут даже думать не надо - ложишь в documents лого и хардкодишь ссылку.

[quote]эта формула в данном случае - просто описание идеи. А что если я хочу, чтобы в объекте "Машины" КОД ежедневно проверял поле "Дата сл замены масла", и если дата совпадает с сегодня или меньше, то менять статус в другом поле этого же объекта на "пора что-то делать с машиной", после чего сработает тригер и т.д. В этом непонятно только вот эта часть "КОД ежедневно самостоятельно проверял дата-поле в объекте Машины ". Как это организовать?[/quote]

Есть два способа. Один мне нравится, другой нет.

Начну с того, который мне не нравится. Не нравится потому что очень сложно контролировать и отлаживать.
Time-based workflow. Подробно не буду рассказывать. Но суть в том что заставить срабатывать workflow относительно даты записаной в одном из полей объекта.

Второй способ более интересный, потому что все находится в коде. Надо запусти scheduled job, который будет срабатывать каждый день в определенное время и обрабатывать все записи, которые удовлетворяют определенному условию. В твоем случае выбирать все машины, у которых дата замены масла сегодня или прошла. 

Попробуй почитай про оба способа доках Salesforce. Если будут вопросы пиши.

Спасибо за ответы

Спасибо за ответы

Dmitry Shnyrev
может модератору дать право редактировать неопределенные заглавия у тем

Ну тогда тут даже думать не надо - ложишь в documents лого и хардкодишь ссылку.

Tам тоже не всё просто если делаешь для cайта Salesforce целая технология использовать документ или картинку.

Sonninho,

I ensured the following things, and was able to make an .xls file attached to a document downloadable on a sites page:

1. In the Sites Profile ("public access settings"), enable Read access to Documents (You indicate that this is already the case)

2. Edit the folder in which the document is stored, and ensure that the Sites profile has access to the folder. To do this, I went to Admin setup ---> Manage Users ---> Public Groups and created a group consisting of ONLY the User defined by my Sites profile. You can then add this "group" to the permissions on the folder.

Use <apex:outputLink> and in the value put "/servlet/servlet.FileDownload?file=(your docs ID here)"

Hope this helps.

Я думаю похожие вопросы могут быть и для внутренних юзеров.Особенно если нету доступа Read access to Document.Буквально вчера с этим столкнулся.

[quote="Dmitry Shnyrev"][quote]может модератору дать право редактировать неопределенные заглавия у тем[/quote]
Ну тогда тут даже думать не надо - ложишь в documents лого и хардкодишь ссылку.
[/quote]
Tам тоже не всё просто если делаешь для cайта Salesforce целая  технология использовать документ или картинку.

Sonninho,
 
I ensured the following things, and was able to make an .xls file attached to a document downloadable on a sites page:
 
1. In the Sites Profile ("public access settings"), enable Read access to Documents (You indicate that this is already the case)
 
2. Edit the folder in which the document is stored, and ensure that the Sites profile has access to the folder. To do this, I went to Admin setup ---> Manage Users ---> Public Groups and created a group consisting of ONLY the User defined by my Sites profile. You can then add this "group" to the permissions on the folder.
 
Use <apex:outputLink> and in the value put "/servlet/servlet.FileDownload?file=(your docs ID here)"
 
Hope this helps.

Я думаю похожие вопросы могут быть и для внутренних юзеров.Особенно если нету доступа Read access to Document.Буквально вчера с этим столкнулся.

Tам тоже не всё просто если делаешь для cайта Salesforce целая технология использовать документ или картинку.

Картинки (как и любой контент) в Documents можно сделать доступным извне. Ниже мой эксперимент.

Возможно, Сергей, твой заказчик имел в виду не Documents, а CRM Content? Там действительно есть такая проблема как расшаривание контента на пользователей, профили или public groups.

Собственно эксперимент:

1. Создаем folder c доступом на всех

2. Загружаем картинку, только обязательно ставим ей Externally Available Image

3. открываем картинку по прямому URL (браузер другой, я в нем не залогинен на Salesforce)

Вот линк картинки https://c.ap1.content.force.com/servlet/servlet.ImageServer?id=01590000001l6IA&oid=00D90000000mjiY&lastMod=1380886317000

[quote]Tам тоже не всё просто если делаешь для cайта Salesforce целая технология использовать документ или картинку.[/quote]

Картинки (как и любой контент) в Documents можно сделать доступным извне. Ниже мой эксперимент.

Возможно, Сергей, твой заказчик имел в виду не Documents, а CRM Content? Там действительно есть такая проблема как расшаривание контента на пользователей, профили или public groups. 

[i]Собственно эксперимент:[/i]

1. Создаем folder c доступом на всех
[img]/phpbb-files/SF-docs-1.png[/img]

2. Загружаем картинку, только обязательно ставим ей Externally Available Image
[img]/phpbb-files/SF-docs-2.png[/img]

3. открываем картинку по прямому URL (браузер другой, я в нем не залогинен на Salesforce)
[img]/phpbb-files/SF-docs-3.png[/img]

Вот линк картинки [url]https://c.ap1.content.force.com/servlet/servlet.ImageServer?id=01590000001l6IA&oid=00D90000000mjiY&lastMod=1380886317000[/url]

Cделал тоже самое для эксперемента не получилось,то есть у меня по умолчанию при создании папки нету ни каких юзеров,только моя паплик группа,пробывал ручками добавить odi= я так понял что это org id не получилось так же.

Cделал тоже самое для эксперемента не получилось,то есть у меня по умолчанию при создании папки нету ни каких юзеров,только моя паплик группа,пробывал ручками добавить odi= я так понял что это org id не получилось так же.

Sergey Prichepo
Cделал тоже самое для эксперемента не получилось,то есть у меня по умолчанию при создании папки нету ни каких юзеров,только моя паплик группа,пробывал ручками добавить odi= я так понял что это org id не получилось так же.

Подожди, при создании папки там есть радиобутоны, первый из которых This folder is accessible by all users. И все! Остальные элементы формы просто неактивные как на моем скриншоте.

Или получается что мы сейчас про разные вещи разговариваем?

[quote="Sergey Prichepo"]Cделал тоже самое для эксперемента не получилось,то есть у меня по умолчанию при создании папки нету ни каких юзеров,только моя паплик группа,пробывал ручками добавить odi= я так понял что это org id не получилось так же.[/quote]

Подожди, при создании папки там есть радиобутоны, первый из которых This folder is accessible by all users. И все! Остальные элементы формы просто неактивные как на моем скриншоте.

Или получается что мы сейчас про разные вещи разговариваем?

Dmitry Shnyrev
Sergey Prichepo
Cделал тоже самое для эксперемента не получилось,то есть у меня по умолчанию при создании папки нету ни каких юзеров,только моя паплик группа,пробывал ручками добавить odi= я так понял что это org id не получилось так же.

Подожди, при создании папки там есть радиобутоны, первый из которых This folder is accessible by all users. И все! Остальные элементы формы просто неактивные как на моем скриншоте.

Или получается что мы сейчас про разные вещи разговариваем?


Догадываюсь что про одни This folder is accessible by all users я так понима предпологает что все юзеры которые в левой колонки будут выбранны. У меня там только public group которая совсем не user. У меня работает тот способ который я описал выше.

[quote="Dmitry Shnyrev"][quote="Sergey Prichepo"]Cделал тоже самое для эксперемента не получилось,то есть у меня по умолчанию при создании папки нету ни каких юзеров,только моя паплик группа,пробывал ручками добавить odi= я так понял что это org id не получилось так же.[/quote]

Подожди, при создании папки там есть радиобутоны, первый из которых This folder is accessible by all users. И все! Остальные элементы формы просто неактивные как на моем скриншоте.

Или получается что мы сейчас про разные вещи разговариваем?[/quote]
Догадываюсь что про одни This folder is accessible by all users я так понима предпологает что все юзеры которые в левой колонки будут выбранны. У меня там только public group которая совсем не user. У меня работает тот способ который я описал выше.

Догадываюсь что про одни This folder is accessible by all users я так понима предпологает что все юзеры которые в левой колонки будут выбранны. У меня там только public group которая совсем не user.

"This folder is accessible by all users" наверное тут имеется в виду вообще все пользователи на орге и пофиг что у тебя там выбрано в левой колонке

[quote]Догадываюсь что про одни This folder is accessible by all users я так понима предпологает что все юзеры которые в левой колонки будут выбранны. У меня там только public group которая совсем не user.[/quote]

"This folder is accessible by all users" наверное тут имеется в виду вообще все пользователи  на орге и пофиг что у тебя там выбрано в левой колонке

Но мы наверное вообще не о том сейчас спорим Чтобы картинка в documents стала доступна извне достаточно у нее поставить Externaly Available Image.
Вот это фигня наверное и откроет доступ.

Но мы наверное вообще не о том сейчас спорим :)
Чтобы картинка в documents стала доступна извне достаточно у нее поставить Externaly Available Image.
Вот это фигня наверное и откроет доступ.

Dmitry Shnyrev
Но мы наверное вообще не о том сейчас спорим Чтобы картинка в documents стала доступна извне достаточно у нее поставить Externaly Available Image.
Вот это фигня наверное и откроет доступ.

Всё разобрались оказывается надо копировать url который показывается НЕ понажатие на кнопку View для просмотра картинки, а заходить на view detail Page находить загружанную картинку нажимать что вроде Сopy Image Url тогда берется целый url картинки и org id и почему то дата последний модефикации.Вообщем все работает Отлично Спасибо за консультацию.

[quote="Dmitry Shnyrev"]Но мы наверное вообще не о том сейчас спорим :)
Чтобы картинка в documents стала доступна извне достаточно у нее поставить Externaly Available Image.
Вот это фигня наверное и откроет доступ.[/quote]
Всё разобрались оказывается надо копировать url который показывается НЕ понажатие на кнопку View для просмотра картинки, а заходить на view detail Page находить загружанную картинку нажимать что вроде Сopy Image Url тогда берется целый url картинки и org id и почему то дата последний модефикации.Вообщем все работает Отлично :D  Спасибо за консультацию.

Sergey Prichepo
Dmitry Shnyrev
Но мы наверное вообще не о том сейчас спорим Чтобы картинка в documents стала доступна извне достаточно у нее поставить Externaly Available Image.
Вот это фигня наверное и откроет доступ.

Всё разобрались оказывается надо копировать url который показывается НЕ понажатие на кнопку View для просмотра картинки, а заходить на view detail Page находить загружанную картинку нажимать что вроде Сopy Image Url тогда берется целый url картинки и org id и почему то дата последний модефикации.Вообщем все работает Отлично Спасибо за консультацию.

я тоже не сразу догадался как это url найти...

[quote="Sergey Prichepo"][quote="Dmitry Shnyrev"]Но мы наверное вообще не о том сейчас спорим :)
Чтобы картинка в documents стала доступна извне достаточно у нее поставить Externaly Available Image.
Вот это фигня наверное и откроет доступ.[/quote]
Всё разобрались оказывается надо копировать url который показывается НЕ понажатие на кнопку View для просмотра картинки, а заходить на view detail Page находить загружанную картинку нажимать что вроде Сopy Image Url тогда берется целый url картинки и org id и почему то дата последний модефикации.Вообщем все работает Отлично :D  Спасибо за консультацию.[/quote]

я тоже не сразу догадался как это url найти...

Пробывал таким же способом сохранить и получить документ,не получилось.

Пробывал таким же способом сохранить и получить документ,не получилось.

Sergey Prichepo
Пробывал таким же способом сохранить и получить документ,не получилось.

Да, у меня тоже не получилось. По ходу доступной всем можно сделать только картинку.
Ну может это и логично? чтобы не превращать Salesforce в очередной файловый хостинг. Хочешь получить доступ к документам хранящимся на орге, залогинься :)

[quote="Sergey Prichepo"]Пробывал таким же способом сохранить и получить документ,не получилось.[/quote]

Да, у меня тоже не получилось. По ходу доступной всем можно сделать только картинку. 
Ну может это и логично? чтобы не превращать Salesforce в очередной файловый хостинг. Хочешь получить доступ к документам хранящимся на орге, залогинься :)

Dmitry Shnyrev
Sergey Prichepo
Пробывал таким же способом сохранить и получить документ,не получилось.

Да, у меня тоже не получилось. По ходу доступной всем можно сделать только картинку.
Ну может это и логично? чтобы не превращать Salesforce в очередной файловый хостинг. Хочешь получить доступ к документам хранящимся на орге, залогинься :)


Логично согласен. Но способ который я описал выше на получения, на самом деле был для документа, просто я подумал тогда что это точно аналогично для карнтинки. То есть если настроить профаил site guest user и остальные настройки.То можно сайта с Salesforce cкачивать документ без регистрации и логина.

[quote="Dmitry Shnyrev"][quote="Sergey Prichepo"]Пробывал таким же способом сохранить и получить документ,не получилось.[/quote]

Да, у меня тоже не получилось. По ходу доступной всем можно сделать только картинку. 
Ну может это и логично? чтобы не превращать Salesforce в очередной файловый хостинг. Хочешь получить доступ к документам хранящимся на орге, залогинься :)[/quote]
Логично согласен. Но способ который я описал выше на получения, на самом деле был для документа, просто я подумал тогда что это точно аналогично для карнтинки. То есть если настроить профаил site guest user и остальные настройки.То можно сайта с Salesforce cкачивать документ без регистрации и логина.

Спасибо всем за участие в обсуждении.

Вот еще одна обычная ситуация и наивный вопрос:

есть кастомный объект одно поле у которого - лук-ап в Эккаунты (отоброжает какой-то эккаунт).
следующее поле должно отоброжать контакт, связанный в выбранным Эккаунтом (кстати их там может быть много, так что давайте предположим, что нужно отобразить тот у которого кастомном поле "Первичный контакт" выставлено в тру).

И как это лучше сделать:
сделать Тригер который заполняет это поле в момент создания/сохранения?
или это можно решить через формульно-текстовое поле?
Непривычный синтаксис формул, их простота и возможности меня до сих пор смущают.
Но там есть достууп от нашего объекта к Эккауну, а от Эккаунта к Контакту нет, так как между последними связь идет от Контакта к Эккаунту.

Спасибо за советы

Спасибо всем за участие в обсуждении.

Вот еще одна обычная ситуация и наивный вопрос:

есть кастомный объект одно поле у которого - лук-ап в Эккаунты (отоброжает какой-то эккаунт).
следующее поле должно отоброжать контакт, связанный в выбранным Эккаунтом (кстати их там может быть много, так что давайте предположим, что нужно отобразить тот у которого  кастомном поле "Первичный контакт" выставлено в тру).

И как это лучше сделать:
сделать Тригер который заполняет это поле в момент создания/сохранения?
или это можно решить через формульно-текстовое поле?
Непривычный синтаксис формул, их простота и возможности меня до сих пор смущают.
Но там есть достууп от нашего объекта к Эккауну, а от Эккаунта к Контакту нет, так как между последними связь идет от Контакта к Эккаунту.

Спасибо за советы

Еще неожиданная хоть и не проблема, но ситуация:
поставил поле Дата на объект в которое будут вводится преимущественно ретроспективные даты (за 1998 и т.д.), так вот, если попробовать его заполнить, то календарь поп-ап не предлагает прошлые года (только 2012, текущий и перспективные).
вручную можно ввести требуюмую дату, но как пить-дать, кастомеры будут пробовать для ввода именно календарный поп-ап, что вполне понятно...

Еще неожиданная хоть и не проблема, но ситуация:
поставил поле Дата на объект в которое будут вводится преимущественно ретроспективные даты (за 1998 и т.д.), так вот, если попробовать его заполнить, то календарь поп-ап не предлагает прошлые года (только 2012, текущий и перспективные).
вручную можно ввести требуюмую дату, но как пить-дать, кастомеры будут пробовать для ввода именно календарный поп-ап, что вполне понятно...

есть кастомный объект одно поле у которого - лук-ап в Эккаунты (отоброжает какой-то эккаунт).
следующее поле должно отоброжать контакт, связанный в выбранным Эккаунтом (кстати их там может быть много, так что давайте предположим, что нужно отобразить тот у которого кастомном поле "Первичный контакт" выставлено в тру).

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

Если это Standard Layout, то тут придется делать автозаполнение на уровне базы данных, т.е. в триггере. Formula field для этого не совсем подходит - в формуле можно обращаться только к родителям, а тут получится выборки подчиненных записей.

[quote]есть кастомный объект одно поле у которого - лук-ап в Эккаунты (отоброжает какой-то эккаунт).
следующее поле должно отоброжать контакт, связанный в выбранным Эккаунтом (кстати их там может быть много, так что давайте предположим, что нужно отобразить тот у которого кастомном поле "Первичный контакт" выставлено в тру).[/quote]

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

Если это Standard Layout, то тут придется делать автозаполнение на уровне базы данных, т.е. в триггере. Formula field для этого не совсем подходит - в формуле можно обращаться только к родителям, а тут получится выборки подчиненных записей.

Den Brown
Еще неожиданная хоть и не проблема, но ситуация:
поставил поле Дата на объект в которое будут вводится преимущественно ретроспективные даты (за 1998 и т.д.), так вот, если попробовать его заполнить, то календарь поп-ап не предлагает прошлые года (только 2012, текущий и перспективные).
вручную можно ввести требуюмую дату, но как пить-дать, кастомеры будут пробовать для ввода именно календарный поп-ап, что вполне понятно...


Интересный баг - задача. Не сталкивался с таким, но по ходу это может действительно предствлять для пользователей проблему.

Google подсказал что данная проблема достаточно актуальна вот первые из ссылок на вокрараунд решений данной проблемы

http://salesforce.stackexchange.com/questions/7944/standard-datepicker-year-values
http://salesforcenow.blogspot.com/2013/02/how-to-show-more-years-in-salesforce.html

[quote="Den Brown"]Еще неожиданная хоть и не проблема, но ситуация:
поставил поле Дата на объект в которое будут вводится преимущественно ретроспективные даты (за 1998 и т.д.), так вот, если попробовать его заполнить, то календарь поп-ап не предлагает прошлые года (только 2012, текущий и перспективные).
вручную можно ввести требуюмую дату, но как пить-дать, кастомеры будут пробовать для ввода именно календарный поп-ап, что вполне понятно...[/quote]
 
Интересный баг - задача. Не сталкивался с таким, но по ходу это может действительно предствлять для пользователей проблему.

Google подсказал что данная проблема достаточно актуальна вот первые из ссылок на вокрараунд решений данной проблемы

[url]http://salesforce.stackexchange.com/questions/7944/standard-datepicker-year-values[/url]
[url]http://salesforcenow.blogspot.com/2013/02/how-to-show-more-years-in-salesforce.html[/url]

Dmitry Shnyrev
Если это Standard Layout, то тут придется делать автозаполнение на уровне базы данных, т.е. в триггере. Formula field для этого не совсем подходит - в формуле можно обращаться только к родителям, а тут получится выборки подчиненных записей.

Вот я так и подумал.

Изучаю Standard Layoutы, и ситуация такая:
три объекта: первый мастер для второго, второй чайлд для первого, но мастер для третьего.

В Standard Layoutе первого объекта есть секция Related Lists в котором представленны связанные записи дочернего второго объекта.

Но фантазия клиентов не иссякает: им нужно Related Lists секция на Standard Layout первого объекта в котором были бы отображены записи третьего объекта, которые дочерние от записей второго объекта, которые дочерние к данной записи первого объекта (кстати, а почему бы и нет).

Но как это сделать? Возможно ли вставлять в Standard Layoutе полностью кастомизированне секции со своей логикой?


спасибо

[quote="Dmitry Shnyrev"]
Если это Standard Layout, то тут придется делать автозаполнение на уровне базы данных, т.е. в триггере. Formula field для этого не совсем подходит - в формуле можно обращаться только к родителям, а тут получится выборки подчиненных записей.[/quote]

Вот я так и подумал.

Изучаю Standard Layoutы, и ситуация такая:
три объекта: первый мастер для второго, второй чайлд для первого, но мастер для третьего.

В  Standard Layoutе первого объекта есть секция Related Lists в котором представленны связанные записи дочернего второго объекта.

Но фантазия клиентов не иссякает: им нужно Related Lists секция на  Standard Layout первого объекта в котором были бы отображены записи третьего объекта, которые  дочерние от  записей второго объекта, которые  дочерние к данной записи первого объекта (кстати, а почему бы и нет).

Но как это сделать? Возможно ли вставлять в Standard Layoutе полностью кастомизированне секции со своей логикой?


спасибо

Вот еще столкнулся с ситуацией вокруг Related Lists секции на какой-нибудь дитейл педж.

Возможно, вы уже устали от моих вопросов. Я тоже устал от них
Но есть в них одно важное свойство:
они не высосаны из пальца, а взяты из реальных ситуаций. С которыми каждый из нас может столкнутся позже.
И если сейчас мы определим какую-то ситуацию как проблему, и подумаем как ее можно преодолеть, то это будет ценными практическими знаниями, навыками на будущее для каждого.

И вот какая ситуация.
Три объекта. Два первых Мастер и Дитейл объекты (например Здание и Этажи). В третьем объекте (Дверь) есть два лук-ап поля, на первые два объекта.
Пользователь может указать что запись Дверь относится только к Зданию и в Дитейл странице Здания в Релайтел Листе Дверей будет видна эта Дверь - все ОК.

Но пользователь, может указать, что Дверь относится в Этажу и выбрать Здание (как же без этого). Но теперь дверь видна в релайтед листе не только соответствующего Этажа, но и Здания - и последнее как раз не нужно.

Как фильтровать записи в Рилейтед Листе на Дитейл странице? я не нашел этого...
Или сделать поле Здания на объекте Двери не лук-ап, а Пик-лист, но это хард-код получается, не серьезно как то...
Или сделать тригер который в момент сохранения Дверей в случае если указан Этаж, сбрасывает поле Здание в ноль, и заполняет какое текстовое поле названием того здания? неплохо, но это название не кликабельно, не ведет на реальную запись того здания, как в случае с лук-ап.

Фильтрование бы дало больше гибкости...

Вот нашел об этом:
https://success.salesforce.com/ideaView?id=08730000000ZBUTAA4
но похоже это только идея, а не реальный скрин...
спасибо

Вот еще столкнулся с ситуацией вокруг Related Lists секции на какой-нибудь дитейл педж.

Возможно, вы уже устали от моих вопросов. Я тоже устал от них :)

Но есть в них одно важное свойство:
они не высосаны из пальца, а взяты из реальных ситуаций. С которыми каждый из нас может столкнутся позже.
И если сейчас мы определим какую-то ситуацию как проблему, и подумаем как ее можно преодолеть, то это будет ценными практическими знаниями, навыками на будущее для каждого.

И вот какая ситуация. 
Три объекта. Два первых Мастер и Дитейл объекты (например Здание и Этажи). В третьем объекте (Дверь) есть два лук-ап поля, на первые два объекта. 
Пользователь может указать что запись Дверь относится только к Зданию и в Дитейл странице Здания в Релайтел Листе Дверей будет видна эта Дверь - все ОК.

Но пользователь, может указать, что Дверь относится в Этажу и выбрать Здание (как же без этого). Но теперь дверь видна в релайтед листе не только соответствующего Этажа, но и Здания - и последнее как раз не нужно. 

Как фильтровать записи в Рилейтед Листе на Дитейл странице? я не нашел этого...
Или сделать поле Здания на объекте Двери не лук-ап, а Пик-лист, но это хард-код получается, не серьезно как то...
Или сделать тригер который в момент сохранения Дверей в случае если указан Этаж, сбрасывает поле Здание в ноль, и заполняет какое текстовое поле названием того здания? неплохо, но это название не кликабельно, не ведет на реальную запись того здания, как в случае с лук-ап.

Фильтрование бы дало больше гибкости...

Вот нашел об этом:
[url]https://success.salesforce.com/ideaView?id=08730000000ZBUTAA4[/url]
но похоже это только идея, а не реальный скрин...
спасибо

Den Brown
Еще неожиданная хоть и не проблема, но ситуация:
поставил поле Дата на объект в которое будут вводится преимущественно ретроспективные даты (за 1998 и т.д.), так вот, если попробовать его заполнить, то календарь поп-ап не предлагает прошлые года (только 2012, текущий и перспективные).
вручную можно ввести требуюмую дату, но как пить-дать, кастомеры будут пробовать для ввода именно календарный поп-ап, что вполне понятно...

Это не проблема даже, так не дочет salesforce.Решается минут за 20 javascript oтом.В цикле дописываешь не достающие даты.Проверяли все было ок.

[quote="Den Brown"]Еще неожиданная хоть и не проблема, но ситуация:
поставил поле Дата на объект в которое будут вводится преимущественно ретроспективные даты (за 1998 и т.д.), так вот, если попробовать его заполнить, то календарь поп-ап не предлагает прошлые года (только 2012, текущий и перспективные).
вручную можно ввести требуюмую дату, но как пить-дать, кастомеры будут пробовать для ввода именно календарный поп-ап, что вполне понятно...[/quote]
Это не проблема даже, так не дочет salesforce.Решается минут за 20 javascript oтом.В цикле дописываешь не достающие даты.Проверяли все было ок.

Den Brown
Но пользователь, может указать, что Дверь относится в Этажу и выбрать Здание (как же без этого). Но теперь дверь видна в релайтед листе не только соответствующего Этажа, но и Здания - и последнее как раз не нужно.

Я вижу тут проблему не в Salesforce и его standard layout, а в реализации. Related list предназначем именно для того чтобы показывать все подчиненные объекты. Теперь к дверям от здания и этажа. Если пользователь указал что дверь принадлежит и зданию и этажу (типо можно это сделать), то почему в списке подчиненных дверей для этажа я не должен показывать двери от здания, если они по логике принадлежат этажу.

К чему я виду. Если предусмотренно что дверь, которая принадлежит зданию, не может принадлежать этажу и наоборот, то может лучше это реализовать на уровне базы данных с помощью дополнительной проверки (validation rule или trigger)? Т.е. если заполнено одно поле, не заполнять другое.

Мне кажется это логичнее.

Иначе придется писать Visualforce page или вставлять inline page с нужной логикой фильтрации

[quote="Den Brown"]Но пользователь, может указать, что Дверь относится в Этажу и выбрать Здание (как же без этого). Но теперь дверь видна в релайтед листе не только соответствующего Этажа, но и Здания - и последнее как раз не нужно. [/quote]

Я вижу тут проблему не в Salesforce  и его standard layout, а в реализации. Related list предназначем именно для того чтобы показывать все подчиненные объекты. Теперь к дверям от здания и этажа. Если пользователь указал что дверь принадлежит и зданию и этажу (типо можно это сделать), то почему в списке подчиненных дверей для этажа я не должен показывать двери от здания, если они по логике принадлежат этажу. 

К чему я виду. Если предусмотренно что дверь, которая принадлежит зданию, не может принадлежать этажу и наоборот, то может лучше это реализовать на уровне базы данных с помощью дополнительной проверки (validation rule или trigger)? Т.е. если заполнено одно поле, не заполнять другое. 

Мне кажется это логичнее.

Иначе придется писать Visualforce page или вставлять inline page с нужной логикой фильтрации

Den Brown
Но фантазия клиентов не иссякает: им нужно Related Lists секция на Standard Layout первого объекта в котором были бы отображены записи третьего объекта, которые дочерние от записей второго объекта, которые дочерние к данной записи первого объекта (кстати, а почему бы и нет).

Но как это сделать? Возможно ли вставлять в Standard Layoutе полностью кастомизированне секции со своей логикой?

На все эти фантазии заказчика ответ один - Visualforce page. Любую кастомную логику, которая отличается от стандартной лучше сразу реализовывать в отдельной странице.

К тому же в нее можно вставить один маленький тег <apex:details />
который вставляет standard layout объетка, так что заказчик не отличит.
Зато можно делать уже все что угодно с выводимыми данныеми.

[quote="Den Brown"]Но фантазия клиентов не иссякает: им нужно Related Lists секция на Standard Layout первого объекта в котором были бы отображены записи третьего объекта, которые дочерние от записей второго объекта, которые дочерние к данной записи первого объекта (кстати, а почему бы и нет).

Но как это сделать? Возможно ли вставлять в Standard Layoutе полностью кастомизированне секции со своей логикой?[/quote]

На все эти фантазии заказчика ответ один - Visualforce page. Любую кастомную логику, которая отличается от стандартной лучше сразу реализовывать в отдельной странице.

К тому же в нее можно вставить один маленький тег [url=http://www.salesforce.com/us/developer/docs/pages/Content/pages_compref_detail.htm]<apex:details />[/url]
который вставляет standard layout объетка, так что заказчик не отличит.
Зато можно делать уже все что угодно с выводимыми данныеми.

Sergey Prichepo
Это не проблема даже, так не дочет salesforce.Решается минут за 20 javascript oтом.В цикле дописываешь не достающие даты.Проверяли все было ок.

Что-то я не могу сообразить, а при стандартном лейауте куда JS вставлять...

[quote="Sergey Prichepo"]
Это не проблема даже, так не дочет salesforce.Решается минут за 20 javascript oтом.В цикле дописываешь не достающие даты.Проверяли все было ок.[/quote]

Что-то я не могу сообразить, а при стандартном лейауте куда JS вставлять...

Dmitry Shnyrev
К чему я виду. Если предусмотренно что дверь, которая принадлежит зданию, не может принадлежать этажу и наоборот, то может лучше это реализовать на уровне базы данных с помощью дополнительной проверки (validation rule или trigger)? Т.е. если заполнено одно поле, не заполнять другое.

Вы все правильно поняли. На записи Дверь есть три лук-ап поля: Здание, Этаж, Комната. Заполняются от большего уровня к меньшему, то есть Дверь может быть заполнена: Здание А, Этаж 2, Комната 23. И при этом официально она стоит на балансе самого нижнего уровня, т.е. принадлежит Комнате 23. И заказчик не хочет видеть ее в Related List дверей на дитейл пейдж Этажа или Здания, эта дверь должна отображаться в Related List только своей комнаты. Был бы фильтр в Related List - и не было бы проблем.

[quote="Dmitry Shnyrev"]
К чему я виду. Если предусмотренно что дверь, которая принадлежит зданию, не может принадлежать этажу и наоборот, то может лучше это реализовать на уровне базы данных с помощью дополнительной проверки (validation rule или trigger)? Т.е. если заполнено одно поле, не заполнять другое. 
[/quote]

Вы все правильно поняли. На записи Дверь есть три лук-ап поля: Здание, Этаж, Комната. Заполняются от большего уровня к меньшему, то есть Дверь может быть заполнена: Здание А, Этаж 2, Комната 23. И при этом официально она стоит на балансе самого нижнего уровня, т.е. принадлежит Комнате 23. И заказчик не хочет видеть ее в Related List дверей на дитейл пейдж Этажа или Здания, эта дверь должна отображаться в Related List только своей комнаты. Был бы фильтр в Related List - и не было бы проблем.

Dmitry Shnyrev
К тому же в нее можно вставить один маленький тег <apex:details />

Спасибо что напомнили. точно пригодится

[quote="Dmitry Shnyrev"]
К тому же в нее можно вставить один маленький тег [url=http://www.salesforce.com/us/developer/docs/pages/Content/pages_compref_detail.htm]<apex:details />[/url]
[/quote]

Спасибо что напомнили. точно пригодится

Отличия и применение связей Master-Detail и Look-Up.

Сегодня еще раз и более внимательно пригляделся к одному из примеров в Workbook и вот что меня удивило.

Ситуация: мастер объект Invoice__c и Detail объект Line_Items__с
Код:
Invoice__c invoice =
[SELECT i.Name, (Select Name FROM Line_Items__r ORDER BY Name)
FROM Invoice__c i
WHERE i.Name = :invoiceName LIMIT 1];

получается что из записи Мастер объекта можно обратится к дочерним объектам как к полю (Line_Items__r) - точнее говоря - это не имя поле - это название связи.
я думал таким образом можно обратиться ТОЛЬКО из дочерней записи.

А в случае с лук-ап связью можно ли так таким образом (как описано выше) обратиться к записям другого(-их) объектов, которые берут в лук-ап поле эту запись. Предполагаю, что можно, и это здорово. Нужно просто указать название связи.

Отличия и применение связей Master-Detail и Look-Up.

Сегодня еще раз и более внимательно пригляделся к одному из примеров в Workbook и вот что  меня удивило.

Ситуация: мастер объект Invoice__c и Detail объект Line_Items__с
Код:
Invoice__c invoice = 
         [SELECT i.Name, (Select Name FROM Line_Items__r ORDER BY Name) 
          FROM Invoice__c i 
          WHERE i.Name = :invoiceName LIMIT 1];

получается что из записи Мастер объекта можно обратится к дочерним объектам как к полю (Line_Items__r) - точнее говоря - это не имя поле - это название связи.
я думал таким образом можно обратиться ТОЛЬКО из дочерней записи.

А в случае с лук-ап связью можно ли так таким образом (как описано выше) обратиться к записям другого(-их) объектов, которые берут в лук-ап поле эту запись. Предполагаю, что можно, и это здорово. Нужно просто указать название связи.

Это яркий пример вложенного запроса. С помошью такого запроса можно получить list всех подчиненных объектов. Очень полезный тип запросов. Его можно использовать как для lookup так и для master-details связей.

Вот официальная документация на эту тему Relationship Queries

Вот пример:

List<Account> accounts = [Select Id, (Select Id From Cases) From Account];

And then iterate over results:

for (Account account : accounts) {
for (Case case : account.Cases) {
...
}
}

Это яркий пример вложенного запроса. С помошью такого запроса можно получить list всех подчиненных объектов. Очень полезный тип запросов. Его можно использовать как для lookup так и для master-details связей.

Вот официальная документация на эту тему [url=http://www.salesforce.com/us/developer/docs/dbcom_soql_sosl/Content/sforce_api_calls_soql_relationships.htm]Relationship Queries[/url]

Вот пример:

[code]List<Account> accounts = [Select Id, (Select Id From Cases) From Account];[/code]

And then iterate over results:

[code]for (Account account : accounts) {
   for (Case case : account.Cases) {
      ...
   }
}[/code]

Вот еще рабочая задача:

у записи два лейаута.
На админском лейауте есть луп-ап (на Contacts) поле "Запрос сделан" имя. Админ может произвольно выбирать значение или менять его.
На пользовательском лейауте этого поля не видно, но оно должно автоматически заполняется.

Вижу два пути:

сделать формульно-текстовое поле которое будет получать имя пользователя по формуле: created by - user - contact. Но в конце-концов это будет Текстовое поле, а не лук-ап.

сделать тригер, который в момент вставки, проверяет профиль пользователи, и если это Пользовательский профиль (а не админский к примеру), то в луп-ап (на Contacts) поле "Запрос сделан" передает ID полученный по схеме - created by - user - contact.

В правильном ли направлении я решаю задачу? может этот как-то проще можно решить.
Может проще решить через Work FLow Rules? но там в Field update action не вижу доступа к API или даже формулам...

спасибо

Вот еще рабочая задача:

у записи два лейаута.
На админском лейауте есть  луп-ап (на Contacts) поле  "Запрос сделан" имя. Админ может произвольно выбирать значение или менять его.
На пользовательском лейауте этого поля не видно, но оно должно автоматически заполняется.

Вижу два пути:

сделать формульно-текстовое поле которое будет получать имя пользователя по формуле: created by - user - contact. Но в конце-концов это будет Текстовое поле, а не лук-ап.

сделать тригер, который в момент вставки, проверяет профиль пользователи, и если это Пользовательский профиль (а не админский к примеру), то в луп-ап (на Contacts) поле  "Запрос сделан" передает ID полученный по схеме - created by - user - contact.

В правильном ли направлении я решаю задачу? может этот как-то проще можно решить.
Может проще решить через Work FLow Rules? но там в Field update action не вижу доступа к API или даже формулам...

спасибо

Интересная задача.

Ты все правильно написал. Я как программист делал бы и советую делать черех Триггер. Все-таки это надежнее и универчальнее. Может быть можно сделать это и с помощью workflow, но мне кажется что это будет сложнее, и не факт что вообще возможно.
Я всегда голосую за код, поэтому и сейчас советую триггер.

Интересная задача.

Ты все правильно написал. Я как программист делал бы и советую делать черех Триггер. Все-таки это надежнее и универчальнее. Может быть можно сделать это и с помощью workflow, но мне кажется что это будет сложнее, и не факт что вообще возможно. 
Я всегда голосую за код, поэтому и сейчас советую триггер.

Вот еще достаточно типичная задача:

у объекта есть 3 типа записи (и даже больше). Когда админ создает запись он выбирает тип записи.

но когда портальный юзер создает запись, он может выбрать из 3 типов записей, и все дело в том, что мы не даем ему возможность напрямую выбрать тип записи (чтобы не пугать его такими формулировками как "тип записи" и промежуточной страницей, где нужно выбрать тип записи).
Портальный юзер выбирает один вариант из пик-листа, назовем его "Выберите услугу" (который к слову контролирует еще один пик-лист).
И при сохранении нужно в соответствии с выбранным значением в "Выберите услугу" указать данной записи рекорд тайп.

Думаю, что сделать это можно только через тригер.Изучаю сейчас примеры, и все примеры тригеров работающих с уже созданными записями. Как в тригере обратиться к текущей, создаваемой, еще не созданной записи, чтобы закинуть в поле рекорд тайп нужное значение исходя из значения в поле "Выберите услугу" в момент создания записи? буду изучать, но может вы ответите быстрее, что съэкономит мне время.

Хотя причем тут экономия времени- нужно самому все внимательно разобраться - тригер - это самый часто используемый элемент програмирования в SFDC.

А может сделать это через WorkFlowAction немедленного типа филд апдейт. хотя какой это WorkFlow?
спасибо

PS. оказалось что Record type это не только поле в записи твоего объекта, это к тому же отдельный объект. Как говорится, и начинаются чудеса...
вот как можно сделать переменную типа какого-то поля из квери:
ID rtId = [SELECT Id FROM RecordType WHERE Name = 'Record Type Name'].Id;

PSS. все сделал.
вот как обратился
for(Custom_Object__c co: trigger.new){

обратите внимание что работаем с массивом записей, вероятно это сделано на тот случай, если програмно будет вставлятся List записей, на которых работает этот тригер...

PSSS. хотел сделать один list view для админа и пользователя, отличие только в том, что админ видит колонку Record Type, а пользователь нет, так как у него нет права видеть это поле объекта, так оказалось у поля Record Type нельзя закрыть видимость в Field Security для профайла...

Вот еще достаточно типичная задача:

у объекта есть 3 типа записи (и даже больше). Когда админ создает запись он выбирает тип записи.

но когда портальный юзер создает запись, он может выбрать из 3 типов записей, и все дело в том, что мы не даем ему возможность напрямую выбрать тип записи (чтобы не пугать его такими формулировками как "тип записи" и промежуточной страницей, где нужно выбрать тип записи).
Портальный юзер выбирает один вариант из пик-листа, назовем его "Выберите услугу" (который к слову контролирует еще один пик-лист).
И при сохранении нужно в соответствии с выбранным значением в "Выберите услугу" указать данной записи рекорд тайп.

Думаю, что сделать это можно только через тригер.Изучаю сейчас примеры, и все примеры тригеров работающих с уже созданными записями. Как в тригере обратиться к текущей, создаваемой, еще не созданной записи, чтобы закинуть в поле рекорд тайп нужное значение исходя из значения в поле "Выберите услугу" в момент создания записи? буду изучать, но может вы ответите быстрее, что съэкономит мне время. 

Хотя причем тут экономия времени- нужно самому все внимательно разобраться - тригер - это самый часто используемый элемент програмирования в SFDC.

А может сделать это через WorkFlowAction немедленного типа филд апдейт. хотя какой это WorkFlow?
спасибо

PS. оказалось что Record type это не только поле в записи твоего объекта, это к тому же отдельный объект. Как говорится, и начинаются чудеса...
вот как можно сделать переменную типа какого-то поля из квери:
ID rtId = [SELECT Id FROM RecordType WHERE Name = 'Record Type Name'][b].Id;[/b]

PSS. все сделал.
вот как обратился
for(Custom_Object__c co: trigger.new){

обратите внимание что работаем с массивом записей, вероятно это сделано на тот случай, если програмно будет вставлятся List записей, на которых работает этот тригер...

PSSS. хотел сделать один list view для админа и пользователя, отличие только в том, что админ видит колонку Record Type, а пользователь нет, так как у него нет права видеть это поле объекта, так оказалось у поля Record Type нельзя закрыть видимость  в Field Security для профайла...

Так, немного дополнений и уточнений:

Триггер - это достаточно сложный элемент в Salesforce. Когда его разрабатываешь, всегда надо учитывать что на вход тебе приходит List объектов в виде Trigger.new или Trigger.old !!! Поэтому код в триггере должен быть рассчитан на обработку 200 (магическое число в SF) записей за раз и не свалиться по лимитам. Обычно для начинающих программистов это самый большой барьер в освоении apex программирования.

Так что вот такая конструкция обязательно должна быть в триггере

for(Custom_Object__c co: trigger.new){

По поводу выбора record type, немного не так. Вот более точный вариант:

List<RecordType> RTypeList = 
[SELECT Id, SobjectType FROM RecordType WHERE DeveloperName = 'some record type name' AND SobjectType = :Some_Custom_Object__c.SObjectType.getDescribe().getName() AND IsActive = true];

1. получения одного объекта через SOQL чревато получению ошибки если записи не будет, поэтому всегда выбираем list и потом проверяем на .size()>0
2. WHERE DeveloperName - поиск по имени, которое record type получил при создании. Даже если какой-то клиент поменяет название, твой код не свалится, потому что DeveloperName всегда остается постоянным
3. SobjectType = :Some_Custom_Object__c.SObjectType.getDescribe().getName() - поиск record type для определенного объекта, ведь одинаковые recordtype могут быть у разных объектов.
4. IsActive = true - record type можно еще деактивировать и тогда его нельзя будет назначить для записи.

Так, немного дополнений и уточнений:

Триггер - это достаточно сложный элемент в Salesforce. Когда его разрабатываешь, всегда надо учитывать что на вход тебе приходит List объектов в виде Trigger.new или Trigger.old !!! Поэтому код в триггере должен быть рассчитан на обработку 200 (магическое число в SF) записей за раз и не свалиться по лимитам. Обычно для начинающих программистов это самый большой барьер в освоении apex программирования.

Так что вот такая конструкция обязательно должна быть в триггере
[code]for(Custom_Object__c co: trigger.new){[/code]

По поводу выбора record type, немного не так. Вот более точный вариант:
[code]List<RecordType> RTypeList = 
[SELECT Id, SobjectType FROM RecordType WHERE DeveloperName = 'some record type name' AND SobjectType = :Some_Custom_Object__c.SObjectType.getDescribe().getName() AND IsActive = true];[/code]

1. получения одного объекта через SOQL чревато получению ошибки если записи не будет, поэтому всегда выбираем list и потом проверяем на .size()>0
2. WHERE DeveloperName - поиск по имени, которое record type получил при создании. Даже если какой-то клиент поменяет название, твой код не свалится, потому что DeveloperName всегда остается постоянным
3. SobjectType = :Some_Custom_Object__c.SObjectType.getDescribe().getName() - поиск record type для определенного объекта, ведь одинаковые recordtype могут быть у разных объектов.
4. IsActive = true - record type можно еще деактивировать и тогда его нельзя будет назначить для записи.

Dmitry Shnyrev
По поводу выбора record type, немного не так. Вот более точный вариант:

Это гораздо более точный вариант. Просто нет конца моему изучению SFDC

[quote="Dmitry Shnyrev"]
По поводу выбора record type, немного не так. Вот более точный вариант:
[/quote]

Это гораздо более точный вариант. Просто нет конца моему изучению SFDC

У меня начался тяни-толкай с тестированием тригеров.

для вставки объекта Г требуется создать запись объекта А, затем передать ее ID во вновь создаваемую запись объекта Б, затем передать ее ID во вновь создаваемую запись объекта В, и только затем создаем запись Г.

И казалось бы все эти поля-зависимости можно хорошо проследить в Schema Builder, а потом в тест классе создать все требуемые дополнительные записи, но не все так просто...

во время вставки записи Г всплывает DML ошибка о не заполненности поля, которого нет в объекте Г, и это поле явно не в числе тех полей на связанных объектах, что отмечены как "обязательные" в Schema Builder.
оказалось, что срабатывают тригеры, стоящие на объектах А, Б, В (и другие тригеры на самом Г) - просто нет конца ошибкам.
Возможно, также срабатывают Валидэйшн рулсы (не уверен - подтвердите).

Не знаю, что и делать. Отключать все эти тригеры в момент тестирования?

Повезло только в том, что тестируемые Тригеры работают на before insert, то есть (внезапно) они покрываются тестом даже если сам insert не произошел (то есть сам тест-метод фейлнул, а покрытие у тригера стало 87%).

еще одна глупая ситуация:
для отработки insert записи Г, пробовал вставить запись в консоли в Execute Anonimous Window. Так вот в самом объекте есть формульное поле, которое заполняется с помощью $user. А есть ли при выполнении кода Execute Anonimous Window какой то $user?
я так и не смог вставить запись Г даже в Execute Anonimous Window, где более комфортные условия для таких экспериметов - можно выкверить требуемые ID...

PS: внезапно проблема с инсертом исчезла.
а дело было так. Отчаявшись найти какое-то решение проблемы с бесконечными ошибками в работе тест юнита, я начал внимательно перечитывать все блоговые статьи о тригерах.
в результате я добавил в код тригера:
(1) юзера-админа
(2) вилку try-catch на insert
и ошибка пропала (в том смысле, что тест метод проходит).
в чем же дело? предположу, что все дело в try-catch. те ошибка возникает, но код уходит на catch.
если это так, то проблема с невыполненным insert так и осталась...

еще подскажите как искать DEBUG в эклипсном логе, не как не могу найти в нем текстовый поиск...

У меня начался тяни-толкай с тестированием тригеров.

для вставки объекта Г требуется создать запись объекта А, затем передать ее ID во вновь создаваемую запись объекта Б, затем передать ее ID во вновь создаваемую запись объекта В, и только затем создаем запись Г.

И казалось бы все эти поля-зависимости можно хорошо проследить в Schema Builder, а потом в тест классе создать все требуемые дополнительные записи, но  не все так просто...

во время вставки записи Г всплывает DML ошибка о не заполненности поля, которого нет в объекте Г, и это поле явно не в числе тех полей на связанных объектах, что отмечены как "обязательные" в Schema Builder.
оказалось, что срабатывают тригеры, стоящие на объектах А, Б, В (и другие тригеры на самом Г) - просто нет конца ошибкам.
Возможно, также срабатывают Валидэйшн рулсы (не уверен - подтвердите).

Не знаю, что и делать. Отключать все эти  тригеры в момент тестирования? 

Повезло только в том, что тестируемые Тригеры работают на before insert, то есть  (внезапно) они покрываются тестом даже если сам insert не произошел (то есть сам тест-метод фейлнул, а покрытие у тригера стало 87%).

еще одна глупая ситуация:
для отработки insert записи Г, пробовал вставить запись в консоли в Execute Anonimous Window. Так вот в самом объекте есть формульное поле, которое заполняется с помощью $user. А есть ли при выполнении кода Execute [b]Anonimous [/b]Window какой то $user?
я так и не смог вставить запись Г даже в Execute Anonimous Window, где более комфортные условия для таких экспериметов - можно выкверить требуемые ID...

[b]PS:[/b] внезапно проблема с инсертом исчезла.
а дело было так. Отчаявшись найти какое-то решение проблемы с бесконечными ошибками в работе тест юнита, я начал внимательно перечитывать все блоговые статьи о тригерах.
в результате я добавил в код тригера:
(1) юзера-админа
(2) вилку try-catch на insert
и ошибка пропала (в том смысле, что тест метод проходит).
в чем же дело? предположу, что все дело в try-catch. те ошибка возникает, но код уходит на catch.
если это так, то проблема с невыполненным insert так и осталась...

еще подскажите как искать DEBUG в эклипсном логе, не как не могу найти в нем текстовый поиск...

Процесс тестироваиня это очень тонкая наука :). И часто тесты по своим размерам могут превышать сам тестируемый участок кода.

Den Brown
во время вставки записи Г всплывает DML ошибка о не заполненности поля, которого нет в объекте Г, и это поле явно не в числе тех полей на связанных объектах, что отмечены как "обязательные" в Schema Builder.
оказалось, что срабатывают тригеры, стоящие на объектах А, Б, В (и другие тригеры на самом Г) - просто нет конца ошибкам.
Возможно, также срабатывают Валидэйшн рулсы (не уверен - подтвердите).

При создании объектов A, Б, В, Г срабатываю все проверки, которые для них предусмотренны, и в триггерах и в validation rules.
Поэтому подготовка тестовых данных это достаточно нудный процесс.
Тут уже без знания структуры приложения никак не обойтись!!! Ты ДОЛЖЕН знать все проверки, все обязательные денные, все зависимости. В принципе это нормальное требование к разработчику приложения.

Den Brown
Не знаю, что и делать. Отключать все эти тригеры в момент тестирования?

Ни в коем случае!!! Создавай все необходимые данные.

Den Brown
Повезло только в том, что тестируемые Тригеры работают на before insert, то есть (внезапно) они покрываются тестом даже если сам insert не произошел (то есть сам тест-метод фейлнул, а покрытие у тригера стало 87%).

"Внезапно" ничего не происходит! Ты должен понимать откуда срабатывает триггер. Если он не должен срабатывать, то это признак скрытого бага.

Процесс тестироваиня это очень тонкая наука :). И часто тесты по своим размерам могут превышать сам тестируемый участок кода. 

[quote="Den Brown"]во время вставки записи Г всплывает DML ошибка о не заполненности поля, которого нет в объекте Г, и это поле явно не в числе тех полей на связанных объектах, что отмечены как "обязательные" в Schema Builder.
оказалось, что срабатывают тригеры, стоящие на объектах А, Б, В (и другие тригеры на самом Г) - просто нет конца ошибкам.
Возможно, также срабатывают Валидэйшн рулсы (не уверен - подтвердите).[/quote]
При создании объектов A, Б, В, Г срабатываю все проверки, которые для них предусмотренны, и в триггерах и в validation rules.
Поэтому подготовка тестовых данных это достаточно нудный процесс.
Тут уже без знания структуры приложения никак не обойтись!!! Ты ДОЛЖЕН знать все проверки, все обязательные денные, все зависимости. В принципе это нормальное требование к разработчику приложения.

[quote="Den Brown"]Не знаю, что и делать. Отключать все эти тригеры в момент тестирования? [/quote]
Ни в коем случае!!! Создавай все необходимые данные.

[quote="Den Brown"]Повезло только в том, что тестируемые Тригеры работают на before insert, то есть (внезапно) они покрываются тестом даже если сам insert не произошел (то есть сам тест-метод фейлнул, а покрытие у тригера стало 87%).[/quote]
"Внезапно" ничего не происходит! Ты должен понимать откуда срабатывает триггер. Если он не должен срабатывать, то это признак скрытого бага.

Den Brown
для отработки insert записи Г, пробовал вставить запись в консоли в Execute Anonimous Window. Так вот в самом объекте есть формульное поле, которое заполняется с помощью $user. А есть ли при выполнении кода Execute Anonimous Window какой то $user?
я так и не смог вставить запись Г даже в Execute Anonimous Window, где более комфортные условия для таких экспериметов - можно выкверить требуемые ID...

В Salesforce ВСЕ выполняется под каким либо пользователем Обычно, чтобы запустить Execute Anonimous надо залогиниться Если хочешь узнать что за пользователь, самый простой вариант:

userInfo.getUserId();

Это вернет тебе Id текущего пользователя.

Den Brown
(2) вилку try-catch на insert

Вот это делать ни в коем случае нельзя!!!!!!! Зачет тесты тебе, если ты ошибки перехватываешь?

В общем итог твоих сообщений:
С написанием тестов у тебя пока большая проблема в плане подхода!!! В принципе на Salesforce это проблема 90% разработчиков. Все гонятся за магическими 75% покрытия, вообще не разбираясь что делает тестируемый участок кода. На нашей фирме все тесты в принципе так и написаны.

НО правильно было бы писать тесты именно для проверки фукционала:
1. создание необходимы данных для воспроизведения ситуации (ситуации должны быть воспроизведены все - и правильные и ошибочные);
2. проверка выходных данные и созданные в базе данные записей (их количество, содержимое)
Вот тогда тесты будут магическим образом покрывать 95-99% кода.

Еще один огромный + данного подхода. При любых изменениях в приложении ты всегда можешь узнать не сломалось ли что-то другое. Правильно написанные тесты помогают сразу выявить скрытый баг.

Нет, можно конечно посадить девочку, которая будет как "обезьянка" (сори за сравнение) каждый день щелкать всякие кнопочки и воспроизводить различные ситуации. Но зачем? Правильные тесты это круто - это лучше девочки :)))))))

[quote="Den Brown"]для отработки insert записи Г, пробовал вставить запись в консоли в Execute Anonimous Window. Так вот в самом объекте есть формульное поле, которое заполняется с помощью $user. А есть ли при выполнении кода Execute Anonimous Window какой то $user?
я так и не смог вставить запись Г даже в Execute Anonimous Window, где более комфортные условия для таких экспериметов - можно выкверить требуемые ID...[/quote]
В Salesforce ВСЕ выполняется под каким либо пользователем :) Обычно, чтобы запустить Execute Anonimous надо залогиниться :)
Если хочешь узнать что за пользователь, самый простой вариант:

[code]userInfo.getUserId();[/code]

Это вернет тебе Id текущего пользователя.

[quote="Den Brown"](2) вилку try-catch на insert[/quote]
Вот это делать ни в коем случае нельзя!!!!!!! Зачет тесты тебе, если ты ошибки перехватываешь?

В общем итог твоих сообщений:
С написанием тестов у тебя пока большая проблема в плане подхода!!! В принципе на Salesforce это проблема 90% разработчиков. Все гонятся за магическими 75% покрытия, вообще не разбираясь что делает тестируемый участок кода. На нашей фирме все тесты в принципе так и написаны.

НО правильно было бы писать тесты именно для проверки фукционала:
1. создание необходимы данных для воспроизведения ситуации (ситуации должны быть воспроизведены все - и правильные и ошибочные);
2. проверка выходных данные и созданные в базе данные записей (их количество, содержимое)
Вот тогда тесты будут магическим образом покрывать 95-99% кода.

Еще один огромный + данного подхода. При любых изменениях в приложении ты всегда можешь узнать не сломалось ли что-то другое. Правильно написанные тесты помогают сразу выявить скрытый баг.

Нет, можно конечно посадить девочку, которая будет как "обезьянка" (сори за сравнение) каждый день щелкать всякие кнопочки  и воспроизводить различные ситуации. Но зачем? [b]Правильные тесты :)  это круто - это лучше девочки :)))))))[/b]

Я так и собрался все сделать - с чувством, с толком, с расстановкой...

И постепенно размотал весь клубок зависимостей. Запись "входит, и выходит. Замечательно выходит"

К слову оказалось что у стандарного объекта Contact есть поле AccountID - которого нет в описании объекта, а мне оно потребовалось из-за тригера, который с ним работает.

Если восстановить всю цепочку зависимостей, и заставить тест юнит работать корректно, то фактически мы тестируем не один тригер - мы тестируем значительную часть функционала всего приложения.


Еще подскажите как искать DEBUG в эклипсном логе, никак не могу найти в нем текстовый поиск...

___

Начал разбираться с Тест юнитами для расширенных и кастомных контроллеров.

Как мне показалось на первый взгляд, есть два пути написания теста:

первый (описан здесь http://wiki.developerforce.com/page/An_Introduction_to_Apex_Code_Test_Methods):

//Use the PageReference Apex class to instantiate a page
PageReference pageRef = Page.success;

//In this case, the Visualforce page named 'success' is the starting point of this test method.
Test.setCurrentPage(pageRef);

//Instantiate and construct the controller class.
thecontroller controller = new thecontroller();

как видим в конроллер мы не передаем запись\си при создании... но позже в примере работаем с параметрами и переменными, вероятно, чтобы оттестировать метода контроллера...
В каких случаях использовать такой подход?

второй (описан здесь http://salesforce.stackexchange.com/questions/104/how-should-i-build-test-methods-for-visualforce-controller-extensions):

Account a = new Account(name='Tester');
insert a;
ApexPages.StandardController sc = new ApexPages.standardController(a);
myExtension e = new myExtension(sc);

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

написал тест юнит для расширение контролера (получает записи, и раскидывает их на несколько страниц распечатки, согласно логике).

при тестировании ошибка:
System.VisualforceException: Modified rows exist in the records collection!

вот что пишут об этом (ответ 6):
http://boards.developerforce.com/t5/Visualforce-Development/VF-pagination-Modified-rows-exist-in-the-records-collection-with/td-p/122446

получается, что ошибка не в юнит тесте, а в самом контроллере?
но страница с ним нормально работает...

или все-таки я снова-как-всегда не написал все необходимые поля в тест-данных для нормальной работы контроллера с записями (сама вставка Листа записей на стадии подготовка данных проходит без ошибок).

ничего не понимаю

Я так и собрался все сделать - с чувством, с толком, с расстановкой...

И постепенно размотал весь клубок зависимостей. Запись "входит, и выходит. Замечательно выходит"

К слову оказалось что у стандарного объекта Contact есть поле AccountID - которого нет в описании объекта, а мне оно потребовалось из-за тригера, который с ним работает.

Если восстановить всю цепочку зависимостей, и заставить тест юнит работать корректно, то фактически мы тестируем не один тригер - мы тестируем значительную часть функционала всего приложения.


Еще подскажите как искать DEBUG в эклипсном логе, никак не могу найти в нем текстовый поиск...

___

Начал разбираться с Тест юнитами для расширенных и кастомных контроллеров.

Как мне показалось на первый взгляд, есть два пути написания теста:

первый (описан здесь [url]http://wiki.developerforce.com/page/An_Introduction_to_Apex_Code_Test_Methods[/url]):

[i]       //Use the PageReference Apex class to instantiate a page
       PageReference pageRef = Page.success;
       
       //In this case, the Visualforce page named 'success' is the starting point of this test method. 
       Test.setCurrentPage(pageRef);
     
       //Instantiate and construct the controller class.   
       thecontroller controller = new thecontroller();[/i]

как видим в конроллер мы не передаем запись\си при создании... но позже в примере работаем с параметрами и переменными, вероятно, чтобы оттестировать метода контроллера...
В каких случаях использовать такой подход?

второй (описан здесь [url]http://salesforce.stackexchange.com/questions/104/how-should-i-build-test-methods-for-visualforce-controller-extensions[/url]):

[i]    Account a = new Account(name='Tester');
    insert a;
    ApexPages.StandardController sc = new ApexPages.standardController(a);
    myExtension e = new myExtension(sc);[/i]

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

написал тест юнит для расширение контролера (получает записи, и раскидывает их на несколько страниц распечатки, согласно логике).

при тестировании ошибка:
System.VisualforceException: Modified rows exist in the records collection!

вот что пишут об этом (ответ 6):
[url]http://boards.developerforce.com/t5/Visualforce-Development/VF-pagination-Modified-rows-exist-in-the-records-collection-with/td-p/122446[/url]

получается, что ошибка не в юнит тесте, а в самом контроллере?
но страница с ним нормально работает...

или все-таки я снова-как-всегда не написал все необходимые поля в тест-данных для нормальной работы контроллера с записями (сама вставка Листа записей на стадии подготовка данных проходит без ошибок).

ничего не понимаю

Den Brown
К слову оказалось что у стандарного объекта Contact есть поле AccountID - которого нет в описании объекта, а мне оно потребовалось из-за тригера, который с ним работает.

Не знаю какое ты описание смотришь, но вот сразу сразу видно что такое поле у Contact есть
Den Brown
Если восстановить всю цепочку зависимостей, и заставить тест юнит работать корректно, то фактически мы тестируем не один тригер - мы тестируем значительную часть функционала всего приложения.

Вот ты опять повторяешь неправильный подход. Тебе надо тестировать не триггер (покрывать триггер тестами). Тебе надо тестировать "ситуацию" при которой данный триггер срабатывает. Конечно такая "ситуация" может захватить кучу функционала - это нормально.
И вот в чем профит такого подхода - 1 ситуация = 1 тест метод = n покрытых триггеров и кода.
В твоем случае n триггеров = n тест методов = n * геморрой с тестами
Den Brown
Еще подскажите как искать DEBUG в эклипсном логе, никак не могу найти в нем текстовый поиск...

В эклипсе смотреть Debug log это полная ж меня только спасает копирование всего лога в текстовый редактор с нормальным текстовым поиском. А вообще лучше пользоваться Debug log в Setup в браузере.

[quote="Den Brown"]К слову оказалось что у стандарного объекта Contact есть поле AccountID - которого нет в описании объекта, а мне оно потребовалось из-за тригера, который с ним работает.[/quote]
Не знаю какое ты описание смотришь, но [url=http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_contact.htm]вот[/url] сразу сразу видно что такое поле у Contact есть :)

[quote="Den Brown"]Если восстановить всю цепочку зависимостей, и заставить тест юнит работать корректно, то фактически мы тестируем не один тригер - мы тестируем значительную часть функционала всего приложения.[/quote]
Вот ты опять повторяешь неправильный подход. Тебе надо тестировать не триггер (покрывать триггер тестами). Тебе надо тестировать "ситуацию" при которой данный триггер срабатывает. Конечно такая "ситуация" может захватить кучу функционала - это нормально.
И вот в чем профит такого подхода - 1 ситуация = 1 тест метод = n покрытых триггеров и кода.
В твоем случае n триггеров = n тест методов = n * геморрой с тестами :)

[quote="Den Brown"]Еще подскажите как искать DEBUG в эклипсном логе, никак не могу найти в нем текстовый поиск...[/quote]
В эклипсе смотреть Debug log это полная ж :) меня только спасает копирование всего лога в текстовый редактор с нормальным текстовым поиском. А вообще лучше пользоваться Debug log в Setup в браузере.

Den Brown
первый (описан здесь http://wiki.developerforce.com/page/An_ ... st_Methods):
//Use the PageReference Apex class to instantiate a page
PageReference pageRef = Page.success;
...

В принципе это правильный подход, но как по мне лишнее. Контроллер можно тестировать и без instantiate a page, если в коде нет явного обращения к ApexPages.currentPage()

Но в общем лучше работать в соответствии с официальными рекомендациями.

Den Brown
В каких случаях использовать такой подход?

Первый случай - это тесты для custom Visualforce page
Второй случай - для страницы extension для standardController.

[quote="Den Brown"]первый (описан здесь [url]http://wiki.developerforce.com/page/An_[/url] ... st_Methods):
//Use the PageReference Apex class to instantiate a page
PageReference pageRef = Page.success;
...
[/quote]
В принципе это правильный подход, но как по мне лишнее. Контроллер можно тестировать и без instantiate a page, если в коде нет явного обращения к ApexPages.currentPage()

Но в общем лучше работать в соответствии с официальными рекомендациями.

[quote="Den Brown"]В каких случаях использовать такой подход?[/quote]
Первый случай - это тесты для custom Visualforce page
Второй случай - для страницы extension для standardController.

при тестировании ошибка:
System.VisualforceException: Modified rows exist in the records collection!

Встечал такую ошибку. Точно не помню что у меня была за проблема, но вроде было связано с тем что у меня как-то менялось содержимое, которое возвращал StandardSetController.

Den Brown
получается, что ошибка не в юнит тесте, а в самом контроллере?
но страница с ним нормально работает...
или все-таки я снова-как-всегда не написал все необходимые поля в тест-данных для нормальной работы контроллера с записями (сама вставка Листа записей на стадии подготовка данных проходит без ошибок).
ничего не понимаю

Вот честно так просто тут не разобраться. Фактором может быть много. Но проблему однозначно надо искать в тест методе. Наверное ты меняешь там какие-то данные из тестируемого контроллера и в результате получаешь такую ошибку.

[quote]при тестировании ошибка:
System.VisualforceException: Modified rows exist in the records collection![/quote]
Встечал такую ошибку. Точно не помню что у меня была за проблема, но вроде было связано с тем что у меня как-то менялось содержимое, которое возвращал StandardSetController.

[quote="Den Brown"]получается, что ошибка не в юнит тесте, а в самом контроллере?
но страница с ним нормально работает...
или все-таки я снова-как-всегда не написал все необходимые поля в тест-данных для нормальной работы контроллера с записями (сама вставка Листа записей на стадии подготовка данных проходит без ошибок).
ничего не понимаю[/quote]
Вот честно так просто тут не разобраться. Фактором может быть много. Но проблему однозначно надо искать в тест методе. Наверное ты меняешь там какие-то данные из тестируемого контроллера и в результате получаешь такую ошибку.

Dmitry Shnyrev
Не знаю какое ты описание смотришь, но вот сразу сразу видно что такое поле у Contact есть :)

конечно, нужно только правильные книжки найти, а не беспомощно "шарится" в SetUpом описании стандартных объектов.

Dmitry Shnyrev
Тебе надо тестировать "ситуацию" при которой данный триггер срабатывает.

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

И обрадую Дмитрия новой "затеей". Пока это только услышанная мной идея в общих чертах.
Как я понял, в проде потребовалось разделисть апекс класы на две части: одни несущие сам функционал, т.е. т.н. утилити-классы, а вторые только вызывают этот функционал.
Смысл в том, чтобы не давать широкому кругу доступа к содержанию утилити классов.
То что "разделить" класс можно - это я не сомневаюсь, а потом вызывать его, ну например, через класс-обертку.
Но как ограничить доступ к классу? через кнопку Security на классе? а после этого этот класс будет работать, елси вызывается профайлом у которого нет доступа к классу....

[quote="Dmitry Shnyrev"]
Не знаю какое ты описание смотришь, но [url=http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_objects_contact.htm]вот[/url] сразу сразу видно что такое поле у Contact есть :)
[/quote]
конечно, нужно только правильные книжки найти, а не беспомощно "шарится" в SetUpом описании стандартных объектов.

[quote="Dmitry Shnyrev"]
Тебе надо тестировать "[b]ситуацию[/b]" при которой данный триггер срабатывает. [/quote]
все правильно сказал.

И обрадую Дмитрия новой "затеей". Пока это только услышанная мной  идея в общих чертах.
Как я понял, в проде потребовалось разделисть апекс класы на две части: одни несущие сам функционал, т.е. т.н. утилити-классы, а вторые только вызывают этот функционал.
Смысл в том, чтобы не давать широкому кругу доступа к содержанию утилити классов.
То что "разделить" класс можно - это я не сомневаюсь, а потом вызывать его, ну например, через класс-обертку.
Но как ограничить доступ к классу? через кнопку Security на классе? а после этого этот класс будет работать, елси вызывается профайлом у которого нет доступа к классу....

Den Brown
Смысл в том, чтобы не давать широкому кругу доступа к содержанию утилити классов.
То что "разделить" класс можно - это я не сомневаюсь, а потом вызывать его, ну например, через класс-обертку.
Но как ограничить доступ к классу? через кнопку Security на классе? а после этого этот класс будет работать, елси вызывается профайлом у которого нет доступа к классу....

"Security на классе"! Ты немного путаешь две несвязанные темы! Доступ к выполению класса и доступ к исходникам класса. Это разные вещи. Если тебе надо скрыть сами исходники, но так чтобы ими можно было пользоваться, то тебе поможет ТОЛЬКО! managed package.

У нас на фирме так и делается - есть managed пакеты, которые закрыты от лишних глаз, над которыми мы строим решения под каждого заказчика.

[quote="Den Brown"]Смысл в том, чтобы не давать широкому кругу доступа к содержанию утилити классов.
То что "разделить" класс можно - это я не сомневаюсь, а потом вызывать его, ну например, через класс-обертку.
Но как ограничить доступ к классу? через кнопку Security на классе? а после этого этот класс будет работать, елси вызывается профайлом у которого нет доступа к классу....[/quote]

"Security на классе"! Ты немного путаешь две несвязанные темы! Доступ к выполению класса и доступ к исходникам класса. Это разные вещи. Если тебе надо скрыть сами исходники, но так чтобы ими можно было пользоваться, то тебе поможет ТОЛЬКО! managed package.

У нас на фирме так и делается - есть managed пакеты, которые закрыты от лишних глаз, над которыми мы строим решения под каждого заказчика.

Den, есть предложение выносить все новые вопросы в новую ветку! Я думаю это будет правильнее :)

Den, есть предложение выносить все новые вопросы в новую ветку! Я думаю это будет правильнее :)

Ах вот оно что!

я то думал, что отличие manage package от unmanage только в том, что первые можно обновлять.

оказывается, все гораздо глубже.

последние посты, наверное, можно вынести в тему "manage packages", как я понял, работа с manage package - это актуальный вопрос

Ах вот оно что!

я то думал, что отличие manage package от unmanage только в том, что первые можно обновлять.

оказывается, все гораздо глубже.

последние посты, наверное, можно вынести в тему "manage packages", как я понял, работа с manage package - это актуальный вопрос

работа с manage package - это актуальный вопрос

Не сказал бы что актуальный! Специфический.
Обычно managed пакеты делают чтобы выложить на AppExchange. А это дело ОЧЕНЬ геморойный процесс. По себе знаю.
Я один проекте согласился вести полностью пока не выложат в AppExchange, так вот проект делался 1 месяц, а выхожить не можем уже больше полугода. Как нибудь будет настроение напишу статью на эту тему!

[quote]работа с manage package - это актуальный вопрос[/quote]
Не сказал бы что актуальный! Специфический.
Обычно managed пакеты делают чтобы выложить на AppExchange. А это дело ОЧЕНЬ геморойный процесс. По себе знаю.
Я один проекте согласился вести полностью пока не выложат в AppExchange, так вот проект делался 1 месяц, а выхожить не можем уже больше полугода. Как нибудь будет настроение напишу статью на эту тему!

да,

вдохновляющее начало изучения новой темы...

скорей пиши статью, я чувствую слова в ней будут написаны твоим потом и кровью, а значит это будут важные слова

да,

вдохновляющее начало изучения новой темы...

скорей пиши статью, я чувствую слова в ней будут написаны твоим потом и кровью, а значит это будут важные слова

Моих пота и крови так нет особо

Тут одна тупость и упертость саппорта Salesforce.

Средняя скорость ответа от них 2-3 недели и каждое письмо полно такого маразма, что без мата просто не обойтись.

Очень напоминает нашу русскую коррупционную гос систему. Сначала перед одним "спецом" покланяйся, все объясни, докажи что ты не дурак, а через неделю уже другой и опять все заново.

Так что на будущее. Если будут просить выложить на AppEchange лучше откажись :)

Моих пота и крови так нет особо :) 

Тут одна тупость и упертость саппорта Salesforce.

Средняя скорость ответа от них 2-3 недели и каждое письмо полно такого маразма, что без мата просто не обойтись.

Очень напоминает нашу русскую коррупционную гос систему. Сначала перед одним "спецом" покланяйся, все объясни, докажи что ты не дурак, а через неделю уже другой и опять все заново. 

Так что на будущее. Если будут просить выложить на AppEchange лучше откажись :)

Рано или поздно, но начальство попросит тебя обобщить какой-то успешный проект и выложить его на маркет.
"Это неизбежно, мистер Андерсон".

Рано или поздно, но начальство попросит тебя обобщить какой-то успешный проект и выложить его на маркет.
"Это неизбежно, мистер Андерсон".

Посты с обсуждением тестирования Тригеров можно вынести в отдельную тему, потому что обсуждение будет продолжаться.

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

Но как насчет тестирования возможности потенциального выпадения тригера по лимитам?
Например, сейчас все наши тригеры работают в сендбоксе и на проде в ситуации, где кол-во записей в любом объекте идет на сотни, что не много. Но скоро их будут тысячи. Не начнется ли тогда "апексо-пад" функционала?

Есть очевидные вещи, которые не следует использовать при написании кода, например, вставка DML операции внутри цикла, так как рано или поздно это может привести к превышению лимитов.

Какие еще есть ситуации в коде тригера (и контроллера тоже), которые могут привести к превышению лимитов, по мере роста содержимого объектов, с которыми тригер.контроллер работает? Вы сталкивались в подобным?

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

спасибо

Посты с обсуждением тестирования Тригеров можно вынести в отдельную тему, потому что обсуждение будет продолжаться.

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

Но как насчет тестирования возможности потенциального выпадения тригера по лимитам?
Например, сейчас все наши тригеры работают в сендбоксе и на проде в ситуации, где кол-во записей в любом объекте идет на сотни, что не много. Но скоро их будут тысячи. Не начнется ли тогда "апексо-пад" функционала?

Есть очевидные вещи, которые не следует использовать при написании кода, например, вставка DML операции внутри цикла, так как рано или поздно это может привести к превышению лимитов.

Какие еще есть ситуации в коде тригера (и контроллера тоже), которые могут привести к превышению лимитов, по мере роста содержимого объектов, с которыми тригер.контроллер работает? Вы сталкивались в подобным? 

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

спасибо

Den Brown
Но как насчет тестирования возможности потенциального выпадения тригера по лимитам?
Например, сейчас все наши тригеры работают в сендбоксе и на проде в ситуации, где кол-во записей в любом объекте идет на сотни, что не много. Но скоро их будут тысячи. Не начнется ли тогда "апексо-пад" функционала?

)) мне всегда нравится, когда программисты говорят что надо протестировать на "падение по лимитам".
Вопрос - а зачем код такой нужен, который может упасть по лимитам?
Запомни - работа кода, не должен зависеть от входящих данных. В идеале количество используемых ресурсов должно быть константой (т.е. например есть метод который жрет - n SOQL, m DML операций, обрабатывает за раз X элементов).

Если ты не знаешь сколько у тебя будет данных в будущем, и твой код может свалиться, то зачем тогда это тестировать? Он и так свалится
для обработки больших данных в Salesforce предусмотрена асинхронная работа. Очень мощный инструмент.

Den Brown
Есть очевидные вещи, которые не следует использовать при написании кода, например, вставка DML операции внутри цикла, так как рано или поздно это может привести к превышению лимитов.

Запомни!!! НИКАКИХ SOQL и DML операций внутри цикла!!! Первый же security review тебя жутко отругает.

[quote="Den Brown"]Но как насчет тестирования возможности потенциального выпадения тригера по лимитам?
Например, сейчас все наши тригеры работают в сендбоксе и на проде в ситуации, где кол-во записей в любом объекте идет на сотни, что не много. Но скоро их будут тысячи. Не начнется ли тогда "апексо-пад" функционала?
[/quote]

:))) мне всегда нравится, когда программисты говорят что надо протестировать на "падение по лимитам". 
Вопрос - а зачем код такой нужен, который может упасть по лимитам?
Запомни - работа кода, не должен зависеть от входящих данных. В идеале количество используемых ресурсов должно быть константой (т.е. например есть метод который жрет - n SOQL, m DML операций, обрабатывает за раз X элементов).

Если ты не знаешь сколько у тебя будет данных в будущем, и твой код может свалиться, то зачем тогда это тестировать? Он и так свалится :)

для обработки больших данных в Salesforce предусмотрена асинхронная работа. Очень мощный инструмент.

[quote="Den Brown"]Есть очевидные вещи, которые не следует использовать при написании кода, например, вставка DML операции внутри цикла, так как рано или поздно это может привести к превышению лимитов.[/quote]
Запомни!!! НИКАКИХ SOQL и DML операций внутри цикла!!! Первый же security review тебя жутко отругает.

Вот только сейчас осознал, что если один тригер вызывает другой тригер, а тот третий - они все исполняются в одном Execution context - а значит, у них у всех в тот момент будет один лимит на всех.

вот почему нельзя отключать во время тестирования другие тригеры, или использовать try-catch в случае с before тригером. Не важно, что тригер формально "покрылся" - нужно выполнить всю цепочку кода, съимитировать все звенья ситуации, иначе могут быть проблемы с лимитами.

вот еще наивный вопрос:

вот такой элемент разметки:

<apex:outputLink value="https://sandbox-test.sd15.my.salesforce.com/{!r.Id}"

все бы ничего, да вот адреса у сендбоксов и прода разные,

возможно ли заменить вот эту чать

https://sandbox-test.sd15.my.salesforce.com

на глобальную переменную?

спасибо

Вот только сейчас осознал, что если один тригер вызывает другой тригер, а тот третий - они все исполняются в одном Execution context - а значит, у них у всех в тот момент будет[b] один лимит на всех[/b].

вот почему нельзя отключать во время тестирования другие тригеры, или использовать try-catch в случае с before тригером. Не важно, что тригер формально "покрылся" - нужно выполнить всю цепочку кода, съимитировать все звенья ситуации, иначе могут быть проблемы с лимитами.

вот еще наивный вопрос:

вот такой элемент разметки:

<apex:outputLink value="https://sandbox-test.sd15.my.salesforce.com/{!r.Id}"

все бы ничего, да вот адреса у сендбоксов и прода разные,

возможно ли заменить вот эту чать

[url]https://sandbox-test.sd15.my.salesforce.com[/url]

на глобальную переменную?

спасибо

Попробуй вот это

URL.getSalesforceBaseUrl().toExternalForm();

А вообще глянь еще в интернете на предмет "salesforce base url", там предлагаются разные варианты. Возможно тебе подойдет что-то другое.

В вообще все ссылки в коде должны быть только относительные

Если ты делаешь ссылку на свой орг, то можно сделать так и это будет работать

<apex:outputLink value="/{!r.Id}"

Попробуй вот это 

[code]URL.getSalesforceBaseUrl().toExternalForm();[/code]

А вообще глянь еще в интернете на предмет "salesforce base url", там предлагаются разные варианты. Возможно тебе подойдет что-то другое.

В вообще все ссылки в коде должны быть только относительные

Если ты делаешь ссылку на свой орг, то можно сделать так и это будет работать

[code]<apex:outputLink value="/{!r.Id}"[/code]

Можешь попробовать Custom Setting'и.

Но смотря какую цель ты пресследуешь. В данном случае, будет лучше как описал Дмитрий

Можешь попробовать Custom Setting'и. 

Но смотря какую цель ты пресследуешь. В данном случае, будет лучше как описал Дмитрий

Спасибо за ответы.

первый случай - совершенно типичный - это ссылка на свой же орг:

Dmitry Shnyrev
Если ты делаешь ссылку на свой орг, то можно сделать так и это будет работать

<apex:outputLink value="/{!r.Id}"

второй случай: в картинке есть src который веден на гугл сервис, возвращающий QR код, при этом в параметры этого урл вписывается размер картики и текст, который, собственно, код и должен содержать. А текст - это урл ведущий к дитейл пейдж этой записи.

надеюсь здесь поможет

URL.getSalesforceBaseUrl().toExternalForm();

еще не проверял, но обязательно проверю позже.

Art Vegas
Можешь попробовать Custom Setting'и.

а как нам могут помочь в данном случае (или в каком то другом) Custom Setting?

И еще один наивный вопрос:
вижу в контроллере то там, то здесь System.Debug.
если бы это JS это были бы Alert-ы, которые вплывали по мере выполнения скрипта, показывая значения переменных.
Но как выводить/смотреть результаты этих System.Debug в контроллере?

Спасибо за ответы.

первый случай - совершенно типичный - это ссылка на свой же орг:

[quote="Dmitry Shnyrev"]
Если ты делаешь ссылку на свой орг, то можно сделать так и это будет работать

[code]<apex:outputLink value="/{!r.Id}"[/code][/quote]

второй случай: в картинке есть src который веден на гугл сервис, возвращающий QR код, при этом в параметры этого урл вписывается размер картики и текст, который, собственно, код и должен содержать. А текст - это урл ведущий к дитейл пейдж этой записи.

надеюсь здесь поможет
[code]URL.getSalesforceBaseUrl().toExternalForm();[/code]

еще не проверял, но обязательно проверю позже.

[quote="Art Vegas"]Можешь попробовать Custom Setting'и.[/quote]
а как нам могут помочь в данном случае (или в каком то другом) Custom Setting?

И еще один наивный вопрос:
вижу в контроллере то там, то здесь System.Debug.
если бы это JS это были бы Alert-ы, которые вплывали по мере выполнения скрипта, показывая значения переменных.
Но как выводить/смотреть результаты этих System.Debug в контроллере?

И еще один наивный вопрос:
вижу в контроллере то там, то здесь System.Debug.
если бы это JS это были бы Alert-ы, которые вплывали по мере выполнения скрипта, показывая значения переменных.
Но как выводить/смотреть результаты этих System.Debug в контроллере?

В Debug log или в Developer Console на орге.

[quote]И еще один наивный вопрос:
вижу в контроллере то там, то здесь System.Debug.
если бы это JS это были бы Alert-ы, которые вплывали по мере выполнения скрипта, показывая значения переменных.
Но как выводить/смотреть результаты этих System.Debug в контроллере?[/quote]
В Debug log или в Developer Console на орге.

Den Brown
Art Vegas
Можешь попробовать Custom Setting'и.

а как нам могут помочь в данном случае (или в каком то другом) Custom Setting?

Представь такую ситуацию. У тебя на твоем сайте/орге есть огромное количество ссылок на внешний ресурс/ или endpoint, который иницирует получение/передачу данных.

Удобнее будет данный Endpoint перенести в Custom Setting и потом на страничке танцевать от него. Нежели по 100-500 раз писать УРЛ на страницах.
А если у тебя поменяется endpoint? Так ты хотя бы в настройках поменяешь и вуаля все готово.

Для чего это надо: Web Service/Rest Api - если стоит такая задача. Или псевдосервисы, на которые ты будешь стучаться за забором данных.

Но если дело касается оргов, то это будет не очень удобно, ибо предусмотрены уже глобальные методы (см выше в своем и Дименом описании).

[quote="Den Brown"]

[quote="Art Vegas"]Можешь попробовать Custom Setting'и.[/quote]
а как нам могут помочь в данном случае (или в каком то другом) Custom Setting?

[/quote]

Представь такую ситуацию. У тебя на твоем сайте/орге есть огромное количество ссылок на внешний ресурс/ или endpoint, который иницирует получение/передачу данных.

Удобнее будет данный Endpoint перенести в Custom Setting и потом на страничке танцевать от него. Нежели по 100-500 раз писать УРЛ на страницах.
А если у тебя поменяется endpoint? Так ты хотя бы в настройках поменяешь и вуаля все готово.

Для чего это надо: Web Service/Rest Api - если стоит такая задача. Или псевдосервисы, на которые ты будешь стучаться за забором данных.

Но если дело касается оргов, то это будет не очень удобно, ибо предусмотрены уже глобальные методы (см выше в своем и Дименом описании).

Art Vegas все правильно написал.

В коде должен быть только код. Любые переменные значения, те же урлы (даже если они не планируются меняться) надо выносить в custom settings, а любые текстовые выражения в custom labels.

Возможно сначала это покажется лишней тратой времени, но потом данные шаги очень помогут сэкономить на том же времени и нервах.

Art Vegas все правильно написал.

В коде должен быть только код. Любые переменные значения, те же урлы (даже если они не планируются меняться) надо выносить в custom settings, а любые текстовые выражения в custom labels. 

Возможно сначала это покажется лишней тратой времени, но потом данные шаги очень помогут сэкономить на том же времени и нервах.

Art Vegas
Удобнее будет данный Endpoint перенести в Custom Setting и потом на страничке танцевать от него.

все понял про Custom Settings. Вижу, это полезная вещь. Буду изучать.

[quote="Art Vegas"]Удобнее будет данный Endpoint перенести в Custom Setting и потом на страничке танцевать от него. [/quote]

все понял про Custom Settings. Вижу, это полезная вещь. Буду изучать.

Dmitry Shnyrev
В Debug log или в Developer Console на орге.

Вот очень важный вопрос, в котором мне нужно разобраться.

Как в Developer Console запускать контроллер? С какими данными он будет работать? получается нужно выкверить запись(-си) (или создать с нуля) и передать контроллеру, и все это делать в Open Execute Anonimous Window?

[quote="Dmitry Shnyrev"]В Debug log или в Developer Console на орге.[/quote]

Вот очень важный вопрос, в котором мне нужно разобраться.

Как в Developer Console запускать контроллер? С какими данными он будет работать? получается нужно выкверить запись(-си) (или создать с нуля) и передать контроллеру, и все это делать в Open Execute Anonimous Window?

Зачем с контроллером работать в developer console?

Контроллер обычно для страницы пишется и запускать его путем открытия страница было бы логичнее.

А вообще контроллер это тот же apex класс у которого есть конструктор. Когда "вызываешь" любой класс (создаешь инстанс, экземпляр) обычно в него надо передавать параметры, которые заданы в конструкторе.

тут вообще никаких сложностей не должно возникнуть.

Зачем с контроллером работать в developer console?

Контроллер обычно для страницы пишется и запускать его путем открытия страница было бы логичнее.

А вообще контроллер это тот же apex класс у которого есть конструктор. Когда "вызываешь" любой класс (создаешь инстанс, экземпляр) обычно в него надо передавать параметры, которые заданы в конструкторе.

тут вообще никаких сложностей не должно возникнуть.

Dmitry Shnyrev
Зачем с контроллером работать в developer console?

для того чтобы иметь возможность видеть sysytem.debug вставленные то тут-то там в контроллер, для его настойки

[quote="Dmitry Shnyrev"]Зачем с контроллером работать в developer console?
[/quote]

для того чтобы иметь возможность видеть sysytem.debug вставленные то тут-то там в контроллер, для его настойки

Так тут не нужно "запускать" контроллер в консоли.

Делается так:
- открываешь developer console.
- открываешь в новом окне страницу нужную.
- возвращаешься в консоль и видишь внизу в списке новую запись
- открываешь ее двойным нажатием и получаешь лог твоего контроллера с кучей информации в том числе всеми system.debug. Используешь фильтр или поиска для того чтобы найти нужный участок. Поищи в моих статьях описан этот процесс.

Так тут не нужно "запускать" контроллер в консоли. 

Делается так:
- открываешь developer console.
- открываешь в новом окне страницу нужную.
- возвращаешься в консоль и видишь внизу в списке новую запись
- открываешь ее двойным нажатием и получаешь лог твоего контроллера с кучей информации в том числе всеми system.debug. Используешь фильтр или поиска для того чтобы найти нужный участок. Поищи в моих статьях описан этот процесс.

Отлично. Сейчас буду пробовать.

Сегодня у меня "день контроллера" (потом будет " ночь контроллера" и за ней "выходные контроллера") :)

Отлично. Сейчас буду пробовать.

Сегодня у меня "день контроллера" (потом будет " ночь контроллера" и за ней "выходные контроллера")  :)

ну вот и завершаются "выходные контроллера".

еще раз внимательно прочитал про контроллеры в workbooks, конечно примеры дают много информации к размышлению и для экспериментов. Но пока у меня простые вопросы.

Первый вопрос:
Увидел два варианта создания Списка записей в контроллере.

В первом метод() возвращает Список просто выкверивая его из БД.

Во втором объявляется переменная Список (List <Something__c> Список), во время выполнения метода(), возвращающего этот список, сначала проверяется Список==нул, и если он пустой, то только тогда записи выкверивается из БД в переменную Список, которая и возвращается, а если он уже заполнен, то просто возвращается переменная без обращения к БД.

Получается, что второй случай - это страница с формой и пост-бэками, возвращающими эту же страницу. Если делаются пост-бэки страницы, то Список не выкверивается снова, и получается меньше обращений к БД. Но где сохраняется переменная Список? во вью-стейт, получается что страница имеет больший размер из-за скрытых полей в форме.

Я правильно понял отличия? Что еще можно сказать об этих вариантах?

Второй вопрос:
кастомный контроллер выводит два списка (описано в APEX workbook 3-17-6). Ведущий список является формой которая аджаксом передергивает ведомый список подчиненных записей, т.е. ты кликаешь на запись в ведущем списке (точнее там кнопка) и внизу страницы появляется\передергивается список подчиненных записей.

Клин на записи в ведущем списке вызывает акшин, который является Page Reference - return null - т.е. возврат той же страницы. Вроде все логично.

Но есть и второй вариант (описан в VF workbook 13-3).
Все примерно тоже самое, но акшин вызываемый при клике на запись ведущего списка - просто метод, не Page Reference.

получается, что в случае с ajax панелью не обязательно использовать Page Reference , чтобы вернуть ту же страницу (точнее ее фрагмент)...
или я недоглядел какой-то важный нюанс, отличие в этих ситуациях...

спасибо

ну вот и завершаются "выходные контроллера".

еще раз  внимательно прочитал про контроллеры в workbooks, конечно примеры дают много информации к размышлению и для экспериментов. Но пока у меня простые вопросы.

[b]Первый вопрос:[/b]
Увидел два варианта  создания Списка записей в контроллере.

В первом метод() возвращает Список просто выкверивая его из БД.

Во втором объявляется переменная Список (List <Something__c> Список), во время выполнения метода(), возвращающего этот список, сначала проверяется Список==нул,  и если он пустой, то только тогда записи выкверивается из БД в переменную Список, которая и возвращается, а если он уже заполнен, то просто возвращается переменная без обращения к БД.

Получается, что второй случай - это страница с формой и пост-бэками, возвращающими эту же страницу. Если делаются пост-бэки страницы, то Список не выкверивается снова, и получается меньше обращений к БД. Но где сохраняется переменная Список? во вью-стейт, получается что страница имеет больший размер из-за скрытых полей в форме.

Я правильно понял отличия? Что еще можно сказать об этих вариантах?

[b]Второй вопрос:[/b]
кастомный контроллер выводит два списка (описано в APEX workbook 3-17-6). Ведущий список является формой которая аджаксом передергивает ведомый список подчиненных записей, т.е. ты кликаешь на запись в ведущем списке (точнее там кнопка) и внизу страницы появляется\передергивается список подчиненных записей.

Клин на записи в ведущем списке вызывает акшин, который является Page Reference - return null - т.е. возврат той же страницы. Вроде все логично.

Но есть и второй вариант (описан в VF workbook 13-3).
Все примерно тоже самое, но акшин вызываемый при клике на запись ведущего списка - просто метод, не  Page Reference. 

получается, что в случае с ajax панелью не обязательно использовать Page Reference , чтобы вернуть ту же страницу (точнее ее фрагмент)...
или я недоглядел какой-то важный нюанс, отличие в этих ситуациях...

спасибо

Den Brown
Первый вопрос:

Все правильно. Тяжело припомнить теорию и определения :), попытаюсь на пальцах. Есть два способа задать список объектов (необязательно чтобы отправить его на страницу).
1. просто объявить и уже позже в том же конструкторе заполнить
типо так:

public List<SomeObject__c> someObjectList;

public constructor() {
someObjectList = [SELECT ....];
}


2. сделать список "интерактивным", чтобы он сам выполнял работу по выборке и если надо обработке данных. Для этого используются getter и setter
public List<SomeObject__c> someObjectList {get{
return [SELECT ....];
} set; }

Выбирай, какой тебе удобнее. Я предпочитаю первый способ.

[quote="Den Brown"]Первый вопрос:[/quote]

Все правильно. Тяжело припомнить теорию и определения :), попытаюсь на пальцах. Есть два способа задать список объектов (необязательно чтобы отправить его на страницу).
1. просто объявить и уже позже в том же конструкторе заполнить
типо так:
[code]
public List<SomeObject__c> someObjectList;

public constructor() {
    someObjectList = [SELECT ....];
}
[/code]
2. сделать список "интерактивным", чтобы он сам выполнял работу по выборке и если надо обработке данных. Для этого используются getter и setter
[code]
public List<SomeObject__c> someObjectList {get{
    return [SELECT ....];
} set; }
[/code]

Выбирай, какой тебе удобнее. Я предпочитаю первый способ.

Den Brown
Получается, что второй случай - это страница с формой и пост-бэками, возвращающими эту же страницу. Если делаются пост-бэки страницы, то Список не выкверивается снова, и получается меньше обращений к БД. Но где сохраняется переменная Список? во вью-стейт, получается что страница имеет больший размер из-за скрытых полей в форме.

И в первом и во втором случае данные, которые ты объявишь как public чтобы использовать на странице будут храниться во view state. Т.е. здесь это значение не имеет.
"Меньше обращений к БД" тоже не имеет значение, потому что ajax запрос это отдельный запуск скрипта со своими лимитами и то что ты при построении страницы делал кучу запросов при вызове ajax значения не имеет. Люблю я Salesforce :)

[quote="Den Brown"]Получается, что второй случай - это страница с формой и пост-бэками, возвращающими эту же страницу. Если делаются пост-бэки страницы, то Список не выкверивается снова, и получается меньше обращений к БД. Но где сохраняется переменная Список? во вью-стейт, получается что страница имеет больший размер из-за скрытых полей в форме.[/quote]
И в первом и во втором случае данные, которые ты объявишь как public чтобы использовать на странице будут храниться во view state. Т.е. здесь это значение не имеет. 
"Меньше обращений к БД" тоже не имеет значение, потому что ajax запрос это отдельный запуск скрипта со своими лимитами и то что ты при  построении страницы делал кучу запросов при вызове ajax значения не имеет. Люблю я Salesforce :)

Den Brown
Второй вопрос:

Тоже нет разницы. То что ты возвращаешь в return зависит от "типа метода".

Вот два абсолютно идентичных метода для ajax запроса:

1.

public void method1() {
...
return; // в void методе его можно не указывать
}

2.

public pageRegerence method2() {

return null;
}

[quote="Den Brown"]Второй вопрос:[/quote]
Тоже нет разницы. То что ты возвращаешь в return зависит от "типа метода".

Вот два абсолютно идентичных метода для ajax запроса:

1.
[code]
public void method1() {
    ...
    return; // в void методе его можно не указывать
}
[/code]

2.
[code]
public pageRegerence method2() {

    return null;
}
[/code]

Dmitry Shnyrev
Den Brown
Первый вопрос:

Все правильно. Тяжело припомнить теорию и определения :), попытаюсь на пальцах. Есть два способа задать список объектов (необязательно чтобы отправить его на страницу).
1. просто объявить и уже позже в том же конструкторе заполнить
типо так:

public List<SomeObject__c> someObjectList;

public constructor() {
someObjectList = [SELECT ....];
}


2. сделать список "интерактивным", чтобы он сам выполнял работу по выборке и если надо обработке данных. Для этого используются getter и setter
public List<SomeObject__c> someObjectList {get{
return [SELECT ....];
} set; }

Выбирай, какой тебе удобнее. Я предпочитаю первый способ.

вот эти варианты создания списка (в конструкторе или свойство с гет\сет) я бы назвал "классикой жанра", это то, как это должно быть. Но в примерах учебников APEX and VF они это не пишут так, там все проще, что оставляет ощущение, что я уже что-то не понимаю.

Создание переменной Список, как я теперь понимаю, нужно не для уменьшения обращений к БД, а для сохранения измененных пользователем данных между пост-бэками (без сохранения в БД), если подразумевается, что пользователь может править их не только один раз, а в любое время в период выполенения сценария страницы.

спасибо за ответы.
двигаемся дальше

[quote="Dmitry Shnyrev"][quote="Den Brown"]Первый вопрос:[/quote]

Все правильно. Тяжело припомнить теорию и определения :), попытаюсь на пальцах. Есть два способа задать список объектов (необязательно чтобы отправить его на страницу).
1. просто объявить и уже позже в том же конструкторе заполнить
типо так:
[code]
public List<SomeObject__c> someObjectList;

public constructor() {
    someObjectList = [SELECT ....];
}
[/code]
2. сделать список "интерактивным", чтобы он сам выполнял работу по выборке и если надо обработке данных. Для этого используются getter и setter
[code]
public List<SomeObject__c> someObjectList {get{
    return [SELECT ....];
} set; }
[/code]

Выбирай, какой тебе удобнее. Я предпочитаю первый способ.[/quote]

вот эти варианты создания списка  (в конструкторе или свойство с гет\сет) я бы назвал "классикой жанра", это то, как это должно быть. Но в примерах учебников APEX and VF они это не пишут так, там все проще, что оставляет ощущение, что я уже что-то не понимаю.

Создание переменной Список, как я теперь понимаю, нужно не для уменьшения обращений к БД, а для сохранения измененных пользователем данных между пост-бэками (без сохранения в БД), если подразумевается, что пользователь может править их не только один раз, а в любое время в период выполенения сценария страницы.

спасибо за ответы.
двигаемся дальше

сегодня столкнулся с двумя ситуациями, но так и не понял в чем проблема.

Первая: в тригере не смог пройти по связи от тригирующей записи (через ее лок-ап поле к полю у связанной записи). не понял в чем дело, просто выкверил что мне нужно было...

Вторая: в консоли в анонимном окне пишу следующее [select id from MyObject__c where createdby ='ffhdk74884fdjf']
просто хотел выкверть свои записи. Система пишет "нет такого поля createdby" в вашем объекте (также как и поля owner).
Не стал спорить, просто согласился...

PS: сегодня день загадок: нашел в одном тригере обращение к кастомному объекту. Но не вижу объекта с таким названием в списке объектом. Пробую с консоли вставить запись в данный объект - ок, вставляется.удаляется - показывает id записи

Заподозрил, что api имя объекта полностью отличается от label имени объекта, поэтому не могу его найти в списке объектов.
Как по api имени выкверить label имя объекта?
PSS: нашел этот объект - он в Кастом сеттингс!!
Спасибо

сегодня столкнулся с двумя ситуациями, но так и не понял в чем проблема.

Первая: в тригере не смог пройти по связи от тригирующей записи (через ее лок-ап поле к полю у связанной записи). не понял в чем дело, просто выкверил что мне нужно было...

Вторая: в консоли в анонимном окне пишу следующее [select id from MyObject__c where createdby ='ffhdk74884fdjf']
просто хотел выкверть свои записи. Система пишет "нет такого поля createdby" в вашем объекте (также как и поля owner).
Не стал спорить, просто согласился...

PS: сегодня день загадок: нашел в одном тригере обращение к кастомному объекту. Но не вижу объекта с таким названием в списке объектом. Пробую с консоли вставить запись в данный объект - ок, вставляется.удаляется - показывает id записи

Заподозрил, что api имя объекта полностью отличается от label имени объекта, поэтому не могу его найти в списке объектов.
Как по api имени выкверить label имя объекта?
PSS: нашел этот объект - он в Кастом сеттингс!!
Спасибо

Первая: в тригере не смог пройти по связи от тригирующей записи (через ее лок-ап поле к полю у связанной записи). не понял в чем дело, просто выкверил что мне нужно было...

Все правильно. В триггер (в Trigger.new) приходят записи со всеми полями 1-ого уровня. Чтобы обратиться к полям других объектов через связи нужно их доставать из базы новым запросом.

Вторая: в консоли в анонимном окне пишу следующее [select id from MyObject__c where createdby ='ffhdk74884fdjf']
просто хотел выкверть свои записи. Система пишет "нет такого поля createdby" в вашем объекте (также как и поля owner).
Не стал спорить, просто согласился..

Тоже все правильно связи в стандартных объектах формируются немного необычным образом.
Нужно кверить либо так: CreatedBy.Name или CreatedById
тоже самое и с Owner.Name или OwnerId
а вообще там еще немного сложнее - почитай здесь, во второй половине документа про CreatedBy и особенно OwnerId

[quote]Первая: в тригере не смог пройти по связи от тригирующей записи (через ее лок-ап поле к полю у связанной записи). не понял в чем дело, просто выкверил что мне нужно было...
[/quote]
Все правильно. В триггер (в Trigger.new) приходят записи со всеми полями 1-ого уровня. Чтобы обратиться к полям других объектов через связи нужно их доставать из базы новым запросом.

[quote]Вторая: в консоли в анонимном окне пишу следующее [select id from MyObject__c where createdby ='ffhdk74884fdjf']
просто хотел выкверть свои записи. Система пишет "нет такого поля createdby" в вашем объекте (также как и поля owner).
Не стал спорить, просто согласился..[/quote]
Тоже все правильно :) связи в стандартных объектах формируются немного необычным образом.
Нужно кверить либо так: CreatedBy.Name или CreatedById
тоже самое и с Owner.Name или OwnerId
а вообще там еще немного сложнее - почитай [url=http://www.salesforce.com/us/developer/docs/dbcom_soql_sosl/Content/sforce_api_calls_soql_relationships.htm]здесь[/url], во второй половине документа про CreatedBy и особенно OwnerId

Заподозрил, что api имя объекта полностью отличается от label имени объекта, поэтому не могу его найти в списке объектов.
Как по api имени выкверить label имя объекта?
PSS: нашел этот объект - он в Кастом сеттингс!!

Есть такая замечательная штука в Force.com IDE - salesforce.schema. Там можно найти и API names для объекта и его Labels и как правильно называются Relationships (нужно когда делаешь вложенные SOQL)

[quote]Заподозрил, что api имя объекта полностью отличается от label имени объекта, поэтому не могу его найти в списке объектов.
Как по api имени выкверить label имя объекта?
PSS: нашел этот объект - он в Кастом сеттингс!![/quote]
Есть такая замечательная штука в Force.com IDE - salesforce.schema. Там можно найти и API names для объекта и его Labels и как правильно называются Relationships (нужно когда делаешь вложенные SOQL)

Спасибо за отличные ответы. SFDCу можно учится бесконечно, просто бесконечно.

И еще чудеса: не могу вывести кастомную дитейл страницу на страндартном контроллере как сайт пейд - внутри орга она работает (принимате id) , а как сайт страница - она не работает:
An error has occured. Please check the required fields and try again.

доступы к объекту и полям открыты.

Неужели стандартный конроллер не применим для сайта?!

Спасибо за отличные ответы. SFDCу можно учится бесконечно, просто бесконечно.

И еще чудеса: не могу вывести кастомную дитейл страницу на страндартном контроллере как сайт пейд - внутри орга она работает (принимате id) , а как сайт страница - она не работает:  
An error has occured. Please check the required fields and try again.

доступы к объекту и полям открыты.

Неужели стандартный конроллер не применим для сайта?!

Интересный вопрос и немного непонятный.

Непонятный потому что за всю свою практику я не помню чтобы на сайте (тот что публичный а не customer portal, я правильно понял?) использовались standard layout. Обычно сайт для незарегистрированных пользователей делают в стиле отличном от салесфорсовского и логика как и верстка там используются кастомные в рамках Visualforce страниц. Это мое субъективное мнение.
А вообще в твоем случае надо смотреть, потому что по описанию не совсем понятно.
Пока что приходит в голову это проблема с правами доступа не только к объектам, но также к Tab, apex classes и visualforce. Их тоже надо открывать для сайта. + еще одно предположение - возможно на сайте (по логике salesforce) ограничен доступ к некоторым стандартным объектам, но это надо проверять.

Интересный вопрос и немного непонятный.

Непонятный потому что за всю свою практику я не помню чтобы на сайте (тот что публичный а не customer portal, я правильно понял?) использовались standard layout. Обычно сайт для незарегистрированных пользователей делают в стиле отличном от салесфорсовского и логика как и верстка там используются кастомные в рамках Visualforce страниц. Это мое субъективное мнение.
А вообще в твоем случае надо смотреть, потому что по описанию не совсем понятно.
Пока что приходит в голову это проблема с правами доступа не только к объектам, но также к Tab, apex classes и visualforce. Их тоже надо открывать для сайта. + еще одно предположение - возможно на сайте (по логике salesforce) ограничен доступ к некоторым стандартным объектам, но это надо проверять.

спасибо, Дмитрий.

я недостаточно точно объяснил ситуацию.

в сайт выведена полностью кастомизированная страница со списком каких-то записей. Теперь поставили новую задачу: при клике на какую-то запись в списке должна открываться вторая страница с описание этой записи (3-4 поля из этой записи). Я пошел кратчайшим путем, т.е. без контроллерным путем: просто вписал в шапку новой второй VF страинце, что использовать стандартный контроллер такой -то, и вывел несколько полей в разметке (пока без стилей - просто тестирование). Затем создал второй сайт и поставил туда эту страницу (возможно можно было поставить эту страницу и на первый сайт, где указана первая страница, но основная часть УРЛ у этих сайтов все равно одинаковая).

Так вот если открыть эту страницу, передав ей ID в пределах орга, т.е. как апекс страницу - она работает. А если зайти на нее как на сайтовую - нет не работает. Буду сегодня разбираться.

PS нашел причину: у другого сайта - другой профайл!

Как разместить две страницы на одном сайте я так и не разобрал...

кстати если у профайла нет доступа к контроллеру, он все равно работает...

спасибо, Дмитрий.

я недостаточно точно объяснил ситуацию.

в сайт выведена полностью кастомизированная страница со списком каких-то записей. Теперь поставили новую задачу: при клике на какую-то запись в списке должна открываться вторая страница с описание этой записи (3-4 поля из этой записи). Я пошел кратчайшим путем, т.е. без контроллерным путем: просто вписал в шапку новой второй VF страинце, что использовать стандартный контроллер такой -то, и вывел несколько полей в разметке (пока без стилей - просто тестирование). Затем создал второй сайт и поставил туда эту страницу (возможно можно было поставить эту страницу и на первый сайт, где указана первая страница, но основная часть УРЛ у этих сайтов все равно одинаковая).

Так вот если открыть эту страницу, передав ей ID в пределах орга, т.е. как апекс страницу - она работает. А если зайти на нее как на сайтовую - нет не работает. Буду сегодня разбираться.

PS нашел причину: у другого сайта - другой профайл!

Как разместить две страницы на одном сайте я так и не разобрал...

кстати если у профайла нет доступа к контроллеру, он все равно работает...

Вот еще пример глупого хард-кода, с которым что-то нужно делать:

PageReference redirect= new PageReference(URL.getSalesforceBaseUrl().toExternalForm() + '/apex/MyPage?ID=' + itemID);

здесь страница перегружается на саму себя, передавая новой странице параметр.

Вот этот фрагмент доводит меня до слез:

/apex/MyPage

дело в том, что я хочу использовать этот контроллер для нескольким аналогичных страниц (да или просто для тестовых вариантов), и вышеуаззанный фрагмент нужно замениь на что-то вроде THIS или $CurrentPage... но как правильно написать....

вот списов глобальных переменных (вкл. $CurrentPage) - замечательные вещи:

http://www.salesforce.com/us/developer/docs/pages/Content/pages_variables_global.htm

но такое чувство, что использовать их можно только в формулах, т.е. разметке View.

ну вот есть такой вариант ApexPages.currentPage(); но как его правильно применить в данном случае
вот так вот не получается:
PageReference redirect= ApexPages.currentPage()+'?ID=' + itemID;

Вот еще пример глупого хард-кода, с которым что-то нужно делать:

PageReference redirect= new PageReference(URL.getSalesforceBaseUrl().toExternalForm() + '/apex/MyPage?ID=' + itemID);

здесь страница перегружается на  саму себя, передавая новой странице параметр.

Вот этот фрагмент доводит меня до слез:

[i]/apex/MyPage[/i]

дело в том, что я хочу использовать этот контроллер для нескольким аналогичных страниц (да или просто для тестовых вариантов), и вышеуаззанный фрагмент нужно замениь на что-то вроде THIS или $CurrentPage... но как правильно написать....

вот списов глобальных переменных (вкл. $CurrentPage) - замечательные вещи:

[url]http://www.salesforce.com/us/developer/docs/pages/Content/pages_variables_global.htm[/url]

но такое чувство, что использовать их можно только в формулах, т.е. разметке View.

ну вот есть такой вариант ApexPages.currentPage(); но как его правильно применить в данном случае
вот так вот не получается:
     PageReference redirect= ApexPages.currentPage()+'?ID=' + itemID;

Ну да, хватает тут не только хардкода, но и лишнего многовато.

Во-первых, можно передавать использовать относительный урл

PageReference pageRef = new PageReference('partialURL');

т.е. получится как-то так:

PageReference redirect= new PageReference('/apex/MyPage?ID=' + itemID);

намного приятнее смотрится
На счет current page, не проверял, но вот в теории как это можно выглядеть:
PageReference redirect= new PageReference(ApexPages.currentPage().getUrl()+'?ID='+itemID)

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

Ну да, хватает тут не только хардкода, но и лишнего многовато.

Во-первых, можно передавать использовать относительный урл
[code]PageReference pageRef = new PageReference('partialURL');[/code]

т.е. получится как-то так:
[code]PageReference redirect= new PageReference('/apex/MyPage?ID=' + itemID);[/code]
намного приятнее смотрится :)

На счет current page, не проверял, но вот в теории как это можно выглядеть:
[code]PageReference redirect= new PageReference(ApexPages.currentPage().getUrl()+'?ID='+itemID)[/code]

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

Dmitry Shnyrev
намного приятнее смотрится :)

да лучше смотрится

Dmitry Shnyrev
PageReference redirect= new PageReference(ApexPages.currentPage().getUrl()+'?ID='+itemID)

нет не работате так: какая то ужасная каша в параметрах, безконечно длинный урл...

[quote="Dmitry Shnyrev"]
намного приятнее смотрится :)
[/quote]

да лучше смотрится

[quote="Dmitry Shnyrev"]

[code]PageReference redirect= new PageReference(ApexPages.currentPage().getUrl()+'?ID='+itemID)[/code]
[/quote]

нет не работате так: какая то ужасная каша в параметрах, безконечно длинный урл...

ну по ходу нельзя использовать List custom settings in FORMULA.

Вот тут https://success.salesforce.com/ideaView?id=08730000000I5NsAAK люди просят добавить этот функционал.

ну по ходу нельзя использовать List custom settings in FORMULA.

Вот тут [url]https://success.salesforce.com/ideaView?id=08730000000I5NsAAK[/url] люди просят добавить этот функционал.

Не успел сегодня попробовать, то хотя бы спрошу:

на Дитейл рекорд VF странице работающей на станд контроллере можно ли вывести поле связанного объекта:

МойКастОбъект__С.ЛукАпПолеНаЭккаунт__R.Email ---- не получилось так пройти, хотя разметка сохраняется без ошибки.

Если нет, то что правильнее:
(1) расширить станд контроллер
или
(2) создать на моем объекте формульное поле которое получает ЛукАпПолеНаЭккаунт__с.Email и затем просто вывести его? --- сделал именно так.

Спасибо

Не успел сегодня попробовать, то хотя бы спрошу: 

на Дитейл рекорд VF странице работающей на станд контроллере можно ли вывести поле связанного объекта:

МойКастОбъект__С.ЛукАпПолеНаЭккаунт__R.Email   ---- [b]не получилось так пройти[/b], хотя разметка сохраняется без ошибки.

Если нет, то что правильнее:
(1) расширить станд контроллер
или
(2) создать на моем объекте формульное поле которое получает ЛукАпПолеНаЭккаунт__с.Email и затем просто вывести его?  --- сделал именно так.

Спасибо

Ну вот опять загадка.

Есть VF страница типа рекорд Дитейл доступная с сайта.

все поля выводятся с помощью apex:outputField

есть два лук-ап поля

одно на Контакты
другое лук-ап поле на кастомный объект.

права на доступ к этим двум объектам для сайтового профайла выставлены по минимуму и одинаково.

Но! контакное поле выводится как просто текст (что и нужно)

а лук-ап поле с именем записи кастомного объекта выводится на сайте как ссылка, что мне совсем ни к чему.

пока не понял, как с этим разобраться.... это даже не загадка, это уже проблема

Ну вот опять загадка.

Есть VF страница типа рекорд Дитейл доступная с сайта.

все поля выводятся с помощью apex:outputField 

есть два лук-ап поля

одно на Контакты
другое лук-ап поле на кастомный объект.

права на доступ к этим двум объектам для сайтового профайла выставлены по минимуму и одинаково.

Но! контакное поле выводится как [b]просто текст[/b] (что и нужно)

а лук-ап поле с именем записи кастомного объекта выводится на сайте как [b]ссылка[/b], что мне совсем ни к чему.

пока не понял, как с этим разобраться.... это даже не загадка, это уже проблема

Но! контакное поле выводится как просто текст (что и нужно)
а лук-ап поле с именем записи кастомного объекта выводится на сайте как ссылка, что мне совсем ни к чему.

Воспроизвел твою проблему. Действительно у контакта выводится просто имя, а у custom object выводится ссылка. Наверное здесь скорее виноват контакт и он неправильно воспроизводится в отличии от кастомного объекта.

Но вот решение твоей проблемы (в примере мои кастомные объекты):

<apex:outputField value="{!tttest__c.doom__r.Name}" />

Таким образом выводится просто имя без ссылки в отличии от <apex:outputField value="{!tttest__c.doom__с}" />

[quote]Но! контакное поле выводится как просто текст (что и нужно)
а лук-ап поле с именем записи кастомного объекта выводится на сайте как ссылка, что мне совсем ни к чему.[/quote]

Воспроизвел твою проблему. Действительно у контакта выводится просто имя, а у custom object выводится ссылка. Наверное здесь скорее виноват контакт и он неправильно воспроизводится в отличии от кастомного объекта.

Но вот решение твоей проблемы (в примере мои кастомные объекты):
[code]<apex:outputField value="{!tttest__c.doom__r.Name}" />[/code]

Таким образом выводится просто имя без ссылки в отличии от <apex:outputField value="{!tttest__c.doom__с}" />

Вот тут сразу появился и ответ на твой предыдущий вопрос:

на Дитейл рекорд VF странице работающей на станд контроллере можно ли вывести поле связанного объекта:
МойКастОбъект__С.ЛукАпПолеНаЭккаунт__R.Email ---- не получилось так пройти, хотя разметка сохраняется без ошибки.

Поля связанного объекта отлично выводятся. В предыдущем ответе отличный пример с полем Name у кастомного объекта через lookup.

Более того я проверил твой пример с Email из контакта, у меня он прекрасно отобразился на сайте:

<apex:outputField value="{!tttest__c.Contact__r.Email}" />

Вот тут сразу появился и ответ на твой предыдущий вопрос:

[quote]на Дитейл рекорд VF странице работающей на станд контроллере можно ли вывести поле связанного объекта:
МойКастОбъект__С.ЛукАпПолеНаЭккаунт__R.Email ---- не получилось так пройти, хотя разметка сохраняется без ошибки.[/quote]

Поля связанного объекта отлично выводятся. В предыдущем ответе отличный пример с полем Name у кастомного объекта через lookup.

Более того я проверил твой пример с Email из контакта, у меня он прекрасно отобразился на сайте:
[code]
<apex:outputField value="{!tttest__c.Contact__r.Email}" />
[/code]

Dmitry Shnyrev
Но вот решение твоей проблемы (в примере мои кастомные объекты):
<apex:outputField value="{!tttest__c.doom__r.Name}" />

Ох, хитро-хитро, Дмитрий! Спасибо за помощь, все работает.

То есть я прошел по связи на поле кастомного объекта.

А вот с контактом не получается, ставлю вот так test__c.Contact__r.Email и:
в пределах орга на данной странице - вижу емейл (значит значение в поле есть );
а на сайте для той же записи - нет значения (даже после перегрузки старницы с сервера, не из кеша, были и такое )
вроде все права открыты, нуд ладно, я эту проблему уже решил,а теперь решил и другие.

спасибо

[quote="Dmitry Shnyrev"]
Но вот решение твоей проблемы (в примере мои кастомные объекты):
[code]<apex:outputField value="{!tttest__c.doom__r.Name}" />[/code]
[/quote]

Ох, хитро-хитро, Дмитрий! Спасибо за помощь, все работает.

То есть я прошел по связи на поле кастомного объекта.

А вот с контактом не получается, ставлю вот так test__c.Contact__r.Email и:
в пределах орга на данной странице - вижу емейл (значит значение в поле  есть  :D );
а на сайте для той же записи - нет значения (даже после перегрузки старницы с сервера, не из кеша, были и такое  :) )
вроде все права открыты, нуд ладно, я эту проблему уже решил,а теперь решил и другие.

спасибо

А вот с контактом не получается, ставлю вот так test__c.Contact__r.Email и:

Неее, тут проблема явно в правах доступа (GRUD и FLS). У меня же заработало. Хотя есть еще такая страшная штука Sharing rules. Если на объетке Contact чтоит что-то отлично от Public, то возможно проблема может быть в этом.

[quote]А вот с контактом не получается, ставлю вот так test__c.Contact__r.Email и:[/quote]
Неее, тут проблема явно в правах доступа (GRUD и FLS). У меня же заработало. Хотя есть еще такая страшная штука Sharing rules. Если на объетке Contact чтоит что-то отлично от Public, то возможно проблема может быть в этом.

Приветствую всех! Новый день - новые веселые задачи.

И вот интересная:

в одном объекте создается запись (бронирование комнаты), и из второго объекта (Инвентарь) выводится например один Проектор (было два - стал один доступный). Но через два часа бронирование заканчивается - и этот Проектор должен "самостоятельно" вернутся в список (был один - и вот снова два).

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

Если у вас есть идеи по реализации задачи - милости просим. И понедельник будет немного легче
PS: от описанной выше логике отказались, ввиду ее бессмысленности: в поле кол-во инвенторя находится значение актуальное только для текущего момента и не дает никаких посказок, а будет ли оно доступно на другой момент. Так что все переделаю. Но идея о том, как сделать так чтобы значение записи менялось в 1 час понедельника и потом еще раз в 3 часа понелеьника в завсисмости от другой записи - это может и пригодится в будущем.

Приветствую всех! Новый день - новые веселые задачи.

И вот интересная:

в одном объекте создается запись (бронирование комнаты), и из второго объекта (Инвентарь) выводится например один Проектор (было два - стал один доступный). Но через два часа бронирование заканчивается - и этот Проектор должен[b] "самостоятельно"[/b] вернутся в список (был один - и вот снова два).

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

Если у вас есть идеи по реализации задачи - милости просим. И понедельник будет немного легче  :D

PS: от описанной выше логике отказались, ввиду ее бессмысленности: в поле кол-во инвенторя находится значение актуальное только для текущего момента и не дает никаких посказок, а будет ли оно доступно на другой момент. Так что все переделаю. Но идея о том, как сделать так чтобы значение записи менялось в 1 час понедельника и потом еще раз в 3 часа понелеьника в завсисмости от другой записи - это может и пригодится в будущем.

Вот еще логический "глюк" в SF.

Два объекта - мастер и дочерний.

Заходим на родительскую запись и в секции дочерних записей создаем новую запись. Нажимаем на сохранение и попадаем на ту же, но уже сохраненную запись. И дальше нам нужно вернутся на родительскую запись, но куда мы дальше можем двинутся?? только на список дочерних записей. Это еще надо додуматься, что можно клинкуть на поле с именем родительской записи, чтобы попасть куда нам надо.

Надо добавить кнопку, линк или что еще? с большими красными буквами - Вернутся на родительскую запись - чтобы пользователь мог вернутся обратно без лишнего стресса. Надо подумать как это реализовать на станд лейауте. Ведь такого рода дочерние записи в реальной жизни будут создаваться только через вход в родителскую запись, а не "самостоятельно".

Вот еще логический "глюк" в SF.

Два объекта - мастер и дочерний.

Заходим на родительскую запись и в секции дочерних записей создаем новую запись. Нажимаем на сохранение и попадаем на ту же, но уже сохраненную запись. И дальше нам нужно вернутся на родительскую запись, но куда мы дальше можем двинутся?? только на список дочерних записей. Это еще надо додуматься, что можно клинкуть на поле с именем родительской записи, чтобы попасть куда нам надо.

Надо добавить кнопку, линк или что еще? с большими красными буквами - Вернутся на родительскую запись - чтобы пользователь мог вернутся обратно без лишнего стресса. Надо подумать как это реализовать на станд лейауте. Ведь такого рода дочерние записи в реальной жизни будут создаваться только через вход в родителскую запись, а не "самостоятельно".

Это наверное самая распространенная задача на SF на свою практику наверное раз сто слышал как с ней народ воевал. Типо есть страница view объекта и с нее надо сделать ссылки <-Back to parent если объект создавался из related list.
Сразу скажу ничего в этом хорошего нет. Если в Salesforce это не предусмотрено из коробки, то пользователя надо учить работать с Salesforce, а не ломать SF под пользователя.
Так с ходу готового решения не приведу потому что обычно отмахивался от этой задачи. Но скажу что тут только жестокий javascript поможет или придется делать Visualforce page c apex:details (последний вариант самый верный).

Это наверное самая распространенная задача на SF :) на свою практику наверное раз сто слышал как с ней народ воевал. Типо есть страница view объекта и с нее надо сделать ссылки <-Back to parent если объект создавался из related list.
Сразу скажу ничего в этом хорошего нет. Если в Salesforce это не предусмотрено из коробки, то пользователя надо учить работать с Salesforce, а не ломать SF под пользователя.
Так с ходу готового решения не приведу :) потому что обычно отмахивался от этой задачи. Но скажу что тут только жестокий javascript поможет или придется делать Visualforce page c apex:details (последний вариант самый верный).

Значит, я не единственный кто это заметил.

Под кастомную кнопку мы можем положить JS, который без проблем может получить текущую запись, взять айди из ее поля "мастер рекорд" и сделать редирект на урл+ТотАйди.

так получается

Значит, я не единственный кто это заметил.

Под кастомную кнопку мы можем положить JS, который без проблем может получить текущую запись, взять айди из ее поля "мастер рекорд" и сделать редирект на урл+ТотАйди.

так получается

Это если Custom Button, то получается самый легкий вариант. Да именно так.
Но у нас обычно требуют переназначить линк "Back to ...", который находится слева ввеху на layout

Это если Custom Button, то получается самый легкий вариант. Да именно так. 
Но у нас обычно требуют переназначить линк "Back to ...", который находится слева ввеху на layout
[img]/phpbb-files/30-01-2014 20-50-48.png[/img]

Переназначить этот линк конечно не получится, лучше писать кастомную страницу (можно конечно под кнопку заложить JS который будет получать этот элемент, менять текст, линк - но это все несерьезно).

Сегодня столкнулся с еще одной странностью, но не страшной, - на объекте есть обязательное поле дата-время, на лейауте оно стоит выше других обязательных полей - как не зайдешь на создание новой записи - фокус на этом поле и оттого календарный поп-ап радостно "на выкате"...

Переназначить этот линк конечно не получится, лучше писать кастомную страницу (можно конечно под кнопку заложить JS который будет получать этот элемент, менять текст, линк - но это все несерьезно).

Сегодня столкнулся с еще одной странностью, но не страшной, - на объекте есть обязательное поле дата-время, на лейауте оно стоит выше других обязательных полей - как не зайдешь на создание новой записи - [b]фокус на этом поле[/b] и оттого календарный поп-ап радостно "на выкате"...

Есть такая проблема, сталкивался.

Решается вполне просто. Вот ссылка на статью по этой проблеме

Preventing focus of first input field and Calendar widget on page load in Salesforce

Есть такая проблема, сталкивался.

Решается вполне просто. Вот ссылка на статью по этой проблеме 

[url=http://www.bulkified.com/Preventing+focus+of+first+input+field+and+Calendar+widget+on+page+load+in+Salesforce]Preventing focus of first input field and Calendar widget on page load in Salesforce[/url]

А я и не знал, что скрытое поле можно взять в фокус.
Но у меня стандартный лэйаут, как туда вставить скрытое поле <input id="hiddenElement" type="hidden" />? разве что програмно скриптом под кнопкой.

Вот небольшая ситуация: пик-лист, и когда кастомер выбирает опцию "Закрыто" и сохраняет запись, происходят какие то калькуляции и нужно чтобы кастомер больше не мог редактировать это поле ("Закрыто" и все!). Я помню это было где-то в описании WF rules, но забыл...

А я и не знал, что скрытое поле можно взять в фокус.
Но у меня стандартный лэйаут, как туда вставить скрытое поле [i]<input id="hiddenElement" type="hidden" />[/i]? разве что програмно скриптом под кнопкой.

Вот небольшая ситуация: пик-лист, и когда кастомер выбирает опцию "Закрыто" и сохраняет запись, происходят какие то калькуляции и нужно чтобы кастомер больше не мог редактировать это поле ("Закрыто" и все!). Я помню это было где-то в описании WF rules, но забыл...

Камрады, не нашел, обсуждали или нет. Возможно плохо искал ;). Вопрос в следующем:
Возможно ли в стандартной форме реализовать автоматический сброс полей при редактировании поля поиска?
Т.е. например при редактировании карточки Обращения выбирая новый контакт автоматически "обнулять" значения выбранных полей?

Камрады, не нашел, обсуждали или нет. Возможно плохо искал ;). Вопрос в следующем:
Возможно ли в стандартной форме реализовать автоматический сброс полей при редактировании поля поиска?
Т.е. например при редактировании карточки Обращения выбирая новый контакт автоматически "обнулять" значения выбранных полей?

Den Brown
Вот небольшая ситуация: пик-лист, и когда кастомер выбирает опцию "Закрыто" и сохраняет запись, происходят какие то калькуляции и нужно чтобы кастомер больше не мог редактировать это поле ("Закрыто" и все!). Я помню это было где-то в описании WF rules, но забыл...

Если это VF page, то сделать получится очень просто - с помощью conditional rendering. Ставищь рядом два поля: apex:inputField и apex:outputField для одного и того же поля, а потом выводишь одно или другое в зависимости от условия.
Если это standard layout, то подменить поле просто так не получится, тогда да, придется использовать или Validation rule или триггер чтобы запретить менять значение в пиклисте если в нем уже стоит значение закрыто. Тогда пользователю показываешь ошибку.

[quote="Den Brown"]Вот небольшая ситуация: пик-лист, и когда кастомер выбирает опцию "Закрыто" и сохраняет запись, происходят какие то калькуляции и нужно чтобы кастомер больше не мог редактировать это поле ("Закрыто" и все!). Я помню это было где-то в описании WF rules, но забыл...[/quote]
Если это VF page, то сделать получится очень просто - с помощью conditional rendering. Ставищь рядом два поля: apex:inputField и apex:outputField для одного и того же поля, а потом выводишь одно или другое в зависимости от условия.
Если это standard layout, то подменить поле просто так не получится, тогда да, придется использовать или Validation rule или триггер чтобы запретить менять значение в пиклисте если в нем уже стоит значение закрыто. Тогда пользователю показываешь ошибку.

tabaccopie
Возможно ли в стандартной форме реализовать автоматический сброс полей

не думаю что это получится сделать "просто". Наверное лучше сразу посмотреть в сторону Visualforce страницы.

[quote="tabaccopie"]Возможно ли в стандартной форме реализовать автоматический сброс полей[/quote]
не думаю что это получится сделать "просто". Наверное лучше сразу посмотреть в сторону Visualforce страницы.

Dmitry Shnyrev
tabaccopie
Возможно ли в стандартной форме реализовать автоматический сброс полей

не думаю что это получится сделать "просто". Наверное лучше сразу посмотреть в сторону Visualforce страницы.

Или после смены значения этого пиклиста поменять рекодтайп и соответственно лайаут. соответственно на новом лайауте вывести поле типа формула которое берет значение из пиклиста. Соответственно это поле будет не редактируемое.

[quote="Dmitry Shnyrev"][quote="tabaccopie"]Возможно ли в стандартной форме реализовать автоматический сброс полей[/quote]
не думаю что это получится сделать "просто". Наверное лучше сразу посмотреть в сторону Visualforce страницы.[/quote]

Или после смены значения этого пиклиста поменять рекодтайп и соответственно лайаут. соответственно на новом лайауте вывести поле типа формула которое берет значение из пиклиста. Соответственно это поле будет не редактируемое.

wilder
Или после смены значения этого пиклиста поменять рекодтайп и соответственно лайаут. соответственно на новом лайауте вывести поле типа формула которое берет значение из пиклиста. Соответственно это поле будет не редактируемое.

Wilder: это сообщение не к моему вопросу относится?

Вот небольшая ситуация: пик-лист, и когда кастомер выбирает опцию "Закрыто" и сохраняет запись, происходят какие то калькуляции и нужно чтобы кастомер больше не мог редактировать это поле ("Закрыто" и все!). Я помню это было где-то в описании WF rules, но забыл...

Если да - то неплохая, неординарная идея. (но в моем случае все рекорд-тайпы регламетированы, нового не должно быть).

[quote="wilder"]

Или после смены значения этого пиклиста поменять рекодтайп и соответственно лайаут. соответственно на новом лайауте вывести поле типа формула которое берет значение из пиклиста. Соответственно это поле будет не редактируемое.[/quote]

Wilder: это сообщение не к моему вопросу относится?

[quote]Вот небольшая ситуация: пик-лист, и когда кастомер выбирает опцию "Закрыто" и сохраняет запись, происходят какие то калькуляции и нужно чтобы кастомер больше не мог редактировать это поле ("Закрыто" и все!). Я помню это было где-то в описании WF rules, но забыл...[/quote]

Если да - то неплохая, неординарная  идея. (но в моем случае все рекорд-тайпы регламетированы, нового не должно быть).

Приветствую!
Продолжаются "мытарства" и изучение платформы. Гуру, подскажите, существует ли способ склонировать кастомные поля стандартного объекта в кастомный объект?
Например есть объект Возможности. В нем заведено много кастомных полей, раскрывающихся списков и т.п. Есть созданный кастомный объект, в котором необходимо создать все такие же поля, с последующим переносом данных в них (это уже вторая задача).
Понятно, что можно сделать руками все поля, но это долго и муторно. Может кто-то из вас уже сталкивался с подобной задачей?
Надеюсь объяснил понятно. Спасибо!

Приветствую!
Продолжаются "мытарства" и изучение платформы. :)
Гуру, подскажите, существует ли способ склонировать кастомные поля стандартного объекта в кастомный объект?
Например есть объект Возможности. В нем заведено много кастомных полей, раскрывающихся списков и т.п. Есть созданный кастомный объект, в котором необходимо создать все такие же поля, с последующим переносом данных в них (это уже вторая задача).
Понятно, что можно сделать руками все поля, но это долго и муторно. Может кто-то из вас уже сталкивался с подобной задачей?
Надеюсь объяснил понятно. Спасибо!

tabaccopie
Приветствую!
Продолжаются "мытарства" и изучение платформы. Гуру, подскажите, существует ли способ склонировать кастомные поля стандартного объекта в кастомный объект?
Например есть объект Возможности. В нем заведено много кастомных полей, раскрывающихся списков и т.п. Есть созданный кастомный объект, в котором необходимо создать все такие же поля, с последующим переносом данных в них (это уже вторая задача).
Понятно, что можно сделать руками все поля, но это долго и муторно. Может кто-то из вас уже сталкивался с подобной задачей?
Надеюсь объяснил понятно. Спасибо!

You can download needed metadata, in your case Opportunity object and custom opportunity in Eclipse and after that you need manually copy / paste fields from opportunity to custom opportunity. And final step you need to save your changes to environment.

I am sorry, russian keyboard unavailable.

[quote="tabaccopie"]Приветствую!
Продолжаются "мытарства" и изучение платформы. :)
Гуру, подскажите, существует ли способ склонировать кастомные поля стандартного объекта в кастомный объект?
Например есть объект Возможности. В нем заведено много кастомных полей, раскрывающихся списков и т.п. Есть созданный кастомный объект, в котором необходимо создать все такие же поля, с последующим переносом данных в них (это уже вторая задача).
Понятно, что можно сделать руками все поля, но это долго и муторно. Может кто-то из вас уже сталкивался с подобной задачей?
Надеюсь объяснил понятно. Спасибо![/quote]

You can download needed metadata, in your case Opportunity object and custom opportunity in Eclipse and after that you need manually copy / paste fields from opportunity to custom opportunity. And final step you need to save your changes to environment.

I am sorry, russian keyboard unavailable.

wilder
tabaccopie
Приветствую!
Продолжаются "мытарства" и изучение платформы. Гуру, подскажите, существует ли способ склонировать кастомные поля стандартного объекта в кастомный объект?
Например есть объект Возможности. В нем заведено много кастомных полей, раскрывающихся списков и т.п. Есть созданный кастомный объект, в котором необходимо создать все такие же поля, с последующим переносом данных в них (это уже вторая задача).
Понятно, что можно сделать руками все поля, но это долго и муторно. Может кто-то из вас уже сталкивался с подобной задачей?
Надеюсь объяснил понятно. Спасибо!

You can download needed metadata, in your case Opportunity object and custom opportunity in Eclipse and after that you need manually copy / paste fields from opportunity to custom opportunity. And final step you need to save your changes to environment.

I am sorry, russian keyboard unavailable.

Спасибо! Рассматривал такой вариант.
В итоге так и сделал. Потом сделал Save и Save to server. В Problems нет никаких Errors относительно данного кастомного объекта. Но сам объект в salesforce не изменился, поля не добавились. В чем может быть дело?
Извините, если уж совсем глупые вопросы задаю, мало опыта еще :(.

Добавлено: Есть Warning "File only saved locally, not to server", хм... Почему такое может происходить?
Добавлено2: Выяснилось, что я вообще через eclipse не могу создать ни один кастомный объект в продакшене. Сохраняет только локально. Хотя в сэндбоксе орга все прекрасно заработало.
При попытке сохранения кастомного объекта в продакшн вылазят ошибки, что отсутствуют обязательные поля, что не выбрана группа. Но я в кастомном объекте никаких таких полей не использую. Еще есть ошибка "Среднее тестовое покрытие всех классов и триггеров Apex составляет 57%, тогда как требуется не менее 75%. " Но в кастомном объекте я использую только xml для формирования полей, никакого apex. И в ошибках Resource указан мой проект. Нет ссылок именно на кастомный объект, который я пытаюсь создать. В общем я теряюсь в догадках...

[quote="wilder"][quote="tabaccopie"]Приветствую!
Продолжаются "мытарства" и изучение платформы. :)
Гуру, подскажите, существует ли способ склонировать кастомные поля стандартного объекта в кастомный объект?
Например есть объект Возможности. В нем заведено много кастомных полей, раскрывающихся списков и т.п. Есть созданный кастомный объект, в котором необходимо создать все такие же поля, с последующим переносом данных в них (это уже вторая задача).
Понятно, что можно сделать руками все поля, но это долго и муторно. Может кто-то из вас уже сталкивался с подобной задачей?
Надеюсь объяснил понятно. Спасибо![/quote]

You can download needed metadata, in your case Opportunity object and custom opportunity in Eclipse and after that you need manually copy / paste fields from opportunity to custom opportunity. And final step you need to save your changes to environment.

I am sorry, russian keyboard unavailable.[/quote]

Спасибо! Рассматривал такой вариант.
В итоге так и сделал. Потом сделал Save и Save to server. В Problems нет никаких Errors относительно данного кастомного объекта. Но сам объект в salesforce не изменился, поля не добавились. В чем может быть дело?
Извините, если уж совсем глупые вопросы задаю, мало опыта еще :(.

Добавлено: Есть Warning "File only saved locally, not to server", хм... Почему такое может происходить?
Добавлено2: Выяснилось, что я вообще через eclipse не могу создать ни один кастомный объект в продакшене. Сохраняет только локально. Хотя в сэндбоксе орга все прекрасно заработало.
При попытке сохранения кастомного объекта в продакшн вылазят ошибки, что отсутствуют обязательные поля, что не выбрана группа. Но я в кастомном объекте никаких таких полей не использую. Еще есть ошибка "Среднее тестовое покрытие всех классов и триггеров Apex составляет 57%, тогда как требуется не менее 75%.	" Но в кастомном объекте я использую только xml для формирования полей, никакого apex. И в ошибках Resource указан мой проект. Нет ссылок именно на кастомный объект, который я пытаюсь создать. В общем я теряюсь в догадках...

Добавлено: Есть Warning "File only saved locally, not to server", хм... Почему такое может происходить?

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

Нужно в eclipse открыть оба файла метаданных для обоих объектов и просто перенести часть, отвечающую за поля из одного в другой и сохранить. После этого либо должна быть ошибка (а не предупреждение), либо все красиво загрузится на орг.

[quote]Добавлено: Есть Warning "File only saved locally, not to server", хм... Почему такое может происходить?[/quote]

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

Нужно в eclipse открыть оба файла метаданных для обоих объектов и просто перенести часть, отвечающую за поля из одного в другой и сохранить. После этого либо должна быть ошибка (а не предупреждение), либо все красиво загрузится на орг.

Dmitry Shnyrev
Добавлено: Есть Warning "File only saved locally, not to server", хм... Почему такое может происходить?

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

Нужно в eclipse открыть оба файла метаданных для обоих объектов и просто перенести часть, отвечающую за поля из одного в другой и сохранить. После этого либо должна быть ошибка (а не предупреждение), либо все красиво загрузится на орг.

Именно так я и делал -- просто переносил поля из одного объекта в другой, уже созданный.
Попробовал просто создать кастомный объект через eclipse -- написал выше, что получается:

Добавлено2: Выяснилось, что я вообще через eclipse не могу создать ни один кастомный объект в продакшене. Сохраняет только локально. Хотя в сэндбоксе орга все прекрасно заработало.
При попытке сохранения кастомного объекта в продакшн вылазят ошибки, что отсутствуют обязательные поля, что не выбрана группа. Но я в кастомном объекте никаких таких полей не использую. Еще есть ошибка "Среднее тестовое покрытие всех классов и триггеров Apex составляет 57%, тогда как требуется не менее 75%. " Но в кастомном объекте я использую только xml для формирования полей, никакого apex. И в ошибках Resource указан мой проект. Нет ссылок именно на кастомный объект, который я пытаюсь создать. В общем я теряюсь в догадках...

[quote="Dmitry Shnyrev"][quote]Добавлено: Есть Warning "File only saved locally, not to server", хм... Почему такое может происходить?[/quote]

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

Нужно в eclipse открыть оба файла метаданных для обоих объектов и просто перенести часть, отвечающую за поля из одного в другой и сохранить. После этого либо должна быть ошибка (а не предупреждение), либо все красиво загрузится на орг.[/quote]

Именно так я и делал -- просто переносил поля из одного объекта в другой, уже созданный.
Попробовал просто создать кастомный объект через eclipse -- написал выше, что получается:
[quote] Добавлено2: Выяснилось, что я вообще через eclipse не могу создать ни один кастомный объект в продакшене. Сохраняет только локально. Хотя в сэндбоксе орга все прекрасно заработало.
При попытке сохранения кастомного объекта в продакшн вылазят ошибки, что отсутствуют обязательные поля, что не выбрана группа. Но я в кастомном объекте никаких таких полей не использую. Еще есть ошибка "Среднее тестовое покрытие всех классов и триггеров Apex составляет 57%, тогда как требуется не менее 75%. " Но в кастомном объекте я использую только xml для формирования полей, никакого apex. И в ошибках Resource указан мой проект. Нет ссылок именно на кастомный объект, который я пытаюсь создать. В общем я теряюсь в догадках...[/quote]

! С Production типом орга все намного сложнее.
Его нельзя просто так взять и подключить к eclipse и делать Save.

На продакшен можно только делать Deploy. При этом там запускаются все тесты.

Самый оптимальный вариант, это внесение изменений на !актуальный Sandbox и перенос этих изменений через changeSet. В eclipse тоже есть Deploy to Production, но все равно твой проект должен быть создан из Sandbox или Dev орга.

К тому же я так понимаю на твоем проде
1. валятся тесты - пока их не исправишь, ничего другого не зальешь.
проверить - иди на прод и делай Run All Test - если есть ошибки и они не твои - ругайся с владельцем прода.
2. твой код не покрыт тестами - пока твой код не покроешь тестами на прод ничего не выльешь!
(сорри, у тебя же нет кода - вылетело из головы - когда актулеан первый вариант )

! С Production типом орга все намного сложнее.
Его нельзя просто так взять и подключить к eclipse и делать Save.

На продакшен можно только делать Deploy. При этом там запускаются все тесты.

Самый оптимальный вариант, это внесение изменений на !актуальный Sandbox и перенос этих изменений через changeSet. В eclipse тоже есть Deploy to Production, но все равно твой проект должен быть создан из Sandbox или Dev орга.

К тому же я так понимаю на твоем проде 
1. валятся тесты - пока их не исправишь, ничего другого не зальешь. 
проверить - иди на прод и делай Run All Test - если есть ошибки и они не твои - ругайся с владельцем прода.
2. твой код не покрыт тестами - пока твой код не покроешь тестами на прод ничего не выльешь!
(сорри, у тебя же нет кода - вылетело из головы - когда актулеан первый вариант )

Dmitry Shnyrev
! С Production типом орга все намного сложнее.
Его нельзя просто так взять и подключить к eclipse и делать Save.

На продакшен можно только делать Deploy. При этом там запускаются все тесты.

Самый оптимальный вариант, это внесение изменений на !актуальный Sandbox и перенос этих изменений через changeSet. В eclipse тоже есть Deploy to Production, но все равно твой проект должен быть создан из Sandbox или Dev орга.

К тому же я так понимаю на твоем проде
1. валятся тесты - пока их не исправишь, ничего другого не зальешь.
проверить - иди на прод и делай Run All Test - если есть ошибки и они не твои - ругайся с владельцем прода.
2. твой код не покрыт тестами - пока твой код не покроешь тестами на прод ничего не выльешь!
(сорри, у тебя же нет кода - вылетело из головы - когда актулеан первый вариант )

Спасибо большое, кое-чего проясняется. Буду разбираться.

[quote="Dmitry Shnyrev"]! С Production типом орга все намного сложнее.
Его нельзя просто так взять и подключить к eclipse и делать Save.

На продакшен можно только делать Deploy. При этом там запускаются все тесты.

Самый оптимальный вариант, это внесение изменений на !актуальный Sandbox и перенос этих изменений через changeSet. В eclipse тоже есть Deploy to Production, но все равно твой проект должен быть создан из Sandbox или Dev орга.

К тому же я так понимаю на твоем проде 
1. валятся тесты - пока их не исправишь, ничего другого не зальешь. 
проверить - иди на прод и делай Run All Test - если есть ошибки и они не твои - ругайся с владельцем прода.
2. твой код не покрыт тестами - пока твой код не покроешь тестами на прод ничего не выльешь!
(сорри, у тебя же нет кода - вылетело из головы - когда актулеан первый вариант )[/quote]

Спасибо большое, кое-чего проясняется. Буду разбираться.

Дмитрий, спасибо, Вы были правы. Все получилось, как пофиксили ошибки и сделали нормальное покрытие кода.

Дмитрий, спасибо, Вы были правы. Все получилось, как пофиксили ошибки и сделали нормальное покрытие кода.

Приветствую всех.

создавал контроллер, который принимает в гет параметре число, и создает в таком кол-ве какие-то новые записи, которые передает на фронт.

Ну так вот: куда-бы я не ставил INSERT (точнее говоря - в конструктор или свойство), всегда созвращалась ошибка (в окне страницы - не в момент сохрания кода), что DML операции не допустимы. И так было, пока я не поставил INSERTв PageReference (ну и соответственно в апекс:пейдж тег поставил этот PageReference в акшин)

Я так и не понял, то ли ошибка возникала по каким-то другим причинам, то ли действительно ДМЛ операцию можно посадить только в PageReference...

Приветствую всех.

создавал контроллер, который принимает в гет параметре число, и создает в таком кол-ве какие-то новые записи, которые передает на фронт.

Ну так вот: куда-бы я не ставил INSERT (точнее говоря - в конструктор или свойство), всегда  созвращалась ошибка (в окне страницы - не в момент сохрания кода), что DML операции не допустимы. И так было, пока я не поставил  INSERTв PageReference (ну и соответственно в апекс:пейдж тег поставил этот PageReference в акшин)

Я так и не понял, то ли ошибка возникала по каким-то другим причинам, то ли действительно ДМЛ операцию можно посадить только в PageReference...

Распространенная ошибка.

В конструкторе запрещены любые DML операции.

Обходится очень просто. Делается init метод, который вешается на action атрибут тега apex:page.

Примерно так:

<apex:page controller="bla-bla" action="{!init}">
...

в контроллере метод init - это обычные метод как и все другие public void

Смысл в чем - отрабатывает контроллер страницы (где запрещены DML операции), начинает строится страница и сразу срабатывает init метод (здесь DML операции уже разрешены) Profit.
Я для себя называю такой init метод "вторым конструктором". :)

Распространенная ошибка.

В конструкторе запрещены любые DML операции.

Обходится очень просто. Делается init метод, который вешается на action атрибут тега apex:page.

Примерно так:

[code]
<apex:page controller="bla-bla" action="{!init}">
...
[/code]

в контроллере метод init - это обычные метод как и все другие public void

Смысл в чем - отрабатывает контроллер страницы (где запрещены DML операции), начинает строится страница и сразу срабатывает init метод (здесь DML операции уже разрешены) Profit.
Я для себя называю такой init метод "вторым конструктором". :)

Спасибо огромное за разъяснения.

Я уже 6 месяцев день и ночь сижу на SFDC - и до сих пор каждый день сталкиваюсь с новыми вопросами и новой информацией. И конца этому не видно.

Спасибо огромное за разъяснения.

Я уже 6 месяцев день и ночь сижу на SFDC - и до сих пор [b]каждый день [/b]сталкиваюсь с новыми вопросами и новой информацией. И конца этому не видно.

Нельзя объять необъятное. Мир программирования очень большой и все знать невозможно
!!!!!!! Предлагаю закрыть эту тему "Наивные вопросы от новичков", потому что здесь поднимаются много важных вопросов, достойных отдельной темы.

На каждый вопрос прошу открывать отдельную тему. Так будет проще в поиске и навигации не только нам, но и новым программистам.

:) Нельзя объять необъятное. Мир программирования очень большой и все знать невозможно :)

!!!!!!! Предлагаю закрыть эту тему "Наивные вопросы от новичков", потому что здесь поднимаются много важных вопросов, достойных отдельной темы.

На каждый вопрос прошу открывать отдельную тему. Так будет проще в поиске и навигации не только нам, но и новым программистам.

Господа! Выручайте!
У меня есть простенькая страница, с которой я загружаю attachment, для своих скучных целей мне необходимо узнавать размер файла. Отчего, чёрт побери, Attachment.BodyLength у меня постоянно NULL?

Господа! Выручайте!
У меня есть простенькая страница, с которой я загружаю attachment, для своих скучных целей мне необходимо узнавать размер файла. Отчего, чёрт побери, Attachment.BodyLength у меня постоянно NULL? 

Sebastian Pareyro
Отчего, чёрт побери, Attachment.BodyLength у меня постоянно NULL?

Ищи проблему у себя в коде. Это поле должно заполняться автоматически при сохранении в базу. Ты проверяешь значение поля сразу после вставки? Попробуй после сохранения снова выбрать эту запись из базы и укажи поле BodyLength. Потом проверь что выдало. Если опять null (что маловероятно) попробуй посмотреть права доступа (хотя это в теории).

[quote="Sebastian Pareyro"]Отчего, чёрт побери, Attachment.BodyLength у меня постоянно NULL?[/quote]
Ищи проблему у себя в коде. Это поле должно заполняться автоматически при сохранении в базу. Ты проверяешь значение поля сразу после вставки? Попробуй после сохранения снова выбрать эту запись из базы и укажи поле BodyLength. Потом проверь что выдало. Если опять null (что маловероятно) попробуй посмотреть права доступа (хотя это в теории).

Нет, отчего-то не сработало. Проверял и до, и после инсерта. Решил проблему добавив filesize в imputfile на странице. Как бы делал, если бы аттачил без страницы, просто в contact, например - даже не представляю.

Нет, отчего-то не сработало. Проверял и до, и после инсерта. Решил проблему добавив filesize в imputfile на странице. Как бы делал, если бы аттачил без страницы, просто в contact, например - даже не представляю.

Ну вот попался наивный пятничный вопрос классически програмистской тематики:

нужно составить четыре квери которые считают кол-во записей в объекте:
- созданных за текущий календарный год;
- созданных за текущий календарный месяц;
- созданных за текущую календарную неделю;
- созданных за текущий календарный день;

вот как составить это условия для даты создания?

"с детства" не люблю работать с Датой-временем особенно по пятницам во вторую половину дня - просто не соображает голова.

может вы уже делали похожее и есть быстрые ответы?

спасибо

ПС: вот нашел об этом - оказывается там море Date Literals которые делают нашу жизнь много проще:
http://www.salesforce.com/us/developer/docs/officetoolkit/Content/sforce_api_calls_soql_select_dateformats.htm

ура- ура-ура

Ну вот попался наивный пятничный вопрос классически програмистской тематики:

нужно составить четыре квери которые считают кол-во записей в объекте:
- созданных за текущий календарный год;
- созданных за текущий календарный месяц;
- созданных за текущую календарную неделю;
- созданных за текущий календарный день;

вот как составить это условия для даты создания?

"с детства" не люблю работать с Датой-временем особенно по пятницам во вторую половину дня - просто не соображает голова.

может вы уже делали похожее и есть быстрые ответы?

спасибо

ПС: вот нашел об этом - оказывается там море Date Literals которые делают нашу жизнь много проще:
http://www.salesforce.com/us/developer/docs/officetoolkit/Content/sforce_api_calls_soql_select_dateformats.htm

ура- ура-ура

Супер!!! Очень интересную доку ты привел. Я не знал про такое.

Сам буквально недавно на одном проекте увидел интересный способ получить временную метку для отсчета используя различные сочетания дней, месяцев, лет (спасибо моему новому коллеге, что подсказал :))) )

вот например узнать начало дня.
Datetime startOfTheDay = datetime.newInstance(System.Today().year(), System.Today().month(), System.Today().day(), 0, 0, 0);

а вот начало недели
DateTime startOfTheNextWeek = datetime.newInstance(System.Today().toStartOfWeek().year(), System.Today().toStartOfWeek().month(), System.Today().toStartOfWeek().day(), 0, 0, 0);

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

Очень удобная конструкция, может и выглядит не очень, может есть более элегантное решение, но я когда увидел влюбился :)

Супер!!! Очень интересную доку ты привел. Я не знал про такое.

Сам буквально недавно на одном проекте увидел интересный способ получить временную метку для отсчета используя различные сочетания дней, месяцев, лет (спасибо моему новому коллеге, что подсказал :))) )

вот например узнать начало дня.
Datetime startOfTheDay = datetime.newInstance(System.Today().year(), System.Today().month(), System.Today().day(), 0, 0, 0);

а вот начало недели
DateTime startOfTheNextWeek = datetime.newInstance(System.Today().toStartOfWeek().year(), System.Today().toStartOfWeek().month(), System.Today().toStartOfWeek().day(), 0, 0, 0);

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

Очень удобная конструкция, может и выглядит не очень, может есть более элегантное решение, но я когда увидел влюбился :)

ТАК, И ХОТЕЛ СКАЗАТЬ, "НОВИЧКИ", которые уже не новички :)!!!
ДЕЛАЕМ НОВЫЕ ТЕМЫ!!! ХВАТИТ УЖЕ СЮДА ПИСАТЬ.
Мало того что тема уже стала неподъемной (врядли кто-то будет читать все это сразу), так еще вы лишаете сайт возможности расти вширь. Каждая тема это отдельная страница, и поисковики индексируют их отдельно.
ТАК ЧТО ХВАТИТ НАЗЫВАТЬ ВОПРОСЫ "НАИВНЫМИ" И ПИСАТЬ СЮДА!!!
:))))

ТАК, И ХОТЕЛ СКАЗАТЬ, "НОВИЧКИ", которые уже не новички :)!!!
ДЕЛАЕМ НОВЫЕ ТЕМЫ!!! ХВАТИТ УЖЕ СЮДА ПИСАТЬ.
Мало того что тема уже стала неподъемной (врядли кто-то будет читать все это сразу), так еще вы лишаете сайт возможности расти вширь. Каждая тема это отдельная страница, и поисковики индексируют их отдельно.
ТАК ЧТО ХВАТИТ НАЗЫВАТЬ ВОПРОСЫ "НАИВНЫМИ" И ПИСАТЬ СЮДА!!!
:)))) 

Dmitry Shnyrev
Очень интересную доку ты привел. Я не знал про такое.

в такие моменты хоть понимаешь, за что такие деньги платим СФу

Dmitry Shnyrev
DateTime startOfTheNextWeek = datetime.newInstance(System.Today().toStartOfWeek().year()

вот именно поэтому и не люблю ДатуВремя...

можно бы открыть отдельную тему с полезными временными формулами, если еще есть что обсудить после этих Date Literals

кстати недале как вчера узнал про сущеcтвование спец библиотеки для работы c Датойвременем в JS:
Moment.JS

[quote="Dmitry Shnyrev"]Очень интересную доку ты привел. Я не знал про такое.[/quote]

в такие моменты хоть понимаешь, за что такие деньги платим СФу

[quote="Dmitry Shnyrev"]DateTime startOfTheNextWeek = datetime.newInstance(System.Today().toStartOfWeek().year() [/quote]

вот именно поэтому и не люблю ДатуВремя...

можно бы открыть отдельную тему с полезными временными формулами, если еще есть что обсудить после этих Date Literals

кстати недале как вчера узнал про сущеcтвование спец библиотеки для работы c Датойвременем в JS:
[url=http://momentjs.com/]Moment.JS[/url]

Den Brown
Moment.JS

Отличная библиотека. Использовал ее в проекте совместно с AngularJs и Visualforce remote actions. Результат отличный, и библиотека просто супер, работу со временем сильно упрощает.

[quote="Den Brown"]Moment.JS[/quote]
Отличная библиотека. Использовал ее в проекте совместно с AngularJs и Visualforce remote actions. Результат отличный, и библиотека просто супер, работу со временем сильно упрощает.

Я полагаю, могу писать всё же здесь, мои вопросы по-прежнему нубские.
Короче, господа, есть страница, есть контроллер, есть триггер.
Со страницы загружается аттачмент, в триггере этот аттачмент переименовывается и отправляется на дропбокс.
Вопрос такой: что (кроме мозга разумеется) нужно использовать, чтобы наладить на странице варианты отправки аттачментов на дропбокс - т.е. через триггер или batch. Иными словами, как мне со страницы управлять миром контроллером. Разумеется, я не прошу пример кода скинуть, просто хотелось бы узнать что ВООБЩЕ для подобного используется.

Я полагаю, могу писать всё же здесь, мои вопросы по-прежнему нубские.
Короче, господа, есть страница, есть контроллер, есть триггер. 
Со страницы загружается аттачмент, в триггере этот аттачмент переименовывается и отправляется на дропбокс.
Вопрос такой: что (кроме мозга разумеется) нужно использовать, чтобы наладить на странице варианты отправки аттачментов на дропбокс - т.е. через триггер или batch. Иными словами, как мне со страницы управлять  [s]миром[/s] контроллером. Разумеется, я не прошу пример кода скинуть, просто хотелось бы узнать что ВООБЩЕ для подобного используется. 

вот такой простой код:

String n = 123456.78.format();
system.debug(n);

и assertEquals не проходит.

system.assertEquals('123 456,78', n);

кто знает почему?

визуально, числа одинаковы. я смотрел в редакторе, оказывается после команды format() там где должен быть пробел, стоят какие-то непонятные символы.

вот такой простой код:

String n = 123456.78.format();
system.debug(n);

и assertEquals не проходит.

system.assertEquals('123 456,78', n);

кто знает почему? :(

визуально, числа одинаковы. я смотрел в редакторе, оказывается после команды format() там где должен быть пробел, стоят какие-то непонятные символы.

Если не ошибаюсь то ты используешь вот это
http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_decimal.htm#apex_System_Decimal_format
Преобразовываешь Decimal в String использую формат для текущей локали.
Как я знаю, в качестве разделителей для Decimal используются "." или "," но не пробел. Просто в зависимости от локали они меняются местами. Т.е. получается что пробела у тебя никак не получится.

Если не ошибаюсь то ты используешь вот это
http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_decimal.htm#apex_System_Decimal_format
Преобразовываешь Decimal в String использую формат для текущей локали.
Как я знаю, в качестве разделителей для Decimal используются "." или "," но не пробел. Просто в зависимости от локали они меняются местами. Т.е. получается что пробела у тебя никак не получится.

Вот тут про это написано
http://salesforce.stackexchange.com/questions/21395/which-decimal-symbol-is-used-in-the-current-users-locale

Decimal value = 1000.10;
String formattedValue = value.format();
String thousandSep = formattedValue.substring(1,2);
String decimalSep = formattedValue.substring(5,6);

Вот тут про это написано
http://salesforce.stackexchange.com/questions/21395/which-decimal-symbol-is-used-in-the-current-users-locale
[code]
Decimal value = 1000.10;
String formattedValue = value.format();
String thousandSep = formattedValue.substring(1,2);
String decimalSep = formattedValue.substring(5,6);
[/code]

в русской локале, для отделения тысяч используется пробел, по крайне визуально, если же разбить на символы то там символ с кодом 160.

в русской локале, для отделения тысяч используется пробел, по крайне визуально, если же разбить на символы то там символ с кодом 160.

Слушай, воспроизвел. Точно косяк
вот код:

Decimal value = 1000.10;
String formattedValue = value.format();
String thousandSep = formattedValue.substring(1,2);
String decimalSep = formattedValue.substring(5,6);
SYSTEM.DEBUG('XXXXX - '+formattedValue);
SYSTEM.DEBUG('XXXXX - '+thousandSep+' - '+decimalSep);
system.assertEquals('1 000,1', formattedValue);

Вот вывод:

11:09:13.043 (43968301)|USER_DEBUG|[5]|DEBUG|XXXXX - 1 000,1
11:09:13.044 (44011472)|USER_DEBUG|[6]|DEBUG|XXXXX - - ,
11:09:13.044 (44100971)|EXCEPTION_THROWN|[7]|System.AssertException: Assertion Failed: Expected: 1 000,1, Actual: 1 000,1
11:09:13.044 (44320677)|FATAL_ERROR|System.AssertException: Assertion Failed: Expected: 1 000,1, Actual: 1 000,1

Слушай, воспроизвел. Точно косяк
вот код:
[code]
Decimal value = 1000.10;
String formattedValue = value.format();
String thousandSep = formattedValue.substring(1,2);
String decimalSep = formattedValue.substring(5,6);
SYSTEM.DEBUG('XXXXX - '+formattedValue);
SYSTEM.DEBUG('XXXXX - '+thousandSep+' - '+decimalSep);
system.assertEquals('1 000,1', formattedValue);
[/code]

Вот вывод:
[code]
11:09:13.043 (43968301)|USER_DEBUG|[5]|DEBUG|XXXXX - 1 000,1
11:09:13.044 (44011472)|USER_DEBUG|[6]|DEBUG|XXXXX -   - ,
11:09:13.044 (44100971)|EXCEPTION_THROWN|[7]|System.AssertException: Assertion Failed: Expected: 1 000,1, Actual: 1 000,1
11:09:13.044 (44320677)|FATAL_ERROR|System.AssertException: Assertion Failed: Expected: 1 000,1, Actual: 1 000,1
[/code]

я пишу в Eclipse и Apex Test Runner в маленьком окне справа (там где лог показывает), я и увидел, что вместо пробелов там что-то странное :(

я пишу в Eclipse и Apex Test Runner в маленьком окне справа (там где лог показывает), я и увидел, что вместо пробелов там что-то странное :(

Приглашаю продолжить последний вопрос в теме
https://salesforce-developer.ru/forum/topic-kosyaki-salesforce-o-kotoryh-vy-vozmozhno-ne-znaete

Остальные вопросы от новичков, пожалуйста, в новые темы (!отдельные)

Приглашаю продолжить последний вопрос в теме
https://salesforce-developer.ru/forum/topic-kosyaki-salesforce-o-kotoryh-vy-vozmozhno-ne-znaete

[b][color=blue]Остальные вопросы от новичков, пожалуйста, в новые темы (!отдельные)[/color][/b]