發表文章

目前顯示的是有「apex class」標籤的文章

[Apex] List all non-editable fields

When we want to customize a FieldHistory object, such as the Opportunity Field History , we would write a small program to check the modification status of all fields when the Opprotunity record is updated. However, some fields are unnecessary, or even should not be checked. For example, some system fields like CreateDate and IsDeleted. In concept, if a field is not Updateable, there is no need to check it. So how do we confirm if a field is Updateable or not? Here is a ready-made method: (Using Opportunity as an example): Opportunity . sObjectType . getDescribe (). fields . getMap (). get ( fieldName ). getDescribe (). isUpdateable () The plain translation of the above line is roughly as follows: Retrieve the field map of the Opportunity object, and then extract the properties of the specified field from the field map. One of the properties that can be checked is isUpdateable. 

[Apex] 列出所有不可編輯的欄位

當我們想要自己客製化一個 FieldHistory object,例如 Opporutunity Field History,我們就會寫一支小程式,在 Opprotunity reocrd 被更新的時候檢查 所有欄位 的異動狀態。 但其實有些欄位是不必要、甚至是不應該檢查的。 例如某些系統欄位:CreateDate、IsDeleted 之類的。 概念上來說,如果某個 field 不是 Updateable,就毋須檢查。 那如何確認某個 field 是不是 Updateable呢? 這裡有一個現成的方法可用: 以 Opportunity 為例: Opportunity . sObjectType . getDescribe (). fields . getMap (). get ( fieldName ). getDescribe (). isUpdateable () 上面這行的白話翻譯大致是∶把 Opportunity 這個 object 的 field map 抓出來之後,再從 field map 裡面提取指定 field 的屬性,其中一個可以檢查屬性就是 isUpdateable。

這個欄位明明就存在啊,為什麼一直得到 error message: "Variable does not exist: ContactId"

圖片
情境 我在 Opportunity Trigger 裡寫了很簡單的 code,使用到 ContactId 這個 field。 for ( Opportunity opp : Trigger . new ){ if ( opp . ContactId != null ){           // Some actions } } 但是要從 VSC deploy 上 sandbox 的時候,被這個 error 給卡住: Variable does not exist: ContactId   原因 我這支 trigger 的 API version 太舊了,沒有支援到這個欄位。 解法 把 API version 升級到 46.0 以上即可。

[Sample Code] 把原本有複數個 OrderItem 的 Order 拆成兩張 Order (Separate a existing order to 2 orders)

背景說明 原本我們把多個產品都放在同一張 Order 下,到時候就會是一張 Order 對應一張發票。 但CSM 說客戶希望發票分兩張比較清楚。 此 sample 的泛用性不高,主要目的是留給未來的我可以回頭來抄作業的。 Sample Code 產生新 Order //總共一年有12張order,CSM已經手動示範了一張,所以程式只需要跑第二張到第十二張 for ( Integer i = 2 ; i <= 12 ; i ++) { order sampleOrder = [ select AccountId , ContractId , Issued_Invoice_Amount__c , CurrencyIsoCode , EffectiveDate , EndDate , Id , OpportunityId , OrderNumber , OwnerId , Pricebook2Id , Status , StatusCode , SystemModstamp , TotalAmount , Type from order where contractid = '800XXXXXXXXXXXXXXX' and =: i limit 1 ]; System . debug ( i ); order newOrder = sampleOrder . clone ( false , true , false , false ); system . debug ( newOrder ); newOrder . Issued_Invoice_Amount__c = 20000 ; insert newOrder ; OrderItem lineItem = new OrderItem (); lineItem . OrderId = newOrder . id ; lineItem . Quantit...

如何抓出某 object 下所有欄位的 Label Name、API Name、Data Type

背景說明 有一個要跟 Salesforce 做 integration 的同事來索取 Opportunity object 的欄位資訊,希望我幫他確認某幾個欄位的 API Name 和資料類型。 他一開始只列了三五個要確認的,我就肉眼手動完成了。 過兩天,他說又有二三十個欄位要確認…… 我就跟他說我會整批倒出來給他。 以下就是倒出來的方法。 方法一 直接從 UI 擷取 直接切換到 Salesforce  Classic 的畫面,剛好  Label Name、API Name、Data Type 都有顯示出來。 看你是要整頁截圖, 還是要整個複製到 Visual Studio Code 或 Sublime Text 並以多行編輯粹取出來, 或是從 HTML 原始碼粹取出來, 皆可。 方法二 用 Apex Code 印出來 String objType='Opportunity'; Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe(); Schema.SObjectType oppSchema = schemaMap.get(objType); Map<String, Schema.SObjectField> fieldMap = oppSchema.getDescribe().fields.getMap(); for (String fieldName: fieldMap.keySet()) {     system.debug(fieldMap.get(fieldName).getDescribe().getLabel() +','+ fieldMap.get(fieldName).getDescribe().getName() +','+ fieldMap.get(fieldName).getDescribe().getType()); }   參考資料 https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_methods_system_fields_describe.htm

Syntax Reference 常用語法備忘: 如何使用SFDX Deploy / How to use SFDX to deploy Apex Code and Run Specific Test Class

Basic 基本語法 sfdx force:source:deploy -m ApexClass:MyClass -l RunSpecifiedTests  --runtests=MyClass_Test -w 3 -u PRD 同時 Deploy Apex Class and Apex Trigger sfdx force:source:deploy -m "ApexTrigger:MyTrigger,ApexClass:MyClass" -l RunSpecifiedTests  --runtests=MyClass_Test -w 3 -u PRD 同時 Deploy Apex Trigger 和多個 Apex Class sfdx force:source:deploy -m "ApexTrigger:MyTrigger,ApexClass:MyClass, ApexClass:MyClass_Test" -l RunSpecifiedTests  --runtests=MyClass_Test -w 3 -u PRD Note 這篇 有說到同一個 type 如果要 deploy 多個 item,comma 需要做 encode: Don’t: sfdx force:source:deploy -m "Profile:Standard User,Layout:Page,Console" Do: sfdx force:source:deploy -m "Profile:Standard User,Layout:Page%2CConsole" 但我試了還是不行……會出現 Error   MyClass%2C MyClass_Test    An object ' MyClass%2C MyClass_Test ' of type ApexClass was named in package.xml, but was not found in zipped directory 若有人知道我哪裡弄錯了,還請分享告知! 

[踩坑] Test Class 失敗原因之一:抓不到 Custom Setting 的 data

 症狀描述 Apex Class明明寫好了,實測功能也都正常。但是要 deploy 到 Production 的時候,對應的 Test Class 一直 fail 。 仔細看了出錯的行數,問題是出在 Custom Setting 抓到的值竟然是空值。 EXCEPTION_THROWN [103]|System.NullPointerException: Argument 1 cannot be null 檢查過了 Production 的 Custom Setting,欄位已經預先開好了,值也填進去了。 在 Production 的 debug console 以 Execute Anonymous Window 測試,確實也可以用 system.debug 成功地把 Custom Setting 的值打印出來。 關鍵 Custom Setting 看似是個系統 setting ,但他本質仍然就是只是個 Custom Object。如果 Test Class 沒有宣告為 @isTest(SeeAllData=true) 的話,一樣是抓不到任何的 data 的。 所以主要解法有二: 把 Test Class 加上@isTest(SeeAllData=true) 在 Class 裡針對 Test Class 寫個 IF 去處理它 參考資料 How to get Custom Settings in Apex Test code? https://salesforce.stackexchange.com/questions/9565/how-to-get-custom-settings-in-apex-test-code