global abstract class NewAndEditBaseController { public List layoutSections{set;get;} public String layoutSectionsStr {get; set;}//for dynamic add readonly attribute 20220316 by Mingjie public String awsToken{set;get;} public static Map schemaMap = Schema.getGlobalDescribe(); public String sobjectTypeValue {private set; get;} public Boolean isNewMode{set;get;} public Boolean isCloneMode{protected set;get;} public String rtTypeId {get; set;} public String AWSDataId{set;get;} public String CurrentUserId{private set;get;} public String CurrentUserName{private set;get;} // 当前对象所有的加密字段集合 public List encryptedAPIList{private set;get;} // 当前页面中的加密字段集合 public List layoutEncryptedAPIList{private set;get;} //fieldLabel fieldAPI public String requiredFieldAPIListStr {get;private set;} public String fieldApiListStr {get;private set;} public String fieldAPIToLabelMapStr {get;private set;} public String staticResource {get; set;} public string SobjectName{get{return sobjectTypeValue;}} public string SobjectLabel{get;private set;} public Map AWSToSobjectMap{ get{ Map temp = new Map(); temp.putAll(AWSToSobjectNonEncryptedMap); temp.putAll(AWSToSobjectEncryptedMap); return temp; } } public string AWSToSobjectMapJson{get{return JSON.serialize(AWSToSobjectMap);}} public Map AWSToSobjectNonEncryptedMap{get;private set;} public string AWSToSobjectNonEncryptedMapJson{get{return JSON.serialize(AWSToSobjectNonEncryptedMap);}} public string AWSToSobjectNonEncryptedMapKeySet{get{return JSON.serialize(new List(AWSToSobjectNonEncryptedMap.keySet()));}} public Map AWSToSobjectEncryptedMap{get;private set;} public string AWSToSobjectEncryptedMapJson{get{return JSON.serialize(AWSToSobjectMap);}} public final string ApiPrefix{get;private set;} public String sobjectPrefix{get;private set;} public String SaveAndNewButtonUrl{get;private set;} @TestVisible public List VLookUpFields{get;private set;} public String VLookUpFieldsJson{get{return Json.serialize(VLookUpFields);}} public List LookUpOverrideFields{get;private set;} public string LookUpOverrideFieldsMapJson{get; set;} public string recordId{get;private set;} public NewAndEditBaseController(){ ApiPrefix = 'PIBackApi'; AWSToSobjectNonEncryptedMap = new Map(); AWSToSobjectEncryptedMap = new Map(); VLookUpFields = new List(); layoutEncryptedAPIList = new List(); LookUpOverrideFields = new List(); CurrentUserName = UserInfo.getName(); CurrentUserId = UserInfo.getUserId(); } @TestVisible protected virtual void Init(SObject obj){ sobjectTypeValue = obj.getSObjectType().getDescribe().getName(); SobjectLabel = obj.getSObjectType().getDescribe().getLabel(); system.debug('obj='+sobjectTypeValue); isNewMode = true; isCloneMode = false; List lso = Database.query('select id from RecordType where SobjectType = :sobjectTypeValue'); Map mso = ApexPages.currentPage().getParameters(); if(mso != null && mso.containsKey('newclone')){ isCloneMode = true; } if(obj.Id != null){ recordId = obj.Id; isNewMode = false; string sql = 'select Id'; if (lso.size()>0) { sql += ',RecordTypeId'; } sql += GenerateReferenceSql()+',AWS_Data_Id__c from '+sobjectTypeValue+' where id =\''+obj.Id+'\' '; System.debug('sql='+sql); Sobject leadData = Database.query(sql); if (lso.size()>0){ rtTypeId = (String)leadData.get('RecordTypeId'); } AWSDataId = (String)leadData.get('AWS_Data_Id__c'); Map sfIdToAWSIdMap = new Map(); for (string f : LookUpOverrideFields) { object o = leadData.get(f); System.debug('leadData.get('+f+')='+o); if (!String.isBlank(String.valueOf(o))) { sfIdToAWSIdMap.put(String.valueOf(o).subString(0,15), String.valueOf(leadData.getSobject(GetReferenceField(f)).get('AWS_Data_Id__c'))); } } LookUpOverrideFieldsMapJson = JSON.serialize(sfIdToAWSIdMap); }else{ rtTypeId = ApexPages.currentPage().getParameters().get('RecordType'); } AssignValueFromUrl(ApexPages.currentPage().getParameters(),obj); PIHelper.PIIntegration piIntegration = PIHelper.getPIIntegrationInfo(sobjectTypeValue); //layoutEncryptedAPIList = piIntegration.PIFields; encryptedAPIList = piIntegration.PIFields; staticResource = JSON.serialize(piIntegration); sobjectPrefix = piIntegration.sobjectPrefix; SaveAndNewButtonUrl = string.format('/{0}/e', new string[]{sobjectPrefix}); if (lso.size() > 1) { SaveAndNewButtonUrl = String.format('/setup/ui/recordtypeselect.jsp?ent={0}&retURL=/{1}/o&save_new_url=/{1}/e?retURL=%2F{1}%2Fo', new String[]{sobjectTypeValue,sobjectPrefix}); } system.debug('piIntegration.PIDetails='+piIntegration.PIDetails); for (PI_Field_Policy_Detail__c PIDetail : piIntegration.PIDetails) { AWSToSobjectNonEncryptedMap.put(PIDetail.AWS_Field_API__c, PIDetail.SF_Field_API_Name__c); AWSToSobjectEncryptedMap.put(PIDetail.AWS_Encrypted_Field_API__c, PIDetail.SF_Field_Encrypted_API__c); } System.debug(new List(AWSToSobjectNonEncryptedMap.keySet())); system.debug('AWSToSobjectNonEncryptedMapJson='); system.debug(AWSToSobjectNonEncryptedMapJson); system.debug('AWSToSobjectEncryptedMap='+AWSToSobjectEncryptedMap); try{ LayoutDescriberHelper.LayoutWrapper LayoutWrapperValue = LayoutDescriberHelper.describeSectionWithFieldsWrapper(rtTypeId, sobjectTypeValue,'classic'); layoutSections = LayoutWrapperValue.layoutSections; List requiredFieldAPIList = LayoutWrapperValue.requiredFieldAPIList; Map fieldAPIToLabelMap = LayoutWrapperValue.fieldAPIToLabelMap; List fieldApiList = new List(); for (LayoutDescriberHelper.LayoutSection ls : layoutSections) { for (LayoutDescriberHelper.LayoutField lf : ls.layoutFields) { if (lf.fieldAPI != '') { System.debug('lf.fieldAPI='+lf.fieldAPI+' fieldType='+lf.fieldType); fieldApiList.add(lf.fieldAPI); if (lf.fieldType == 'reference') { VLookUpFields.add(lf.fieldAPI); } //在view解密section中只需显示当前layout中的加密字段 if (encryptedAPIList.contains(lf.fieldAPI)) { layoutEncryptedAPIList.add(lf.fieldAPI); } } } } layoutSectionsStr = JSON.serialize(layoutSections); //for dynamic add readonly attribute 20220316 by Mingjie fieldApiListStr = JSON.serialize(fieldApiList); fieldAPIToLabelMapStr = JSON.serialize(fieldAPIToLabelMap); requiredFieldAPIListStr = JSON.serialize(requiredFieldAPIList); //awsToken = AWSServiceTool.getAWSToken(); }catch(Exception e){ layoutEncryptedAPIList = piIntegration.PIFields; system.debug('Exception from get layout service:'+e.getmessage()); } } // 从url参数赋值到当前页面 public static void AssignValueFromUrl(Map mso, sobject sobj){ String sobject_name = sobj.getSObjectType().getDescribe().getName(); Map temp = new Map(); Map fdm = new Map(); List fds = [SELECT Id, DurableId, QualifiedApiName,ValueTypeId , EntityDefinitionId, NamespacePrefix,EntityDefinition.NamespacePrefix, DeveloperName, MasterLabel, Label FROM FieldDefinition where EntityDefinition.QualifiedApiName = :sobject_name]; for(FieldDefinition fd : fds){ //system.debug(fd.DurableId); fdm.put(fd.DurableId.split('\\.')[1],fd); } for(string key : mso.keySet()){ if (key.toLowerCase() == 'id') { System.debug('skip id assign'); continue; } string new_key = key; system.debug('new_key='+new_key); if(new_key.contains('_lkid')){ new_key = new_key.replace('_lkid', ''); new_key = new_key.substring(2); }else{ if(temp.containsKey(new_key)){ continue; } } system.debug('now new_key='+new_key); if(fdm.containsKey(new_key)){ system.debug('fdm.get(new_key)='+fdm.get(new_key)); string val_str = mso.get(key); system.debug('val_str='+val_str); /*无需做decode,sf内部已经做好 try{ val_str = EncodingUtil.urlDecode(mso.get(key),'UTF-8'); }catch(Exception e){ continue; system.debug('Exception from get Key:'+e.getMessage()); system.debug(e.getStackTraceString()); } */ object val = null; string type_id = fdm.get(new_key).ValueTypeId; // address, boolean, date, datetime, double, id, location, string, time if(string.isBlank(val_str)){ val = null; }else if(type_id == 'boolean'){ if(val_str == '1'){ val = true; }else{ val = boolean.valueOf(val_str); } }else if(type_id == 'date'){ // try{ val = date.parse(val_str); }catch(Exception e){ system.debug('val_str='+val_str); system.debug(e.getMessage()); system.debug(e.getStackTraceString()); try{ val = date.valueOf(val_str); }catch(Exception ee){ system.debug('val_str='+val_str); system.debug(ee.getMessage()); system.debug(ee.getStackTraceString()); continue; } } }else if(type_id == 'datetime'){ // try{ val = datetime.parse(val_str); }catch(Exception e){ system.debug('val_str='+val_str); system.debug(e.getMessage()); system.debug(e.getStackTraceString()); try{ val = datetime.valueOf(val_str); }catch(Exception ee){ system.debug('val_str='+val_str); system.debug(ee.getMessage()); system.debug(ee.getStackTraceString()); continue; } } }else if(type_id == 'double' || type_id == 'number'){ try{ val = decimal.valueOf(val_str.replace(',', '')); }catch(Exception ee){ system.debug('val_str='+val_str); system.debug(ee.getMessage()); system.debug(ee.getStackTraceString()); continue; } }else if(type_id == 'id' || type_id == 'string'){ val = val_str; }else{ system.debug('type_id='+type_id+' is not support to convert'); continue; } temp.put(fdm.get(new_key).QualifiedApiName,val); }else{ system.debug(key+' is not in fdm'); } } for(string key : temp.keySet()){ system.debug('assign '+key+'='+temp.get(key)); try{ sobj.put(key, temp.get(key)); }catch(Exception e){ system.debug(e.getMessage()); system.debug(e.getStackTraceString()); } } } public static boolean IsCurrentUserAdministrator() { return IsAdministrator(UserInfo.getUserId()); } public static boolean IsAdministrator(Id user_id) { return IsAdministrator(new List{user_id}).get(user_id); } public static Map IsAdministrator(List user_ids) { Map pfs = new Map([select id from User where id in :user_ids and profileid in ( SELECT profileId FROM PermissionSet WHERE IsOwnedByProfile = true AND IsCustom = false and permissionsmanageusers = true)]); Map res = new Map(); for(Id uid: user_ids){ res.put(uid, pfs.containsKey(uid)); } return res; } public static string GetReferenceField(string f){ if (f.endsWith('__c')) { return f.substring(0,f.length()-1)+'r'; } else if(f.endsWith('Id') || f.endsWith('id') || f.endsWith('ID')) { return f.substring(0, f.length()-2); } else{ return f; } } public string GenerateReferenceSql(){ string res =''; for (string f : LookUpOverrideFields) { res += ','+f+','+GetReferenceField(f)+'.AWS_Data_Id__c'; } return res; } global class Response{ public String recordId{set;get;} public String message{set;get;} public String status{set;get;} } @RemoteAction global static Response save(Sobject sobj, String leadJson,String transId,Boolean isNew) { string sobjectTypeValue = sobj.getSObjectType().getDescribe().getName(); System.debug('sobjectTypeValue:'+sobjectTypeValue+' Info:' + JSON.serialize(leadJson)); System.debug('json length='+leadJson.length()); System.debug('leadJson---------'+leadJson); System.debug('isNew---------'+isNew); //1. Prepare the payload for Lead Schema.SObjectType leadSchema = schemaMap.get(sobjectTypeValue); Map fieldAPIToTypeMap = leadSchema.getDescribe().fields.getMap(); Map fieldValueMap = (Map)JSON.deserializeUntyped(leadJson); string rtid = null; if (fieldValueMap.containsKey('RecordTypeId')) { rtid = String.valueOf(fieldValueMap.get('RecordTypeId')); } List invalid_fields = GetInvalidFieldFromLayout(rtid,sobjectTypeValue); Boolean isClone = false; //2. Save Record Process String status = 'success'; Response resp = new Response(); String awsDataId = ''; Savepoint sp = Database.setSavepoint(); Sobject leadInfo = sobj; try{ for (String fieldAPI: fieldValueMap.keySet()) { system.debug('field API='+fieldAPI); if(invalid_fields.contains(fieldAPI) && !IsCurrentUserAdministrator()){ system.debug(fieldAPI+' is invalid'); continue; } if(!fieldAPIToTypeMap.containskey(fieldAPI)){ continue; } Schema.DisplayType fielddataType = fieldAPIToTypeMap.get(fieldAPI).getDescribe().getType(); String fieldValue = String.valueOf(fieldValueMap.get(fieldAPI)); system.debug('Field Type:'+fielddataType+' field Value='+fieldValue); if(String.valueOf(fielddataType)=='DATE'){ leadInfo.put(fieldAPI,(String.isBlank(fieldValue)||String.isEmpty(fieldValue))? null:Date.valueOf(fieldValue.replace('/', '-'))); }else if(String.valueOf(fielddataType)=='DATETIME'){ if(String.isNotBlank(fieldValue)&&fieldValue.contains('T')){ fieldValue = fieldValue.replace('T',' '); leadInfo.put(fieldAPI, Datetime.valueOfGmt(fieldValue)); //20220405 By ChenYanan Start }else if(String.isNotBlank(fieldValue)) { fieldValue = fieldValue.replace('/', '-') + ':00'; leadInfo.put(fieldAPI, Datetime.valueOf(fieldValue)); //20220405 By ChenYanan End }else{ leadInfo.put(fieldAPI, null); } }else if(String.valueof(fielddataType)=='CURRENCY'|| String.valueof(fielddataType)=='PERCENT'||String.valueOf(fielddataType)=='Number'||String.valueOf(fielddataType)=='DOUBLE' ){ leadInfo.put(fieldAPI, (String.isBlank(fieldValue)||String.isEmpty(fieldValue))?null:Decimal.valueOf(fieldValue.replace(',', ''))); } else if(String.valueof(fielddataType)=='BOOLEAN'){ leadInfo.put(fieldAPI, fieldValueMap.get(fieldAPI)); }else { leadInfo.put(fieldAPI,fieldValue); } } system.debug('for (String fieldAPI: fieldValueMap.keySet()) end'); awsDataId = (String)leadInfo.get('AWS_Data_Id__c'); if (string.isBlank(awsDataId)) { throw new DMLException('更新时AWS_Data_Id__c不能为空'); } System.debug('awsDataId = ' + awsDataId); Sobject[] sobjects = Database.query('select id from '+sobjectTypeValue+' where AWS_Data_Id__c =:awsDataId'); if(!isNew){ isClone = sobjects.size() == 0; } System.debug('isNew---------'+isNew); if(isNew || isClone){ System.debug('leadInfozhj = ' + leadInfo); if(!Test.isRunningTest()){ insert leadInfo; } }else{ System.debug('into update'); System.debug('sobjects[0].id = ' + sobjects[0].id); leadInfo.put('Id',sobjects[0].id);//For testing; if(!Test.isRunningTest()){ update leadInfo; } } // //saveTransLog(transId, leadInfo.AWS_Data_Id__c, status, ''); // Transaction_Log__c traLog = new Transaction_Log__c(); // // AWS_Data_Id__c=AWSDataId,TransId__c=transId,JsonContent__c=leadJson,Status__c=status // traLog.AWS_Data_Id__c = AWSDataId; // traLog.TransId__c = transId; // traLog.JsonContent__c = leadJson; // traLog.Status__c = status; // insert traLog; resp.recordId = leadInfo.Id; // resp.message = 'success saveLead'; resp.status = status; PIHelper.saveTransLog(sobjectTypeValue,awsDataId,leadInfo.Id,transId, leadJson ,status,''); // (String module,String awsDataId,String sfId, String transId,String content,String status,String respMsg) System.debug('respzhj = ' + resp); return resp; } catch(DmlException e) { Integer index = 0; System.debug(e.getNumDml()); System.debug(e.getDmlFields(index)); System.debug(e.getDmlId(index)); System.debug(e.getDmlIndex(index)); System.debug(e.getDmlMessage(index)); System.debug(e.getDmlStatusCode(index)); System.debug(e.getDmlType(index)); system.debug(e.getMessage()); system.debug(e.getStackTraceString()); System.debug('into catch'+e.getMessage()); Database.rollback(sp); resp.status = 'Exception'; resp.message ='保存失败,原因:'+ e.getDmlMessage(index); PIHelper.saveTransLog(sobjectTypeValue,awsDataId,leadInfo.Id,transId, leadJson ,status,e.getMessage()+e.getStackTraceString()); return resp; }catch(Exception e) { System.debug('into catch'+e.getMessage()); Database.rollback(sp); resp.status = 'Exception'; resp.message = e.getMessage()+e.getStackTraceString(); PIHelper.saveTransLog(sobjectTypeValue,awsDataId,leadInfo.Id,transId, leadJson ,status,resp.message); // PIHelper.saveTransLog(sobjectTypeValue,(String)leadInfo.get('AWS_Data_Id__c'),transId, leadJson,status,e.getStackTraceString()); return resp; } } public static List GetInvalidFieldFromLayout(string rtid, string sobject_name){ List sections = MetaDataUtility.GetRecordTypePageLayout(rtid, sobject_name); List ls = new List(); if (sections == null) { System.debug('sections=null'); return ls; } system.debug(Json.serialize(sections)); for (Metadata.LayoutSection section : sections) { if (section.layoutColumns != null) { for (Metadata.LayoutColumn layoutColumn : section.layoutColumns) { if(layoutColumn.layoutItems != null){ for (Metadata.LayoutItem item : layoutColumn.layoutItems) { System.debug(item); if(item.field==null)continue; if (item.behavior == Metadata.UiBehavior.READONLY ) { ls.add(item.field); } } } } } } return ls; } }