儲存共用商業物件的服務

當針對程序或服務實例啟用自動同步化時,或當呼叫 save 方法時,會自動儲存共用商業物件的更新項目。 在儲存處理期間,使用儲存服務對共用商業物件執行驗證檢查、計算或存取權檢查。 您可以在處理程序或服務中包括錯誤處理,以偵測及處理資料驗證期間發生的錯誤。
儲存服務 是系統在合併共用商業物件中的資料之後以及儲存變更之前所呼叫的服務流程。 在資料庫中儲存共用商業物件的更新之前,系統會先啟動儲存服務作為儲存及合併處理的一部分。 為下列作業建立儲存服務:
  • 在用戶端上驗證更新的資料。 驗證可以傳回驗證物件。
  • 執行基於所輸入資料的計算。
  • 套用替代合併結果。 如果在儲存服務執行時儲存共用商業物件的另一個版本,則會重新計算合併結果,然後再次啟動儲存服務。
注意: 多個使用者或系統活動可以同時更新共用商業物件。 例如, user1 想要儲存共用商業物件的變更,且儲存服務已啟動。 不過,在將變更儲存至資料庫之前, user2 會先儲存共用商業物件的新版本。 在此情況下,系統會從 user2擷取新版本,合併 user1中的變更,然後再次啟動儲存服務。 因此,當儲存服務未傳回任何驗證錯誤時,您無法假設共用商業物件的版本持續保存。

服務變數

儲存服務具有下列輸入及輸出變數:
輸入變數
表 1. 儲存服務的輸入變數
可變 說明
object (shared business object type) 要儲存的共用商業物件值。 您可以將邏輯新增至儲存服務,以在儲存作業期間操作變數值,例如,計算基於已更新資料的總計。
baseVersion (shared business object type) 共用商業物件在變更之前的值。 當儲存共用商業物件的第一個版本時,此值為 null
latestVersion (shared business object type) 儲存至資料庫之共用商業物件的最新值。 如果此值與 baseVersion 變數的值不同,則會將變更套用至共用商業物件的舊版本,且系統會將其變更與最新版本合併。
changes (BPMBOPropertyChange business object type) 包含對共用商業物件值所做的個別變更的清單。 清單中的每一個項目都有下列內容:
property (String)
變更的變數。 格式指出共用商業物件中的哪個變數已變更。
  • propertyName: propertyName 變數已變更。
  • boPropertyName.propertyName: boPropertyName 複式類型變數,其類型包含已變更的 propertyName 變數。
  • listProperty名稱 [n]: listProperty名稱 清單變數具有已變更的清單項目。 數字 n 指出已變更的清單項目。
  • sboPropertyName.@metadata.key: 參照已變更值之共用商業物件類型的 sboProperty名稱 複式類型變數
  • listPropertyName.listLength(): 已變更清單長度的 listProperty名稱 清單變數
oldValue (Any)
變數的前一個值。
newValue (Any)
變數的新值。
輸出變數
表 2. 儲存服務的輸出變數
可變 說明
validationErrors (BPMBOValidationError business object type) 驗證錯誤的清單。 如果服務 或服務流程 未完成變數或傳回空清單,則會將共用商業物件視為有效,並儲存至資料庫。 不過,在某些情況下,雖然未傳回錯誤,但共用商業物件可能無效。 如需相關資訊,請參閱 錯誤處理
如果傳回錯誤清單,則共用商業物件無效,且會引發錯誤。 清單中的每一個項目都有下列內容:
property (字串)
無效的變數名稱。 請使用用於 BPMBOPropertyChange 商業物件的相同格式。
errorCode (字串)
可用來在 BPD 或服務中以程式化方式處理錯誤的程式碼。
errorText (字串)
在執行時期發生錯誤時可以向使用者顯示的訊息文字。 您也可以提供錯誤訊息的翻譯版本。

儲存服務範例

下列範例使用客戶類型的共用商業物件。 它包含下列變數:
  • givenName (字串): 客戶的名字
  • surname (字串): 客戶的姓氏
  • address (地址): 客戶的地址
  • dateOfBirth (日期): 客戶的出生日期
  • status (字串): 客戶的狀態,例如 new、gold 或 platinum
  • creditScore (小數): 客戶的信用評分
範例: 驗證變數未變更
您可能想要驗證共用商業物件中的變數 (例如出生日期) 在起始設定之後未變更。 您可以在儲存服務中使用伺服器 Script 來進行驗證。
範例 Script 會反覆運算變更清單。 如果 dateOfBirth 變數的值已變更, Script 會檢查舊值是否不是空值。 如果不是 null,則使用者已變更變數,並將驗證錯誤新增至 validationErrors 變數。
for(var i = 0; i < tw.local.changes.listLength; i ++) {
    var change = tw.local.changes[i];
    if(change.property == "dateOfBirth" && change.oldValue != null) {
        if(tw.local.validationErrors == null) {
            tw.local.validationErrors = new tw.object.listOf.BPMBOValidationError();
        }

        var validationError = new tw.object.BPMBOValidationError();
        validationError.property = change.property;
        validationError.errorText = "The date of birth must not be changed.";
        tw.local.validationErrors[tw.local.validationErrors.listLength] = validationError;
    }
}
範例: 驗證使用者許可權
您的共用商業物件中可能有只能由一組特定使用者變更的變數。 在此情況下,儲存服務必須檢查進行變更的使用者是否已獲授權執行此動作。 例如,只有團隊領導人才能變更客戶的狀態。
下列範例伺服器 Script 顯示如何檢查使用者許可權。 Script 會判斷現行使用者是否為團隊領導人團隊的成員。 如果使用者不是團隊成員, Script 會反覆運算變更清單。 如果有 status 變數的項目,則該值已由非團隊領導人變更,並將驗證錯誤新增至 validationErrors 變數。
// check if current user is team lead
var teamLeadTeam = tw.system.org.findTeamByName("Team Lead");
var isTeamLead = tw.system.user.isInTeam(teamLeadTeam);

if(!isTeamLead) {
    for(var i = 0; i < tw.local.changes.listLength; i ++) {
        var change = tw.local.changes[i];
        if(change.property == "status" && (change.oldValue != null || change.newValue != "new")) {
            if(tw.local.validationErrors == null) {
                tw.local.validationErrors = new tw.object.listOf.BPMBOValidationError();
            }

            var validationError = new tw.object.BPMBOValidationError();
            validationError.property = change.property;
            validationError.errorText = "The status must only be changed by a team lead.";
            tw.local.validationErrors[tw.local.validationErrors.listLength] = validationError;
        }
    }
}
注意: 儲存共用商業物件時,系統會以導致儲存發生之使用者的許可權來啟動儲存服務。 如果直接在系統作業中對共用商業物件進行變更,則使用者是技術使用者。
範例: 合併資料
您可以使用 baseVersionlatestVersion 變數,將自訂合併邏輯新增至儲存服務,以偵測共用商業物件的過期版本何時更新。

下列範例伺服器 Script 會檢查 baseVersionlatestVersion 值是否不同。 如果不同,則會合併更新項目。 然後, Script 會從共用商業物件的不同版本中擷取不同的狀態值。 會檢查 status 變數的值,以判定該值在這兩個版本中是否已變更,以及最新狀態是否為 "platinum"。 如果是這樣,則會施行白金級狀態,以防止從該層次降級客戶。

// check if a merge happened because an outdated version was updated
if(tw.local.baseVersion != tw.local.latestVersion) {
    var baseStatus = tw.local.baseVersion.status;
    var latestStatus = tw.local.latestVersion.status;
    var newStatus = tw.local.object.status;

    // check if the status was updated and merged
    if(newStatus != baseStatus && baseStatus != latestStatus) {
        // Make sure a downgrade from platinum does not happen
        if(latestStatus == "platinum") {
            tw.local.object.status = "platinum";
        }
    }
}
範例: 在儲存服務中包括計算
在儲存服務中,您可以將修改套用至共用商業物件變數的值。 例如,您可以呼叫巢狀服務,以計算您傳入客戶資訊 (例如客戶地址) 之客戶的信用評分,並將傳回的信用評分對映至 tw.local.object.creditScore 內容。

錯誤處理

如果一個以上儲存服務呼叫至少傳回一個驗證錯誤,則會引發錯誤。 錯誤類型由 BPMBOSaveFailed錯誤商業物件定義。 您可以將錯誤處理新增至處理程序或服務,以偵測及處理資料驗證期間發生的錯誤。
若要捕捉具有中間錯誤事件的錯誤,請指定 BPMBOSaveFailed「錯誤」作為您要捕捉的錯誤碼。 然後,將錯誤資料對映至區域變數。 錯誤類型由 BPMBOSaveFailed錯誤商業物件定義。 商業物件有一個內容 errors,這是 BPMBOSaveServiceValidationErrors的清單。 errors 內容針對每一個共用商業物件包含一個項目,在執行儲存時發生驗證錯誤。 BPMBOSaveServiceValidationErrors 商業物件具有下列內容:
object (Any)
保留由於驗證錯誤而無法儲存的共用商業物件。
variablePath (字串)
執行儲存的環境定義中變數的路徑,由執行時期自動設定,例如 tw.local.customer。 請注意,雖然相同的共用商業物件可能由多個變數或複式變數的內容參照,但在這裡只會設定其中一個。 在 BPD 中,共用商業物件的自動同步化可能會導致跨數個 (已鏈結) BPD 進行儲存。 如果發生儲存的位置未參照變數,則 variablePath 可以是空值。
validationErrors (BPMBOValidationError, list)
儲存服務傳回的驗證錯誤清單。 具有驗證錯誤的共用商業物件會標示為無效。 這些共用商業物件會從自動同步化中排除,直到進行另一項變更,且使用者儲存共用商業物件或自動儲存它為止。

如果未在活動或步驟上捕捉到錯誤,則會將它延伸到母項實例。 如果完全未捕捉到錯誤,則會捨棄所有更新項目,並將實例標示為「失敗」。

發生驗證錯誤的共用商業物件會從自動同步化中排除,直到進行另一項變更,且使用者儲存共用商業物件或自動儲存它為止。

錯誤處理範例

範例: 在用戶端人工服務中向使用者顯示錯誤資訊
下列範例顯示您可以新增至錯誤事件處理程式的邏輯,以將儲存服務中的驗證錯誤對映至可在 Coach 中顯示的資料結構。 錯誤事件處理程式會將驗證錯誤對映至用戶端人工服務中的 sharedBOSaveError 變數。 變數屬於 BPMBOSaveFailedError 類型。
  tw.system.coachValidation.populateFromBPMBOSaveFailedError(tw.local.sharedBOSaveError);
如需相關資訊,請參閱 處理用戶端人工服務中的錯誤