Example #1
0
        SessionInfo GetTempSessionInfo()
        {
            if (this.m_tempSessionInfo != null)
                return this.m_tempSessionInfo;

            // 临时的SessionInfo对象
            SessionInfo sessioninfo = new SessionInfo(this.App);

            // 模拟一个账户
            Account account = new Account();
            account.LoginName = "replication";
            account.Password = "";
            account.Rights = "setreaderinfo,devolvereaderinfo";

            account.Type = "";
            account.Barcode = "";
            account.Name = "replication";
            account.UserID = "replication";
            account.RmsUserName = this.App.ManagerUserName;
            account.RmsPassword = this.App.ManagerPassword;

            sessioninfo.Account = account;

            this.m_tempSessionInfo = sessioninfo;

            return sessioninfo;
        }
Example #2
0
        // TODO: 各个环节要改为尽量使用 refID。要做大量测试
        // text-level: 内部处理
        // 在 预约到书 库中,追加一条新的记录,并作 email / dpmail / mq 通知
        // 注:本函数可能要删除部分通知记录
        // parameters:
        //      strItemBarcode  册条码号。必须是册条码号。如果册条码号为空,参考ID需要使用 strRefID 参数
        //      strRefID        参考ID
        //      bOnShelf    要通知的册是否在架。在架指并没有人借阅过,本来就在书架上。
        //      strLibraryCode  读者所在的馆代码
        //      strReaderXml    预约了图书的读者的XML记录。用于消息通知接口
        int AddNotifyRecordToQueueDatabase(
            // RmsChannelCollection channels,
            RmsChannel channel,
            string strItemBarcodeParam,
            string strRefIDParam,
            string strItemXml,
            bool bOnShelf,
            string strLibraryCode,
            string strReaderBarcode,
            string strReaderXml,
            out List<string> DeletedNotifyRecPaths,
            out string strError)
        {
            strError = "";
            DeletedNotifyRecPaths = new List<string>();

            // 2010/12/31
            if (String.IsNullOrEmpty(this.ArrivedDbName) == true)
            {
                strError = "预约到书库尚未定义, AddNotifyRecordToQueue()调用失败";
                return -1;
            }

            // 准备写记录
            byte[] timestamp = null;
            byte[] output_timestamp = null;
            string strOutputPath = "";
            int nRet = 0;
            long lRet = 0;

            if (String.IsNullOrEmpty(strItemBarcodeParam) == true)
            {
                // 如果检索用的册条码号为空,加上对命中结果数量不设限,那就会造成系统严重繁忙。
                strError = "参数strItemBarcode中的册条码号不能为空。";
                return -1;
            }

#if NO
            RmsChannel channel = channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }
#endif

        REDODELETE:
            // 如果队列中已经存在同册条码号的记录, 要先删除
            string strNotifyXml = "";
            // 获得预约到书队列记录
            // return:
            //      -1  error
            //      0   not found
            //      1   命中1条
            //      >1  命中多于1条
            nRet = GetArrivedQueueRecXml(
                // channels,
                channel,
                strItemBarcodeParam,
                out strNotifyXml,
                out timestamp,
                out strOutputPath,
                out strError);
            if (nRet == -1)
            {
                // 写入错误日志?
                this.WriteErrorLog("在还书操作中,检索册条码号为 " + strItemBarcodeParam + " 的预约到书库记录时出错: " + strError);
            }
            if (nRet >= 1)
            {
                int nRedoDeleteCount = 0;
            // TODO: 这一段删除代码可以专门编制在一个函数中,不必这么费力循环。可以优化处理
            REDO_DELETE:
                lRet = channel.DoDeleteRes(strOutputPath,
                    timestamp,
                    out output_timestamp,
                    out strError);
                if (lRet == -1)
                {
                    // 时间戳不匹配
                    if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch
                        && nRedoDeleteCount < 10)
                    {
                        nRedoDeleteCount++;
                        timestamp = output_timestamp;
                        goto REDO_DELETE;
                    }

                    // 写入错误日志?
                    this.WriteErrorLog("在还书操作中,加入新预约到书记录前, 删除已存在的预约到书库记录 '" + strOutputPath + "' 出错: " + strError);
                }

                DeletedNotifyRecPaths.Add(strOutputPath);    // 记忆已经被删除的记录路径 2007/7/5 

                goto REDODELETE;    // 如果有多条,循环删除
            }

            XmlDocument itemdom = null;
            nRet = LibraryApplication.LoadToDom(strItemXml,
                out itemdom,
                out strError);
            if (nRet == -1)
            {
                strError = "装载册记录 '" + strItemBarcodeParam + "' 的 XML 进入 DOM 时发生错误: " + strError;
                return -1;
            }

            string strLocation = DomUtil.GetElementText(itemdom.DocumentElement, "location");
            strLocation = StringUtil.GetPureLocationString(strLocation);

            string strAccessNo = DomUtil.GetElementText(itemdom.DocumentElement, "accessNo");

            /*
  <reservations>
        <request reader="R0000001" requestDate="Mon, 05 Sep 2016 16:57:47 +0800" operator="R0000001" /> 
  </reservations>
             * */
            // 从册记录 reservations 元素下找第一个 request 元素,其 requestDate 属性
            string strRequestDate = "";
            XmlElement request = itemdom.DocumentElement.SelectSingleNode("reservations/request") as XmlElement;
            if (request != null)
                strRequestDate = request.GetAttribute("requestDate");

            // 创建预约到书记录
            XmlDocument new_queue_dom = new XmlDocument();
            new_queue_dom.LoadXml("<root />");

            // TODO: 以后增加 <refID> 元素,存储册记录的参考ID

#if NO
            XmlNode nodeItemBarcode = DomUtil.SetElementText(dom.DocumentElement, "itemBarcode", strItemBarcode);

            // 在<itemBarcode>元素中增加一个onShelf属性,表示属于在架情况
            Debug.Assert(nodeItemBarcode != null, "");
            if (bOnShelf == true)
                DomUtil.SetAttr(nodeItemBarcode, "onShelf", "true");
#endif
            string strItemRefID = "";   // 计划存储纯粹的 refid
            string strItemBarcode = strItemBarcodeParam;    // 计划存储纯粹的册条码号

            // 兼容 strItemBarcode 中含有前缀的用法
            string strHead = "@refID:";
            if (StringUtil.HasHead(strItemBarcodeParam, strHead, true) == true)
            {
                strItemRefID = strItemBarcodeParam.Substring(strHead.Length);
                strItemBarcode = "";
            }

            string strUnionItemBarcode = GetUnionBarcode(strItemBarcode, strItemRefID);

            if (this.ArrivedDbKeysContainsRefIDKey() == true)
            {
                DomUtil.SetElementText(new_queue_dom.DocumentElement, "itemBarcode", strItemBarcode);
                DomUtil.SetElementText(new_queue_dom.DocumentElement, "refID", strItemRefID);
            }
            else
            {
                if (string.IsNullOrEmpty(strItemBarcode) == true)
                {
                    if (string.IsNullOrEmpty(strItemRefID) == true)
                    {
                        strError = "AddNotifyRecordToQueue() 函数当 strItemBarcode 参数为空的时候,必须让 strRefID 参数不为空";
                        return -1;
                    }

                    Debug.Assert(string.IsNullOrEmpty(strItemRefID) == false, "");
                    // 旧的用法。避免检索时候查不到
                    DomUtil.SetElementText(new_queue_dom.DocumentElement, "itemBarcode", "@refID:" + strItemRefID);
                }
                else
                    DomUtil.SetElementText(new_queue_dom.DocumentElement, "itemBarcode", strItemBarcode); // 2015/5/20 添加,修正 BUG
            }

            // 改为存储在元素中 2015/5/7
            if (bOnShelf == true)
                DomUtil.SetElementText(new_queue_dom.DocumentElement, "onShelf", "true");

            // 2012/10/26
            DomUtil.SetElementText(new_queue_dom.DocumentElement, "libraryCode", strLibraryCode);

            DomUtil.SetElementText(new_queue_dom.DocumentElement, "readerBarcode", strReaderBarcode);
            DomUtil.SetElementText(new_queue_dom.DocumentElement, "notifyDate", this.Clock.GetClock());

            // 2015/6/13
            DomUtil.SetElementText(new_queue_dom.DocumentElement, "location", strLocation);

            string strPath = this.ArrivedDbName + "/?";

            // 写新记录
            lRet = channel.DoSaveTextRes(
                strPath,
                new_queue_dom.OuterXml,
                false,
                "content,ignorechecktimestamp",
                timestamp,
                out output_timestamp,
                out strOutputPath,
                out strError);
            if (lRet == -1)
            {
                // 写入错误日志 2007/1/3 
                this.WriteErrorLog("创建新的预约到书队列记录时出错: " + strError);
                return -1;
            }

            string strReaderEmailAddress = "";
            string strName = "";
            nRet = GetReaderNotifyInfo(
                strReaderXml,
                out strName,
                out strReaderEmailAddress,
                out strError);
            if (nRet == -1)
                return -1;

            // 获得图书摘要信息
            string strSummary = "";     // 没有被截断的摘要字符串
            string strShortSummary = "";    // 截断后的摘要字符串
            string strBiblioRecPath = "";

            nRet = this.GetBiblioSummary(strUnionItemBarcode,
                "", //  strConfirmItemRecPath,
                null,   //  strBiblioRecPathExclude,
                -1, // 25,
                out strBiblioRecPath,
                out strSummary,
                out strError);
            if (nRet == -1)
            {
                strSummary = "ERROR: " + strError;
            }
            else
            {
                strShortSummary = LibraryApplication.CutSummary(strSummary, 25);
            }

#if NO
            // 临时的SessionInfo对象
            SessionInfo sessioninfo = new SessionInfo(this);
            // 模拟一个账户
            Account account = new Account();
            account.LoginName = "CacheBuilder";
            account.Password = "";
            account.Rights = "getbibliosummary";

            account.Type = "";
            account.Barcode = "";
            account.Name = "AddNotifyRecordToQueue";
            account.UserID = "AddNotifyRecordToQueue";
            account.RmsUserName = this.ManagerUserName;
            account.RmsPassword = this.ManagerPassword;

            sessioninfo.Account = account;
            try
            {

                string strBiblioRecPath = "";
                LibraryServerResult result = this.GetBiblioSummary(
                    sessioninfo,
                    strItemBarcode,
                    "", // strConfirmItemRecPath,
                    null,
                    out strBiblioRecPath,
                    out strSummary);
                if (result.Value == -1)
                {
                    strSummary = "ERROR: " + result.ErrorInfo;
                }
                else
                {
                    // 截断
                    if (strSummary.Length > 25)
                        strSummary = strSummary.Substring(0, 25) + "...";
                }
            }
            finally
            {
                sessioninfo.Close();
                sessioninfo = null;
            }
#endif

            // 发送短消息通知
            string strTotalError = "";

            // *** dpmail
            if (this.MessageCenter != null
                && StringUtil.IsInList("dpmail", this.ArrivedNotifyTypes))
            {
                string strTemplate = "";
                // 获得邮件模板
                nRet = GetMailTemplate(
                    "dpmail",
                    bOnShelf == false ? "预约到书通知" : "预约到书通知(在架)",
                    out strTemplate,
                    out strError);
                if (nRet == -1)
                    return -1;
                if (nRet == 0)
                {
                    strError = "预约到书通知<mailTemplate/template>尚未配置。";
                    return -1;
                }

                /*
                %item%  册信息
                %reservetime%   保留期限
                %today% 发出email的当天
                %summary% 书目摘要
                %itembarcode% 册条码号 
                %name% 读者姓名
                 * */
                Hashtable table = new Hashtable();
                table["%item%"] = "(册条码号为: " + strUnionItemBarcode + " URL为: " + this.OpacServerUrl + "/book.aspx?barcode=" + strUnionItemBarcode + " )";
                table["%reservetime%"] = this.GetDisplayTimePeriodStringEx(this.ArrivedReserveTimeSpan);
                table["%today%"] = DateTime.Now.ToString();
                table["%summary%"] = strShortSummary;
                table["%itembarcode%"] = strUnionItemBarcode;
                table["%name%"] = strName;
                string strBody = "";

                nRet = GetMailText(strTemplate,
                    table,
                    out strBody,
                    out strError);
                if (nRet == -1)
                    return -1;

                if (String.IsNullOrEmpty(this.MessageCenter.MessageDbName) == false)
                {
                    Debug.Assert(channel.Container != null, "");
                    // 发送消息
                    nRet = this.MessageCenter.SendMessage(
                        channel.Container,  // channels,
                        strReaderBarcode,
                        "图书馆",
                        "预约到书通知",
                        "text",
                        strBody,
                        false,
                        out strError);
                    if (nRet == -1)
                    {
                        strTotalError += "发送dpmail消息时出错: " + strError + "\r\n";
                    }
                }
            }

            // 2016/4/26
            // *** mq
            if (string.IsNullOrEmpty(this.OutgoingQueue) == false
                && StringUtil.IsInList("mq", this.ArrivedNotifyTypes))
            {
                XmlDocument dom = new XmlDocument();
                dom.LoadXml("<root />");

                /* 元素名
                 * type 消息类型。预约到书通知
                 * itemBarcode 册条码号
                 * location 馆藏地 2016/9/5
                 * refID    册的参考 ID
                 * onShelf 是否在架。true/false
                 * opacURL  图书在 OPAC 中的 URL。相对路径
                 * requestDate 预约请求创建时间 2016/9/5
                 * reserveTime 保留的时间
                 * today 今天的日期
                 * summary 书目摘要
                 * patronName   读者姓名
                 * patronRecord 读者 XML 记录
 * */
                DomUtil.SetElementText(dom.DocumentElement, "type", "预约到书通知");

                DomUtil.SetElementText(dom.DocumentElement,
                    "itemBarcode", strItemBarcode);
                DomUtil.SetElementText(dom.DocumentElement,
                    "location", strLocation);
                // 2016/11/15
                DomUtil.SetElementText(dom.DocumentElement,
                    "accessNo", strAccessNo);

                // 2016/9/5
                if (string.IsNullOrEmpty(strItemRefID))
                    strItemRefID = DomUtil.GetElementText(itemdom.DocumentElement, "refID");

                DomUtil.SetElementText(dom.DocumentElement,
                    "refID", strItemRefID);
                DomUtil.SetElementText(dom.DocumentElement,
                    "onShelf", bOnShelf ? "true" : "false");

                DomUtil.SetElementText(dom.DocumentElement,
                    "opacURL", this.OpacServerUrl + "/book.aspx?barcode="
                    + strUnionItemBarcode);
                DomUtil.SetElementText(dom.DocumentElement,
                    "requestDate", strRequestDate);
                DomUtil.SetElementText(dom.DocumentElement,
                    "reserveTime", this.GetDisplayTimePeriodStringEx(this.ArrivedReserveTimeSpan));
                DomUtil.SetElementText(dom.DocumentElement,
                    "today", DateTime.Now.ToString());
                DomUtil.SetElementText(dom.DocumentElement,
                    "summary", strSummary);
                DomUtil.SetElementText(dom.DocumentElement,
                    "patronName", strName);

                string strReaderRefID = "";
                {
                    XmlDocument readerdom = new XmlDocument();
                    readerdom.LoadXml(strReaderXml);

                    strReaderRefID = DomUtil.GetElementText(readerdom.DocumentElement, "refID");

                    XmlElement record = dom.CreateElement("patronRecord");
                    dom.DocumentElement.AppendChild(record);
                    record.InnerXml = readerdom.DocumentElement.InnerXml;

                    DomUtil.DeleteElement(record, "borrowHistory");
                    DomUtil.DeleteElement(record, "password");
                    DomUtil.DeleteElement(record, "fingerprint");
                    DomUtil.SetElementText(record, "libraryCode", strLibraryCode);
                }

                try
                {
                    MessageQueue queue = new MessageQueue(this.OutgoingQueue);

                    // 向 MSMQ 消息队列发送消息
                    nRet = ReadersMonitor.SendToQueue(queue,
                        (string.IsNullOrEmpty(strReaderRefID) ? strReaderBarcode : "!refID:" + strReaderRefID)
                        + "@LUID:" + this.UID,
                        "xml",
                        dom.DocumentElement.OuterXml,
                        out strError);
                    if (nRet == -1)
                    {
                        strTotalError += "发送 MQ 消息时出错: " + strError + "\r\n";
                    }
                }
                catch (Exception ex)
                {
                    strTotalError += "创建路径为 '" + this.OutgoingQueue + "' 的 MessageQueue 对象失败: " + ExceptionUtil.GetDebugText(ex);
                }
            }

            // ** email
            if (String.IsNullOrEmpty(strReaderEmailAddress) == false
                && StringUtil.IsInList("email", this.ArrivedNotifyTypes))
            {
                string strTemplate = "";
                // 获得邮件模板
                nRet = GetMailTemplate(
                    "email",
                    bOnShelf == false ? "预约到书通知" : "预约到书通知(在架)",
                    out strTemplate,
                    out strError);
                if (nRet == -1)
                    return -1;
                if (nRet == 0)
                {
                    strError = "预约到书通知<mailTemplate/template>尚未配置。";
                    return -1;
                }

                /*
                %item%  册信息
                %reservetime%   保留期限
                %today% 发出email的当天
                %summary% 书目摘要
                %itembarcode% 册条码号 
                %name% 读者姓名
                 * */
                Hashtable table = new Hashtable();
                table["%item%"] = "(册条码号为: " + strUnionItemBarcode + " URL为: " + this.OpacServerUrl + "/book.aspx?barcode=" + strUnionItemBarcode + " )";
                table["%reservetime%"] = this.GetDisplayTimePeriodStringEx(this.ArrivedReserveTimeSpan);
                table["%today%"] = DateTime.Now.ToString();
                table["%summary%"] = strShortSummary;
                table["%itembarcode%"] = strUnionItemBarcode;
                table["%name%"] = strName;

                string strBody = "";

                nRet = GetMailText(strTemplate,
                    table,
                    out strBody,
                    out strError);
                if (nRet == -1)
                    return -1;

                {
                    // 发送email
                    // return:
                    //      -1  error
                    //      0   not found smtp server cfg
                    //      1   succeed
                    nRet = SendEmail(strReaderEmailAddress,
                        "预约到书通知",
                        strBody,
                        "text",
                        out strError);
                    if (nRet == -1)
                    {
                        strTotalError += "发送email消息时出错: " + strError + "\r\n";
                    }
                }
            }

            // *** external messageinterfaces
            if (this.m_externalMessageInterfaces != null)
            {
                foreach (MessageInterface message_interface in this.m_externalMessageInterfaces)
                {
                    // types
                    if (StringUtil.IsInList(message_interface.Type, this.ArrivedNotifyTypes) == false)
                        continue;

                    string strTemplate = "";
                    // 获得邮件模板
                    nRet = GetMailTemplate(
                        message_interface.Type,
                        bOnShelf == false ? "预约到书通知" : "预约到书通知(在架)",
                        out strTemplate,
                        out strError);
                    if (nRet == -1)
                        return -1;
                    if (nRet == 0)
                    {
                        strError = "预约到书通知<mailTemplate/template>尚未配置。";
                        return -1;
                    }

                    /*
                    %item%  册信息
                    %reservetime%   保留期限
                    %today% 发出email的当天
                %summary% 书目摘要
                %itembarcode% 册条码号 
                %name% 读者姓名
                     * */
                    Hashtable table = new Hashtable();
                    table["%item%"] = "(册条码号为: " + strUnionItemBarcode + " URL为: " + this.OpacServerUrl + "/book.aspx?barcode=" + strUnionItemBarcode + " )";
                    table["%reservetime%"] = this.GetDisplayTimePeriodStringEx(this.ArrivedReserveTimeSpan);
                    table["%today%"] = DateTime.Now.ToString();
                    table["%summary%"] = strShortSummary;
                    table["%itembarcode%"] = strUnionItemBarcode;
                    table["%name%"] = strName;

                    string strBody = "";

                    nRet = GetMailText(strTemplate,
                        table,
                        out strBody,
                        out strError);
                    if (nRet == -1)
                        return -1;

                    // 发送消息
                    nRet = message_interface.HostObj.SendMessage(
                        strReaderBarcode,
                        strReaderXml,
                        strBody,
                        strLibraryCode,
                        out strError);
                    if (nRet == -1)
                    {
                        strTotalError += "发送" + message_interface.Type + "消息时出错: " + strError + "\r\n";
                    }
                }
            }

            if (String.IsNullOrEmpty(strTotalError) == false)
            {
                strError = strTotalError;
                return -1;
            }

            return 0;
        }
Example #3
0
        // 将更新卡户信息完整表(AccountsCompleteInfo_yyyymmdd.xml)写入读者库
        // return:
        //      -1  error
        //      0   succeed
        //      1   中断
        int WriteToReaderDb(string strLocalFilePath,
            out string strError)
        {
            strError = "";
            int nRet = 0;

            XmlNode node = this.App.LibraryCfgDom.DocumentElement.SelectSingleNode("//zhengyuan/replication");

            if (node == null)
            {
                strError = "尚未配置<zhangyuan><replication>参数";
                return -1;
            }

            string strMapDbName = DomUtil.GetAttr(node, "mapDbName");
            if (String.IsNullOrEmpty(strMapDbName) == true)
            {
                strError = "尚未配置<zhangyuan/replication>元素的mapDbName属性";
                return -1;
            }

            Stream file = File.Open(strLocalFilePath,
                FileMode.Open,
                FileAccess.Read);

            if (file.Length == 0)
                return 0;

            try
            {

                XmlTextReader reader = new XmlTextReader(file);

                bool bRet = false;

                // 临时的SessionInfo对象
                SessionInfo sessioninfo = new SessionInfo(this.App);

                // 模拟一个账户
                Account account = new Account();
                account.LoginName = "replication";
                account.Password = "";
                account.Rights = "setreaderinfo";

                account.Type = "";
                account.Barcode = "";
                account.Name = "replication";
                account.UserID = "replication";
                account.RmsUserName = this.App.ManagerUserName;
                account.RmsPassword = this.App.ManagerPassword;

                sessioninfo.Account = account;

                // 找到根
                while (true)
                {
                    try
                    {
                        bRet = reader.Read();
                    }
                    catch (Exception ex)
                    {
                        strError = "读XML文件发生错误: " + ex.Message;
                        return -1;
                    }

                    if (bRet == false)
                    {
                        strError = "没有根元素";
                        return -1;
                    }
                    if (reader.NodeType == XmlNodeType.Element)
                        break;
                }

                for (int i = 0; ; i++)
                {
                    if (this.Stopped == true)
                        return 1;


                    bool bEnd = false;
                    // 第二级元素
                    while (true)
                    {
                        bRet = reader.Read();
                        if (bRet == false)
                        {
                            bEnd = true;  // 结束
                            break;
                        }
                        if (reader.NodeType == XmlNodeType.Element)
                            break;
                    }

                    if (bEnd == true)
                        break;

                    this.AppendResultText("处理 " + (i + 1).ToString() + "\r\n");

                    // 记录体
                    string strXml = reader.ReadOuterXml();

                    // return:
                    //      -1  error
                    //      0   已经写入
                    //      1   没有必要写入
                    nRet = WriteOneReaderInfo(
                        sessioninfo,
                        strMapDbName,
                        strXml,
                        out strError);
                    if (nRet == -1)
                        return -1;

                }

                return 0;
            }
            finally
            {
                file.Close();
            }
        }
Example #4
0
        // 执行脚本函数ItemCanReturn
        // parameters:
        // return:
        //      -2  not found script
        //      -1  出错
        //      0   成功
        public int DoItemCanReturnScriptFunction(
            Account account,
            XmlDocument itemdom,
            out bool bResultValue,
            out string strMessage,
            out string strError)
        {
            strError = "";
            strMessage = "";
            bResultValue = false;

            if (this.m_strAssemblyLibraryHostError != "")
            {
                strError = this.m_strAssemblyLibraryHostError;
                return -1;
            }

            if (this.m_assemblyLibraryHost == null)
            {
                strError = "未定义<script>脚本代码,无法执行脚本函数ItemCanReturn()。";
                return -2;
            }

            Type hostEntryClassType = ScriptManager.GetDerivedClassType(
                this.m_assemblyLibraryHost,
                "DigitalPlatform.LibraryServer.LibraryHost");
            if (hostEntryClassType == null)
            {
                strError = "<script>脚本中未找到DigitalPlatform.LibraryServer.LibraryHost类的派生类,无法执行脚本函数ItemCanReturn()。";
                return -2;
            }

            // 迟绑定技术。从assembly中实时寻找特定名字的函数
            MethodInfo mi = hostEntryClassType.GetMethod("ItemCanReturn");
            if (mi == null)
            {
                strError = "<script>脚本中DigitalPlatform.LibraryServer.LibraryHost类的派生类中,没有提供public bool ItemCanReturn(Account account, XmlDocument itemdom, out string strMessageText)函数,因此无法获得可借状态。";
                return -2;
            }

            LibraryHost host = (LibraryHost)hostEntryClassType.InvokeMember(null,
                BindingFlags.DeclaredOnly |
                BindingFlags.Public | BindingFlags.NonPublic |
                BindingFlags.Instance | BindingFlags.CreateInstance, null, null,
                null);
            if (host == null)
            {
                strError = "创建DigitalPlatform.LibraryServer.LibraryHost类的派生类的对象(构造函数)失败。";
                return -1;
            }

            host.App = this;

            // 执行函数
            try
            {
                object[] args = new object[3];
                args[0] = account;
                args[1] = itemdom;
                args[2] = strMessage;
                bResultValue = (bool)mi.Invoke(host,
                     BindingFlags.DeclaredOnly |
                     BindingFlags.Public | BindingFlags.NonPublic |
                     BindingFlags.Instance | BindingFlags.InvokeMethod,
                     null,
                     args,
                     null);

                // 取出out参数值
                strMessage = (string)args[2];
            }
            catch (Exception ex)
            {
                strError = "执行脚本函数'" + "ItemCanReturn" + "'出错:" + ExceptionUtil.GetDebugText(ex);
                return -1;
            }

            return 0;
        }
Example #5
0
        // 获得图书摘要信息
        // 调用时不需要SessionInfo
        public int GetBiblioSummary(string strItemBarcode,
            string strConfirmItemRecPath,
            string strBiblioRecPathExclude,
            int nMaxLength,
            out string strBiblioRecPath,
            out string strSummary,
            out string strError)
        {
            strError = "";
            strSummary = "";
            strBiblioRecPath = "";

            // 临时的SessionInfo对象
            SessionInfo sessioninfo = new SessionInfo(this);
            // 模拟一个账户
            Account account = new Account();
            account.LoginName = "内部调用";
            account.Password = "";
            account.Rights = "getbibliosummary";

            account.Type = "";
            account.Barcode = "";
            account.Name = "内部调用";
            account.UserID = "内部调用";
            account.RmsUserName = this.ManagerUserName;
            account.RmsPassword = this.ManagerPassword;

            sessioninfo.Account = account;
            try
            {
                RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl);
                if (channel == null)
                {
                    strError = "get channel error";
                    return -1;
                }

                LibraryServerResult result = this.GetBiblioSummary(
                    sessioninfo,
                    channel,
                    strItemBarcode,
                    strConfirmItemRecPath,
                    strBiblioRecPathExclude,
                    out strBiblioRecPath,
                    out strSummary);
                if (result.Value == -1)
                {
                    strError = result.ErrorInfo;
                    return -1;
                }
                else
                {
                    if (nMaxLength != -1)
                    {
                        // 截断
                        if (strSummary.Length > nMaxLength)
                            strSummary = strSummary.Substring(0, nMaxLength) + "...";
                    }
                }
            }
            finally
            {
                sessioninfo.CloseSession();
                sessioninfo = null;
            }

            return 0;
        }
Example #6
0
        // 从library.xml文件定义 获得一个帐户的信息
        // TODO: 多文种提示
        // return:
        //      -1  error
        //      0   not found
        //      1   found
        public int GetAccount(string strUserID,
            out Account account,
            out string strError)
        {
            strError = "";
            account = null;

            // 2015/9/9
            if (this.LibraryCfgDom == null || LibraryCfgDom.DocumentElement == null)
            {
                strError = "LibraryCfgDom 尚未初始化。请检查 dp2library 错误日志";
                return -1;
            }

            XmlNode root = this.LibraryCfgDom.DocumentElement.SelectSingleNode("accounts");
            if (root == null)
            {
                strError = "<accounts>元素尚未配置...";
                return -1;
            }

            XmlElement node = root.SelectSingleNode("account[@name='" + strUserID + "']") as XmlElement;
            if (node == null)
            {
                strError = "用户 '" + strUserID + "' 不存在";
                return 0;
            }

            account = new Account();
            account.XmlNode = node;
            account.LoginName = node.GetAttribute("name");
            account.UserID = node.GetAttribute("name");

            string strText = "";
            try
            {
                strText = node.GetAttribute("password");
                if (String.IsNullOrEmpty(strText) == true)
                    account.Password = "";
                else
                {
#if NO
                    // 以前的做法,取出密码明文
                    account.Password = Cryptography.Decrypt(
                                strText,
                                EncryptKey);
#endif
                    // 现在的做法,取出密码的 hashed 字符串
                    account.Password = strText;
                }
            }
            catch
            {
                strError = "用户名为 '" + strUserID + "' 的<account> password参数值错误";
                return -1;
            }
            account.Type = DomUtil.GetAttr(node, "type");
            account.Rights = DomUtil.GetAttr(node, "rights");
            account.AccountLibraryCode = DomUtil.GetAttr(node, "libraryCode");

            account.Access = DomUtil.GetAttr(node, "access");
            account.RmsUserName = DomUtil.GetAttr(node, "rmsUserName");

            // 2016/10/26
            account.Binding = node.GetAttribute("binding");

            try
            {
                strText = DomUtil.GetAttr(node, "rmsPassword");
                if (String.IsNullOrEmpty(strText) == true)
                    account.RmsPassword = "";
                else
                {
                    account.RmsPassword = Cryptography.Decrypt(
                              strText,
                              EncryptKey);
                }
            }
            catch
            {
                strError = "用户名为 '" + strUserID + "' 的<account> rmsPassword参数值错误";
                return -1;
            }

            return 1;
        }
Example #7
0
        // 公共查询读者登录
        // text-level: 用户提示
        // parameters:
        //      strLoginName 登录名
        //          1) 如果以"NB:"开头,表示利用姓名生日进行检索。姓名和生日之间间隔以'|'。姓名必须完整,生日为8字符形式
        //          2) 如果以"EM:"开头,表示利用email地址进行检索
        //          3) 如果以"TP:"开头,表示利用电话号码进行检索
        //          4) 否则用证条码号进行检索
        //      strPassword 密码。如果为null,表示不进行密码判断。注意,不是""
        //              还可以为 token: 形态
        //      nIndex  如果有多个匹配的读者记录,此参数表示要选择其中哪一个。
        //              如果为-1,表示首次调用此函数,还不知如何选择。如此时命中多个,函数会返回>1的值
        //      strGetToken 是否要获得 token ,和有效期。 空 / day / month / year
        //      alter_type_list 已经实施的绑定验证类型和尚未实施的类型列表
        //      strOutputUserName   返回读者证条码号
        // return:
        //      -1  error
        //      0   登录未成功
        //      1   登录成功
        //      >1  有多个账户符合条件。
        public int LoginForReader(SessionInfo sessioninfo,
            string strLoginName,
            string strPassword,
            string strLocation,
            string strLibraryCodeList,
            int nIndex,
            string strGetToken,
            out List<string> alter_type_list,
            out string strOutputUserName,
            out string strRights,
            out string strLibraryCode,
            out string strError)
        {
            strError = "";
            // 读者身份登录
            string strXml = "";
            string strOutputPath = "";
            byte[] timestamp = null;
            strRights = "";
            strOutputUserName = "";
            strLibraryCode = "";
            alter_type_list = new List<string>();

            // 2009/9/22 
            if (String.IsNullOrEmpty(strLoginName) == true)
            {
                strError = "参数 strLoginName 不能为空";
                return -1;
            }

            if (this.LoginCache != null)
            {
                Account temp_account = this.LoginCache.Get(strLoginName) as Account;
                if (temp_account != null)
                {
                    if (strPassword != null)    // 2014/12/20
                    {
                        if (temp_account.Password != strPassword)
                        {
                            bool bIsToken1 = StringUtil.HasHead(strPassword, "token:");
                            bool bIsToken2 = StringUtil.HasHead(temp_account.Password, "token:");

                            if (bIsToken1 == bIsToken2)
                            {
                                // text-level: 用户提示
                                strError = this.GetString("帐户不存在或密码不正确");    // "帐户不存在或密码不正确"
                                return -1;
                            }
                            else
                                goto DO_LOGIN;  // 继续作普通登录
                        }
                    }

                    sessioninfo.Account = temp_account;

                    strRights = temp_account.RightsOrigin;
                    strOutputUserName = temp_account.UserID;
                    strLibraryCode = temp_account.AccountLibraryCode;   // 2016/1/17
                    return 1;
                }
            }

        DO_LOGIN:

            bool bTempPassword = false;
            string strToken = "";

            RmsChannel channel = sessioninfo.Channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

            // 获得读者记录, 并检查密码是否符合。为登录用途
            // 该函数的特殊性在于,它可以用多种检索入口,而不仅仅是条码号
            // parameters:
            //      strQueryWord 登录名
            //          1) 如果以"NB:"开头,表示利用姓名生日进行检索。姓名和生日之间间隔以'|'。姓名必须完整,生日为8字符形式
            //          2) 如果以"EM:"开头,表示利用email地址进行检索
            //          3) 如果以"TP:"开头,表示利用电话号码进行检索
            //          4) 如果以"ID:"开头,表示利用身份证号进行检索
            //          5) 如果以"CN:"开头,表示利用证件号码进行检索
            //          6) 否则用证条码号进行检索
            //      strPassword 密码。如果为null,表示不进行密码判断。注意,不是""
            // return:
            //      -2  当前没有配置任何读者库,或者可以操作的读者库
            //      -1  error
            //      0   not found
            //      1   命中1条
            //      >1  命中多于1条
            int nRet = this.GetReaderRecXmlForLogin(
                // sessioninfo.Channels,
                channel,
                strLibraryCodeList,
                strLoginName,
                strPassword,
                nIndex,
                sessioninfo.ClientIP,
                strGetToken,
                out bTempPassword,
                out strXml,
                out strOutputPath,
                out timestamp,
                out strToken,
                out strError);
            if (nRet == -1 || nRet == -2)
            {
                // text-level: 用户提示
                strError = string.Format(this.GetString("以登录名s登录时, 检索读者帐户记录出错s"),  // "以登录名 '{0}' 登录时, 检索读者帐户记录出错: {1}";
                    strLoginName,
                    strError);

                // "以登录名 '" + strLoginName + "' 登录时, 检索读者帐户记录出错: " + strError;
                return -1;
            }

            if (nRet == 0)
            {
                // text-level: 用户提示
                strError = this.GetString("帐户不存在或密码不正确");    // "帐户不存在或密码不正确"
                return 0;   // 2015/12/4 注:这里不应返回 -1。因为返回 -1,会导致调主不去判断探测密码攻击
            }

            if (nRet > 1)
            {
                // 若未加以选择
                if (nIndex == -1)
                {
                    // text-level: 用户提示
                    strError = string.Format(this.GetString("以登录名s登录时, 因所匹配的帐户多于一个,无法登录"),  // "以登录名 '{0}' 登录时, 因所匹配的帐户多于一个,无法登录。可用证条码号作为登录名重新进行登录。"
                        strLoginName);
                    // "以登录名 '" + strLoginName + "' 登录时, 因所匹配的帐户多于一个,无法登录。可用证条码号作为登录名重新进行登录。";
                    return nRet;
                }
            }

            XmlDocument readerdom = null;
            nRet = LibraryApplication.LoadToDom(strXml,
                out readerdom,
                out strError);
            if (nRet == -1)
            {
                strError = "装载读者记录进入 XML DOM 时发生错误: " + strError;
                return -1;
            }

            // 检查 access 元素里面的星号
            string strAccess = DomUtil.GetElementText(readerdom.DocumentElement, "access");
            if (strAccess != null && strAccess.Trim() == "*")
            {
                strError = "读者记录中的存取定义(access 元素值)不允许使用 * 形态";
                return -1;
            }

            // 获得一个参考帐户
            Account accountref = null;
            // 从library.xml文件定义 获得一个帐户的信息
            // return:
            //      -1  error
            //      0   not found
            //      1   found
            nRet = GetAccount("reader",
                out accountref,
                out strError);
            if (nRet == -1)
            {
                // text-level: 用户提示
                strError = string.Format(this.GetString("获得reader参考帐户时出错s"),    // "获得reader参考帐户时出错: {0}"
                    strError);
                // "获得reader参考帐户时出错: " + strError;
                return -1;
            }

            if (nRet == 0)
                accountref = null;
            else
            {
                // 匹配 IP 地址
                if (string.IsNullOrEmpty(sessioninfo.ClientIP) == false)    // 2016/11/2
                {
                    List<string> temp = new List<string>();

                    bool bRet = accountref.MatchClientIP(sessioninfo.ClientIP,
                        ref temp,
                        out strError);
                    if (bRet == false)
                    {
                        if (temp.Count == 0)
                            return -1;

                        // 不允许,又没有可以替代的方式,就要返回出错了
                        if (Account.HasAlterBindingType(temp) == false)
                            return -1;

                        // 有替代的验证方式,先继续完成登录
                        alter_type_list.AddRange(temp);
                    }
                    else
                        alter_type_list.Add("ip");
                }

                // 星号表示不进行 router client ip 检查
                if (sessioninfo.RouterClientIP != "*"
                    // && alter_type_list.Count == 0
                    )
                {
                    List<string> temp = new List<string>();

                    // 匹配 dp2Router 前端的 IP 地址
                    bool bRet = accountref.MatchRouterClientIP(sessioninfo.RouterClientIP,
                        ref temp,
                        out strError);
                    if (bRet == false)
                    {
                        if (temp.Count == 0)
                            return -1;

                        // 不允许,又没有可以替代的方式,就要返回出错了
                        if (Account.HasAlterBindingType(temp) == false)
                            return -1;

                        // 否则继续完成登录
                        alter_type_list.AddRange(temp);
                    }
                    else
                        alter_type_list.Add("router_ip");
                }
            }

            Account account = new Account();
            account.LoginName = strLoginName;
            account.Password = strPassword; // TODO: 如果本函数用 strPassword == null 来调用,这里的 null 就不是实际的密码字符串了
            account.Rights = "";    // 是否需要缺省值?
            account.AccountLibraryCode = "";
            account.Access = "";
            if (accountref != null)
            {
                account.Rights = accountref.Rights;
                // account.LibraryCode = accountref.LibraryCode;
                account.Access = accountref.Access;
            }

            // 追加读者记录中定义的权限值
            string strAddRights = DomUtil.GetElementText(readerdom.DocumentElement, "rights");
            if (string.IsNullOrEmpty(strAddRights) == false)
                account.Rights += "," + strAddRights;

            {
                // 2016/6/7
                // 如果读者记录状态有值,则需要从 account.Rights 中删除 patron 权限值
                // 反之则增加 patron 值
                string strState = DomUtil.GetElementText(readerdom.DocumentElement, "state");
                string strTemp = account.Rights;
                StringUtil.SetInList(ref strTemp, "patron", string.IsNullOrEmpty(strState));
                account.Rights = strTemp;
            }

            // 2015/1/15
            if (string.IsNullOrEmpty(strToken) == false)
                account.Rights += ",token:" + strToken;  // 如果保存在缓存中,如何决定何时失效?

            // 追加读者记录中定义的存取定义
            string strAddAccess = DomUtil.GetElementText(readerdom.DocumentElement, "access");
            if (string.IsNullOrEmpty(strAddAccess) == false)
            {
                // TODO: 可以优化为,如果发现前一个字符串末尾已经有 ';' 就不加 ';' 了。
                account.Access += ";" + strAddAccess;
            }

            account.Type = "reader";
            account.Barcode = DomUtil.GetElementText(readerdom.DocumentElement,
                "barcode");
            account.UserID = account.Barcode;

            // 2012/9/8
            // string strLibraryCode = "";
            nRet = this.GetLibraryCode(strOutputPath,
                    out strLibraryCode,
                    out strError);
            if (nRet == -1)
                return -1;
            account.AccountLibraryCode = strLibraryCode;

            // 2009/9/26 
            if (String.IsNullOrEmpty(account.Barcode) == true)
            {
                // text-level: 用户提示
                strError = string.Format(this.GetString("读者记录中证条码号内容为空,登录失败"),    // "读者记录中证条码号内容为空,登录失败"
                    strError);
                return -1;
            }

            account.Name = DomUtil.GetElementText(readerdom.DocumentElement,
                "name");
            // 2010/11/11
            account.DisplayName = DomUtil.GetElementText(readerdom.DocumentElement,
"displayName");
            account.PersonalLibrary = DomUtil.GetElementText(readerdom.DocumentElement,
"personalLibrary");


            // 2007/2/15 
            account.ReaderDom = readerdom;
            account.ReaderDomLastTime = DateTime.Now;


            account.Location = strLocation;
            account.ReaderDomPath = strOutputPath;
            account.ReaderDomTimestamp = timestamp;

            sessioninfo.Account = account;

            strRights = account.RightsOrigin;   //  sessioninfo.RightsOrigin;

            strOutputUserName = account.UserID; // 2011/7/29 读者证条码号

            // 把临时密码设置为正式密码
            if (bTempPassword == true)
            {
                byte[] output_timestamp = null;
                // 修改读者密码
                nRet = ChangeReaderPassword(
                    sessioninfo,
                    strOutputPath,
                    ref readerdom,
                    strPassword,    // TODO: 如果 strPassword == null 会怎么样?
                    timestamp,
                    out output_timestamp,
                    out strError);
                if (nRet == -1)
                    return -1;
                timestamp = output_timestamp;

                account.ReaderDom = readerdom;
                account.ReaderDomTimestamp = timestamp;
            }

            if (this.LoginCache != null && string.IsNullOrEmpty(account.LoginName) == false
                && account.Password != null)    // 防止 null password 进入 cache 引起其他问题 2014/12/20
            {
                DateTimeOffset offset = DateTimeOffset.Now.AddMinutes(20);
                this.LoginCache.Set(account.Barcode, account, offset);
            }

            return 1;
        }
Example #8
0
        // readerdom发生变化后,刷新相关域
        public static void RefreshReaderAccount(ref Account account,
            XmlDocument readerdom)
        {
            account.DisplayName = DomUtil.GetElementText(readerdom.DocumentElement,
"displayName");
            account.PersonalLibrary = DomUtil.GetElementText(readerdom.DocumentElement,
"personalLibrary");
            account.ReaderDomLastTime = DateTime.Now;

        }
Example #9
0
        // 将用户信息更新表(User_Infor_Message)写入读者库
        // parameters:
        //      strLastNumber   如果为空,表示全部处理
        // return:
        //      -1  error
        //      0   succeed
        //      1   中断
        int WriteToReaderDb(string strLastNumber,
            out string strMaxNumber,
            out string strError)
        {
            strError = "";
            strMaxNumber = "";
            int nRet = 0;

            /*
    <dkyw>
        <dataCenter connection="Persist Security Info=False;User ID=dp2rms;Password=dp2rms;Data Source=test111;Connect Timeout=30" db="zzdy" startTime="20:00" />
        <replication mapDbName="读者" />
    </dkyw>
             * */

            XmlNode node = this.App.LibraryCfgDom.DocumentElement.SelectSingleNode("//dkyw/replication");
            if (node == null)
            {
                strError = "尚未配置<dkyw><replication>参数";
                return -1;
            }

            string strReaderDbName = DomUtil.GetAttr(node, "mapDbName");
            if (String.IsNullOrEmpty(strReaderDbName) == true)
            {
                strError = "尚未配置<dkyw/replication>元素的mapDbName属性";
                return -1;
            }

            node = this.App.LibraryCfgDom.DocumentElement.SelectSingleNode("//dkyw/dataCenter");
            if (node == null)
            {
                strError = "尚未配置<dkyw><dataCenter>参数";
                return -1;
            }
            string strConnectionString = DomUtil.GetAttr(node, "connection");
            if (String.IsNullOrEmpty(strConnectionString) == true)
            {
                strError = "尚未配置<dkyw/dataCenter>元素的connection属性";
                return -1;
            }

            string strDbName = DomUtil.GetAttr(node, "db");
            if (String.IsNullOrEmpty(strDbName) == true)
            {
                strError = "尚未配置<dkyw/dataCenter>元素的db属性";
                return -1;
            }

            // 身份代码字典
            Hashtable pid_table = null;
            nRet = GetDictionary("Pid_Ctrl",
                "PID",
                "PNAME",
                out pid_table,
                out strError);
            if (nRet == -1)
                return -1;

            // 部门代码字典
            Hashtable dept_table = null;
            nRet = GetDictionary("Dept_Ctrl",
                "DeptStr",
                "DeptName1,DeptName2,DeptName3,DeptName4,DeptName5",
                out dept_table,
                out strError);
            if (nRet == -1)
                return -1;

            // 职位(岗位)代码字典
            Hashtable job_table = null;
            nRet = GetDictionary("Job",
                "Code",
                "Name",
                out job_table,
                out strError);
            if (nRet == -1)
                return -1;

            SqlConnection connection = new SqlConnection(strConnectionString);
            try
            {
                connection.Open();
            }
            catch (Exception ex)
            {
                strError = "连接到SQL服务器失败: " + ex.Message;
                return -1;
            }

            try
            {
                SqlCommand command = null;
                SqlDataReader dr = null;

                string strCommand = "";

                strCommand = "use " + strDbName + "\r\nselect * from User_Infor_Message";
                if (String.IsNullOrEmpty(strLastNumber) == false)
                {
                    strCommand += " where IDNumber > " + strLastNumber;
                }

                strCommand += " order by IDNumber";

                command = new SqlCommand(strCommand,
                    connection);
                try
                {
                    dr = command.ExecuteReader();
                }
                catch (Exception ex)
                {
                    strError = "查询SQL时出错: "
                        + ex.Message + "; "
                        + "SQL命令: "
                        + strCommand;
                    return -1;
                }

                // bool bRet = false;

                // 临时的SessionInfo对象
                SessionInfo sessioninfo = new SessionInfo(this.App);

                // 模拟一个账户
                Account account = new Account();
                account.LoginName = "replication";
                account.Password = "";
                account.Rights = "setreaderinfo,devolvereaderinfo";

                account.Type = "";
                account.Barcode = "";
                account.Name = "replication";
                account.UserID = "replication";
                account.RmsUserName = this.App.ManagerUserName;
                account.RmsPassword = this.App.ManagerPassword;

                sessioninfo.Account = account;

                int nRecordCount = 0;
                for (int i = 0; ; i++)
                {
                    Thread.Sleep(1);    // 避免处理太繁忙

                    if (this.Stopped == true)
                    {
                        return 1;
                    }

                    try
                    {
                        if (dr == null || dr.HasRows == false)
                        {
                            break;
                        }
                        if (dr.Read() == false)
                            break;
                    }
                    catch (Exception ex)
                    {
                        strError = "读SQL表行发生错误: " + ex.Message;
                        return -1;
                    }

                    // 获得字段值
                    int nIDNumber = GetSqlIntValue(dr, "IDNumber");

                    this.SetProgressText("同步 " + (i + 1).ToString() + " IDNumber=" + nIDNumber.ToString());
                    this.AppendResultText("同步 " + (i + 1).ToString() + " IDNumber=" + nIDNumber.ToString() + "\r\n");

                    string strMessageType = GetSqlStringValue(dr,"MessageType");
                    string strCardNo = GetSqlStringValue(dr,"CARDNO");
                    string strCardID = GetSqlStringValue(dr,"CARDID");
                    string strOldCardNo = GetSqlStringValue(dr,"OLDCARDNO");
                    string strOldCardID = GetSqlStringValue(dr,"OLDCARDID");
                    string strCardType = GetSqlStringValue(dr,"CDTYPE");
                    string strUserName = GetSqlStringValue(dr,"USERNAME");
                    string strIdType = GetSqlStringValue(dr,"IDTYPE");
                    string strIdSerial = GetSqlStringValue(dr,"IDSERIAL");
                    string strPersonID = GetSqlStringValue(dr,"PID");
                    string strDepartmentCode = GetSqlStringValue(dr,"DEPTSTR");
                    string strCountryCode = GetSqlStringValue(dr,"CTRCODE");
                    string strNationCode = GetSqlStringValue(dr,"NATCODE");
                    string strSex = GetSqlStringValue(dr,"SEX");
                    string strBirthday = GetSqlStringValue(dr,"BIRTHDAY");
                    string strInSchoolDate = GetSqlStringValue(dr,"INSCHOOL");
                    string strJobCode = GetSqlStringValue(dr,"JOBCODE");
                    string strRecType = GetSqlStringValue(dr,"RECTYPE");
                    string strGrade = GetSqlStringValue(dr,"GRADE");
                    string strIdSerial1 = GetSqlStringValue(dr,"IDSERIAL1");
                    string strOtherString = GetSqlStringValue(dr,"OTHERSTR");


                    // 规整号码字符串
                    if (String.IsNullOrEmpty(strOldCardNo) == false)
                        strOldCardNo = strOldCardNo.Trim().PadLeft(8, '0');

                    string strXml = "";
                    string strBarcode = strCardNo.Trim().PadLeft(8, '0');;

                    string strRfc1123Birthday = "";

                    if (String.IsNullOrEmpty(strBirthday) == false)
                    {
                        nRet = DateTimeUtil.Date8toRfc1123(strBirthday,
                            out strRfc1123Birthday,
                            out strError);
                        if (nRet == -1)
                            return -1;
                    }

                    string strCreateDate = "";

                    if (String.IsNullOrEmpty(strInSchoolDate) == false)
                    {
                        nRet = DateTimeUtil.Date8toRfc1123(strInSchoolDate,
                            out strCreateDate,
                            out strError);
                        if (nRet == -1)
                            return -1;
                    }

                    // 构造记录体
                    nRet = BuildReaderXml(
                        strBarcode,
                        strUserName,
                        strSex == "0" ? "女" : "男",
                        // (string)pid_table[strPersonID.Trim()],
                        (string)dept_table[strDepartmentCode.Trim()],
                        (string)pid_table[strPersonID.Trim()],  // (string)job_table[strJobCode.Trim()],
                        strRfc1123Birthday,
                        strIdSerial1,   // 身份证号
                        strOtherString, // address
                        "", // comment
                        strCreateDate,
                        out strXml,
                        out strError);
                    if (nRet == -1)
                        return -1;

                    /*
                    if (nIDNumber > 200)
                    {
                        strError = "模拟错误";
                        return -1;
                    }*/

                    if (strMessageType == "3")
                    {
                        // 进行换卡操作
                        // parameters:
                        //      strOriginReaderXml  原始记录。里面的<barcode>元素值为新的卡号
                        //      strOldCardNo    旧的卡号。
                        // return:
                        //      -1  error
                        //      0   已经写入
                        //      1   没有必要写入
                        nRet = DoChangeCard(
                            sessioninfo,
                            strOldCardNo,
                            strReaderDbName,
                            strXml,
                            out strError);
                    }
                    else
                    {
                        // return:
                        //      -1  error
                        //      0   已经写入
                        //      1   没有必要写入
                        nRet = WriteOneReaderInfo(
                            sessioninfo,
                            strMessageType,
                            strReaderDbName,
                            strXml,
                            out strError);
                    }

                    if (nRet == -1)
                        return -1;

                    // 记录处理完成的记录ID
                    strMaxNumber = nIDNumber.ToString();

                    nRecordCount++;
                }

                this.SetProgressText("同步读者记录完成,实际处理记录 " + nRecordCount.ToString() + " 条");

                if (nRecordCount == 0)
                {
                    if (String.IsNullOrEmpty(strLastNumber) == false)
                        this.AppendResultText("没有大于记录号 " + strLastNumber + "的任何新记录\r\n");
                    else
                        this.AppendResultText("没有任何记录\r\n");
                }

                return 0;
            }
            catch (Exception ex)
            {
                strError = "WriteToReaderDb() Exception: " + ExceptionUtil.GetDebugText(ex);
                return -1;
            }
            finally
            {
            }
        }
Example #10
0
        // 将黑名单中的卡挂失入读者库
        // parameters:
        // return:
        //      -1  error
        //      0   succeed
        //      1   中断
        int DoBlackList(out string strError)
        {
            strError = "";
            int nRet = 0;

            DateTime timeStart = DateTime.Now;

            if (String.IsNullOrEmpty(this.BlackListDoneDate) == false)
            {
                // 当日没有必要重复了
                if (this.BlackListDoneDate == DateTimeUtil.DateTimeToString8(timeStart))
                {
                    this.AppendResultText("本日("+this.BlackListDoneDate+")内不再重做\r\n");
                    return 0;
                }
            }

            /*
    <dkyw>
        <dataCenter connection="Persist Security Info=False;User ID=dp2rms;Password=dp2rms;Data Source=test111;Connect Timeout=30" db="zzdy" startTime="20:00" />
        <replication mapDbName="读者" />
    </dkyw>
             * */
            XmlNode node = this.App.LibraryCfgDom.DocumentElement.SelectSingleNode("//dkyw/replication");
            if (node == null)
            {
                strError = "尚未配置<dkyw><replication>参数";
                return -1;
            }

            string strReaderDbName = DomUtil.GetAttr(node, "mapDbName");
            if (String.IsNullOrEmpty(strReaderDbName) == true)
            {
                strError = "尚未配置<dkyw/replication>元素的mapDbName属性";
                return -1;
            }

            node = this.App.LibraryCfgDom.DocumentElement.SelectSingleNode("//dkyw/dataCenter");
            if (node == null)
            {
                strError = "尚未配置<dkyw><dataCenter>参数";
                return -1;
            }
            string strConnectionString = DomUtil.GetAttr(node, "connection");
            if (String.IsNullOrEmpty(strConnectionString) == true)
            {
                strError = "尚未配置<dkyw/dataCenter>元素的connection属性";
                return -1;
            }

            string strDbName = DomUtil.GetAttr(node, "db");
            if (String.IsNullOrEmpty(strDbName) == true)
            {
                strError = "尚未配置<dkyw/dataCenter>元素的db属性";
                return -1;
            }

            // 临时的SessionInfo对象
            SessionInfo sessioninfo = new SessionInfo(this.App);

            // 模拟一个账户
            Account account = new Account();
            account.LoginName = "replication";
            account.Password = "";
            account.Rights = "setreaderinfo";

            account.Type = "";
            account.Barcode = "";
            account.Name = "replication";
            account.UserID = "replication";
            account.RmsUserName = this.App.ManagerUserName;
            account.RmsPassword = this.App.ManagerPassword;

            sessioninfo.Account = account;

            /*
             * 检索出全部挂失状态的读者记录
             * */
            RmsChannel channel = sessioninfo.Channels.GetChannel(this.App.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }

            List<string> loss_barcodes = null;
                    // 根据读者证状态对读者库进行检索
        // parameters:
        //      strMatchStyle   匹配方式 left exact right middle
        //      strState  读者证状态
        //      bOnlyIncirculation  是否仅仅包括参与流通的数据库? true :仅仅包括; false : 包括全部
        //      bGetPath    == true 获得path; == false 获得barcode
        // return:
        //      -1  error
        //      其他    命中记录条数(不超过nMax规定的极限)
            nRet = this.App.SearchReaderState(
                // sessioninfo.Channels,
                channel,
                "挂失",
                "left",
                false,
                false,  // bGetPath,
                -1,
                out loss_barcodes,
                out strError);
            if (nRet == -1)
            {
                strError = "检索全部挂失读者记录信息时出错: " + strError;
                return -1;
            }

            if (nRet == 0)
            {
                if (loss_barcodes == null)
                    loss_barcodes = new List<string>();
            }

            SqlConnection connection = new SqlConnection(strConnectionString);
            try
            {
                connection.Open();
            }
            catch (Exception ex)
            {
                strError = "连接到SQL服务器失败: " + ex.Message;
                return -1;
            }

            try
            {
                SqlCommand command = null;
                SqlDataReader dr = null;

                string strCommand = "";

                strCommand = "use " + strDbName + "\r\nselect * from balck_list";
                command = new SqlCommand(strCommand,
                    connection);
                try
                {
                    dr = command.ExecuteReader();
                }
                catch (Exception ex)
                {
                    strError = "查询SQL时出错: "
                        + ex.Message + "; "
                        + "SQL命令: "
                        + strCommand;
                    return -1;
                }

                // bool bRet = false;



                for (int i = 0; ; i++)
                {
                    Thread.Sleep(1);    // 避免处理太繁忙

                    if (this.Stopped == true)
                    {
                        return 1;
                    }

                    try
                    {
                        if (dr == null || dr.HasRows == false)
                        {
                            break;
                        }
                        if (dr.Read() == false)
                            break;
                    }
                    catch (Exception ex)
                    {
                        strError = "读SQL表行发生错误: " + ex.Message;
                        return -1;
                    }

                    // 获得字段值
                    string strCardNo = GetSqlStringValue(dr, "CardNo");
                    // 规整号码字符串
                    if (String.IsNullOrEmpty(strCardNo) == false)
                        strCardNo = strCardNo.PadLeft(8, '0');

                    this.SetProgressText("挂失 " + (i + 1).ToString() + " CardNumber=" + strCardNo);

                    // 观察集合中是否已经具有
                    int nIndex = loss_barcodes.IndexOf(strCardNo);
                    if (nIndex != -1)
                    {
                        loss_barcodes.RemoveAt(nIndex);
                        this.AppendResultText("挂失 " + (i + 1).ToString() + " CardNumber=" + strCardNo + "  原本就是挂失状态\r\n");
                        continue;
                    }

                    this.AppendResultText("挂失 " + (i + 1).ToString() + " CardNumber=" + strCardNo + " ");

                    string strLossDate = GetSqlStringValue(dr, "LossDate");

                    /*
                    string strRfc1123LossDate = "";

                    if (String.IsNullOrEmpty(strLossDate) == false)
                    {
                        nRet = DateTimeUtil.Date8toRfc1123(strLossDate,
                            out strRfc1123LossDate,
                            out strError);
                        if (nRet == -1)
                            return -1;
                    }
                     * */

                    // return:
                    //      -1  error
                    //      0   已经写入
                    //      1   没有必要写入
                    nRet = LossOneReaderInfo(
                            sessioninfo,
                            strCardNo,
                            strLossDate,
                            out strError);
                    if (nRet == -1)
                        return -1;

                    this.AppendResultTextNoTime(strError + "\r\n");
                }

                // Thread.Sleep(2 * 60 * 1000);    // test
                // 现在集合中剩下的,就是黑名单以外的,状态不应为“挂失”的条码号
                for (int i = 0; i < loss_barcodes.Count; i++)
                {
                    string strBarcode = loss_barcodes[i];

                    if (String.IsNullOrEmpty(strBarcode) == true)
                        continue;

                    this.SetProgressText("解挂 " + (i + 1).ToString() + " CardNumber=" + strBarcode);

                    this.AppendResultText("解挂 " + (i + 1).ToString() + " CardNumber=" + strBarcode + " ");
                    // return:
                    //      -1  error
                    //      0   已经写入
                    //      1   没有必要写入
                    nRet = UnLossOneReaderInfo(
                            sessioninfo,
                            strBarcode,
                            out strError);
                    if (nRet == -1)
                        return -1;

                    this.AppendResultTextNoTime(strError + "\r\n");
                }

                // 观察消耗的时间
                TimeSpan delta = DateTime.Now - timeStart;
                int nMaxMinutes = 5;
                if (delta.Minutes > nMaxMinutes)
                {
                    // 如果超过5分钟,则记载下当日的日期,避免同一日后面重做
                    this.BlackListDoneDate = DateTimeUtil.DateTimeToString8(timeStart);
                    this.AppendResultText("黑名单同步过程处理时间为 "+delta.ToString()+",超过了 "+nMaxMinutes.ToString()+" 分钟,本日("+this.BlackListDoneDate+")内将不再重复处理\r\n");
                }

                this.SetProgressText("同步黑名单完成,耗费时间 " + delta.ToString() + " ");

                return 0;
            }
            catch (Exception ex)
            {
                strError = "DoBlackList() Exception: " + ExceptionUtil.GetDebugText(ex);
                return -1;
            }
            finally
            {
            }
        }
Example #11
0
        // 借阅API的从属函数
        // 检查借阅权限
        // text-level: 用户提示 OPAC的续借要调用Borrow()函数,进而调用本函数
        // parameters:
        //      strLibraryCode  读者记录所在读者库的馆代码
        //      strAccessParameters 许可操作的馆藏地点列表。如果为 空 或者 "*",表示全部许可
        // return:
        //      -1  配置参数错误
        //      0   权限不够,借阅操作应当被拒绝
        //      1   权限够
        int CheckBorrowRights(
            Account account,
            Calendar calendar,
            bool bRenew,
            string strLibraryCode,
            string strAccessParameters,
            ref XmlDocument readerdom,
            ref XmlDocument itemdom,
            ref StringBuilder debugInfo,
            out string strError)
        {
            strError = "";
            int nRet = 0;

            LibraryApplication app = this;

            if (StringUtil.IsInList("pauseBorrowing", this.OverdueStyle) == true)
            {
                /* 这一段已经移动到本函数外面去做了,因为涉及到对readerdom的修改问题
                //
                // 处理以停代金功能
                // return:
                //      -1  error
                //      0   readerdom没有修改
                //      1   readerdom发生了修改
                nRet = ProcessPauseBorrowing(ref readerdom,
                    "refresh",
                    out strError);
                if (nRet == -1)
                {
                    strError = "在刷新以停代金的过程中发生错误: " + strError;
                    return -1;
                }
                 * */

                // 是否存在以停代金事项?
                string strMessage = "";
                nRet = HasPauseBorrowing(
                    calendar,
                    strLibraryCode,
                    readerdom,
                    out strMessage,
                    out strError);
                if (nRet == -1)
                {
                    // text-level: 内部错误
                    strError = "在计算以停代金的过程中发生错误: " + strError;
                    return -1;
                }
                if (nRet == 1)
                {
                    // text-level: 用户提示
                    strError = string.Format(this.GetString("借阅操作被拒绝,因该读者s"),   // "借阅操作被拒绝,因该读者{0}"
                        strMessage);

                    // "借阅操作被拒绝,因该读者" + strMessage;
                    return 0;
                }
            }

            string strOperName = this.GetString("借阅");

            if (bRenew == true)
                strOperName = this.GetString("续借");

            string strRefID = DomUtil.GetElementText(itemdom.DocumentElement,
"refID");
            string strReaderBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode");
            string strItemBarcode = DomUtil.GetElementText(itemdom.DocumentElement, "barcode");

            string strItemBarcodeParam = strItemBarcode;
            if (String.IsNullOrEmpty(strItemBarcode) == true)
            {
#if NO
                // text-level: 内部错误
                strError = "册记录中册条码号不能为空";
                return -1;
#endif
                // 如果册条码号为空,则使用 参考ID
                if (String.IsNullOrEmpty(strRefID) == true)
                {
                    // text-level: 内部错误
                    strError = "册记录中册条码号和参考ID不应同时为空";
                    return -1;
                }
                strItemBarcodeParam = "@refID:" + strRefID;
            }

            // 馆藏地点
            string strLocation = DomUtil.GetElementText(itemdom.DocumentElement, "location");

            // 去掉#reservation部分
            // StringUtil.RemoveFromInList("#reservation", true, ref strLocation);
            strLocation = StringUtil.GetPureLocationString(strLocation);

            // 检查册所属的馆藏地点是否合读者所在的馆藏地点吻合
            string strRoom = "";
            string strCode = "";
            {

                // 解析
                ParseCalendarName(strLocation,
            out strCode,
            out strRoom);
                if (strCode != strLibraryCode)
                {
                    strError = "借阅操作被拒绝。因册记录的馆藏地 '" + strLocation + "' 不属于读者所在馆代码 '" + strLibraryCode + "' ";
                    return 0;
                }
            }

            // 检查馆藏地列表
            if (string.IsNullOrEmpty(strAccessParameters) == false && strAccessParameters != "*")
            {
                bool bFound = false;
                List<string> locations = StringUtil.SplitList(strAccessParameters);
                foreach (string s in locations)
                {
                    string c = "";
                    string r = "";
                    ParseCalendarName(s,
                        out c,
                        out r);
                    if (/*string.IsNullOrEmpty(c) == false && */ c != "*")
                    {
                        if (c != strCode)
                            continue;
                    }

                    if (/*string.IsNullOrEmpty(r) == false && */ r != "*")
                    {
                        if (r != strRoom)
                            continue;
                    }

                    bFound = true;
                    break;
                }

                if (bFound == false)
                {
                    strError = "借阅操作被拒绝。因册记录的馆藏地 '" + strLocation + "' 不在当前用户存取定义规定的馆藏地许可范围 '" + strAccessParameters + "' 之内";
                    return 0;
                }
            }

            // 2006/12/29
            // 检查册是否能够被借出
            bool bResultValue = false;
            string strMessageText = "";

            // 执行脚本函数ItemCanBorrow
            // parameters:
            // return:
            //      -2  not found script
            //      -1  出错
            //      0   成功
            nRet = app.DoItemCanBorrowScriptFunction(
                bRenew,
                account,
                itemdom,
                out bResultValue,
                out strMessageText,
                out strError);
            if (nRet == -1)
            {
                // text-level: 内部错误
                strError = "执行CanBorrow()脚本函数时出错: " + strError;
                return -1;
            }
            if (nRet == -2)
            {
                // 如果没有配置脚本函数,就根据馆藏地点察看地点允许配置来决定是否允许借阅
                List<string> locations = app.GetLocationTypes(strLibraryCode, true);

                if (debugInfo != null)
                    debugInfo.Append("获得馆代码 '"+strLibraryCode+"' 的可以借阅的馆藏地列表为: '" + StringUtil.MakePathList(locations) + "'\r\n");

                if (locations.IndexOf(strRoom) == -1)
                {
                    // text-level: 用户提示
                    strError = string.Format(this.GetString("册s的馆藏地点为s,按规定此册不允许外借"),  // "册 {0} 的馆藏地点为 {1},按规定(<locationTypes>配置)此册不允许外借。"
                        strItemBarcodeParam,
                        strLocation);

                    // "册 " + strItemBarcode + " 的馆藏地点为 " + strLocation + ",按规定(<locationTypes>配置)此册不允许外借。";

                    if (debugInfo != null)
                        debugInfo.Append("在列表 '" + StringUtil.MakePathList(locations) + "' 中没有匹配上 '"+strRoom+"'\r\n");

                    return 0;
                }

                if (debugInfo != null)
                    debugInfo.Append("在列表 '" + StringUtil.MakePathList(locations) + "' 中匹配上了 '" + strRoom + "'\r\n");
            }
            else
            {
                // 根据脚本返回结果
                if (bResultValue == false)
                {
                    strError = string.Format(this.GetString("不允许s。因为册s的状态为s"),   // "不允许 {0}。因为册 {1} 的状态为 {2}"
                        strOperName,
                        strItemBarcodeParam,
                        strMessageText);
                    /*
                    strError = "不允许" 
                        + (bRenew == true ? "续借" : "外借")
                        + "。因为册 " + strItemBarcode + " 的状态为 "+strMessageText;
                     * */
                    return 0;
                }
            }

            // 
            // 个人书斋的检查
            string strPersonalLibrary = "";
            if (account != null)
                strPersonalLibrary = account.PersonalLibrary;

            if (string.IsNullOrEmpty(strPersonalLibrary) == false)
            {
                if (strPersonalLibrary != "*" && StringUtil.IsInList(strRoom, strPersonalLibrary) == false)
                {
                    strError = "当前用户 '" + account.Barcode + "' 只能操作馆代码 '" + strLibraryCode + "' 中地点为 '" + strPersonalLibrary + "' 的图书,不能操作地点为 '" + strRoom + "' 的图书";
                    // text-level: 用户提示
                    strError = string.Format(this.GetString("s操作被拒绝,原因s"),  // "{0} 操作被拒绝,原因: {1}"
                        strOperName,
                        strError);
                    return 0;
                }
            }

            if (bRenew == false)
            {
                // 检查读者记录中是否已经有了对应册的<borrow>
                XmlNode node = readerdom.DocumentElement.SelectSingleNode("borrows/borrow[@barcode='" + strItemBarcodeParam + "']");
                if (node != null)
                {
                    if (string.IsNullOrEmpty(strItemBarcode) == false)
                        node = readerdom.DocumentElement.SelectSingleNode("borrows/borrow[@barcode='" + strItemBarcode + "']");
                    if (node != null)
                    {
                        // text-level: 用户提示

                        // string strReaderBarcode = DomUtil.GetElementText(readerdom.DocumentElement, "barcode");
                        strError = "借阅操作被拒绝。读者 '" + strReaderBarcode + "' 早先已经借阅了册 '" + strItemBarcodeParam + "' 。(读者记录中已存在对应的<borrow>元素)";
                        // strError = "操作前在读者记录中发现居然已存在表明读者借阅了册'"+strItemBarcode+"'的字段信息 " + node.OuterXml;
                        return -1;
                    }
                }
            }

            // 检查借阅证是否超期,是否有挂失等状态
            // return:
            //      -1  检测过程发生了错误。应当作不能借阅来处理
            //      0   可以借阅
            //      1   证已经过了失效期,不能借阅
            //      2   证有不让借阅的状态
            nRet = CheckReaderExpireAndState(readerdom,
                out strError);
            if (nRet != 0)
            {
                // text-level: 用户提示
                strError = string.Format(this.GetString("s操作被拒绝,原因s"),  // "{0} 操作被拒绝,原因: {1}"
                    strOperName,
                    strError);
                // strOperName + "操作被拒绝,原因: " + strError;
                return -1;
            }

            // 检查是否已经有记载了的<overdue>字段
            XmlNodeList nodes = readerdom.DocumentElement.SelectNodes("overdues/overdue");
            if (nodes.Count > 0)
            {
                // text-level: 用户提示
                strError = string.Format(this.GetString("该读者当前有s个已还违约记录尚未处理"), // "该读者当前有 {0} 个已还违约记录尚未处理,因此{1}操作被拒绝。请读者尽快办理违约后相关手续(如交纳违约金),然后方可进行{2}。"
                    nodes.Count.ToString(),
                    strOperName,
                    strOperName);
                // "该读者当前有 " + Convert.ToString(nodes.Count) + " 个已还违约记录尚未处理,因此" + strOperName + "操作被拒绝。请读者尽快办理违约后相关手续(如交纳违约金),然后方可进行" + strOperName + "。";
                return 0;
            }

            if (this.BorrowCheckOverdue == true)
            {
                // 检查当前是否有潜在的超期册
                // return:
                //      -1  error
                //      0   没有超期册
                //      1   有超期册
                nRet = CheckOverdue(
                    calendar,
                    readerdom,
                    false,  // bForce,
                    out strError);
                if (nRet == -1)
                    return -1;
                if (nRet == 1)
                {
                    // text-level: 用户提示
                    strError = string.Format(this.GetString("因为超期,操作s被拒绝"),   //  + "{0},因此{1}操作被拒绝。请读者尽快将这些已超期册履行还书手续。"
                        strError,
                        strOperName);
                    // strError + ",因此" + strOperName + "操作被拒绝。请读者尽快将这些已超期册履行还书手续。";
                    return 0;
                }
            }

            // 2008/4/14
            string strBookState = DomUtil.GetElementText(itemdom.DocumentElement, "state");
            if (String.IsNullOrEmpty(strBookState) == false)
            {
                // text-level: 用户提示
                strError = string.Format(this.GetString("s操作被拒绝,因为册状态为s"),  // "{0}操作被拒绝,原因: 册 '{1}' 的状态为 '{2}'。"
                    strOperName,
                    strItemBarcodeParam,
                    strBookState);
                // strOperName + "操作被拒绝,原因: 册 '" + strItemBarcode + "' 的状态为 '"+ strBookState + "'。";
                return 0;
            }

            // 2010/3/19
            XmlNode nodeParentItem = itemdom.DocumentElement.SelectSingleNode("binding/bindingParent");
            if (nodeParentItem != null)
            {
                // text-level: 用户提示
                strError = string.Format(this.GetString("s操作被拒绝,因为合订成员册不能单独外借"),  // "{0}操作被拒绝,原因: 合订成员册 {1} 不能单独外借。"
                    strOperName,
                    strItemBarcodeParam);
                return 0;
            }

            // 从想要借阅的册信息中,找到图书类型
            string strBookType = DomUtil.GetElementText(itemdom.DocumentElement, "bookType");

            // 从读者信息中, 找到读者类型
            string strReaderType = DomUtil.GetElementText(readerdom.DocumentElement, "readerType");

            // 首次借阅情况,需要判断册数限制条件
            // 而续借情况,因为先前的借阅已经判断过相关权限了,因此不必判断了
            if (bRenew == false)
            {
                // 从读者信息中,找出该读者以前已经借阅过的同类图书的册数
                nodes = readerdom.DocumentElement.SelectNodes("borrows/borrow[@type='" + strBookType + "']");

                int nThisTypeCount = nodes.Count;

                // 得到该类图书的册数限制配置
                MatchResult matchresult;
                string strParamValue = "";
                // return:
                //      reader和book类型均匹配 算4分
                //      只有reader类型匹配,算3分
                //      只有book类型匹配,算2分
                //      reader和book类型都不匹配,算1分
                nRet = app.GetLoanParam(
                    //null,
                    strLibraryCode,
                    strReaderType,
                    strBookType,
                    "可借册数",
                    out strParamValue,
                    out matchresult,
                    out strError);
                if (nRet == -1 || nRet < 4)
                {
                    // text-level: 用户提示
                    strError = "馆代码 '" + strLibraryCode + "' 中 读者类型 '" + strReaderType + "' 图书类型 '" + strBookType + "' 尚未定义 可借册数 参数, 因此拒绝" + strOperName + "操作";
                    return -1;
                }

                // 看看是此类否超过册数限制
                int nThisTypeMax = 0;
                try
                {
                    nThisTypeMax = Convert.ToInt32(strParamValue);
                }
                catch
                {
                    strError = "馆代码 '" + strLibraryCode + "' 中 读者类型 '" + strReaderType + "' 图书类型 '" + strBookType + "' 的 可借册数 参数值 '" + strParamValue + "' 格式有问题, 因此拒绝" + strOperName + "操作";
                    return -1;
                }

                if (nThisTypeCount + 1 > nThisTypeMax)
                {
                    strError = "读者 '" + strReaderBarcode + "' 所借 '" + strBookType + "' 类图书数量将超过 馆代码 '" + strLibraryCode + "' 中 该读者类型 '" + strReaderType + "' 对该图书类型 '" + strBookType + "' 的最多 可借册数 值 '" + strParamValue + "',因此本次" + strOperName + "操作被拒绝";
                    return 0;
                }

                // 得到该读者类型针对所有类型图书的总册数限制配置
                // return:
                //      reader和book类型均匹配 算4分
                //      只有reader类型匹配,算3分
                //      只有book类型匹配,算2分
                //      reader和book类型都不匹配,算1分
                nRet = app.GetLoanParam(
                    //null,
                    strLibraryCode,
                    strReaderType,
                    "",
                    "可借总册数",
                    out strParamValue,
                    out matchresult,
                    out strError);
                if (nRet == -1)
                {
                    // text-level: 用户提示
                    strError = "在获取馆代码 '" + strLibraryCode + "' 中 读者类型 '" + strReaderType + "' 的 可借总册数 参数过程中出错: " + strError + "。因此拒绝" + strOperName + "操作";
                    return -1;
                }
                if (nRet < 3)
                {
                    // text-level: 用户提示
                    strError = "馆代码 '" + strLibraryCode + "' 中 读者类型 '" + strReaderType + "' 尚未定义 可借总册数 参数, 因此拒绝" + strOperName + "操作";
                    return -1;
                }

                // 然后看看总册数是否已经超过限制
                int nMax = 0;
                try
                {
                    nMax = Convert.ToInt32(strParamValue);
                }
                catch
                {
                    // text-level: 用户提示
                    strError = "馆代码 '" + strLibraryCode + "' 中 读者类型 '" + strReaderType + "' 的 可借总册数 参数值 '" + strParamValue + "' 格式有问题, 因此拒绝" + strOperName + "操作";
                    return -1;
                }

                // 从读者信息中,找出该读者已经借阅过的册数
                nodes = readerdom.DocumentElement.SelectNodes("borrows/borrow");

                int nCount = nodes.Count;

                if (nCount + 1 > nMax)
                {
                    // text-level: 用户提示
                    strError = "读者 '" + strReaderBarcode + "' 所借册数将超过 馆代码 '" + strLibraryCode + "' 中 类型 '" + strReaderType + "' 可借总册数 值'" + strParamValue + "',因此本次" + strOperName + "操作被拒绝";
                    return 0;
                }
            }

            if (bRenew == false)
            {
                // 检查所借图书的总价格是否超过押金余额
                // return:
                //      -1  error
                //      0   没有超过
                //      1   超过
                nRet = CheckTotalPrice(readerdom,
                    itemdom,
                    out strError);
                if (nRet == -1)
                    return -1;

                if (nRet == 1)
                    return 0;
            }

            return 1;
        }
Example #12
0
        // text-level: 内部处理
        // 在 预约到书 库中,追加一条新的记录
        // 并作email通知
        // 注:本函数可能要删除部分通知记录
        // parameters:
        //      strItemBarcode  册条码号。必须是册条码号。如果册条码号为空,参考ID需要使用 strRefID 参数
        //      strRefID        参考ID
        //      bOnShelf    要通知的册是否在架。在架指并没有人借阅过,本来就在书架上。
        //      strLibraryCode  读者所在的馆代码
        //      strReaderXml    预约了图书的读者的XML记录。用于消息通知接口
        int AddNotifyRecordToQueue(
            // RmsChannelCollection channels,
            RmsChannel channel,
            string strItemBarcode,
            string strRefID,
            string strItemXml,
            bool bOnShelf,
            string strLibraryCode,
            string strReaderBarcode,
            string strReaderXml,
            out List<string> DeletedNotifyRecPaths,
            out string strError)
        {
            strError = "";
            DeletedNotifyRecPaths = new List<string>();
            
            // 2010/12/31
            if (String.IsNullOrEmpty(this.ArrivedDbName) == true)
            {
                strError = "预约到书库尚未定义, AddNotifyRecordToQueue()调用失败";
                return -1;
            }

            // 准备写记录
            byte[] timestamp = null;
            byte[] output_timestamp = null;
            string strOutputPath = "";
            int nRet = 0;
            long lRet = 0;

            if (String.IsNullOrEmpty(strItemBarcode) == true)
            {
                // 如果检索用的册条码号为空,加上对命中结果数量不设限,那就会造成系统严重繁忙。
                strError = "参数strItemBarcode中的册条码号不能为空。";
                return -1;
            }

#if NO
            RmsChannel channel = channels.GetChannel(this.WsUrl);
            if (channel == null)
            {
                strError = "get channel error";
                return -1;
            }
#endif

        REDODELETE:
            // 如果队列中已经存在同册条码号的记录, 要先删除
            string strNotifyXml = "";
            // 获得预约到书队列记录
            // return:
            //      -1  error
            //      0   not found
            //      1   命中1条
            //      >1  命中多于1条
            nRet = GetArrivedQueueRecXml(
                // channels,
                channel,
                strItemBarcode,
                out strNotifyXml,
                out timestamp,
                out strOutputPath,
                out strError);
            if (nRet == -1)
            {
                // 写入错误日志?
                this.WriteErrorLog("在还书操作中,检索册条码号为 " + strItemBarcode + " 的预约到书库记录时出错: " + strError);
            }
            if (nRet >= 1)
            {
                int nRedoDeleteCount = 0;
            // TODO: 这一段删除代码可以专门编制在一个函数中,不必这么费力循环。可以优化处理
            REDO_DELETE:
                lRet = channel.DoDeleteRes(strOutputPath,
                    timestamp,
                    out output_timestamp,
                    out strError);
                if (lRet == -1)
                {
                    // 时间戳不匹配
                    if (channel.ErrorCode == ChannelErrorCode.TimestampMismatch
                        && nRedoDeleteCount < 10)
                    {
                        nRedoDeleteCount++;
                        timestamp = output_timestamp;
                        goto REDO_DELETE;
                    }

                    // 写入错误日志?
                    this.WriteErrorLog("在还书操作中,加入新预约到书记录前, 删除已存在的预约到书库记录 '" + strOutputPath + "' 出错: " + strError);
                }

                DeletedNotifyRecPaths.Add(strOutputPath);    // 记忆已经被删除的记录路径 2007/7/5 

                goto REDODELETE;    // 如果有多条,循环删除
            }

            XmlDocument itemdom = null;
            nRet = LibraryApplication.LoadToDom(strItemXml,
                out itemdom,
                out strError);
            if (nRet == -1)
            {
                strError = "装载册记录 '"+strItemBarcode+"' 的 XML 进入 DOM 时发生错误: " + strError;
                return -1;
            }

            string strLocation = DomUtil.GetElementText(itemdom.DocumentElement, "location");
            strLocation = StringUtil.GetPureLocationString(strLocation);

            // 创建预约到书记录
            XmlDocument new_queue_dom = new XmlDocument();
            new_queue_dom.LoadXml("<root />");

            // TODO: 以后增加 <refID> 元素,存储册记录的参考ID

#if NO
            XmlNode nodeItemBarcode = DomUtil.SetElementText(dom.DocumentElement, "itemBarcode", strItemBarcode);

            // 在<itemBarcode>元素中增加一个onShelf属性,表示属于在架情况
            Debug.Assert(nodeItemBarcode != null, "");
            if (bOnShelf == true)
                DomUtil.SetAttr(nodeItemBarcode, "onShelf", "true");
#endif
            // 兼容 strItemBarcode 中含有前缀的用法
            string strHead = "@refID:";
            if (StringUtil.HasHead(strItemBarcode, strHead, true) == true)
            {
                strRefID = strItemBarcode.Substring(strHead.Length);
                strItemBarcode = "";
            }

            if (this.ArrivedDbKeysContainsRefIDKey() == true)
            {
                DomUtil.SetElementText(new_queue_dom.DocumentElement, "itemBarcode", strItemBarcode);
                DomUtil.SetElementText(new_queue_dom.DocumentElement, "refID", strRefID);
            }
            else
            {
                if (string.IsNullOrEmpty(strItemBarcode) == true)
                {
                    if (string.IsNullOrEmpty(strRefID) == true)
                    {
                        strError = "AddNotifyRecordToQueue() 函数当 strItemBarcode 参数为空的时候,必须让 strRefID 参数不为空";
                        return -1;
                    }

                    Debug.Assert(string.IsNullOrEmpty(strRefID) == false, "");
                    // 旧的用法。避免检索时候查不到
                    DomUtil.SetElementText(new_queue_dom.DocumentElement, "itemBarcode", "@refID:" + strRefID);
                }
                else
                    DomUtil.SetElementText(new_queue_dom.DocumentElement, "itemBarcode", strItemBarcode); // 2015/5/20 添加,修正 BUG
            }

            // 改为存储在元素中 2015/5/7
            if (bOnShelf == true)
                DomUtil.SetElementText(new_queue_dom.DocumentElement, "onShelf", "true");

            // 2012/10/26
            DomUtil.SetElementText(new_queue_dom.DocumentElement, "libraryCode", strLibraryCode);

            DomUtil.SetElementText(new_queue_dom.DocumentElement, "readerBarcode", strReaderBarcode);
            DomUtil.SetElementText(new_queue_dom.DocumentElement, "notifyDate", this.Clock.GetClock());

            // 2015/6/13
            DomUtil.SetElementText(new_queue_dom.DocumentElement, "location", strLocation);

            string strPath = this.ArrivedDbName + "/?";

            // 写新记录
            lRet = channel.DoSaveTextRes(
                strPath,
                new_queue_dom.OuterXml,
                false,
                "content,ignorechecktimestamp",
                timestamp,
                out output_timestamp,
                out strOutputPath,
                out strError);
            if (lRet == -1)
            {
                // 写入错误日志 2007/1/3 
                this.WriteErrorLog("创建新的预约到书队列记录时出错: " + strError);
                return -1;
            }

            string strReaderEmailAddress = "";
            string strName = "";
            nRet = GetReaderNotifyInfo(
                strReaderXml,
                out strName,
                out strReaderEmailAddress,
                out strError);
            if (nRet == -1)
                return -1;

            // 获得图书摘要信息
            string strSummary = "";
            string strBiblioRecPath = "";

            nRet = this.GetBiblioSummary(strItemBarcode,
                "", //  strConfirmItemRecPath,
                null,   //  strBiblioRecPathExclude,
                25,
                out strBiblioRecPath,
                out strSummary,
                out strError);
            if (nRet == -1)
            {
                strSummary = "ERROR: " + strError;
            }
#if NO
            // 临时的SessionInfo对象
            SessionInfo sessioninfo = new SessionInfo(this);
            // 模拟一个账户
            Account account = new Account();
            account.LoginName = "CacheBuilder";
            account.Password = "";
            account.Rights = "getbibliosummary";

            account.Type = "";
            account.Barcode = "";
            account.Name = "AddNotifyRecordToQueue";
            account.UserID = "AddNotifyRecordToQueue";
            account.RmsUserName = this.ManagerUserName;
            account.RmsPassword = this.ManagerPassword;

            sessioninfo.Account = account;
            try
            {

                string strBiblioRecPath = "";
                LibraryServerResult result = this.GetBiblioSummary(
                    sessioninfo,
                    strItemBarcode,
                    "", // strConfirmItemRecPath,
                    null,
                    out strBiblioRecPath,
                    out strSummary);
                if (result.Value == -1)
                {
                    strSummary = "ERROR: " + result.ErrorInfo;
                }
                else
                {
                    // 截断
                    if (strSummary.Length > 25)
                        strSummary = strSummary.Substring(0, 25) + "...";
                }
            }
            finally
            {
                sessioninfo.Close();
                sessioninfo = null;
            }
#endif


            // 发送短消息通知
            string strTotalError = "";

            // *** dpmail
            if (this.MessageCenter != null)
            {
                string strTemplate = "";
                // 获得邮件模板
                nRet = GetMailTemplate(
                    "dpmail",
                    bOnShelf == false ? "预约到书通知" : "预约到书通知(在架)",
                    out strTemplate,
                    out strError);
                if (nRet == -1)
                    return -1;
                if (nRet == 0)
                {
                    strError = "预约到书通知<mailTemplate/template>尚未配置。";
                    return -1;
                }

                /*
                %item%  册信息
                %reservetime%   保留期限
                %today% 发出email的当天
                %summary% 书目摘要
                %itembarcode% 册条码号 
                %name% 读者姓名
                 * */
                Hashtable table = new Hashtable();
                table["%item%"] = "(册条码号为: " + strItemBarcode + " URL为: " + this.OpacServerUrl + "/book.aspx?barcode=" + strItemBarcode + " )";
                table["%reservetime%"] = this.GetDisplayTimePeriodStringEx(this.ArrivedReserveTimeSpan);
                table["%today%"] = DateTime.Now.ToString();
                table["%summary%"] = strSummary;
                table["%itembarcode%"] = strItemBarcode;
                table["%name%"] = strName;
                string strBody = "";

                nRet = GetMailText(strTemplate,
                    table,
                    out strBody,
                    out strError);
                if (nRet == -1)
                    return -1;

                if (String.IsNullOrEmpty(this.MessageCenter.MessageDbName) == false)
                {
                    Debug.Assert(channel.Container != null, "");
                    // 发送消息
                    nRet = this.MessageCenter.SendMessage(
                        channel.Container,  // channels,
                        strReaderBarcode,
                        "图书馆",
                        "预约到书通知",
                        "text",
                        strBody,
                        false,
                        out strError);
                    if (nRet == -1)
                    {
                        strTotalError += "发送dpmail消息时出错: " + strError + "\r\n";
                    }
                }
            }

            // ** email
            if (String.IsNullOrEmpty(strReaderEmailAddress) == false)
            {
                string strTemplate = "";
                // 获得邮件模板
                nRet = GetMailTemplate(
                    "email",
                    bOnShelf == false ? "预约到书通知" : "预约到书通知(在架)",
                    out strTemplate,
                    out strError);
                if (nRet == -1)
                    return -1;
                if (nRet == 0)
                {
                    strError = "预约到书通知<mailTemplate/template>尚未配置。";
                    return -1;
                }

                /*
                %item%  册信息
                %reservetime%   保留期限
                %today% 发出email的当天
                %summary% 书目摘要
                %itembarcode% 册条码号 
                %name% 读者姓名
                 * */
                Hashtable table = new Hashtable();
                table["%item%"] = "(册条码号为: " + strItemBarcode + " URL为: " + this.OpacServerUrl + "/book.aspx?barcode=" + strItemBarcode + " )";
                table["%reservetime%"] = this.GetDisplayTimePeriodStringEx(this.ArrivedReserveTimeSpan);
                table["%today%"] = DateTime.Now.ToString();
                table["%summary%"] = strSummary;
                table["%itembarcode%"] = strItemBarcode;
                table["%name%"] = strName;

                string strBody = "";

                nRet = GetMailText(strTemplate,
                    table,
                    out strBody,
                    out strError);
                if (nRet == -1)
                    return -1;

                {
                    // 发送email
                    // return:
                    //      -1  error
                    //      0   not found smtp server cfg
                    //      1   succeed
                    nRet = SendEmail(strReaderEmailAddress,
                        "预约到书通知",
                        strBody,
                        "text",
                        out strError);
                    if (nRet == -1)
                    {
                        strTotalError += "发送email消息时出错: " + strError + "\r\n";
                    }
                }
            }

            // *** external messageinterfaces
            if (this.m_externalMessageInterfaces != null)
            {
                foreach (MessageInterface message_interface in this.m_externalMessageInterfaces)
                {
                    string strTemplate = "";
                    // 获得邮件模板
                    nRet = GetMailTemplate(
                        message_interface.Type,
                        bOnShelf == false ? "预约到书通知" : "预约到书通知(在架)",
                        out strTemplate,
                        out strError);
                    if (nRet == -1)
                        return -1;
                    if (nRet == 0)
                    {
                        strError = "预约到书通知<mailTemplate/template>尚未配置。";
                        return -1;
                    }

                    /*
                    %item%  册信息
                    %reservetime%   保留期限
                    %today% 发出email的当天
                %summary% 书目摘要
                %itembarcode% 册条码号 
                %name% 读者姓名
                     * */
                    Hashtable table = new Hashtable();
                    table["%item%"] = "(册条码号为: " + strItemBarcode + " URL为: " + this.OpacServerUrl + "/book.aspx?barcode=" + strItemBarcode + " )";
                    table["%reservetime%"] = this.GetDisplayTimePeriodStringEx(this.ArrivedReserveTimeSpan);
                    table["%today%"] = DateTime.Now.ToString();
                    table["%summary%"] = strSummary;
                    table["%itembarcode%"] = strItemBarcode;
                    table["%name%"] = strName;

                    string strBody = "";

                    nRet = GetMailText(strTemplate,
                        table,
                        out strBody,
                        out strError);
                    if (nRet == -1)
                        return -1;

                    // 发送消息
                    nRet = message_interface.HostObj.SendMessage(
                        strReaderBarcode,
                        strReaderXml,
                        strBody,
                        strLibraryCode,
                        out strError);
                    if (nRet == -1)
                    {
                        strTotalError += "发送"+message_interface.Type+"消息时出错: " + strError + "\r\n";
                    }
                }
            }

            if (String.IsNullOrEmpty(strTotalError) == false)
            {
                strError = strTotalError;
                return -1;
            }

            return 0;
        }