2014年8月19日 星期二

ASP.NET MVC 用自訂Action Filter來做Log

參考這篇

張小呆的碎碎唸

稍微改成log到資料庫並記錄下當時所處理的資料.

public class LogActionFilterAttribute : ActionFilterAttribute
    {
        public string ControllerName { get; set; }
        public string ActionName { get; set; }

        private ApplicationDbContext db = new ApplicationDbContext();

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            string uid = filterContext.HttpContext.User.Identity.Name.ToString();
            string originController = filterContext.RouteData.Values["controller"].ToString();
            string originAction = filterContext.RouteData.Values["action"].ToString();
            string originArea = String.Empty;
            if (filterContext.RouteData.DataTokens.ContainsKey("area"))
                originArea = filterContext.RouteData.DataTokens["area"].ToString();

          //這邊利用傳遞參數的名稱來判定要如取出相關資料與以記錄, 所以Action的參數名稱就必須要有可鑑別性

            string result = "";
            if (filterContext.ActionParameters.ContainsKey("empv"))
            {
                empEditViewModels viewModel = (empEditViewModels)filterContext.ActionParameters["empv"];
                result = viewModel.emp1.eid + viewModel.emp1.cname + " 職稱: " + viewModel.emp1.title + " 部門編號: " + viewModel.emp1.dept;

            };
            if (filterContext.ActionParameters.ContainsKey("emp"))
            {
                emp emp1 = (emp)filterContext.ActionParameters["emp"];
                result = emp1.eid + emp1.cname + " 職稱: " + emp1.title + " 部門編號: " +emp1.dept;

            };
            if (filterContext.ActionParameters.ContainsKey("id"))
            {
                int id1 = (int)filterContext.ActionParameters["id"];
                result = " 序號: " + id1.ToString();

            };

          //紀錄相關資料到資料庫

            actlog logmodel = new actlog()
            {
                App = ControllerName+originController,
                Act = ActionName+originAction,
                Pepo = String.IsNullOrEmpty(SessionHelper.RealName) ? uid : SessionHelper.RealName,
                Ext ="進入網頁 : "+result,
                Tm = DateTime.Now              
            };
            db.actlogs.Add(logmodel);
            db.SaveChanges();
        }

        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
        }

        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            string uid = filterContext.HttpContext.User.Identity.Name.ToString();
            actlog logmodel = new actlog()
            {

                App = ControllerName,
                Act = ActionName,
                Pepo = String.IsNullOrEmpty(SessionHelper.RealName) ? uid : SessionHelper.RealName,
                Ext = "傳回的動作結果執行完成",
                Tm = DateTime.Now
            };
            db.actlogs.Add(logmodel);
            db.SaveChanges();
        }
    }

在control中使用範例 :

[HttpPost]
        [ValidateAntiForgeryToken]
        [LogActionFilter(ControllerName = "員工資料管理", ActionName = "新增完成")]
        public ActionResult Create([Bind(Include = "id,eid,cname,dept,title")] emp emp, int? page, int? itemsPerPage, string sortOrder, string currentFilter)
        {
            ViewBag.DropDownList = new SelectList(db.deps, "Id", "title");
            ViewBag.CurrentPage = page;
            ViewBag.CurrentItemsPerPage = itemsPerPage;
            ViewBag.OldSortParm = sortOrder;
            ViewBag.CurrentFilter = currentFilter;
            if (ModelState.IsValid)
            {
                db.emps.Add(emp);
                db.SaveChanges();
                return RedirectToAction("Index", new { page = ViewBag.CurrentPage, itemsPerPage = ViewBag.CurrentItemsPerPage, sortOrder = ViewBag.OldSortParm, searchString = "", CurrentFilter = ViewBag.CurrentFilter });
            }
            return View(emp);
        }


紀錄結果 :

在authentication mode="Forms"下使用 membership defaultProvider="ADMembershipProvider", 搭配Fluent Security的測試及如何使用AD群組來做權限控管

參考這篇,
Fluent Security - 在MVC集中管理頁面權限的套件

真的不錯用, 但受到Form登入無法直接使用 AD的群組當Roles的影響.

所以只能用上

configue.ForAllControllers().Ignore();

configue.For<HomeController>().DenyAnonymousAccess();

configue.For<HomeController>().DenyAuthenticatedAccess();

而一直找不到使用角色的辦法..

configue.For<HomeController>(hc => hc.Contact()).RequireAnyRole("Everyone");

只好回頭用自訂 action filter的辦法來處理 AD的Group.

1.加入參考
C:\Program Files\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.DirectoryServices.AccountManagement.dll

2. Using System.DirectoryServices.AccountManagement;

3.使用者登入時取回AD Group資料塞入Session, 給自訂Action Filter及View使用.
 [HttpPost]
    public ActionResult Login(LoginModel model, string returnUrl)
    {
        if (!this.ModelState.IsValid)
        {
            return this.View(model);
        }

        if (Membership.ValidateUser(model.UserName, model.Password))
        {
            //取回AD Group資料塞入Session
            var context = new PrincipalContext(ContextType.Domain, "Adimmune");
            var userPrincipal = UserPrincipal.FindByIdentity(context,
                                                 IdentityType.SamAccountName,
                                                 model.UserName);
            var UGS = userPrincipal.GetAuthorizationGroups();
            string uGroup = "";
            foreach (var ug in UGS)
                uGroup = uGroup + ug.Name + ";";
            SessionHelper.UserGroup = uGroup;

            FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
            if (this.Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
            {
                return this.Redirect(returnUrl);
            }

            return this.RedirectToAction("Index", "Home");
        }

        this.ModelState.AddModelError(string.Empty, "您提供的Windows帳號或密碼並不正確,如有疑問請與資訊人員聯絡.");

        return this.View(model);
    }

//!!切記要在LogOff時清空SessionHelper.UserGroup,否則會影響權限控管
 public ActionResult LogOff()
    {
        SessionHelper.UserGroup = "";
        SessionHelper.RealName = "";
        FormsAuthentication.SignOut();

        return this.RedirectToAction("Index", "Home");
    }

4.自訂Action Filter.
 public class AuthorizeADAttribute : AuthorizeAttribute
    {
        public string Groups { get; set; }

        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
                /* Return true immediately if the authorization is not
                locked down to any particular AD group */
                if (String.IsNullOrEmpty(Groups))
                    return true;

                // Get the AD groups
                var groups = Groups.Split(',').ToList<string>();

                // Verify that the user is in the given AD group (if any)
                foreach (var group in groups)
                            if (SessionHelper.UserGroup.Contains(group+";"))
                            return true;                
            return false;
        }

5. Control使用範例

 [AuthorizeAD(Groups = "IT")]
 public class empsController : Controller
    {
..................................
}

6 View使用範例
if (Session["UserGroup"].ToString().Contains("webAdmin01;"))
                    {
                        <ul class="nav pull-right">
                            <li class="dropdown">
                                <a href="#" class="dropdown-toggle" data-toggle="dropdown">後台管理<b class="caret"></b></a>
                                <ul class="dropdown-menu">
                                    <li><a href="@Url.Action("Index", "emps")"><i class="icon-off"></i>員工</a></li>
                                    <li><a href="@Url.Action("Index", "deps")"><i class="icon-off"></i>部門</a></li>
                                    <li><a href="@Url.Action("Index", "exms")"><i class="icon-off"></i>評核類別</a></li>
                                    <li><a href="@Url.Action("Index", "ots")"><i class="icon-off"></i>評核時間</a></li>
                                    <li><a href="@Url.Action("Index", "ts")"><i class="icon-off"></i>評核紀錄</a></li>
                                    <li><a href="@Url.Action("Index", "actlogs")"><i class="icon-off"></i>Logs</a></li>
                                </ul>
                            </li>
                        </ul>
                    }

2014年7月3日 星期四

Domino 7.0 透過JCO以BAPI新增SAP流程式製程單報工的範例

範例如下

(如果是JCO ver 3以上, 則必須以JcoContext.begin()與JcoContext.end()來包住兩個execute才能真正commit喔)

import lotus.domino.*;
import java.util.*;
import com.sap.mw.jco.*;
public class SAPApprove extends AgentBase {
private Session session;
private AgentContext agentContext;
private Database db;
private String sapIP,sapClient,sapAccount,sapPasswd,sapLang,sapSysNo;
private JCO.Function function;
private JCO.Function commFunct;
private JCO.Client client ;
private Log log;
private boolean isError=false;
private String errMsg="";
private String resultCode;
private String resultMsg ;
private String wgroup ;
private String ponumber ;
private JCO.Structure returnStructure;
private Document doc;
private JCO.ParameterList params;

public void init(Session session,AgentContext agentContext) throws NotesException{
try {
this.session=session;
this.agentContext=agentContext;
this.db=agentContext.getCurrentDatabase();
Document profile=db.getProfileDocument("SystemProfile",null);
sapIP=profile.getItemValueString("SAPIP");
sapClient=profile.getItemValueString("SAPClient");
sapAccount=profile.getItemValueString("SAPAccount");
sapPasswd=profile.getItemValueString("SAPPasswd");
sapLang=profile.getItemValueString("SAPCode");
sapSysNo=profile.getItemValueString("SAPSysNO");
String logPath=profile.getItemValueString("LogPath");
log = session.createLog( db.getTitle()+" 's Agent "+agentContext.getCurrentAgent().getName()+" on " + db.getServer());
log.openNotesLog(db.getServer(),logPath);

Agent agent = agentContext.getCurrentAgent();
doc = db.getDocumentByID(agent.getParameterDocID());

System.out.println("Load Profile OK.");
}catch(Exception e) {
e.printStackTrace();
try{
session.setEnvironmentVar("AgentResult","載入SAP 設定時,發生錯誤 !!");
}catch ( Exception ex){}
}
}


public void processApprove() {
boolean isok;
Item notifyitem;
try{
System.out.println("Begin JCO Connection....");
log.logAction("Begin JCO Connection....");
client = JCO.createClient(sapClient, sapAccount, sapPasswd, sapLang, sapIP, sapSysNo);
client.connect();
JCO.Repository repository = new JCO.Repository( "Notes", client );
JCO.Attributes attr = client.getAttributes();
IFunctionTemplate ftemplate = repository.getFunctionTemplate( "BAPI_ACC_ACTIVITY_ALLOC_POST" );
function = new JCO.Function( ftemplate );
params = function.getImportParameterList();
JCO.Structure structure1 = params.getStructure("DOC_HEADER");
    JCO.Table table = function.getTableParameterList().getTable("DOC_ITEMS"); //it is taken from the response value of metadata
System.out.println("No of Columns: "+ table.getNumColumns());
 //-----------------------------------------------------------------------------------------------------------------------------
System.out.println("Begin Load Not Procsess Documents....");
log.logAction("Begin Load Not Procsess Documents....");
if (doc != null) {
String sn="00"+doc.getItemValueString("PONumber").replaceAll("\\s+", "");
Date date = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int thismonth = cal.get(Calendar.MONTH);
int thisyear = cal.get(Calendar.YEAR);
structure1.setValue("TW00", "CO_AREA");
structure1.setValue(date, "DOCDATE");
structure1.setValue(date, "POSTGDATE");
structure1.setValue(doc.getItemValueString("DOC_HDR_TX").replaceAll("\\s+", ""), "DOC_HDR_TX");
structure1.setValue("ROOT", "USERNAME");
structure1.setValue(thismonth, "VAL_PERIOD");
structure1.setValue(thisyear, "VAL_FISYEAR");
     System.out.println("Trying to execute append row");
     wgroup=doc.getItemValueString("WorkGroup").replaceAll("\\s+", "");
         table.appendRow(); // Add  rows to internal table for OHV
           table.setValue(wgroup,"SEND_CCTR");
           table.setValue("OHV","ACTTYPE");
           table.setValue(doc.getItemValueDouble("Amount"),"ACTVTY_QTY");
           table.setValue("STD","ACTIVITYUN");
           table.setValue(sn,"REC_ORDER");
           table.appendRow(); // Add  rows to internal table for OHF
           table.setValue(wgroup,"SEND_CCTR");
           table.setValue("OHF","ACTTYPE");
           table.setValue(doc.getItemValueDouble("Amount"),"ACTVTY_QTY");
           table.setValue("STD","ACTIVITYUN");
           table.setValue(sn,"REC_ORDER");        
           table.appendRow(); // Add  rows to internal table for LH
           table.setValue(wgroup,"SEND_CCTR");
           table.setValue("LH","ACTTYPE");
           table.setValue(doc.getItemValueDouble("Amount"),"ACTVTY_QTY");
           table.setValue("STD","ACTIVITYUN");
           table.setValue(sn,"REC_ORDER");        
//table.setValue(query_input_column4,new java.util.Date(query_input_column4_value));
System.out.println("Begin Process PO No: " + sn );
log.logAction("Begin ProcessPO No: " + sn );
function.getImportParameterList().setValue(structure1,"DOC_HEADER");
function.getTableParameterList().setValue(table,"DOC_ITEMS");
IFunctionTemplate ftemplate1 = repository.getFunctionTemplate( "BAPI_TRANSACTION_COMMIT" );
commFunct = new JCO.Function( ftemplate1 );
commFunct.getImportParameterList().setValue("10", "WAIT");
client.execute( function );
              client.execute(commFunct);
JCO.Table returnTable1 = function.getTableParameterList().getTable("RETURN");
returnTable1.setRow(1);
String sn2 = (String)function.getExportParameterList().getValue("DOC_NO");
String sn1=returnTable1.getString("TYPE")+":"+returnTable1.getString("MESSAGE");
String ck=returnTable1.getString("TYPE");
System.out.println("FeedBack: " + sn1 );
log.logAction("FeedBack: " + sn1 );
if (ck.equals("S"))
{
System.out.println("Get Doc No: " + sn2 );
log.logAction("Get Doc No: " + sn2 );
                  returnStructure = (JCO.Structure)commFunct.getExportParameterList().getValue("RETURN");
                  String sn3=returnStructure.getString("TYPE")+":"+returnStructure.getString("MESSAGE");
                  System.out.println("FeedBack: " + sn3);
log.logAction("FeedBack: " + sn3);
                  System.out.println("Function BAPI_TRANSACTION_COMMIT executed .");
session.setEnvironmentVar("AgentResult","OK");
}
else
{
System.out.println("It's failed to create DOC....");
log.logAction("It's failedto create DOC...");
session.setEnvironmentVar("AgentResult","產生報工文件時,發生錯誤 !!");
}
log.logAction("BAPI_ACC_ACTIVITY_ALLOC_POST: " + sn);
}
}catch(java.lang.NoClassDefFoundError e){
e.printStackTrace();
try{
session.setEnvironmentVar("AgentResult","SAP 元件未安裝!!");
}catch ( Exception ex){}
}
catch(Exception e) {
e.printStackTrace();
try{
log.logError(0,e.getLocalizedMessage());
session.setEnvironmentVar("AgentResult","代理程式發生不明錯誤!!");
}catch(Exception err){}
}finally{
try{
  JCO.releaseClient(client);
log.close();
}catch(Exception err){}
}
}

public void NotesMain() {

try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
SAPApprove sapobj=new SAPApprove();
sapobj.init(session,agentContext);

Agent agent = agentContext.getCurrentAgent();

sapobj.processApprove();

} catch(Exception e) {
e.printStackTrace();
}
}
}

2014年7月2日 星期三

Lotus Domino 7.0利用Java呼叫BAPI的範例

這次我們讓Notes的支援工時報工單可以利用BAPI來取回工單的材料說明及實際核發日期來做為簽核的參考.

這篇比上次叫RFC的範例多了
1.取回Structure並輸入參數的例子(有Import及Table)
2.BAPI傳回的Table取值的範例

import lotus.domino.*;
import java.util.*;
import com.sap.mw.jco.*;
public class SAPApprove extends AgentBase {
private Session session;
private AgentContext agentContext;
private Database db;
private String sapIP,sapClient,sapAccount,sapPasswd,sapLang,sapSysNo;
private JCO.Function function;
private JCO.Client client ;
private Log log;
private boolean isError=false;
private String errMsg="";
private String resultCode;
private String resultMsg ;
private JCO.Structure returnStructure;
private Document doc;
private JCO.ParameterList params;

public void init(Session session,AgentContext agentContext) throws NotesException{
try {
this.session=session;
this.agentContext=agentContext;
this.db=agentContext.getCurrentDatabase();
Document profile=db.getProfileDocument("SystemProfile",null);
sapIP=profile.getItemValueString("SAPIP");
sapClient=profile.getItemValueString("SAPClient");
sapAccount=profile.getItemValueString("SAPAccount");
sapPasswd=profile.getItemValueString("SAPPasswd");
sapLang=profile.getItemValueString("SAPCode");
sapSysNo=profile.getItemValueString("SAPSysNO");
String logPath=profile.getItemValueString("LogPath");
log = session.createLog( db.getTitle()+" 's Agent "+agentContext.getCurrentAgent().getName()+" on " + db.getServer());
log.openNotesLog(db.getServer(),logPath);

Agent agent = agentContext.getCurrentAgent();
doc = db.getDocumentByID(agent.getParameterDocID());

System.out.println("Load Profile OK.");
}catch(Exception e) {
e.printStackTrace();
try{
session.setEnvironmentVar("AgentResult","載入SAP 設定時,發生錯誤 !!");
}catch ( Exception ex){}
}
}


public void processApprove() {
boolean isok;
Item notifyitem;
try{
System.out.println("Begin JCO Connection....");
log.logAction("Begin JCO Connection....");
client = JCO.createClient(sapClient, sapAccount, sapPasswd, sapLang, sapIP, sapSysNo);
client.connect();
JCO.Repository repository = new JCO.Repository( "Notes", client );
JCO.Attributes attr = client.getAttributes();
IFunctionTemplate ftemplate = repository.getFunctionTemplate( "BAPI_PROCORD_GET_DETAIL" );
function = new JCO.Function( ftemplate );
//取回structure來設定輸入參數
params = function.getImportParameterList();
JCO.Structure structure1 = params.getStructure("ORDER_OBJECTS");
structure1.setValue("1", "HEADER");

//用Table傳參數的例子
//     JCoTable table = function.getTableParameterList().getTable(targetTableUnderBAPI); //it is taken from the response value of metadata
//System.out.println("No of Columns: "+ table.getNumColumns());
//      System.out.println("Trying to execute append row");
//        table.appendRow();
 //          table.setValue(query_input_column1,query_input_column1_value);
 //        table.setValue(query_input_column2,query_input_column2_value);
 //      table.setValue(query_input_column3,query_input_column3_value);
 //table.setValue(query_input_column4,new java.util.Date(query_input_column4_value));
 //-----------------------------------------------------------------------------------------------------------------------------

System.out.println("Begin Load Not Procsess Documents....");
log.logAction("Begin Load Not Procsess Documents....");
if (doc != null) {
String sn="00"+doc.getItemValueString("PONumber").replaceAll("\\s+", "");
System.out.println("Begin Process PO No: " + sn );
log.logAction("Begin ProcessPO No: " + sn );
function.getImportParameterList().setValue(sn,"NUMBER");
function.getImportParameterList().setValue(structure1,"ORDER_OBJECTS");
client.execute( function );
returnStructure = (JCO.Structure)function.getExportParameterList().getValue("RETURN");
//取回結果的Table並取值
JCO.Table returnTable1 = function.getTableParameterList().getTable("HEADER");
int records = returnTable1.getNumRows();
if (records == 0) {
session.setEnvironmentVar("AgentResult","無此工單");
session.setEnvironmentVar("AgentResult2", "");
}
else {
String rMessage="";
for (int i=0;i<records;i++) {
returnTable1.setRow(i);
rMessage =  rMessage + returnTable1.getString("MATERIAL_TEXT") + "; "; }
returnTable1.setRow(1);
// Date RelaseDate= returnTable1.getDate("ACTUAL_RELEASE_DATE");
String dateString = returnTable1.getString("ACTUAL_RELEASE_DATE");
session.setEnvironmentVar("AgentResult",rMessage);
session.setEnvironmentVar("AgentResult2", dateString);
}
log.logAction("BAPI_PROCORD_GET_DETAIL PONumber: " + sn);
}
}catch(java.lang.NoClassDefFoundError e){
e.printStackTrace();
try{
session.setEnvironmentVar("AgentResult","SAP 元件未安裝!!");
}catch ( Exception ex){}
}
catch(Exception e) {
e.printStackTrace();
try{
log.logError(0,e.getLocalizedMessage());
session.setEnvironmentVar("AgentResult","代理程式發生不明錯誤!!");
}catch(Exception err){}
}finally{
try{
  JCO.releaseClient(client);
log.close();
}catch(Exception err){}
}
}

public void NotesMain() {

try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
SAPApprove sapobj=new SAPApprove();
sapobj.init(session,agentContext);

Agent agent = agentContext.getCurrentAgent();

sapobj.processApprove();

} catch(Exception e) {
e.printStackTrace();
}
}
}

2014年4月24日 星期四

Domino Notes 7.0 呼叫SAP RFC來取得資產說明

上一篇做了一個簡單的RFC, 這一篇是紀錄如何呼叫SAP RFC來取得資產說明

1.首先要做一個Java agent, 接受doc.NoteID,並將結果用
session.setEnvironmentVar("AgentResult",resultMsg);來傳回Lotusscript

範例:
import lotus.domino.*;
import java.util.*;
import com.sap.mw.jco.*;
public class SAPApprove extends AgentBase {
private Session session;
private AgentContext agentContext;
private Database db;
private String sapIP,sapClient,sapAccount,sapPasswd,sapLang,sapSysNo;
private JCO.Function function;
private JCO.Client client ;
private Log log;
private boolean isError=false;
private String errMsg="";
private String resultCode;
private String resultMsg ;
private Document doc;

public void init(Session session,AgentContext agentContext) throws NotesException{
try {
this.session=session;
this.agentContext=agentContext;
this.db=agentContext.getCurrentDatabase();
Document profile=db.getProfileDocument("SystemProfile",null);
sapIP=profile.getItemValueString("SAPIP");
sapClient=profile.getItemValueString("SAPClient");
sapAccount=profile.getItemValueString("SAPAccount");
sapPasswd=profile.getItemValueString("SAPPasswd");
sapLang=profile.getItemValueString("SAPCode");
sapSysNo=profile.getItemValueString("SAPSysNO");
String logPath=profile.getItemValueString("LogPath");
log = session.createLog( db.getTitle()+" 's Agent "+agentContext.getCurrentAgent().getName()+" on " + db.getServer());
log.openNotesLog(db.getServer(),logPath);

Agent agent = agentContext.getCurrentAgent();
doc = db.getDocumentByID(agent.getParameterDocID());

System.out.println("Load Profile OK.");
}catch(Exception e) {
e.printStackTrace();
try{
session.setEnvironmentVar("AgentResult","載入SAP 設定時,發生錯誤 !!");
}catch ( Exception ex){}
}
}


public void processApprove() {
boolean isok;
Item notifyitem;
try{
System.out.println("Begin JCO Connection....");
log.logAction("Begin JCO Connection....");
client = JCO.createClient(sapClient, sapAccount, sapPasswd, sapLang, sapIP, sapSysNo);
client.connect();
JCO.Repository repository = new JCO.Repository( "Notes", client );
JCO.Attributes attr = client.getAttributes();
IFunctionTemplate ftemplate = repository.getFunctionTemplate( "Z_RFC_ASSETCHECK" );
function = new JCO.Function( ftemplate );
System.out.println("Begin Load Not Procsess Documents....");
log.logAction("Begin Load Not Procsess Documents....");
if (doc != null) {
String sn=doc.getItemValueString("ANLN1").replaceAll("\\s+", "");
String sn2=doc.getItemValueString("ANLN2").replaceAll("\\s+", "");
System.out.println("Begin Process Asset No: " + sn + "-" + sn2);
log.logAction("Begin Process Asset No: " + sn + "-" + sn2);
function.getImportParameterList().setValue(sn,"IANLN1");
function.getImportParameterList().setValue(sn2,"IANLN2");
client.execute( function );
resultCode = (String)function.getExportParameterList().getValue("STATUS");
resultMsg = (String)function.getExportParameterList().getValue("MESSAGE");
if (! (resultCode.equals("") | resultCode.equals("O")) ){
System.out.println("Return Code :"+resultCode);
System.out.println("Return Message :"+resultMsg);
log.logError(1,"Error Code : "+resultCode);
log.logError(1,"Error Message : "+sn+ "-" + sn2+" - "+resultMsg);
isError=true;
errMsg="Notes 與 SAP 溝通作業時發生錯誤";
session.setEnvironmentVar("AgentResult",resultMsg);
}else{
log.logAction("Z_RFC_ASSETCHECK SN: " + sn + "-" + sn2);
isError=false;
session.setEnvironmentVar("AgentResult",resultMsg);
}
}
}catch(java.lang.NoClassDefFoundError e){
e.printStackTrace();
try{
session.setEnvironmentVar("AgentResult","SAP 元件未安裝!!");
}catch ( Exception ex){}
}
catch(Exception e) {
e.printStackTrace();
try{
log.logError(0,e.getLocalizedMessage());
session.setEnvironmentVar("AgentResult","代理程式發生不明錯誤!!");
}catch(Exception err){}
}finally{
try{
  JCO.releaseClient(client);
log.close();
}catch(Exception err){}
}
}

public void NotesMain() {

try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
SAPApprove sapobj=new SAPApprove();
sapobj.init(session,agentContext);

Agent agent = agentContext.getCurrentAgent();

sapobj.processApprove();

} catch(Exception e) {
e.printStackTrace();
}
}

2.Lotusscript呼叫範例:

Sub Click(Source As Button)
If uidoc.EditMode Then
uidoc.Save
Dim agent As NotesAgent
Dim m_agnrtn As String
Set agent=db.GetAgent("SAPAssetCheck")
If (agent.Run(doc.NoteID)><0) Then
Messagebox "執行 SAP 溝通之代理程式,執行錯誤!!",MB_ICONSTOP,"執行錯誤!!"
Exit Sub
End If
m_agnrtn=session.GetEnvironmentString("AgentResult")
If m_agnrtn="SAP 元件未安裝!!" Then
Messagebox "您尚未安裝與SAP溝通之必要元件,若要使用此功能,請連絡相關人員,謝謝!!",MB_ICONSTOP,"元件未安裝"
Exit Sub
End If
Call uidoc.FieldSetText("ANLATXT50", m_agnrtn )
End If
End Sub

2014年4月17日 星期四

我的第一個SAP RFC喔!

由於單據報銷電子簽核時,有要求資產必須先進SAP建檔才可進財務請款,

因此就需要寫個SAP RFC來檢查報銷單據所輸入的資產編碼是否有在SAP當中輸入完成

FUNCTION Z_RFC_ASSETCHECK.
*"----------------------------------------------------------------------
*"*"區域介面:
*"  IMPORTING
*"     VALUE(IANLN1) TYPE  ANLN1
*"     VALUE(IANLN2) TYPE  ANLN2
*"  EXPORTING
*"     VALUE(STATUS) TYPE  CHAR1
*"     VALUE(MESSAGE) TYPE  TEXT300
*"----------------------------------------------------------------------

  DATA : wa_ANLA TYPE  ANLA.

 IF ianln1 IS INITIAL.
    status = 'E'.
    message = '資產編號不得為空值'.
    RETURN.
  ENDIF.

 IF ianln2 IS INITIAL.
    status = 'E'.
    message = '資產子編號不得為空值'.
    RETURN.
  ENDIF.

  SELECT SINGLE *
    FROM ANLA
        INTO  wa_ANLA
    WHERE anln1 EQ ianln1
      AND anln2  EQ ianln2.
  IF sy-subrc NE 0.
    status = 'E'.
    message = '查無此資產'.
  ELSE.
    status = 'O'.
    message = wa_ANLA-TXT50.
  ENDIF.

    RETURN.
ENDFUNCTION.

2014年4月15日 星期二

Domino Notes 7.0 透過web API撈Json資料的範例

取網頁資料請參考這一篇(Notes Client只能在Windows平台上操作喔)

http://stackoverflow.com/questions/12719192/get-a-field-value-from-a-webpage-lotusscript

取json則請使用這個ntf建好的script程式庫

http://www.openntf.org/main.nsf/project.xsp?r=project/JSON%20LS

請先把用到的Class先準備好

這個例子是做當人事單位按開始審核按鈕時,系統自動透過webAPI取回相關打卡紀錄存入PunchCards欄位做佐證.

我放在Form的Postopen事件

Sub Postopen(Source As Notesuidocument)
If source.EditMode Then
Dim internet As New RemoteHTML()
Dim html As String
Dim sJSON As String
Dim PunchTime As String
Dim jsonReader As JSONReader
Dim vResults As Variant
Set jsonReader = New JSONReader
Set doc=uidoc.Document
url$="http://10.100.2.1:8080/API/Employees/"
url2$="/"+Format$(doc.STime(0),"yyyymmdd")+"/"+Format$(doc.ETime(0),"yyyymmdd")
url1$=url$+Ucase(Trim(doc.EmployeeID(0)))+url2$
html = internet.GetHTTP(url1$)
Set vResults = jsonReader.Parse(html) 'this is a JSONObject
If  vResults.Count > 0 Then
PunchTime = PunchTime +Chr(13) + Chr(10)+ vResults.items(0).GetItemValue("RSENO") + vResults.items(0).GetItemValue("BPNME")
For iV = 1 To  vResults.Count
PunchTime = PunchTime +Chr(13) + Chr(10) + "                   "+FindReplace(vResults.items(iv-1).GetItemValue("RSNOW"),"T", "   ")
Next
End If
Dim m_item As NotesItem
Set m_item=doc.GetFirstItem("ApplyListID")
If Not m_item  Is Nothing Then
Forall x In m_item.Values
If Len(Ucase(Cstr(x))) > 0 Then
url1$=url$+Ucase(Cstr(x))+url2$
html = internet.GetHTTP(url1$)
Set vResults = jsonReader.Parse(html) 'this is a JSONObject
If  vResults.Count > 0 Then
PunchTime = PunchTime +Chr(13) + Chr(10)+ vResults.items(0).GetItemValue("RSENO") + vResults.items(0).GetItemValue("BPNME")
For iV = 1 To  vResults.Count
PunchTime = PunchTime +Chr(13) + Chr(10)+ "                   "+FindReplace(vResults.items(iv-1).GetItemValue("RSNOW") , "T", "   ")
Next
End If
End If
End Forall
End If
Call Source.FieldSetText("PunchCards",PunchTime)
End If
End Sub

WebAPI Help

http://10.100.2.1:8080/API/Employees/ID/DATE1/DATE2

ID: 卡號 (EX:K1116)
DATE1 :日期 (EX:20140101)
DATE 2:日期 (EX:20140131)


傳回json範例

[{"RSENO":"K1116","RSTME":"07:53","RSDAT":"2014-04-01T00:00:00","RSNOW":"2014-04-01T07:53:00","BPNME":"Jeff","BPEML":"Jeff@adimxxne.com.tw"},{"RSENO":"K1116","RSTME":"17:24","RSDAT":"2014-04-01T00:00:00","RSNOW":"2014-04-01T17:24:00","BPNME":"Jeff","BPEML":"Jeff@adimxxne.com.tw"}

2014年2月11日 星期二

C#使用OLE來操作Lotus Notes 的 UI

1.加入lotus的參考(當然要先裝Lotus Notes Client)


2.Source Code Sample

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using lotus;
using System.Reflection;


namespace NotesOle
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Type NotesSession = Type.GetTypeFromProgID("Notes.NotesSession");
            Type NotesUIWorkspace = Type.GetTypeFromProgID("Notes.NotesUIWorkspace");
            Object sess = Activator.CreateInstance(NotesSession);
            Object ws = Activator.CreateInstance(NotesUIWorkspace);

            NotesUIWorkspace.InvokeMember("OpenDatabase", BindingFlags.InvokeMethod, null, ws, new Object[] { "NotesSrv3/Adimmune", "Record\\AgnSchedule.nsf", "MailView" });
            Object uidb = NotesUIWorkspace.InvokeMember("GetCurrentDatabase", BindingFlags.InvokeMethod, null, ws, null);

            Object db = NotesUIWorkspace.InvokeMember("Database", BindingFlags.GetProperty, null, uidb, null);
            Type NotesDatabase = db.GetType();

            Type NotesView = Type.GetTypeFromProgID("Notes.NotesView");
            Object view = NotesUIWorkspace.InvokeMember("GetView", BindingFlags.InvokeMethod, null, db, new Object[] { "MailView" });

            Object Document = NotesUIWorkspace.InvokeMember("GetFirstDocument", BindingFlags.InvokeMethod, null, view, new Object[] { });
            Object DocumentUI = NotesUIWorkspace.InvokeMember("EditDocument", BindingFlags.InvokeMethod, null, ws, new Object[] { true, Document });

            //Object uidoc = NotesUIWorkspace.InvokeMember("ComposeDocument", BindingFlags.InvokeMethod, null, ws, new Object[] { "NotesSrv3/Adimmune", "Record\\AgnSchedule.nsf", "Memo", 0, 0, true });
            //Type NotesUIDocument = uidoc.GetType();
            Type NotesUIDocument2 = Document.GetType();

            //NotesUIDocument.InvokeMember("FieldSetText", BindingFlags.InvokeMethod, null, uidoc, new Object[] { "EnterSendTo", "Test sendto" });
            //NotesUIDocument.InvokeMember("FieldSetText", BindingFlags.InvokeMethod, null, uidoc, new Object[] { "Subject", "Test subject" });
            //NotesUIDocument.InvokeMember("FieldSetText", BindingFlags.InvokeMethod, null, uidoc, new Object[] { "Body", "Test body" });

            // bring the Notes window to the front
            //String windowTitle = (String)NotesUIDocument.InvokeMember("WindowTitle", BindingFlags.GetProperty, null, uidoc, null);
            String[] TestString= (String[])NotesUIDocument2.InvokeMember("SendTO", BindingFlags.GetProperty, null, Document, null);

        }
    }
}


2014年1月13日 星期一

Calling Lotus Notes Agent From .NET (Domino 7)

今天參考 http://ithelp.ithome.com.tw/question/10109131 的做法來寫一支Winform去啟動 Notes的Agent(因為Scheduled Agent經常會罷工只好手動).

做完之後, 發現大部份Agent都無法執行RunOnServer.(報錯)

找不到原因之下,最後只好在其中一個看板寫一個簡單的啟動其他Agent之轉接Agent程式.再由C#來啟動這支轉接Agent就都OK啦!

這支轉接Agent的Code 如下
(Declarations)
Dim session As NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim view As NotesView

Dim agent As NotesAgent
Dim profile As NotesDocument
Dim currentLog As NotesLog

Sub Initialize
Dim m_item As NotesItem
Dim m_db As NotesDatabase
Dim m_agent As NotesAgent
'Dim m_col As NotesDocumentCollection
Dim m_mail As NotesDocument
Set session=New NotesSession
Set db=session.CurrentDatabase
Set agent = session.CurrentAgent
Set currentLog = New NotesLog( db.Title+" - Agent - "+agent.Name+" on "+db.Server )
Set profile=db.GetProfileDocument("SystemProfile")
Call currentLog.OpenNotesLog( db.Server, profile.LogPath(0) )
Call currentLog.LogAction("代理程式執行檢查 : "+agent.Name)
Set m_db=session.GetDatabase(db.Server,"Flow\CheckFlow.nsf",False)
If Not m_db Is Nothing Then
Call currentLog.LogAction("取得資料庫 : "+m_db.Title)
Set m_agent =m_db.GetAgent("GetSapDataAgent")
If Not m_agent Is Nothing Then
m_find=True
Print "Run Agent : "+m_agent.Name
Call currentLog.LogAction("開始執行代理程式 : "+m_agent.Name)
If m_agent.RunOnServer=0 Then
m_runOk=True
Call currentLog.LogAction("完成執行代理程式 : "+m_agent.Name)
Else
Call currentLog.LogError(1,"代理程式執行錯誤!!")
End If
Else
Call currentLog.LogError(1,"無法取得代理程式,代理程式執行錯誤!!")
End If
Else
Call currentLog.LogError(1,"無法取得資料庫,代理程式執行錯誤!!")
End If
currentLog.LogAction("代理程式結束作業完成!!")
Call currentLog.Close
End Sub