系统配置:馆藏地定义,ItemCanBorrow() ItemCanReturn() 脚本
为优化自定义册允许借出和还回的特性:
-
library.xml 中 locationTypes//item 馆藏地定义中增加了 javascript 脚本
-
library.xml 中 ItemCanBorrow() 和 ItemCanReturn 脚本增加了一个新参数 readerdom
GetEntities() API 当 strStyle 中包含 'opac' 时
opac 风格的册记录 XML 产生原理
所返回的册记录 XML 中包含了一些服务器添加的成分,以更好地反应册的各种状态。注意这些元素或者属性,不是册记录里面固有的,而是 GetEntities() API 请求返回前服务器给添加的东西。这种特殊的 XML 记录内容,一般是提供给 OPAC 等前端使用;而出于编辑保存目的,不要用这种方式获取册记录 XML。
<dprms:item path="中文图书实体/1229" timestamp="e03cc15aa117d4080000000000001160">
<barcode>T0000011</barcode>
<location>流通库</location>
<parent>611</parent>
<refID>d2018abf-b750-4037-b09d-46a2357324d0</refID>
<bookType>普通</bookType>
<canBorrow canBorrow="false">册 T0000011 的馆藏地点为 '流通库',不允许外借。原因: 读者记录未指定,无法判断是否可以外借</canBorrow>
<stateMessage>册 T0000011 的馆藏地点为 '流通库',不允许外借。原因: 读者记录未指定,无法判断是否可以外借</stateMessage>
</dprms:item>
服务器会检查这一册图书是否允许外借。如果不允许外借,则会在册记录 XML 中创建一个 canBorrow 元素,其文本内容为详细信息。canBorrow 元素具有一个 canBorrow 属性,表示是否允许外借,默认值“yes”。如果册允许外借,canBorrow 元素不会被创建。
检查的具体流程为:1) 先尝试调用 library.xml 中 script 元素内的 ItemCanBorrow() 脚本函数。如果函数存在,则根据调用返回值决定是否允许外借;如果函数不存在,则继续检查。2) 从 locationTypes 元素内馆藏地定义中,找到册所在分馆的馆藏地定义,看 canborrow 属性值。如果为 "yes" 或者 "no",即可决定允许或者不允许外借;如果为 "javascript:" 开头的脚本,则需要执行这一段脚本,详情可看 library.xml 介绍文字。执行脚本的 result 返回值可能为 "yes" "no" "unknown" 三种。后两种会当作不允许外借。(注:"unknown"一般对应 readerdom 参数为空的情况,表示无法判断)
检查使用当前登录用户的身份进行。这个身份会影响到调用脚本时的参数。如果当前登录者是工作人员,则 readerdom 为空;如果当前登录者的身份是读者,则 readerdom 不为空。
dp2OPAC 如何显示册记录详情页面
dp2OPAC 是通过 'opac' 风格的 GetEntities() API 获得需要显示的册记录信息的。所以册记录 XML 记录中可能会包含 canBorrow 元素。用它可以决定每一册前面的 checkbox 是否 enabled。如果不允许借出的图书,就把 checkbox 显示为 disabled 状态。并且 checkbox 上可以出现解释文字的 tooltips。
册信息中“状态”栏,本来是显示册记录 state 元素的内容。但做了一些优化。如果 canBorrow 表明此册不允许外借,则主动为 state 元素内容附加上一段 “[不可借]”显示出来。曾经有一种做法是直接把解释如何不允许外借的文字作为状态显示,但这段文字太长会把表格撑宽不好看,所以最后还是采用了这种方括号显示固定几个汉字的做法,但在这几个汉字上用 HTML a 元素做了一个 tips,可以飞出来显示详细的如何不允许外借的解释文字。
那么,实际上不允许外借的图书,其 checkbox 已经被显示为 disabled 状态,无法进行预约操作了。所以这里无法直接测试验证,明明不可外借非要进行预约的操作。需要借助其他工具模块进行测试了。目前最新版的 dp2library Reservation() API 已经主动检查 new 的时候是否允许外借,如果不允许外借预约也不能成功。
如何体验和调试 canborrow 或 canreturn 属性中的 javascript 代码
这里提供一种方法。 准备条件和操作办法:
- 准备一条册记录,记下它的册条码号;记下它的馆藏地(例如,馆藏地为 '流通库');
- 在内务前端系统管理窗的“馆藏地”属性页,给这个馆藏地(例如 '流通库')定义 canborrow 脚本(脚本例子后面给出);
- 在内务前端打开快捷出纳窗,执行借书功能。先输入一个读者证条码号,然后输入刚才准备的册记录的册条码号,模拟借出操作。
在每轮模拟借出操作之前,设置好如下的例子 javascript 脚本代码。这里是为了理解 javascript 代码运行的效果;而操作时在出纳窗中显示借阅操作被拒绝是意料之中的,我们不在意这个结果。
例1:
javascript:
result = "no";
message = "Account:Location=(" + account.Location + ")";
这一段代码是为了显示 dp2library 为 javascript 脚本执行准备的环境变量 account,它的 Location 成员。Location 成员显示了当前用户的工作台号。这是启动内务前端时候,在登录对话框的“工作台号”里面输入的字符串。 这里解释一下,工作台号,是工作人员为了规划工作流程,主动在内务登录时候输入的一个字符串。这个字符串是自由的,设定为人容易理解的地点名字即可。比如“一楼出纳台”。这样,javascript 脚本就可以用这个字符串来识别出,借书操作是某个具体的工作地点的电脑发出的。当希望约束读者在某些特定的出纳台进行借书还书的时候,这个成员变量很有用处。但强调一下,前端登录时候设定什么工作台号,这完全是前端工作人员的自由,从系统管理员的角度,一般没法强制约束工作人员一定设定什么内容(只能是建议和督促)。 第三方应用的前端,登录时候用什么工作台号,也是这些前端的自由了。
例2:
javascript:
result = "no";
message = "Account:Type=(" + account.Type + ")";
这段代码是为了显示 dp2library 为 javascript 脚本执行准备的环境变量 account,它的 Type 成员。Type 成员显示了当前用户的身份类型。这是启动内务前端时候,在登录对话框的是否勾选“读者”checkbox 所决定的。可能的值,有 空/worker/reader 三种。空和worker 都表示这是工作人员身份。reader 是读者身份。
Patron可用对象成员详细的情况
patron对象下有很多成员,每个成员获取的读者信息不同,在馆藏地借还脚本中可以用javascript代码调用patron对象,用来对借还权限详细规划.
例如:patron.department 获取读者部门信息,用以下javascript代码可以测试效果:
javascript:
result = "no";
message = "Patron.department=(" + patron.department + ")";
下面为可用的Patron对象成员详细列表
| 对象成员 | 获取读者内容 |
|---|---|
| patron.barcode | 读者条形码 |
| patron.state | 读者状态 |
| patron.readerType | 读者类型 |
| patron.createDate | 创建日期 |
| patron.expireDate | 失效日期 |
| patron.name | 读者姓名 |
| patron.namePinyin | 姓名拼音 |
| patron.gende | 读者性别 |
| patron.dateOfBirth | 出生日期 |
| patron.refID | 读者参考ID |
| patron.idCardNumber | 读者身份证号 |
| patron.department | 读者部门 |
| patron.post | 读者职务 |
| patron.address | 读者地址信息 |
| patron.tel | 读者电话 |
| patron.email | 读者电话 |
| patron.cardNumber | 读者证号 |
| patron.fingerprint | 读者指纹信息 |
| patron.rights | 读者权限 |
| patron.friends | 读者好友 |
| patron.access | 存取定义 |
| patron.DbName | 读者记录所在的读者库 |
| patron.Path | 读者记录路径 |
Item可用对象成员详细的情况
Item是关于册信息的对象,调用Item成员可以读取到册的相关信息,在馆藏地借还脚本中可以用javascript代码调用Item对象,根据册的属性调整借还权限. 例如:item.bookType获取读者部门信息,用以下javascript代码可以测试效果: 以读取册的册类型举例:
javascript:
result = "no";
message = "Item.bookType=(" + item.bookType + ")";
| 对象成员 | 获取册内容 |
|---|---|
| item.refID | 册参考ID |
| item.state | 册状态 |
| item.barcode | 册条形码 |
| item.publishTime | 册出版日期 |
| item.location | 馆藏地 |
| item.bookType | 册类型 |
| item.batchNo | 册批次号 |
| item.mergeComment | 合并注释 |
| item.comment | 附注 |
| item.registerNo | 登录号 |
| item.price | 册价格 |
| item.source | 经费来源 |
| item.seller | 渠道 |
| item.barcode | 册条码号 |
| item.parent | 册ID号 |
| item.volume | 未知 |
| item.accessNo | 索取号 |
| item.intact | 完好率 |
| item.bindingCost | 装订费 |
| item.oldRefID | 未知 |
| item.shelfNo | 未知 |
| item.DbName | 册记录所在的实体数据库名 |
| item.Path | 册记录路径 |
account对象可用成员详细
account是关于账户的相关信息变量对象,调用account函数可以获取到账户相关的一些信息 以account.LoginName为例,可以用下面的JS代码在dp2内务中实际测试效果:
javascript:
result = "no";
message = "account.LoginName=(" +account.LoginName + ")";
下面是account对象成员列表:
| 对象成员 | 获取账户内容 |
|---|---|
| account.Location | 工作台号 |
| account.LoginName | 登录名 |
| account.Type | 账户类型(工作人员或读者) |
| account.Rights | 账户权限 |
| account.AccountLibraryCode | 账户所属的馆代码(馆代码空表示这是一个全局账户) |
| account.Access | 账户存取权限代码 |
| account.UserID | 账户ID(对于工作人员类型,这是账户名;对于读者类型,这就是证条码号) |
| account.Binding | 账户绑定信息 |
| account.Barcode | 证条码号(读者类型账户) |
| account.Name | 账户名(读者类型账户) |
| account.PersonalLibrary | 书斋名(读者类型账户) |
| account.XmlDocument | 读者记录的XML信息 |
| account.PatronDomPath | 读者记录路径 |
| account.RightsOrigin | 账户原始权限定义 |
参见: https://github.com/DigitalPlatform/dp2/issues/644