function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Siva SakthiSiva Sakthi 

I have below requirement with Apex Coding

Hi 

1. Create a field “Number of attachments “in accounts. Whenever an attachment is attached or deleted from the account, count the number of attachments and display in the field.

2. Create a Page with two buttons “Start” and ”Increment” .When “Start” is clicked start a counter decrementing from 60 seconds. When the “Increment” button is clicked 3 times stop the counter. Else after 60 seconds display an alert message.

How to achive this two scenario. Please guide me to solve this issue.Post some code to achive this.

Advance Thanks
Maheshwar 
Best Answer chosen by Siva Sakthi
Siddharth ManiSiddharth Mani
U should probably open a new thread for this. However for the first req., try the below controller and page code as a reference(again may not be the most elegant way of doing it) - This doesnt use Wrapper class though:

VF Page:
<apex:page controller="displayItemsController">
<apex:pageBlock title="List of Items">
<apex:pageblockSection >
<apex:pageblockTable value="{!Orders}" var="ord">
<apex:column headerValue="Item" value="{!ord.Item_Type__c}"/>
<apex:column headerValue="Maximum Price" value="{!ord.Price__c}"/>
<apex:column headerValue="Customer" value="{!ord.Customer__c}"/>
</apex:pageblockTable>
</apex:pageblockSection>
</apex:pageBlock>
</apex:page>
Controller:
public class displayItemsController {
    public List<Order__c> getOrders () {
        AggregateResult[] aggr = [SELECT Item_Type__c, max(Price__c) maxp FROM Order__c GROUP BY Item_Type__c];
        List<Decimal> maxPrices = new List<Decimal>();
            for(AggregateResult ag : aggr) {
                maxPrices.add(decimal.valueOf(String.valueof(ag.get('maxp'))));
            }
        List<Order__c> custList = [SELECT Customer__c,Item_Type__c,Price__c FROM Order__c WHERE Price__c IN : maxPrices];
        return custList;
    }
}
For the second requirement (It needs to be implemented using Wrapper Class), more details are needed as to the type of Object and Fields being used as I am not clear on how its being represented currently.



 

All Answers

AshlekhAshlekh
Hi,

You need to write a trigger on Attachment standard object. I've provided you code when attachment is newly attached.

Now you need to hanlde the case of Delete of Attachment than decrease the counter.
trigger TEST on Attachment (after insert,before delete) {
    
    List<Account> acclist = new List<Account>();
    Map<id,integer> accoutMAP = new MAp<id,Counter>();
	if(Trigger.isAfter && Trigger.isinsert)
    {
	    for(Attachment att: Trigger.new )
    	{
            String prefix = att.ParentId;
        	if(prefix.startsWith('001'))
            {
				if(accoutMAP.containsKey(prefix))
                {
                    accoutMAP.put(prefix, accoutMAP.get(prefix)+1);
                }else{
                    accoutMAP.put(prefix,1);
                }
            }    
        }
        if(accoutMAP.size()>0)
        {
            for(Account c:[select id,yourCounterField from Account where id in :accoutMAP.keySet()])
            {
                c.yourCounterField = c.yourCounterField==null?accoutMAP.get(c.id):c.yourCounterField+accoutMAP.get(c.id);
            	acclist.add(c);
            }
            
            if(acclist.size()>0)
                update acclist;
        }
    }


if(Trigger.isBefore && Trigger.isdelete) {
 YOU NEED TO WRITE A CODE FOR DELETE CASE

}
}


-Thanks
Ashlekh Gera
 
Siva SakthiSiva Sakthi
I am getting Error  Like : 
Error: Compile Error: Incorrect SObject type: Attachment should be Account at line 1 column 1


trigger attechmentcount on Attachment(after insert,before delete) {

    List<Account> acclist = new List<Account>();

    Map<id,integer> accoutMAP = new Map<id,integer>();

    if(Trigger.isAfter && Trigger.isinsert) {

        for(Attachment att: Trigger.new )
        {

            String prefix = att.ParentId;

            if(prefix.startsWith('001'))

            {

                if(accoutMAP.containsKey(prefix))
                {
                
                    accoutMAP.put(prefix, accoutMAP.get(prefix)+1);

                }else{

                    accoutMAP.put(prefix,1);

                }

        }   

     }

        if(accoutMAP.size()>0) {

            for(Account c:[select id,Attachment_Count__c from Account where id in :accoutMAP.keySet()]) {

                c.Attachment_Count__c = c.Attachment_Count__c==null?accoutMAP.get(c.id):c.Attachment_Count__c+accoutMAP.get(c.id);

                acclist.add(c);

            }             

            if(acclist.size()>0)

                update acclist;

        }

    }


       /* if(Trigger.isBefore && Trigger.isdelete) {
        
         NEED TO WRITE A CODE FOR DELETE CASE
         
       }*/
  }      
Siddharth ManiSiddharth Mani
Try the below code for 1st req. Not sure if this is the optimal way of doing it:
public Class checkRecursive{
    private static boolean run = true;
    public static boolean runOnce(){
    if(run){
     run=false;
     return true;
    }else{
        return run;
    }
    }
}


trigger NoOfAttch on Attachment (after insert, after update, after delete) {
    if(checkRecursive.runOnce()) {
        if(Trigger.isupdate || Trigger.isInsert) {
			List<Id> accIds = new List<Id>();
			List<Id> accIdsupd = new List<Id>();
			Set<Id> ids=Trigger.newmap.keyset();
			Map<String,Integer> mapIds = new Map<String,Integer>();
        
			for(Attachment att : trigger.new) {
				accIds.add(att.ParentId);
			}
    
    
			List<aggregateResult> aggres = [SELECT ParentId,count(Id) FROM Attachment WHERE ParentId IN : accIds GROUP BY ParentId];
        
			for(AggregateResult aggr : aggres) {
				mapIds.put(string.valueof(aggr.get('ParentId')), integer.valueOf(aggr.get('expr0')));
			}

        
			for(Attachment attch : Trigger.new) {
				accIdsupd.add(attch.ParentId);
			}
        
			List<Account> accList = [SELECT Id, Number_of_attachments__c FROM Account WHERE Id IN : accIdsupd];
    
			for(Account accnt : accList) {
				accnt.Number_of_attachments__c = mapIds.get(accnt.Id);
			}
			update accList;
        }
        
		if(trigger.isdelete) {
			//Integer noOfrecords = [SELECT count() FROM Attachment WHERE Id IN :Trigger.newMap.keySet()];
        	List<Id> accDel = new List<Id>();
            for(Attachment att : Trigger.old) {
                accDel.add(att.ParentId);
            }
            List<Account> accListDel = [SELECT Id, Number_of_attachments__c FROM Account WHERE Id IN : accDel];
            for(Account acc : accListDel) {
                acc.Number_of_attachments__c = acc.Number_of_attachments__c - 1;
            }
            update accListDel;
		}
    }

}

 
Siddharth ManiSiddharth Mani
The above is assuming that you delete the attachments one by one as is there in the standard Account Attachment related list provided by Salesforce!
Siva SakthiSiva Sakthi

I am getting Error  Like : 
Error: Compile Error: Incorrect SObject type: Attachment should be Account at line 1 column 1
Siddharth ManiSiddharth Mani
The trigger is on "Attachment" object and not "Account". Can you please check on that ?
Siddharth ManiSiddharth Mani
The second requirement may be done with javascript as I am not sure if its possible with native apex and visualforce. Here's some starter javascript with Start and Reset functionality (U can modify this as per your requirement) - Save the below code as a Visualforce page and test the same:
<apex:page docType="html">
<script type="text/javascript">
var interval;
    var minutes = 0;
    var seconds = 60;
    window.onload = function() {
        //countdown('countdown');
    }

    function countdown(element) {
        interval = setInterval(function() {
            var el = document.getElementById(element);
            if(seconds == 0) {
                if(minutes == 0) {
                    alert(el.innerHTML = "Alert Message!");                    
                    clearInterval(interval);
                    return;
                } else {
                    minutes--;
                    seconds = 60;
                }
            }
            if(minutes > 0) {
                var minute_text = minutes + (minutes > 1 ? ' minutes' : ' minute');
            } else {
                var minute_text = '';
            }
            var second_text = seconds > 1 ? 'seconds' : 'second';
            el.innerHTML = seconds;
            seconds--;
        }, 1000);
    }
    
</script> 

<input type="button" onclick="countdown('countdown')" value="Start" />
<input type="button" onclick="minutes=0;seconds=60" value="Reset" />
<div id='countdown'></div>

</apex:page>

 
Siva SakthiSiva Sakthi

Thank you Siddharth ! Its working Fine
Siva SakthiSiva Sakthi
I am new to write map and wrapper class. Guide to achive this via wrapper class with mapping.
a) Create the following “Order”  Table in Database  with columns “Item Type” ,“Price” and ”Customer”. Display a list of only the highest price in each Item Type with the customer Name (VF Page).
b) Display the List of Employees with Attendance Percentage without duplicates, in a table with a checkbox by the side. Have a button “Calculate Attendance” which when clicked displays the Attendance for only for the Employee whose checkboxes are checked.

Advance Thanks
SivaSakthi
Siddharth ManiSiddharth Mani
U should probably open a new thread for this. However for the first req., try the below controller and page code as a reference(again may not be the most elegant way of doing it) - This doesnt use Wrapper class though:

VF Page:
<apex:page controller="displayItemsController">
<apex:pageBlock title="List of Items">
<apex:pageblockSection >
<apex:pageblockTable value="{!Orders}" var="ord">
<apex:column headerValue="Item" value="{!ord.Item_Type__c}"/>
<apex:column headerValue="Maximum Price" value="{!ord.Price__c}"/>
<apex:column headerValue="Customer" value="{!ord.Customer__c}"/>
</apex:pageblockTable>
</apex:pageblockSection>
</apex:pageBlock>
</apex:page>
Controller:
public class displayItemsController {
    public List<Order__c> getOrders () {
        AggregateResult[] aggr = [SELECT Item_Type__c, max(Price__c) maxp FROM Order__c GROUP BY Item_Type__c];
        List<Decimal> maxPrices = new List<Decimal>();
            for(AggregateResult ag : aggr) {
                maxPrices.add(decimal.valueOf(String.valueof(ag.get('maxp'))));
            }
        List<Order__c> custList = [SELECT Customer__c,Item_Type__c,Price__c FROM Order__c WHERE Price__c IN : maxPrices];
        return custList;
    }
}
For the second requirement (It needs to be implemented using Wrapper Class), more details are needed as to the type of Object and Fields being used as I am not clear on how its being represented currently.



 
This was selected as the best answer