-
-
Save britishboyindc/e471313957e8f66c26794e673cab0fb8 to your computer and use it in GitHub Desktop.
<apex:page controller="DemoController" applyHtmlTag="false" showHeader="false" lightningStylesheets="true" sidebar="false"> | |
<html> | |
<body> | |
<apex:form > | |
<apex:slds /> | |
<div class="slds-grid"> | |
<div class="slds-col"> | |
<apex:panelGrid columns="1" width="100%"> | |
<apex:pageBlock mode="Account"> | |
<apex:pageBlockSection title="Section 1" columns="1" collapsible="true"> | |
<apex:selectRadio label="Question 1?" | |
value="{!objNew1.Test_Parent_Question_1__c}" | |
required="true" | |
> | |
<apex:selectOptions value="{!yesNoOptions}" /> | |
</apex:selectRadio> | |
</apex:pageBlockSection> | |
</apex:pageBlock> | |
</apex:panelGrid> | |
</div> | |
<div class="slds-m-top_medium" align="Center"> | |
<apex:commandButton value="SUBMIT" action="{!submit}"/> | |
</div> | |
</div> | |
</apex:form> | |
</body> | |
</html> | |
</apex:page> | |
//Main Controller | |
/** | |
* Created by peter on 1/29/2024. | |
*/ | |
public with sharing class DemoController { | |
public Custom_Obj_1__c objNew1 {get;set;} | |
public Custom_Obj_1__c objExisting; | |
public Custom_Obj_2__c clist; | |
public String recordId; | |
public DemoController() { | |
recordId = ApexPages.currentPage().getParameters().get('id'); | |
if (String.isNotBlank(recordId)) { | |
getData(); | |
} | |
} | |
private void getData() { | |
List<Custom_Obj_1__c> records = [Select Id, Test_Parent_Question_1__c FROM Custom_Obj_1__c WHERE Id = :recordId]; | |
if (records.size() > 0) { | |
objExisting = records[0]; | |
objNew1 = objExisting.clone(false); | |
} | |
} | |
public PageReference submit() { | |
objNew1.Id = objExisting.Id; | |
DemoController_WS.updateObject(objNew1); | |
Custom_Obj_2__c clist = new Custom_Obj_2__c(); | |
clist.Custom_Obj_1__c = objExisting.Id; | |
System.debug(objNew1.Test_Parent_Question_1__c); | |
clist.Test_Question_1__c = objNew1.Test_Parent_Question_1__c; | |
System.debug(clist.Test_Question_1__c); | |
DemoController_WS.insertObject(clist); | |
objNew1.Id = NULL; | |
PageReference pageref = new PageReference('/apex/Thankyoupage'); | |
return pageref; | |
} | |
public List<SelectOption> getYesNoOptions() { | |
List<SelectOption> options = new List<SelectOption>(); | |
options.add(new SelectOption('Yes', 'Yes')); | |
options.add(new SelectOption('No', 'No')); | |
return options; | |
} | |
} | |
public without sharing class DemoController_WS { | |
public static void updateObject(sObject recordToUpdate) { | |
update recordToUpdate; | |
} | |
public static void insertObject(sObject recordToUpdate) { | |
insert recordToUpdate; | |
} | |
} |
I have managed to get a flow like this to work with the Guest Site User on Experience Cloud, if you run it in system mode. You have to make sure the GSU profile has access to the objects, and the Parent\Child data you have might make it harder.
But I have found any file upload to be challenging even when you enable GSU file uploads in the settings, especially if you want to link it to a record - though you can capture the ContentId of a new file upload via flow, and link them in a separate record triggered flow.
But if this is working, I would stick with this approach for now
Okay, understood. Thank you so much.
Hi @britishboyindc,
Hope you are doing well.
I'm stuck in a similar requirement as above for another object.
Could you please help me - as of now within salesforce as admin , I'm able to do the submit successfully. However, as GSU, its throwing me this error - "core.apexpages.exceptions.ApexPagesGenericException: system.security.NoAccessException: Update access denied for Summary_Detail__c, controller action methods may not execute"
Here is the data model -
Summary_Header__c is the Primary object, which has Summary_Details__c as child object (Lookup with Summary_Header__c).
Requirement is to get all Summary details records associated to Sumary_Header__c. Then send the same set to records as questions in another object Form__c(ResponseForm__c is in M-D with SummaryHeader__c). After that when user submits the form, the responses to be captured in another object - ResponseDetails__c(Lookup with ReponseForm__c)
I did similar implementation as the other one, which you guided, however, its not working here :-(
In below code, responseForm__c record is not getting created. Only responses are getting created in ResponseDetails__c object.
Also, as per few articles available, tried other ways, but still stuck on this.
Could you please guide me, how to proceed on this?
public without sharing class BPA_AttestationController {
public List<Summary_Detail__c> bpaDetails { get; set; }
public List<Summary_Detail__c> bpaDetailsExisting;
public Summary_Header__c bpaHeader { get; set; }
public Summary_Header__c bpaHeaderExisting;
public Response_Form__c bpaForm {get; set;}
public Response_Form__c bpaFormExisting;
public String selectedContact { get; set; }
public BPAAttestationResponseDetails__c Clist;
public String recordId;
public String bpaHeaderName { get; private set; }
// Wrapper class to hold BPA details and header
public class BPAWrapper {
public Summary_Detail__c detail { get; set; }
public Summary_Header__c header { get; set; }
public BPAAttestationResponseDetails__c Clist;
public BPAWrapper(Summary_Detail__c detail, Summary_Header__c header) {
this.detail = detail;
this.header = header;
}
}
// Get BPA Details and Header as wrappers
public List<BPAWrapper> bpaWrappers { get; set; }
public String bpaName { get; set; }
public BPA_AttestationController() {
String recordId = ApexPages.currentPage().getParameters().get('id');
if (String.isNotBlank(recordId)) {
getData(recordId);
}
}
private void getData(String recordId) {
// Query BPA header
Summary_Header__c bpaHeader = [SELECT Id, Name,Status__c
FROM Summary_Header__c
WHERE Id = :recordId LIMIT 1];
system.debug('BPA Header: ' + bpaHeader);
String bpaHeaderId = bpaHeader.Id;
String bpaHeaderName = bpaHeader.Name;
// Query BPA details
List<Summary_Detail__c> bpaDetails = [SELECT Id, Name,Summary_Name__c,Comment__c,Information__c,Confirmation_Accurate__c
FROM Summary_Detail__c
WHERE Summary_Name__c = :bpaHeaderId];
system.debug('BPA Details: ' + bpaDetails);
if (!bpaDetails.isEmpty()) {
bpaName = bpaDetails[0].Summary_Name__r.Name;
// system.debug('Details: ' + bpaDetails);
}
bpaWrappers = new List<BPAWrapper>();
for (Summary_Detail__c detail : bpaDetails) {
bpaWrappers.add(new BPAWrapper(detail, bpaHeader));
String HeaderId = bpaHeader.Id;
system.debug('Test1');
}
}
public PageReference submit() {
system.debug('Test2');
List<BPAAttestationResponseDetails__c> attestationResponseDetailsList = new List<BPAAttestationResponseDetails__c>();
system.debug('bpaWrappers' + bpaWrappers);
if (bpaWrappers != null && !bpaWrappers.isEmpty()) {
for (BPAWrapper wrapper : bpaWrappers) {
// wrapper.Id = wrapper.header.Id;
// BPA_AttestationController_WS.updateObject(bpaHeader);
Summary_Detail__c bpaRecord = wrapper.detail;
// Summary_Header__c bpaSummaryHeader = wrapper.header;
// system.debug('bpaSummaryHeader' + bpaSummaryHeader);
BPAAttestationResponseDetails__c attestationResponseDetail = new BPAAttestationResponseDetails__c();
attestationResponseDetail.BPA_Detail__c = bpaRecord.Id;
attestationResponseDetail.Name = bpaRecord.Name;
attestationResponseDetail.BPA__c = bpaRecord.Summary_Name__c;
attestationResponseDetail.Comment__c = bpaRecord.Comment__c;
attestationResponseDetail.Information__c = bpaRecord.Information__c;
attestationResponseDetail.Confirmation_Accurate__c = bpaRecord.Confirmation_Accurate__c;
attestationResponseDetailsList.add(attestationResponseDetail);
}
try {
insert attestationResponseDetailsList;
update attestationResponseDetailsList;
} catch (Exception e) {
ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR, 'Error inserting records: ' + e.getMessage()));
return null;
}
}
// Redirect to the thank you page
PageReference pageref = Page.Thankyoupage;
pageref.setRedirect(true);
return pageref;
}
}
VF Page
<apex:page Controller="BPA_AttestationController" applyHtmlTag="false" showHeader="false" lightningStylesheets="true" sidebar="false" cache="true" >
<html>
<body style="text-align:center; font-weight: lighter; font-stretch: ultra-condensed; font-family:Ariel ;">
<apex:form >
<apex:slds />
<apex:messages />
<div class="slds-grid">
<div class="slds-col">
<table class="full-width-table" style="border-spacing: 10px;">
<tr>
<th style="text-align: center;border: 1px solid black;background-color:#DAA520; width: 150px;"><b>Attestation Question</b></th>
<th style="text-align: center;border: 1px solid black;background-color:#DAA520;width: 150px;"><b>Comment</b></th>
<th style="text-align: center;border: 1px solid black;background-color:#DAA520;width: 150px;"><b>Information</b></th>
<th style="text-align: center;border: 1px solid black;background-color:#DAA520;"><b>Confirmation Accurate</b></th>
</tr>
<apex:repeat value="{!bpaWrappers}" var="wrapper">
<tr>
<td style="text-align: left; border: 1px solid black;padding-left:1%;">{!wrapper.detail.Name}</td>
<td style="border: 1px solid black; width: 500px;">
<apex:inputTextarea value="{!wrapper.detail.Comment__c}" cols="100" rows="4"/>
</td>
<td style="border: 1px solid black; width: 500px;"><apex:inputTextarea value="{!wrapper.detail.Information__c}" cols="100" rows="4" /></td>
<td style="border: 1px solid black;padding-right:1%;"><apex:inputField value="{!wrapper.detail.Confirmation_Accurate__c}" ignoreEditPermissionForRendering="true"/></td>
</tr>
</apex:repeat>
</table>
<br/>
<apex:commandButton value="SUBMIT" action="{!submit}" />
</div>
</div>
</apex:form>
</body>
</html>
</apex:page>
I'm not sure if we really need reponseForm__c object at all. As we can send the questions based on records in summary_Detail__c object and then get responses in reponseDetails__c object.
Please advise.
Thanks a lot for your guidance and support :-)
Hello BritishBoyindc,
With above code, I'm able to submit as an Admin but not as GSU.
Evenif I modify the code in try block, it wont allow me to update.
try {
BPA_AttestationController_WS.insertObject(attestationResponseDetailsList);
// insert attestationResponseDetailsList;
// update attestationResponseDetailsList;
} catch (Exception e) {}
public without sharing class BPA_AttestationController_WS {
public static void insertObject(List recordToUpdate) {
insert recordToUpdate;
}
public static void updateObject(List recordToUpdate) {
update recordToUpdate;
}
}
As per debug logs, all fields are getting called it this line -
if (bpaWrappers != null && !bpaWrappers.isEmpty()) {}, then it throws all errors for each summaryDetail record. Then it enters into system mode.
Not sure how to proceed, please suggest if there is any alternative approach.
Thank you for your time and help :-)
I am out of the office this week - will take a look when I get back on Monday
ok,Thank you
Hi there,
I would assume this line is causing the issue?
update attestationResponseDetailsList;
You'll need to move that to the withoutsharing class since the Standard Controller cannot update any record if it is running under GSU
Hi britishboyindc,
I updated my code as below :
public PageReference submit() {
system.debug('Test2');
List<BPAAttestationResponseDetails__c> attestationResponseDetailsList = new List<BPAAttestationResponseDetails__c>();
system.debug('bpaWrappers' + bpaWrappers);
if (bpaWrappers != null && !bpaWrappers.isEmpty()) {
for (BPAWrapper wrapper : bpaWrappers) {
// wrapper.Id = wrapper.header.Id;
// BPA_AttestationController_WS.updateObject(bpaHeader);
Summary_Detail__c bpaRecord = wrapper.detail;
// Summary_Header__c bpaSummaryHeader = wrapper.header;
// system.debug('bpaSummaryHeader' + bpaSummaryHeader);
BPAAttestationResponseDetails__c attestationResponseDetail = new BPAAttestationResponseDetails__c();
attestationResponseDetail.BPA_Detail__c = bpaRecord.Id;
attestationResponseDetail.Name = bpaRecord.Name;
attestationResponseDetail.BPA__c = bpaRecord.Summary_Name__c;
attestationResponseDetail.Comment__c = bpaRecord.Comment__c;
attestationResponseDetail.Information__c = bpaRecord.Information__c;
attestationResponseDetail.Confirmation_Accurate__c = bpaRecord.Confirmation_Accurate__c;
attestationResponseDetailsList.add(attestationResponseDetail);
}
try {
BPA_AttestationController_WS.insertObject(attestationResponseDetailsList);
BPA_AttestationController_WS.updateObject(attestationResponseDetailsList);
// insert attestationResponseDetailsList;
// update attestationResponseDetailsList;
Still getting below error - when I submit as GSU. As an admin, able to submit record successfully.
core.apexpages.exceptions.ApexPagesGenericException: system.security.NoAccessException: Update access denied for
BPA_Summary_Detail__c, controller action methods may not execute.
How can we handle this? please advise.
Thank you :-)
I don't understand why you are performing an insert followed by an update? What is the update doing at that point?
BPA_AttestationController_WS.insertObject(attestationResponseDetailsList);
BPA_AttestationController_WS.updateObject(attestationResponseDetailsList);
But I think that is being seen as the GSU directly trying to update an object which it isn't allowed to do.
But why do you need the update call? What is that doing if you have just inserted the records?
yes, if we insert the records, as an admin able to do so.
However as GSU, I'm getting this error message -
core.apexpages.exceptions.ApexPagesGenericException: system.security.NoAccessException: Update access denied for BPA_Summary_Detail__c, controller action methods may not execute
Is BPA_Summary_Detail__c the Master to BPAAttestationResponseDetails__c?
If so, if the relationship is defined as requiring update access vs just read access, that could be an issue? But otherwise, the without sharing should override all that
Hi @britishboyindc,
I still keep getting this error as GSU.
core.apexpages.exceptions.ApexPagesGenericException: system.security.NoAccessException: Update access denied for BPA_Summary_Detail__c, controller action methods may not execute.
Do I need to check any other permissions? As of now did, setup sharing rule on BPA_Summary_Detail__c owner id not equal to 0
I don't think sharing rules won't help you here - GSU can never have edit access to the records.
Did you check the sharing setting for the lookup to BPA_Summary_Detail__c from BPAAttestationResponseDetails__c .
Is it Read/Write or Read Only? If read \ write, that might be an issue
yes, its public read/write BPA_Summary_Detail__c
Can you change it to only read access and see if that solves it?
Yes,did but still got same error
This worked perfectly on a new record.Thank you so much.
I did that earlier as per your suggestion but I tested in old record.so it was still showing values. My bad.
Is there a better approach for this requirement?
Looks like we can send using flow/lwc but didn't deep dive much as it might need more.
I did gave an attempt with flow over the weekend but it was giving me unauthorised error.I did override settings in flow and added it to guest user profile.