瀏覽次數: 627316

  • Refval關聯元件可以使用WhereItem過濾資料,如果過濾條件較複雜無法以WhereItem設定時,應如何處理?
    可以從server的該關聯的infocommand裡用SQL語法去過濾資料。
    以出貨單為例,如果想要過濾 已審核 且 客戶編號為'1' 的"報價單號" : 

    可以先在server端的infocommand寫入SQL語法過濾出已審核的報價單。








    再從DataForm的column中的"報價單號"欄位設定WhereItem




  • 如何在前端下SQL語法取得資料?
    基於資訊安全的原因,eepcloud是不允許在前端直接執行SQL語法的,只能夠過後端的 Server Method來執行。

    後端的ServerMethod寫法,如下:
    exports.dosql = function(param, callback){
        var clientInfo = this.clientInfo;
       var id=param.id;
        var sql = "select 名稱 from 客戶資料表 where 客戶編號 = '"+id+"'"; //SQL條件句
       this.queryRaw(clientInfo, clientInfo.database, sql, {}, callback);
    }

    Client端的調用,如下的JS
    function Test()
    {
        var result =$.callSyncMethod('客戶資料表', 'dosql',{id:001}); //非同步調用
        var param = $.parseJSON(result); //傳回result為JSON格式
        if (param.length != 0){
            alert(param[0].名稱);  //假設只傳回1筆資料
       }
    }









  • 如何在前端執行後端的SQL?
    舉一個去後端更改一個Table某個欄位的日期格式例子,前端的JS:
    function mymethod(){ 
        $.callMethod('庫存進出明細表','dosql',{},function(result){
            alert('執行成功!');
        });
    }
    庫存進出明細表 ->後端模組名稱
    dosql -> callServerMethod 的名稱(請自行命名)

    後端的JS:
    exports.dosql = function(param, callback){
        var clientInfo = this.clientInfo;
        this.query(clientInfo, clientInfo.database, ['update [庫存進出明細表] set F010=LEFT(CONVERT(varchar(50),F003,112),6)'],{}, callback);
    };









  • 如何在後端資料存檔後,下達自己的SQL?
    可以使用UpdateComp的onAfterUpdate事件寫一段後端JS來完成,如下:



    sqls.push()為送出的自訂SQL語法,row._客戶編號 為該更改資料的欄位名稱。




  • 如何Call Stored?
    後端的js

    exports.testMethod = function(param, callback){
        var clientInfo = this.clientInfo;
        var module = this;
        var sql =" exec test '"+param.userid+"' "; //SQL條件句
        module.query(clientInfo,clientInfo.database,[sql],{},function(err, result){
            if(err){
                callback(err)
            }
    else{
                callback(null,result);
            }
        }); 
    };


    前端的js

    function callservermethod(){
        var user = $.getVariableValue('user');
        $.callMethod('test', 'testMethod', {userid:user}, function(result){
         alert('成功執行');
        });
    }
    test -> 後端模組名稱
    testMethod -> callServerMethod 的名稱(請自行命名)
    userid:user -> 上傳的參數(如果沒有的話可以填null)







  • 如何在Server端存檔前(新增或更改) 再決定某個欄位的內容並存入資料庫?
    後端的js:

    exports.uc盤點單明細_onBeforeInsert = function(row, sqls, callback)
    {
        var dm = this.dataModule;
        var clientInfo = dm.clientInfo;
      
        var sql = "select max(年月) AS LASTYM from 庫存結帳表";
        dm.queryRaw(clientInfo, clientInfo.database, sql, {}, function(err, datas) {
            var last_period = datas[0].LASTYM;
            sql = "select 平均成本 from 庫存結帳表 Where 產品編號='"+row.產品編號+"' and 年月='"+last_period+"'";
            dm.queryRaw(clientInfo, clientInfo.database, sql,{}, function(err, datas) {
                if (datas.length>0) {
                   row.單價 = datas[0].平均成本;
                }
                callback(null, true);
            });
        });
    }







  • 為何在server端的infocommand寫sql語法使用(不等於<>)會報錯?
    因網頁安全問題『<>』要改用『 != 』

    會報錯的語法 :
    SELECT vUSERS.* FROM vUSERS 
    where STATE <> '離職' 
    ORDER BY USERID

    須改為下列正確語法 :
    SELECT vUSERS.* FROM vUSERS 
    where STATE != '離職' 
    ORDER BY USERID







  • 如何在EEPCloud中開發Stored Procedure? 如何呼叫?
    在EEPCloud的Table節點中, 可以右鍵"儲存過程"(預存程序), 打開頁面後可以用"+新增"來增加一個Stored Procedure, 如下, 填寫 Name為Stored Procedure Name, Parameters為Input/Output參數, Text代表Stored Procedure的程式內容,並按下確定即可。



    如果在Server端要執行此SP, 只要使用 "Exec" 來執行即可, 如下的Server Method:
    exports.doCreate = function(param,callback){
        var year = param.year; // 取出年度
        var clientInfo = this.clientInfo;
        var dm = this;
        dm.query(clientInfo, clientInfo.database, ['exec sp_vacation '+year],{}, callback); //執行sp
    };



  • TRS交易時, 是否可以控制某些條件成立在過帳, 否則就不過帳?
    可以的, 在EEPCloud的Transaction組件中, 每一個交易都有一個onBeforeTrans事件, 可以控制是否要持續交易或動態改變對方的交易欄位, 如下為控制是否交易的例子:
    exports.trs請假單_年度特休假表_onBeforeTrans = function(row, oldRow, fields)
    {
       if (row.請假類型!='特休假')  return false;  //不為特休假就不過帳
       return true;
    };
    上面的情況是針對'請假類型'不能更改的情況, 如果請假類型可以更改的話, 要改成這樣:
    exports.trs請假單_年度特休假表_onBeforeTrans = function(row, oldRow, fields)
    {
       if (row.請假類型!='特休假' && oldRow.請假類型!='特休假') {  //考慮更改時新舊值都不為特休假
           return false;
       }
       else if (oldRow.請假類型=='特休假') {  //如果是特休假改為其他假時
           row.請假天數=0;
       }
       return true;
    };







  • Server端的JS程式非常不好Debug, 常常不知道錯誤在哪? 有沒有比較好的方法可以Debug?
    Server端在主機, 服務大眾用戶, 確實很難Debug, 可以如下的方式來debug:
    1. 可以在Server端中使用 dataModule.echo()方法, 回應到SQL Profiler的"Server"訊息中, 如使用 echo('pass 1'); 等等了解JS的程式邏輯與執行到哪個階段出錯, 或echo()你自己的變數, 看看是否變數的內容有錯。
    2. 另一個方法, 就是當Server端程式比較複雜, 需要調用非同步的程式時, 如果非同步程式內出錯, 會回不來, 此時最好在非同步程式中, 使用 try/catch的方式來避免回不來, 如下:







  • 後端Command中的SQL比較複雜, 用了很多Left Join與欄位AS別名後, 前端的Query送出後會發生Where錯誤, 因為前端並不知道後端的實際的欄名, 如何解決?
    可以透過後端Command的onBeforeExecuteSQL事件來重新替換Where的欄位名稱, 如下的範例:
    exports.GPT010RA_onBeforeExecuteSQL = function(sql, whereStrs)
    {
         for (var i = 0; i < whereStrs.length; i++) {
          whereStrs[i] =  whereStrs[i].replace(/M_SVS/g, 'A.M_MA');  //將M_SVS別名欄位換成實際的A.M_MA欄位
         }
     return sql;  
    };




  • 執行後端的Server Method如果時間較長,如何告知使用者執行中,並於結束後關閉此訊息?
    如下, 可以透過 $.loading()與$loaded() 這兩個方法來處理: 
    function sendMail()
    {
        $.confirm( "確認發送薪資eMail嗎?", function() {
            $.loading($('#dgMaster').closest('div'), '處理中...');
            $.callMethod('薪資明細表','doSendMails',{},function(result){ 
                $.alert(yymm+' 薪資eMail發送成功!','info');
                $.loaded($('#dgMaster').closest('div')) //關閉訊息框
             });
         });
    }}









  • 如何在後端利用資料表內容發送不同對象的eMail?
    發送多封不同對象的EMail時, 因為EMail發送為非同步的機制, 所以這裡要採用一個 async非同步機制來執行, 可以透過Server端infoMail這個組件來發送eMail, 如下的範例, 其中, 可透過InfoMail.htmlrow()以網格形式來輸出欄位內容到Email內容中:
    exports.doSendMails = function(param,callback){
    this.echo('do send mail begin');
        var yymm = param.yymm;  // 取得薪資發放月份
        var co = param.co; //取得子公司
        var dm = this;
        var async = this.getModule('async'); // 改用新的方式來引用 async 非同步模組
    this.getComponent('InfoMail1','infomail',function(err,mail){   
            var sql = "SELECT A.薪資年月,A.員工編號,A.部門,A.姓名,A.子公司,A.實發薪資,B.電子郵件 FROM 薪資發放作業 A,員工資料表 B";
    sql = sql + " WHERE A.員工編號=B.員工編號 AND (B.電子郵件 IS NOT NULL AND B.電子郵件<>'') AND A.薪資年月='"+ yymm +"' AND A.子公司='"+ co +"'"; //取得當月員工薪資資料
    dm.queryRaw(dm.clientInfo, dm.clientInfo.database, sql, {},function(err, rows) {
                if(err){
                    callback(err);
                }
    else{
    async.eachSeries(rows,function(row,cb){
    dm.echo(row.電子郵件);
                        var subject = yymm+"月份薪資發放通知";
                        var table1 = mail.HtmlRow(row, [{ field: '薪資年月', title: '薪資年月'},{ field: '員工編號', title: '員工編號'},{ field: '姓名', title: '姓名'},{ field: '子公司', title: '子公司'},{ field: '部門', title: '部門'},{ field: '實發薪資', title: '實發薪資'}]);
                        var param = {'subject':subject,'to':row.電子郵件,'body':table1};
    mail.Send(param,cb);  // 發送郵件
    },callback);   
                }            
            });
        });
    };




  • 為何我在 Server端的 InfoCommand中使用Group By命令, 沒Select到Key的欄位時, 會報錯 "Group By子句"的錯誤?
    這是因為InfoCommand預設SelectPaging=True的屬性(資料快速分頁功能), 如果要特殊使用Group by時, 須配合SelectPaging=False即可。
  • 執行Server Method時, 如何控制後端所發生的錯誤或訊息, 來告知前端?
    通常後端的錯誤透過 callback(err) 傳送回前端, 如果想自定訊息內容, 可以透過 Error() 來定義, 如下:
    exports.doCreate = function(param,callback)
    {
        var clientInfo = this.clientInfo;
        var sql =" exec sp_create"; // call sp
        var dm=this;
        this.query(clientInfo,clientInfo.database,[sql],{},function(err, result){
            if(err) callback(new Error('後端的過帳程式出現錯誤, 請聯絡資訊人員!'));
            else callback(null);
        }); 
    };





  • 如何正確使用Server端infocommand的SecStyle和SecExcept屬性?
    SecExcept要配合SecStyle, SecStyle=User那SecExcept要填Userid,
    如果SecStyle=Group, SecExcept則填Groupid, 
    如果SecExcept要填多個以”,”或”;”隔開





  • 請問Server端的 JS 如何讓別人共用, 或互相調用?
    可以使用 getServerModule來取得對象並直接調用, 如以下為被調用的 出貨單 ServerModule:
    exports.readData = function(param,callback)
    {
        var dm=param.dm; // 不能用 this.dataModule要從原來的方法中傳進來
        var clientInfo = dm.clientInfo;
        dm.queryRaw(clientInfo, clientInfo.database, "Select * from INVO WHERE F001='"+param.no+"'", {},callback)
    }        
    如下, 有一個 出貨單的Server Method要調用上面的readData()方法:
    exports.writeData = function(param,callback)
    {
        var clientInfo = this.clientInfo;
        var dm=this;
        var no=param.no;
        this.getServerModule('出貨單').readData({no:no,dm:dm}, function(err, result){  // call 出貨單.readData() export方法
            try {
                if (result.length != 0){
                    dm.query(clientInfo, clientInfo.database, ["update INVO set F018='"+result[0].F016+"'"],{}, callback);
                }
            }
            catch(e)
            {
                callback(e);
            }
        });
    }





  • 自動編號中, 如何使用指定欄位作為前引碼來編號?
    透過 AutoNumber組建的 onGetFixed事件即可, 如下:
    exports.an出貨單_onGetFixed = function(fixedString, rows)
    {
        fixedString = rows[0].客戶編號;  // 以客戶編號為前引碼
        return fixedString;
    };









  • 為何我CallServerMethod幾次以後, Server會掛掉不回應? 及Server Method如何傳回執行結果?
    通常都是Server Method中,沒有執行Callback回不來的原因, 或是執行了兩次Callback,在Server端的Callback注意事項如下:
    1. 一定要有callback,而且不能執行2次callback。
    2. callback傳回參數的方法,通常會傳兩個參數,第一個參數:Err, 第二個參數: 自訂傳回值(如果有的話)。如下幾種:
      callback(err);  // 只傳回是否錯誤
      callback(err,datas);  // 傳回是否錯誤及datas資料內容
      callback(null);  // 回應正常無錯誤
      callback(new Error('程式發生錯誤, 請聯絡IT部門處理…'));  // 回應自訂的錯誤訊息
      callback;  // 預設傳遞兩個參數, 第1個err,第2個Data
      如以下兩種寫法是一樣的結果, 上面為省略的寫法:
       this.queryRaw(clientInfo, clientInfo.database, sql, {}, callback);  // 第一種寫法
       this.queryRaw(clientInfo, clientInfo.database, sql, {}, function(err,datas) {
        callback(err,datas);
    }); // 第二種寫法





  • 為何我在 TRS的onBeforeTrans中, 取不到 this.clientInfo的變數內容?
    在UpdateComp或Transaction的事件對象中的 this 並非 dataModule本身, 而是更外層, 所以需使用 this.dataModule來取出 dataModule, 如下:
    exports.trs你的表單_TRS_onBeforeTrans = function(row, oldRow, fields)
    {
       var dm = this.dataModule;  //取出 dataModule
       var user = dm.clientInfo.user;  // 取得 user等
       .....
       return true;
    }





  • TRS中如何使用後端來編明細表的自動序號?
    自動序號通常在前端使用 AutoSeq組件來處理,如果要在TRS中使用自動序號的功能,需要在TRS中設定onBeforeTrans事件,如先在TRS設定好來源是"銷貨單明細.序號",目的是"庫存進出明細表.序號"(Replace模式),其實並要真正讀取來源的序號,而是利用這個機制,透過onBeforeTrans事件來動態替換來源數據來達到目的,如下:
    exports.trs銷貨單明細_庫存進出明細表_onBeforeTrans = function(row, oldRow, fields,callback)
    {
        var dm = this.dataModule;
        if (oldRow==null) {  // 新增的狀態才處理
            var clientInfo = dm.clientInfo;
            var sql = "SELECT MAX(序號) AS 序號 from 庫存進出明細表 Where 單據號碼='"+row.銷貨單號+"'"; // 取出對應的最大序號
            dm.queryRaw(clientInfo, clientInfo.database, sql, {}, function(err,datas) {
                if (err) callback(err);
                else if (datas.length==0 || (! datas[0].序號)) row.序號='001';  // 第一筆明細為 '001'
                else if (datas.length>0)  row.序號= ((parseInt(datas[0].序號)+1001).toString()).substring(1); // 序號+1
                callback(null, true); // callback要return true讓TRS繼續交易
            });
        }
        else {
            fields.splice(5,1); //刪除 '序號' 過帳欄位, 避免被覆蓋
            return true; // 沒有使用 callback請return true;
        }
    };




  • 如何在後端取得系統變數(如今天及時間等)?
    舉例:
    //後端servermethod的取值
    this.getDateValue('today').Format("yyyy/MM/dd");  // 今天
    this.getDateValue('firstday').Format("yyyy/MM/dd"); // 本月第一天
    new Date().Format("yyyy/MM/dd hh:mm:ss"); //取得目前時間
     
    //後端在UpdateComp的事件裡則用
    this.dataModule.getDateValue('today').Format("yyyy/MM/dd"); 
    this.dataModule.getDateValue('firstday').Format("yyyy/MM/dd");
     
    系統變數如下:
    變數名稱        內容
    today         今天日期  
    todayc8     今天日期(varchar8)    
    firstday    本月首日  
    lastday    本月末日  
    firstdaylm  上月首日  
    lastdaylm  上月末日  
    firstdayty  本年首日  
    lastdayty    本年末日  
    firstdayly  去年首日  
    lastdayly    去年末日




  • 如果只是要到後端取關聯的名稱, 一定要寫Server Method嗎?  
    如果只是單純的取某個資料表的每一個欄位值, 可以透過 getDisplayText() 系統方法來取值, 省去後端的Server Method,如下:  
    var userMail = getDisplayText('購物車.User','USERID','EMAIL', $('#dfMaster_客戶編號').val() );  // 用客戶編號去取USERS的EMAIL欄位內容  
    $('#dfMaster_電子郵件').val( userMail ); // 設值到電子郵件欄位  
    以上需注意: "購物車.User"是一個RemoteName,需事先在"購物車"Server端模組中, 設定好"Select * From Users"這個Command  




  • 後端如何傳送非資料表結構的訊息回到前端回?
    如下的範例: 
    後端的JS:
    exports.test = function(param, callback)
    {
       if (param.no=='1')  callback(null,'傳送你的訊息!'); // 傳回你的訊息
       else callback(new Error('錯誤!')); // 送出錯誤訊息
    }
    前端的JS:
    function test()
    {   
        $.callMethod('出貨單4','test',{no:'1'},function(result){ 
            $.alert(result,'info'); // 傳回正常的訊息
           });
    }