天天看點

jxTMS使用示例--降低合規性檢查時的規則複雜度

使用本示例需通過docker容器,請先下拉jxTMS的docker鏡像并按說明啟動tms容器,并從helloWorld開始嘗試。

降低合規性檢查時的規則複雜度

大家應該了解什麼是業務規則了:其實就是對業務目前狀态的判斷條件與處置邏輯,等價于開發人員的直接程式設計。隻不過我們用容易了解的、經過可靠實作的機制将其實作為業務人員容易了解與編寫的文本。

但業務不可能都是我們上一節中這麼簡單的,對于複雜業務則其狀态判斷與處置也自然會複雜起來,那麼由業務人員來編寫複雜的規則檢測邏輯,可能就超出了業務人員的能力範圍。

是以在上一節介紹合規性保證時,筆者說的是:讓業務人員在開發者配合下自行編寫業務規則。即業務人員和業務系統的開發人員是互相分工配合的,在業務規則的編寫上就展現為将複雜的單點邏輯交給更專業的開發人員來實作,以簡化業務人員編寫業務規則的難度。

為了實作這個雙方配合下降低業務規則的編寫難度,jxTMS在業務規則中引入了調用函數的能力。這樣一來,就可以把複雜的單點邏輯抽離由開發人員程式設計,然後業務人員直接在規則調用就實作了規則編寫的簡化。

大家是否還記得我們前面用excel導入過銷售折扣權限,如果我們的業務規則是銷售訂單審批時查驗申請人的權限,如果超權限則标紅。我們現在就示範如何實作這個稍有點複雜的業務規則。

相關界面、入口等都是正常性的,是以我們就不再制作了,就利用之前的成果,主要是模拟一下,讓大家知道該如何實作在業務規則中使用權限類似的功能。

還是老樣子,我們先看效果再來講解。

修改業務規則

在capa.py檔案中修改demoRule規則表為:

@myModule.rule('demoRule')
def demoRule():
	'''
	/* 根據輸入的名稱,擷取産品品類名,然後儲存到臨時存儲區中的productName變量中 */
	如果 true 則 cache.productName = getProductName (input.demoName) ;
	/* 根據品類名擷取權限值,并和預設門限進行比較,做出動作 */
	如果 getRight(cache.productName,'user1') >50 則 outAttr.demoName.boder = '紅',local.disp = '超出權限' 否則 outAttr.demoName.boder = '綠',local.disp = '授權許可',result.productName = cache.productName  ;
	'''
	pass
           

然後增加兩個函數:

@myModule.request('dataGet', 'restrict','getRight')
def getRight(self, db, ctx,productName,peopleName):
	return ctx.getAuthorizeValue(db,peopleName,'discount',productName)

@myModule.request('dataGet', 'restrict','getProductName')
def getProductName(self, db, ctx,dn):
	if dn == 'p1':
		return '洗眼器'.decode('utf-8')
	if dn == 'p2':
		return '安全存儲系列'.decode('utf-8')
           

我們還是先看效果,然後再來講解。将capa.py等檔案按用sftp管理jxTMS的代碼所述更新到/home/tms/codeDefine/demo/demo/demo1目錄中。

然後執行一次熱機重新整理後,然後點選快捷欄中的【示範->發起申請】,然後在名稱欄中填入p1,然後點選工具條中的【用規則表檢測】;然後在名稱欄中填入p2,然後點選工具條中的【用規則表檢測】。比較一下兩次有什麼差別。

新的demoRule規則表包含了兩條規則,第一條:

如果 true 則 cache.productName = getProductName (input.demoName) ;
           

條件直接寫了就是true,也就是說,條件永遠成立,是以這句話的意思就是明确要求一定要執行則分支中的語句。既然一定要執行,那我們也可以直接将條件省略掉:

cache.productName = getProductName (input.demoName) ;
           

這個語句的意思非常簡單,就是調用運作規則表的功能子產品中的getProductName函數,而這個函數有一個參數:來自demoName的輸入。需要在規則中執行的取值函數和流程的節點處理函數一樣,被request修飾一下:

@myModule.request('dataGet', 'restrict','函數名')
def 函數名(self, db, ctx,參數1,參數2......):
	#函數執行語句
           

request修飾的函數除self、db、ctx之外又指定了幾個參數,在規則中調用時,就必須送入幾個參數。如,getProductName額外定義了dn一個參數,則規則中就送入了一個值;getRight函數額外定義了兩個參數,則規則中就送入了兩個值。

getProductName函數取到的值被放入到了cache.productName中,上一節說過,cache是本次運作中的臨時變量區,即取出的産品品類名,被放入臨時變量區暫存。

第二條規則:

如果 getRight(cache.productName,'user1') >50 則 outAttr.demoName.boder = '紅',local.disp = '超出權限' 否則 outAttr.demoName.boder = '綠',local.disp = '授權許可',result.productName = cache.productName  ;
           

條件成立的則分支以及不成立時的否則分支,上一節都說過了,是以我們重點講下其條件部分:

getRight(cache.productName,'user1') >50
           

即将cache.productName中暫存的值和一個user1的字元串,作為參數來調用getRight函數,getRight函數傳回的折扣值和門限50進行比較,看是否超出權限。

大家看到這兩條規則中,cache.productName作為一個中轉器,在兩條規則之間進行了資料交換,這就是cache的主要作用,甚至是唯一作用,因為一旦規則表執行完畢,cache即會被清除,其中所有的臨時變量都将被丢棄。

結語

因為表達式都是靜态的,處理能力有限,是以jxTMS引入了動态的、處理能力近乎無限的函數,以便于在複雜業務的處理時,由開發人員來降低業務人員編寫業務規則的難度。

注:大家要不要試一下中文函數名,即把規則中的函數名修改為中文,來試一下吧:

  • 把三個getRight其中的兩個改為【擷取折扣權限】
  • 把三個getProductName其中的兩個改為【擷取品類品】

哪一個不用改呢?當然是具體的函數名。好,看下我改好的:

@myModule.rule('testDemoRule')
def testDemoRule():
	'''
	/* 根據輸入的名稱,擷取産品品類名,然後儲存到臨時存儲區中的productName變量中 */
	如果 true 則 cache.品類品 = 擷取品類品 (input.demoName) ;
	/* 根據品類名擷取權限值,并和預設門限進行比較,做出動作 */
	如果 擷取折扣權限(cache.品類品,'user1') >50 則 outAttr.demoName.boder = '紅',local.disp = '超出權限' 否則 outAttr.demoName.boder = '綠',local.disp = '授權許可',result.品類品 = cache.productName  ;
	'''
	pass

@myModule.request('dataGet', 'restrict','擷取折扣權限'.decode('utf-8'))
def getRight(self, db, ctx,productName,peopleName):
	return ctx.getAuthorizeValue(db,peopleName,'discount',productName)

@myModule.request('dataGet', 'restrict','擷取品類品'.decode('utf-8'))
def getProductName(self, db, ctx,dn):
	if dn == 'p1':
		return '洗眼器'.decode('utf-8')
	if dn == 'p2':
		return '安全存儲系列'.decode('utf-8')
           

注1:别忘了:出現在python代碼中的中文字元串要執行decode(‘utf-8’)來正确轉碼!

注2:規則文本中的中文不需要轉碼,因為這些規則是jxTMS通過__doc__直接讀取,在讀到後jxTMS已經對其進行了轉碼。而request(‘dataGet’, ‘restrict’,‘擷取折扣權限’.decode(‘utf-8’))這樣作為request函數的參數的中文字元串,是被python所加載,然後傳入java中的,而python和java兩者的字元集是不同的,是以需要用decode(‘utf-8’)進行轉碼