Установка checkbox триггером before insert/before update
Здравствуйте. Я недавно совсем познакомился с VIsualforce. Много чего не понятно пока. Поэтому ищу помощи у знающих. У меня имеется объект, хранящий в себе информацию о каких-то товарах. На странице же необходимо автоматически выставлять поле есть/нет в наличии (checkbox) триггером before insert/before update в зависимости от значения в поле количество. Как провернуть это колдунство, подскажите пожалуйста.
public String inputName{get;set;} public String inputNameDel{get;set;} public String inputPrice{get;set;} public String inputNumber{get;set;} public String inputType{get;set;} public String inputDate{get;set;} public String inputRelease{get;set;} public String inputNameSearch{get;set;} public Boolean Availb=false;
private Product__c merchandise; public DisplayProducts(Product__c item) { this.merchandise = item; } public String name { get { return merchandise.Name__c; } } public Decimal price{ get { return merchandise.Price__c; } } public Decimal kolvo{ get { return merchandise.Kolvo__c; } } public String type{ get { return merchandise.Type__c; } } public String date_add{ get { return merchandise.Date_Add__c.format(); } } public String date_del{ get { return merchandise.Date_Del__c.format(); } } public Boolean availability{ get { return merchandise.Availability__c; } }
} }
Я прекрасно понимаю, как плохо выглядит мой код) Но пока ничего лучше не получилось)
Здравствуйте. Я недавно совсем познакомился с VIsualforce. Много чего не понятно пока.
Поэтому ищу помощи у знающих.
У меня имеется объект, хранящий в себе информацию о каких-то товарах. На странице же необходимо автоматически выставлять поле есть/нет в наличии (checkbox) триггером before insert/before update в зависимости от значения в поле количество. Как провернуть это колдунство, подскажите пожалуйста.
Страница:
[code]
<apex:page controller="ProductController" tabStyle="Product__c" >
<apex:form >
<apex:pageBlock title="Our Products">
<apex:pageBlockSection columns="1">
<apex:pageBlockTable value="{!products}" var="pitem">
<apex:column headerValue="Product">
<apex:outputText value="{!pitem.Name}"/>
</apex:column>
<apex:column headerValue="Price">
<apex:outputText value="{!pitem.Price}$"/>
</apex:column>
<apex:column headerValue="Number of">
<apex:outputText value="{!pitem.Kolvo}"/>
</apex:column>
<apex:column headerValue="Type">
<apex:outputText value="{!pitem.Type}"/>
</apex:column>
<apex:column headerValue="Date">
<apex:outputText value="{!pitem.Date_add}"/>
</apex:column>
<apex:column headerValue="Release Date">
<apex:outputText value="{!pitem.Date_del}"/>
</apex:column>
<apex:column headerValue="Availability">
<apex:inputCheckbox id="box" />
</apex:column>
</apex:pageBlockTable>
</apex:pageBlockSection>
</apex:pageBlock>
<apex:pageBlock id="block1">
<apex:pageBlockSection columns="2" id="section1" >
<apex:pageBlockSection id="section2" columns="1" collapsible="true" title="Add product">
<apex:pageBlockSection columns="1">
<apex:outputLabel value="Enter a description of the product:"/>
<apex:inputText label="Name:" value="{!inputName}"/>
<apex:inputText label="Price:" value="{!inputPrice}"/>
<apex:inputText label="Number of:" value="{!inputNumber}"/>
<apex:inputText label="Type:" value="{!inputType}"/>
<apex:inputText label="Date YYYY M D:" value="{!inputDate}"/>
<apex:inputText label="Release Date YYYY M D:" value="{!inputRelease}"/>
<apex:commandButton action="{!addProduct}" value="Add product"/>
</apex:pageBlockSection>
</apex:pageBlockSection>
<apex:pageBlockSection title="Delete product" id="section3">
<apex:pageBlockSection columns="1">
<apex:outputText value="Enter a name of the product:"/>
<apex:inputText label="Name:" value="{!inputNameDel}"/>
<apex:commandButton action="{!deleteProduct}" value="Delete"/>
</apex:pageBlockSection>
</apex:pageBlockSection>
</apex:pageBlockSection>
<apex:pageBlockSection title="Search" id="section4">
<apex:pageBlockSection columns="1">
<apex:outputText value="Enter a name for search:"/>
<apex:inputText label="Name:" value="{!inputNameSearch}"/>
<apex:commandButton action="{!searchProduct}" value="Search"/>
<apex:outputText value="You need this:"/>
<apex:outputText value="{!productSearch[0].Type} {!productSearch[0].Name}"/>
</apex:pageBlockSection>
</apex:pageBlockSection>
<script> twistSection(document.getElementById('{!$Component.block1.section1.section2}').getElementsByTagName('img')[0]) </script>
<script> twistSection(document.getElementById('{!$Component.block1.section1.section3}').getElementsByTagName('img')[0]) </script>
<script> twistSection(document.getElementById('{!$Component.block1.section4}').getElementsByTagName('img')[0]) </script>
</apex:pageBlock>
</apex:form>
</apex:page>
[/code]
Контроллер:
[code]
public with sharing class ProductController{
public String inputName{get;set;}
public String inputNameDel{get;set;}
public String inputPrice{get;set;}
public String inputNumber{get;set;}
public String inputType{get;set;}
public String inputDate{get;set;}
public String inputRelease{get;set;}
public String inputNameSearch{get;set;}
public Boolean Availb=false;
List<DisplayProducts> products;
List<DisplayProducts> productSearch;
public List<DisplayProducts> getProducts(){
if(products==null){
products=new List<DisplayProducts>();
for(Product__c item : [SELECT Id__c, Name__c, Price__c, Kolvo__c, Type__c, Date_Add__c, Date_Del__c, Availability__c
FROM Product__c ]){
products.add(new DisplayProducts(item));
}
}
return products;
}
public List<DisplayProducts> getProductSearch() {
return ProductSearch;
}
// Action method to handle purchasing process
public void addProduct() {
Product__c[] m1 = new List<Product__c>();
if(integer.valueof(inputNumber)>0){
Availb=true;
}
String[] Date_str=inputDate.split(' ');
String[] DateRelease_str=inputRelease.split(' ');
Product__c m = new Product__c(
Availability__c=Availb,
Date_Add__c=Date.newInstance(integer.valueof(Date_str[0]),integer.valueof(Date_str[1]),integer.valueof(Date_str[2])),
Date_Del__c=Date.newInstance(integer.valueof(DateRelease_str[0]),integer.valueof(DateRelease_str[1]),integer.valueof(DateRelease_str[2])),
Kolvo__c=integer.valueof(inputNumber),
Name__c=inputName,
Price__c=integer.valueof(inputPrice),
Type__c=inputType
);
insert m;
}
public void deleteProduct(){
for(Product__c pr : [SELECT Id__c, Name__c, Price__c, Kolvo__c, Type__c, Date_Add__c, Date_Del__c, Availability__c
FROM Product__c ]){
if(inputNameDel.equals(pr.Name__c)){
delete pr;
}
}
}
public void searchProduct(){
productSearch=new List<DisplayProducts>();
for(Product__c pr : [SELECT Id__c, Name__c, Price__c, Kolvo__c, Type__c, Date_Add__c, Date_Del__c, Availability__c
FROM Product__c ]){
if(inputNameSearch.equals(pr.Name__c)){
productSearch.add(new DisplayProducts(pr));
}
}
}
public class DisplayProducts{
private Product__c merchandise;
public DisplayProducts(Product__c item) {
this.merchandise = item;
}
public String name {
get { return merchandise.Name__c; }
}
public Decimal price{
get { return merchandise.Price__c; }
}
public Decimal kolvo{
get { return merchandise.Kolvo__c; }
}
public String type{
get { return merchandise.Type__c; }
}
public String date_add{
get { return merchandise.Date_Add__c.format(); }
}
public String date_del{
get { return merchandise.Date_Del__c.format(); }
}
public Boolean availability{
get { return merchandise.Availability__c; }
}
}
}
[/code]
Я прекрасно понимаю, как плохо выглядит мой код) Но пока ничего лучше не получилось)
Тестовое задание В apex/triggers создаешь триггер с именем name, где name - твое название туда пишешь
trigger name on Product__c (before insert, before update) {//product__c замени на своё,как и названия остальных объектов for (Product__c p : Trigger.new) { if (g.Count__c == 0) {//само условие - если количество товара == 0 p.Availability__c = false;//чекбокс 0 } else p.Availability__c = true;//чекбокс 1 } }
p.s по крайней мере, я делал так и колдунства тут нет, колдунство начнется к моменту создания тестового класса По твоему коду - Id__c и Name__c можно было не создавать - они создаются автоматически, а давать объектам "транслитные(Kolvo__c)" названия - нехорошо.
Тестовое задание :)
В apex/triggers создаешь триггер с именем name, где name - твое название
туда пишешь
[code][code]
trigger name on Product__c (before insert, before update) {//product__c замени на своё,как и названия остальных объектов
for (Product__c p : Trigger.new) {
if (g.Count__c == 0) {//само условие - если количество товара == 0
p.Availability__c = false;//чекбокс 0
}
else
p.Availability__c = true;//чекбокс 1
}
}[/code][/code]
p.s по крайней мере, я делал так
и колдунства тут нет, колдунство начнется к моменту создания тестового класса :)
По твоему коду - Id__c и Name__c можно было не создавать - они создаются автоматически, а давать объектам "транслитные(Kolvo__c)" названия - нехорошо.
Таки да, тестовое)) К тестовым классам пока не приступал, а уже как-то страшно стало, после комментария) И спасибо большое, за помощь)
[quote="mesandman"]Тестовое задание :)
[/quote]
Таки да, тестовое))
К тестовым классам пока не приступал, а уже как-то страшно стало, после комментария)
И спасибо большое, за помощь)
Вот для таких ситуаций советую научиться использовать тернарные операции:
[quote="mesandman"]
if (g.Count__c == 0) {//само условие - если количество товара == 0
p.Availability__c = false;//чекбокс 0
}
else {
p.Availability__c = true;//чекбокс 1
}
[/quote]
Вот для таких ситуаций советую научиться использовать тернарные операции:
[code]p.Availability__c = g.Count__c == 0 ? true : false[/code]
А если делать совсем по-Салесфорски то тут лучше сделать [b]Formula Field[/b] c типом checkbox, которое будет рассчитываться автоматически.
Вот за такое в Salesforce расстреливают
Во-первых, FROM Product__c без WHERE - можно влететь в лимиты. Если на орге больше 50000 продуктов, то получишь exception Во-вторых, почему if(inputNameDel.equals(pr.Name__c)){ не переместить в WHERE запроса?
FROM Product__c WHERE Name__c = :inputNameDel
B третьих, у ВСЕХ объектов в Salesforce по-умолчанию есть поле Name. Зачем делать кастомное Name__c И напоследок самое страшное - DML операция внутри FOR!!! (DML операция - это "delete pr;")
Всю твою красоту что ты написал выше можно преобразовать в одну строчку:
delete [SELECT Id FROM Product__c WHERE Name__c = :inputNameDel LIMIT 10000];
Если разберешься что эта строчка делает по каждому элементу - поймешь очень многое в SF
[quote="DikiiSlon"]
[code]
public void deleteProduct(){
for(Product__c pr : [SELECT Id__c, Name__c, Price__c, Kolvo__c, Type__c, Date_Add__c, Date_Del__c, Availability__c FROM Product__c ]){
if(inputNameDel.equals(pr.Name__c)){
delete pr;
}
}
}
[/code]
[/quote]
Вот за такое в Salesforce расстреливают :)
Во-первых, FROM Product__c без WHERE - можно влететь в лимиты. Если на орге больше 50000 продуктов, то получишь exception
Во-вторых, почему if(inputNameDel.equals(pr.Name__c)){ не переместить в WHERE запроса?
[code]FROM Product__c WHERE Name__c = :inputNameDel[/code]
B третьих, у ВСЕХ объектов в Salesforce по-умолчанию есть поле Name. Зачем делать кастомное Name__c
И напоследок самое страшное - DML операция внутри FOR!!! (DML операция - это "delete pr;")
Всю твою красоту что ты написал выше можно преобразовать в одну строчку:
[code]
delete [SELECT Id FROM Product__c WHERE Name__c = :inputNameDel LIMIT 10000];
[/code]
Если разберешься что эта строчка делает по каждому элементу - поймешь очень многое в SF
Не знаю как там у вас задача тестовая ставится, но вообще вот так массово удалять записи только по имени - это большое зло! На продакшен такое никак нельзя выпускать :))) Вообще во всем мире delete операции под большим запретом - если хотите удалить запись - лучше сделать поле isDeleted (Boolean) и ставить его в TRUE. Естественно во всех запросах после этого надо добавить проверку что isDelete = FALSE чтобы не выбирать такие записи. Но поверьте, бизнес только спасибо скажет
Не знаю как там у вас задача тестовая ставится, но вообще вот так массово удалять записи только по имени - это большое зло! На продакшен такое никак нельзя выпускать :))) Вообще во всем мире delete операции под большим запретом - если хотите удалить запись - лучше сделать поле isDeleted (Boolean) и ставить его в TRUE. Естественно во всех запросах после этого надо добавить проверку что isDelete = FALSE чтобы не выбирать такие записи. Но поверьте, бизнес только спасибо скажет :)
Вот про тернарную операцию я совсем забыл, спасибо. А вообще в этом задании по реализации search и delete можно понять, кто что читал и где искал:)
[quote="Dmitry Shnyrev"][quote="mesandman"]
if (g.Count__c == 0) {//само условие - если количество товара == 0
p.Availability__c = false;//чекбокс 0
}
else {
p.Availability__c = true;//чекбокс 1
}
[/quote]
Вот для таких ситуаций советую научиться использовать тернарные операции:
[code]p.Availability__c = g.Count__c == 0 ? true : false[/code]
А если делать совсем по-Салесфорски то тут лучше сделать [b]Formula Field[/b] c типом checkbox, которое будет рассчитываться автоматически.[/quote]
Вот про тернарную операцию я совсем забыл, спасибо.
А вообще в этом задании по реализации search и delete можно понять, кто что читал и где искал:)
а я вот когда написал
[code]
<apex:column headerValue="Availability">
<apex:inputCheckbox value="{!pitem.Availability}"/>
</apex:column>
[/code]
мне выдало:
Error: Read only property 'ProductController.DisplayProducts.Availability'
Это я где накосячил?
Error: Read only property 'ProductController.DisplayProducts.Availability'
может поле Product__c.Availability__c для твоего профайла открыто только на чтение?
[quote="DikiiSlon"]Error: Read only property 'ProductController.DisplayProducts.Availability'[/quote]
может поле Product__c.Availability__c для твоего профайла открыто только на чтение?
Error: Read only property 'ProductController.DisplayProducts.Availability'
может поле Product__c.Availability__c для твоего профайла открыто только на чтение?
[quote="Den Brown"][quote="DikiiSlon"]Error: Read only property 'ProductController.DisplayProducts.Availability'[/quote]
может поле Product__c.Availability__c для твоего профайла открыто только на чтение?[/quote]
вроде как все облазил там, везде Visible стоит
посмотри твой профайл, доступ к объекту Product__c и к полю Availability__c. может у тебя только READ?
[quote="Den Brown"]посмотри твой профайл, доступ к объекту Product__c и к полю Availability__c. может у тебя только READ?[/quote]
А подскажи пожалуйста, где проверить это? куда залезть?
иди в свои Personal Information и там увидишь какой у тебя профайл, кликай на него , далее Object Settings и выбирай нужный объект и далее смотри поля
А вот еще: При добавлении или удалении записей, по нажатию кнопки страница обновляется, но без изменений. Запись добавляется (или удаляется) только после того, как я ручками обновлю страницу. Так ведь быть не должно?
А вот еще:
При добавлении или удалении записей, по нажатию кнопки страница обновляется, но без изменений. Запись добавляется (или удаляется) только после того, как я ручками обновлю страницу. Так ведь быть не должно?
А вот еще: При добавлении или удалении записей, по нажатию кнопки страница обновляется, но без изменений. Запись добавляется (или удаляется) только после того, как я ручками обновлю страницу. Так ведь быть не должно?
[quote="DikiiSlon"]А вот еще:
При добавлении или удалении записей, по нажатию кнопки страница обновляется, но без изменений. Запись добавляется (или удаляется) только после того, как я ручками обновлю страницу. Так ведь быть не должно?[/quote]
[url=https://salesforce-developer.ru/forum/topic-visualforce-dlya-nachinauschih]Где-то[/url] уже это спрашивали
Есть у меня еще уж больно глупый вопрос) В apex workbook, в разделе Lesson 2: Adding Test Methods описаны действия для добавдения тестовых методов, а именно: 1.In the Repository tab, click Classes in the Setup Entity Type section, and then click New. Так вот: я не могу найти эту вкладку Repository(( Где же она?
И еще:
Для обновления записей в таблице без перезагрузки страницы Dmitry Shnyrev в соседней ветке советовал обернуть ее в
Есть у меня еще уж больно глупый вопрос)
В apex workbook, в разделе Lesson 2: Adding Test Methods описаны действия для добавдения тестовых методов, а именно:
1.In the Repository tab, click Classes in the Setup Entity Type section, and then click New.
Так вот: я не могу найти эту вкладку Repository(( Где же она?
И еще:
Для обновления записей в таблице без перезагрузки страницы Dmitry Shnyrev в соседней ветке советовал обернуть ее в
[code] <apex:outputPanel layout="block" id="rerender_me">...</apex:outputPanel>[/code]
сделал. Написал еще:
[code]<apex:commandButton action="{!deleteProduct}" value="Delete" reRender="rerender_me"/>[/code]
но ничего.
Нужно ли что-то в контроллере еще дописать? Или может commandButton тоже должна находиться внутри
[code] <apex:outputPanel layout="block" id="rerender_me">...</apex:outputPanel>[/code] ?
[quote="DikiiSlon"]Видимо достал я всех своими вопросами))[/quote]
Google все знает.
Есть у меня еще уж больно глупый вопрос) В apex workbook, в разделе Lesson 2: Adding Test Methods описаны действия для добавдения тестовых методов, а именно: 1.In the Repository tab, click Classes in the Setup Entity Type section, and then click New. Так вот: я не могу найти эту вкладку Repository(( Где же она?
[quote="DikiiSlon"]Есть у меня еще уж больно глупый вопрос)
В apex workbook, в разделе Lesson 2: Adding Test Methods описаны действия для добавдения тестовых методов, а именно:
1.In the Repository tab, click Classes in the Setup Entity Type section, and then click New.
Так вот: я не могу найти эту вкладку Repository(( Где же она?
[/quote]
подсказка: @isTest