以ServerMove來終結應用
訊光科技/Andy Kao
前言
應用軟體的三大功能: 資料輸入、資料輸出、資料處理與交易。iCoder分別以Word來設計資料輸入及以Excel來設計資料輸出(報表) 、以TRS(商業邏輯)設計資料的過帳交易等,大致可以滿足多數的需求。其中TRS的過帳通常都是以即時的方式(Online)來處理資料交易,但有些過帳與交易並不是即時的,而是以整批的方式來進行;最明顯的例子就是有些表單必須經過主管審核後,才能成為正式單據,這種情況就不能在表單輸入時就進行TRS的過帳處理,是必須在該單經過審核程序之後才進行TRS過帳,所以才有整批處理的需求,而ServerMove也是為了這種整批的複雜處理而來的,目的就是要終結應用系統最難最麻煩的一塊區域。
ServerMove用途
iCoder只能用TRS方式來即時過帳,而ServerMove是一個專業的Server端組件,歸屬在 EEPCloud平台中,所以不適合由一般iCoder用戶來使用。ServerMove的用途基本上有下列三種,如下:
1. 整批過帳: 配合TRS (Transaction)組件,來進行整批過帳功能。TRS平常是在User編輯資料時(新增/更改/刪除)與別的資料表進行過帳處理;ServerMove可以控制TRS不在User編輯資料的狀況下整批處理過帳。例如,出貨單的庫存扣除過帳,可以改在工作流程的"庫存領貨"再整批扣除。
2. 批次分單: 同樣透過TRS來控制整批過帳,但此會利用TRS來自動產生其他單據,除了產生單據主表資料也可以同時產生單據的明細資料。例如,收到的訂單資料,如果品項中有不同的廠商,可以透過ServerMove進行批次分單,把相同廠商的料品歸類到同一張採購單,也就是說一張客戶訂單,可以自動分成不同的採購單下單給廠商。
3. 結帳處理: 很多商業應用都有些結帳處理,不管是日結、月結、年結等。結帳除了配合TRS進行累加累減處理外,最重要的就是自動幫你處理期初餘額(上期)與期末餘額。例如,庫存管理的月結處理,結算出期初存貨、本期進貨、本期銷貨、期末存貨等,還有應收帳款、應付帳款、會計總帳等系統也都需要類似的結帳功能,就可以用ServerMove來實現。
整批過帳實例
就以iCoder所設計的出貨單為實例,透過SeverMove組件可以讓出貨單的過帳改成批次的方式,如下:
1. 下圖為出貨單的庫存過帳TRS設定, "出貨單" 的含稅總計累加到 "客戶資料表" 的營業額";"出貨單" 的聯絡人會替換"客戶資料表" 的聯絡人。 "出貨明細表" 會同步新增到"庫存進出明細表"。
2. iCoder的TRS所生成的EEPCloud Server端的組件為 Transaction,如下的"trs出貨單"與"trs出貨單明細"等。為了能處理整批過帳,貼上 ServerMove組件,如下:
設定ServerMove1的屬性如下:
SourceCommand代表要進行整批過帳的資料來源,這裡選擇 "出貨單";Transaction則選擇 "trs出貨單" 這個組件,代表要以此組件來進行批次過帳處理;TransScope設定為"All"代表整個ServerMove為同一個交易,交易採整體方式,如果失敗會全數滾回。
3. 接著針對 "trs出貨單" 與 "trs出貨明細表" 中的過帳採用整批的方式,可以更改Transaction中的"BatchProcess"屬性為True。這樣,使用者輸入 "出貨單" 時就不會即時同步去進行交易過帳了。
4. 然後在後端增加以下的 Server Method (後端服務程式),命名為 "doMove",如下程式:
其中 param為前端傳上來參數,type為過帳模式,id為出貨單號;最後執行 ServerMove的Excute(),需傳入ServerMove的Where條件,mode為1表示正向過帳(-1代表逆過帳)等。
5. 再來,透過EEPCloud打開 "出貨單" 這個RWD表單,在出貨單的 "ToolItems"中增加一個 "過帳" Button,並呼叫一個 batchmethod的JS方法,如下:
6. 最後,前端增加這個 "batchmethod" 的JS方法,如下:
從DataGrid中取出出貨單號,如果沒有選中就告知用戶 "請選擇一筆資料",然後呼叫 "doMove" 的Server Method,並把type:1 (正向過帳)及出貨單號傳過去即可。
7. 在 出貨單的表單中"預覽"執行畫面,選中一筆出貨單,然後按下 "過帳" 功能,如下:
8. 可以透過 EEPCloud的 "工具"/"SQL Profiler"來查看執行的後端SQL語句,就可以查看並求證上面TRS整批過帳的 SQL資料庫命令,如下:
以上就可以讓出貨單的過帳原本是以On-Line的即時方式過帳,改成以人工按下"過帳"才會進行交易。
批次分單實例
接著就以客戶訂購單要轉成廠商採購單為例,來說明ServerMove具有批次分單的功能;本例中是以接到客戶的訂購單後,要把訂購單的品項明細按廠商歸類,然後分成多張採購單下單給廠商。如下的案例:
1. 在iCoder中,上傳的客戶"訂購單"如下:
注意客戶訂購單明細 PIDetail中的產品編號與廠商及成本價,將以這些欄位來自動生成廠商的採購單。
2. 接著,將下面的"採購單"格式上傳到 iCoder上,也就是說,上面的客戶訂購單會能自動分單成數張的廠商"採購單",格式如下:
3. 在 "訂購單" 的 TRS 中設定 "PIDetail"(訂購明細),過帳給 "PO"(採購單主表),以訂單及廠商找到對應的採購單,找不到則自動新增一張PO採購單,欄位對應關係為: 訂單號碼;廠商編號;採購日期為今天;交貨日取PI交貨日;請購人取目前user:金額合計為PIDetail成本小計等。
另外"PIDetail"也同步過帳給 "PODetail"(採購單明細),採用同步新增方式,就是每一筆PIDetail會產生一筆對應的PODetail資料,只是PO的表頭可能不同(相同廠商才會合併在同一張PO當中)。欄位對應明細為:產品編號;產品名稱;數量;單位;成本價;採購單號取$LASTKEY(代表會根據最後一次找到或新增的 PO主表的鍵值)。以上這個TRS會自動產生PI訂購單的Server端過帳元件。
4. 打開iCoder所產生的Server端的組件,如下的"trsPIDetail,為了達到整批處理,將 trsPIDetail的BatchProcess屬性設為True並貼上 ServerMove組件,另外為了自動新增的PO採購單可以自動編號,我們貼上anPO的AutoNumber組件,如下:
設定ServerMove1的屬性如下:
SourceCommand代表要進行整批過帳的資料來源,選擇"PIDetail "(訂單明細表);Transaction則選擇 "trsPIDetail "這個組件,代表要以此組件來進行批次過帳處理。
設定anPO這個AutoNumber組件屬性,如下:
對應的Field為F001代表自動編號的欄位;GetFixed設為 _Pyy代表'P'加上年度兩碼為前引碼;StartVale與Step都為1代表從1開始編號每次加1;NumDig為5代表流水號為5碼(從00001編到99999)。
5. 然後在後端增加以下的 Server Method (後端服務程式),同樣命名為 "doMove",如下程式:
其中 param為前端傳上來參數,type為過帳模式,id為所要分單的訂單號碼;最後執行 ServerMove的Excute(),需傳入ServerMove的Where條件,其中 TRSSWT IS NULL OR TRSSWT<>'Y'的判斷是用來避免已經下過採購單的就不要重複下單。
6. 再來,透過EEPCloud打開"訂購單"這個RWD表單,並在訂購單的 "ToolItems"中增加一個 "產生採購單" Button,並呼叫一個 batchmethod的JS方法,如下:
7. 最後,前端增加這個 "batchmethod" 的JS方法,如下:
從DataGrid中取出訂單號碼,如果沒有選中就告知用戶 "請選擇一筆訂單",然後呼叫 "doMove" 的Server Method,並把type:1 (正向過帳)及訂購單號傳過去即可。
8. 在 訂購單表單中"預覽"執行畫面,選中一筆訂單,然後按下 "產生採購單" ,如下:
上圖中的訂單編號 1800001中,共購買了如下的4個品項與不同的廠商,因為003與008產品採購對象都是"台山電子"的廠商,所以被分到同一張PO當中;而006與009採購對象為"家家科技",所以被分到另一張PO當中。
9. 執行完 "產生採購單"後,自動產生兩張PO採購單,透過 採購單的"預覽"如下:
第一張PO為"台山電子",採購產品有003與008。
第二張PO為"家家科技",採購產品有006與009。
結帳處理實例
接著利用庫存結帳的案例,來說明ServerMove如何配合TRS組件來執行各種結帳的交易。案例中,我們使用 "庫存進出明細表" 來進行月結的動作,並結帳到"庫存進出結帳表"中。
1. 首先打開 "庫存進出明細表" ,該明細表是透過TRS機制合併了進貨與銷貨的進出明細,如下圖,每個產品編號都會有進貨與銷貨的明細(我們刻意把進貨數量與銷貨數量分開)。
2. 在iCoder中,特別再增加一個 "庫存進出結帳表",用來結帳。其中"年月"代表結帳的年月,並按產品編號從 "庫存進出明細表" 中累加到"本期進貨"與"本期銷貨"中。這裡比較特殊的是"期初"與"期末"的處理,後面將會在ServerMove組件中特別來設定。
3. 接著,透過 "庫存進出明細表"來設定 TRS,讓庫存進出明細表以"年月+產品編號"為單位把進貨數量累加到本期進貨;把銷貨數量累加到本期銷貨。
上面的TRS中是以 "庫存進出明細表"的年月+產品編號 的方式來自動累加到"庫存進出結帳表"中,所以設定為"自動新增"的模式。
4. 打開iCoder所產生的Server端的組件,如下的"trs庫存進出明細表",為了達到整批處理,將 BatchProcess屬性設為True並貼上 ServerMove組件,如下:
ServerMove1的SourceCommand設定來源為"庫存進出明細表",TRS的對象為"trs庫存進出明細表"這個組件,代表要以此組件來進行批次過帳處理。
ServerMove組件在處理結帳時,有5個屬性需要特別設定,分別如下:
CloseTable: 代表結帳的資料表,也是TRS中的對方資料表,這裡設定為"庫存進出結帳表"。
KeyField: 指CloseTable的主鍵欄位,這裡設定為"F001+F002",也就是"年月+產品編號"。
BeginningField: 指CloseTable裡的期初欄位,這裡設定為F004(期初庫存)。
EndingField: 指CloseTable裡的期末欄位,這裡設定為F008(期末庫存)。
Calculation: 指計算期末的公式,這裡設定為"F004+F005-F006",代表"期初+本期進貨-本期銷貨"等。
5. 然後在後端增加以下兩個的 Server Method (後端服務程式),命名為 "doClose"與"doDelete",分別代表"結帳"與"刪除結帳",如下程式:
其中 param為前端傳上來參數,ym為要結帳的年月。
"DoClose"中,有一段"Updte [庫存進出明細表] ...." 是用來先將"庫存進出明細表"中的F003日期轉換到F010成YYMM的格式後,再來執行ServerMove的CarryOver方法。
CarryOver與之前的Execute類似,只是CarryOver除了執行Execute對TRS進行了批次過帳外,在執行Execute之前會先處理 CloseTable的期初值(自動將上期的期末值Copy到本期中做為期初值);處理完TRS後(累加本期進貨與本期銷貨),又會自動處理ServerMove所設定的期末公式來進行期末值的計算。
"DoDelete"這個方法就簡單多了,只要執行ServerMove的DeletePeriod方法即可將指定的結帳年月刪除,目的就是可以重新結帳。
6. 再來,透過EEPCloud打開"庫存進出明細表"這個RWD表單,並在"ToolItems"中增加兩個Button,分別為"月結"與"刪除月結",分別呼叫一個 sureclose與suredele的JS方法,如下:
7. 最後,前端增加這兩個 "sureclose"與"suredele" 的JS方法,如下:
sureclose中,使用 $.prompt()來讓User確認結帳的年月後,再進行呼叫Server端的"doClose"方法進行月結;suredele也是,確認刪除結帳的年月後,呼叫Server端的"doDelete"方法進行刪除結帳。
8. 在 "庫存進出明細表" 表單中"預覽"執行畫面,然後進行"月結"的處理,如下:
這裡輸入"201901"代表要結帳2019年01月,確定後執行了後端的doClose方法後,打開 "庫存進出結帳表",如下,可以看到多了一期"201901"的結帳資料。201812的期末會轉到201901的期初,201901的期末也可以根據201901的本期進貨與銷貨自動計算出期末。
結語
商業系統中,通常資料的輸入與輸出作業都不太複雜,比較複雜的通常就是後端的商業邏輯處理,線上即時的交易可以用 iCoder的TRS機制來處理,但針對這種批次處理或需要進行結帳處理的交易,iCoder就很難應付得來,但也沒關係,iCoder後面還有EEPCloud,可以使用ServerMove這個強大的組件來面對這種特殊需求。再如果ServerMove也無法處理,更可透過EEPCloud使用傳統的開發方式,使用後端的Server Method或資料庫Stored Procedure,同樣可以滿足用戶更進階的需求。