|
|
|
@ -6,21 +6,34 @@
|
|
|
|
|
*/
|
|
|
|
|
package com.emr.controller;
|
|
|
|
|
|
|
|
|
|
import com.emr.dao.ArchiveDetailCaCopyMapper;
|
|
|
|
|
import com.emr.dao.Archive_Detail_ca_reqParamMapper;
|
|
|
|
|
import com.emr.dao.CaDepartIdMapper;
|
|
|
|
|
import com.emr.dao.CaSignatureMapper;
|
|
|
|
|
import com.emr.dto.Archive_DetailPdfPathDto;
|
|
|
|
|
import com.emr.entity.*;
|
|
|
|
|
import com.emr.service.*;
|
|
|
|
|
import com.emr.service.ipml.CaSignServiceImpl;
|
|
|
|
|
import com.emr.service.ipml.Archive_Detai_CaSignServiceImpl;
|
|
|
|
|
import com.emr.util.*;
|
|
|
|
|
import com.emr.vo.CaDepartIdVo;
|
|
|
|
|
import com.emr.webservice.MedicalRecordShowBackContent.MR_FILE_CALLBACK_RECORD;
|
|
|
|
|
import com.emr.webservice.MedicalRecordShowBackContent.MR_FILE_INDEX_CALLBACK;
|
|
|
|
|
import com.lowagie.text.pdf.PdfReader;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import okhttp3.*;
|
|
|
|
|
import org.apache.axis.client.Call;
|
|
|
|
|
import org.apache.axis.client.Service;
|
|
|
|
|
import org.apache.axis.encoding.XMLType;
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
import org.json.JSONObject;
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
|
|
import org.springframework.stereotype.Controller;
|
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
import org.springframework.ui.Model;
|
|
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
|
|
import org.springframework.web.bind.annotation.RequestMapping;
|
|
|
|
|
import org.springframework.web.bind.annotation.ResponseBody;
|
|
|
|
|
|
|
|
|
@ -30,19 +43,19 @@ import javax.servlet.http.HttpServletResponse;
|
|
|
|
|
import javax.xml.namespace.QName;
|
|
|
|
|
import javax.xml.rpc.ParameterMode;
|
|
|
|
|
import javax.xml.rpc.ServiceException;
|
|
|
|
|
import java.io.FileInputStream;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.io.OutputStream;
|
|
|
|
|
import java.io.UnsupportedEncodingException;
|
|
|
|
|
import java.io.*;
|
|
|
|
|
import java.nio.file.Files;
|
|
|
|
|
import java.rmi.RemoteException;
|
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
|
|
|
|
|
@Controller
|
|
|
|
|
@RequestMapping("lastVerify")
|
|
|
|
|
@Slf4j
|
|
|
|
|
public class lastVerifyController {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Value("${EMRQualityControl}")
|
|
|
|
|
private String EMRQualityControl;
|
|
|
|
|
@Value("${EMRQualityControlParamName}")
|
|
|
|
@ -58,11 +71,36 @@ public class lastVerifyController {
|
|
|
|
|
|
|
|
|
|
@Autowired(required = false)
|
|
|
|
|
private Archive_Master_FollowingService archive_master_followingService;
|
|
|
|
|
@Resource
|
|
|
|
|
private CaSignServiceImpl caSignService;
|
|
|
|
|
@Value("${isCaOpen}")
|
|
|
|
|
private int isCaOpen;
|
|
|
|
|
@Value("${newPdfPath}")
|
|
|
|
|
private String newPdfPath;
|
|
|
|
|
@Autowired
|
|
|
|
|
private Archive_DetailService archiveDetailService;
|
|
|
|
|
@Autowired
|
|
|
|
|
private Archive_Detai_CaSignServiceImpl archiveDetaiCaSignService;
|
|
|
|
|
@Autowired
|
|
|
|
|
private Archive_Detail_ca_reqParamMapper archiveDetailCaReqParamMapper;
|
|
|
|
|
@Autowired
|
|
|
|
|
private CaSignatureMapper caSignatureMapper;
|
|
|
|
|
@Autowired
|
|
|
|
|
private ArchiveDetailCaCopyMapper archiveDetailCaCopyMapper;
|
|
|
|
|
@Autowired
|
|
|
|
|
private CaDepartIdMapper caDepartIdMapper;
|
|
|
|
|
@Value("${synDepartUrl}")
|
|
|
|
|
private String synDepartUrl;
|
|
|
|
|
@Value("${signUrl}")
|
|
|
|
|
private String signUrl;
|
|
|
|
|
|
|
|
|
|
@Value("${clientId}")
|
|
|
|
|
private String clientId;
|
|
|
|
|
@Value("${clientSecret}")
|
|
|
|
|
private String clientSecret;
|
|
|
|
|
@Autowired
|
|
|
|
|
private Emr_DictionaryService emrDictionaryService;
|
|
|
|
|
|
|
|
|
|
private static final Logger log = LoggerFactory.getLogger(lastVerifyController.class);
|
|
|
|
|
|
|
|
|
|
@RequestMapping(value = "/lastVerifys")
|
|
|
|
|
public String faults(Model model) {
|
|
|
|
|
return "lastVerifyDir/lastVerifyList";
|
|
|
|
@ -263,9 +301,11 @@ public class lastVerifyController {
|
|
|
|
|
String handleName = user.getUserPosition();//姓名
|
|
|
|
|
String username = user.getUserName();//工号
|
|
|
|
|
//调用ca签章接口
|
|
|
|
|
Msg msg = caSignService.caSignByMasterId(emrFaultDetail.getArchiveDetailId(), user);
|
|
|
|
|
if (msg.getCode()==200){
|
|
|
|
|
return Msg.fail("使用签章时失败");
|
|
|
|
|
if (isCaOpen==1){
|
|
|
|
|
Msg msg = caSignByMasterId(emrFaultDetail.getArchiveDetailId(), user);
|
|
|
|
|
if (msg.getCode()==200){
|
|
|
|
|
return Msg.fail(msg.getMsg());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//修改病案归档状态
|
|
|
|
|
Archive_Master archiveMaster = new Archive_Master();
|
|
|
|
@ -276,7 +316,6 @@ public class lastVerifyController {
|
|
|
|
|
//归档记录添加到commomtable表
|
|
|
|
|
CommomVo commomVo = new CommomVo();
|
|
|
|
|
archiveMaster.setCmtNurse(1);
|
|
|
|
|
|
|
|
|
|
List<Archive_Master> archiveMasters = archiveMasterService.selectCommonlyUsed(emrFaultDetail.getArchiveDetailId());
|
|
|
|
|
for (Archive_Master list : archiveMasters) {
|
|
|
|
|
commomVo.setPatientId(list.getId());
|
|
|
|
@ -320,6 +359,96 @@ public class lastVerifyController {
|
|
|
|
|
return Msg.success();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Msg caSignByMasterId(String masterId, Power_User user) {
|
|
|
|
|
if (isCaOpen == 0) {
|
|
|
|
|
return Msg.success();
|
|
|
|
|
}
|
|
|
|
|
//根据masterId查询文件集合
|
|
|
|
|
try {
|
|
|
|
|
List<Archive_DetailPdfPathDto> pdfPathList = archiveDetailService.getPdfPathByMasterId(masterId);
|
|
|
|
|
if (!CollectionUtils.isEmpty(pdfPathList)) {
|
|
|
|
|
|
|
|
|
|
//判断该部门是否存在签章
|
|
|
|
|
CaDepartIdVo caDepartIdVo = caDepartIdMapper.getDepartId(user.getRemark());
|
|
|
|
|
//没有保存部门签章id时需要请求获取一个新的departId
|
|
|
|
|
if (caDepartIdVo==null){
|
|
|
|
|
//请求医院科室在医网信标识id
|
|
|
|
|
String departId = getDepartId(user);
|
|
|
|
|
caDepartIdMapper.addDepartId(user.getRemark(),departId);
|
|
|
|
|
return Msg.fail("该用户科室没有在医信网平台申请部门签章请联系医信网人员");
|
|
|
|
|
}
|
|
|
|
|
if (StringUtils.isBlank(caDepartIdVo.getDataId())) {
|
|
|
|
|
return Msg.fail("部门标识为空");
|
|
|
|
|
}
|
|
|
|
|
String dataId = caDepartIdVo.getDataId();
|
|
|
|
|
System.out.println("dataId:"+dataId);
|
|
|
|
|
//保存文件表数据list
|
|
|
|
|
List<Archive_DetailPdfPathDto> list = new ArrayList<>();
|
|
|
|
|
//签章后保存目录
|
|
|
|
|
String newPath = newPdfPath + File.separator + masterId;
|
|
|
|
|
//没有目录创建目录
|
|
|
|
|
if (!new File(newPath).isDirectory()) {
|
|
|
|
|
new File(newPath).mkdirs();
|
|
|
|
|
}
|
|
|
|
|
//查询签章位置比例
|
|
|
|
|
Archive_Detail_ca_reqParam caReqParam = archiveDetailCaReqParamMapper.selectAll();
|
|
|
|
|
//定义此次需要签章的文件id集合
|
|
|
|
|
List<String> idList = new ArrayList<>();
|
|
|
|
|
//签章失败文件id集合
|
|
|
|
|
List<String> failIdList = new ArrayList<>();
|
|
|
|
|
System.out.println("11");
|
|
|
|
|
//遍历文件集合
|
|
|
|
|
for (Archive_DetailPdfPathDto dto : pdfPathList) {
|
|
|
|
|
SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMddHHmmssSSS");
|
|
|
|
|
//获取今天日期
|
|
|
|
|
String todayDate = fmt.format(new Date());
|
|
|
|
|
//签章后地址
|
|
|
|
|
String newPdfPath = newPath + File.separator + todayDate+".pdf";
|
|
|
|
|
//获取文件路径
|
|
|
|
|
String pdfPath = dto.getPdfPath();
|
|
|
|
|
File file = new File(pdfPath);
|
|
|
|
|
System.out.println("22:");
|
|
|
|
|
if (file.isFile()) {
|
|
|
|
|
String pdfPathString = pdfToBase64(pdfPath);
|
|
|
|
|
PdfReader pdfReader = new PdfReader(pdfPath);
|
|
|
|
|
System.out.println("44");
|
|
|
|
|
int pageCount = pdfReader.getNumberOfPages();
|
|
|
|
|
Msg msg = sign(pdfPathString, dataId,caReqParam,pageCount);
|
|
|
|
|
if (msg.getCode()!=100){
|
|
|
|
|
return Msg.fail();
|
|
|
|
|
}
|
|
|
|
|
String newPdfPathBase64 = msg.getMsg();
|
|
|
|
|
if (!convertBase64ToPdf(newPdfPathBase64, newPdfPath)){
|
|
|
|
|
return Msg.fail();
|
|
|
|
|
}
|
|
|
|
|
dto.setPdfPath(newPdfPath);
|
|
|
|
|
} else {
|
|
|
|
|
return Msg.fail();
|
|
|
|
|
}
|
|
|
|
|
list.add(dto);
|
|
|
|
|
}
|
|
|
|
|
//添加签章记录
|
|
|
|
|
updateCaFileState(idList, failIdList, masterId);
|
|
|
|
|
//判断是否存在,存在在先删除
|
|
|
|
|
int caMasterId = caSignatureMapper.getCaMasterId(masterId, 1);
|
|
|
|
|
if (caMasterId > 0) {
|
|
|
|
|
archiveDetailCaCopyMapper.updateByMasterID(masterId);
|
|
|
|
|
caSignatureMapper.delCaMasterId(masterId);
|
|
|
|
|
}
|
|
|
|
|
//签章完后保存新的文件表
|
|
|
|
|
archiveDetailCaCopyMapper.addArchiveDetailCaCopyMapper(list);
|
|
|
|
|
//签章完成后保存状态
|
|
|
|
|
caSignatureMapper.addCaSignature(masterId, 1);
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println(e+e.getMessage());
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
return Msg.fail("请求失败");
|
|
|
|
|
}
|
|
|
|
|
return Msg.success();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ResponseBody
|
|
|
|
|
@RequestMapping(value = "/updateSignState")
|
|
|
|
|
public String updateSignState(HttpServletRequest request, HttpServletResponse response, Archive_Master archiveMaster) throws UnsupportedEncodingException {
|
|
|
|
@ -609,6 +738,210 @@ public class lastVerifyController {
|
|
|
|
|
|
|
|
|
|
return archiveMaster;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//将pdf文件base64方法
|
|
|
|
|
public static String pdfToBase64(String filePath) throws IOException {
|
|
|
|
|
File file = new File(filePath);
|
|
|
|
|
// 读取文件内容到字节数组
|
|
|
|
|
byte[] fileContent = Files.readAllBytes(file.toPath());
|
|
|
|
|
// 将字节数组编码为Base64字符串
|
|
|
|
|
System.out.println("33");
|
|
|
|
|
return Base64.getEncoder().encodeToString(fileContent);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
//将base64转为pdf方法
|
|
|
|
|
public Boolean convertBase64ToPdf(String base64String, String filePath) {
|
|
|
|
|
try {
|
|
|
|
|
// 解码Base64字符串
|
|
|
|
|
byte[] decodedBytes = Base64.getDecoder().decode(base64String);
|
|
|
|
|
|
|
|
|
|
// 将解码后的数据写入PDF文件
|
|
|
|
|
try (FileOutputStream fos = new FileOutputStream(filePath)) {
|
|
|
|
|
fos.write(decodedBytes);
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//签章接口
|
|
|
|
|
private Msg sign(String pdfPathString,String departId,Archive_Detail_ca_reqParam caReqParam,int pageCount) {
|
|
|
|
|
try {
|
|
|
|
|
System.out.println("55");
|
|
|
|
|
// 创建OkHttpClient实例
|
|
|
|
|
OkHttpClient client = HttpClientUtil.getClient();
|
|
|
|
|
System.out.println("10");
|
|
|
|
|
// 定义请求的URL
|
|
|
|
|
String url = signUrl;
|
|
|
|
|
String pdfSignBase64="";
|
|
|
|
|
// 创建请求体
|
|
|
|
|
String json = "{"
|
|
|
|
|
+ "\"head\": {"
|
|
|
|
|
+ "\"clientId\": \"" + clientId + "\","
|
|
|
|
|
+ "\"clientSecret\": \"" + clientSecret + "\","
|
|
|
|
|
+ "},"
|
|
|
|
|
+ "\"body\": {"
|
|
|
|
|
+ "\"pdfBase64\": \"" + pdfPathString + "\","
|
|
|
|
|
+ "\"departId\": \"" + departId + "\","
|
|
|
|
|
// + "\"keyword\": \"医师签名\","
|
|
|
|
|
// + "\"moveType\": \"1\","
|
|
|
|
|
// + "\"searchOrder\": \"2\","
|
|
|
|
|
// + "\"scale\": \"0.4\","
|
|
|
|
|
// + "\"fileType\": \"2\","
|
|
|
|
|
+ "\"positionType\": \"1\","
|
|
|
|
|
+ "\"x\": \"" + caReqParam.getSignTop() + "\","
|
|
|
|
|
+ "\"y\": \"" + caReqParam.getSignLeft() + "\","
|
|
|
|
|
+ "}"
|
|
|
|
|
+ "}";
|
|
|
|
|
// 创建RequestBody
|
|
|
|
|
|
|
|
|
|
log.info("签章传参“:"+json);
|
|
|
|
|
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
|
|
|
|
|
System.out.println("77");
|
|
|
|
|
// 创建Request
|
|
|
|
|
Request request = new Request.Builder()
|
|
|
|
|
.url(url)
|
|
|
|
|
.post(requestBody)
|
|
|
|
|
.build();
|
|
|
|
|
try {
|
|
|
|
|
// 执行请求
|
|
|
|
|
Response response = client.newCall(request).execute();
|
|
|
|
|
|
|
|
|
|
// 检查响应状态码
|
|
|
|
|
if (response.isSuccessful()) {
|
|
|
|
|
// 获取响应体
|
|
|
|
|
String responseData = response.body().string();
|
|
|
|
|
|
|
|
|
|
// 解析JSON响应
|
|
|
|
|
JSONObject jsonResponse = new JSONObject(responseData);
|
|
|
|
|
// 获取返回的参数
|
|
|
|
|
pdfSignBase64 = jsonResponse.getJSONObject("data").getString("pdfSignBase64");
|
|
|
|
|
String status = jsonResponse.getString("status");
|
|
|
|
|
if (!status.equals("0")){
|
|
|
|
|
return Msg.fail("请求失败");
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
System.out.println("请求失败,状态码:" + response.code());
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println(e+e.getMessage());
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
return Msg.fail("请求失败,状态码:");
|
|
|
|
|
}
|
|
|
|
|
return Msg.success(pdfSignBase64);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
System.out.println(e+e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
return Msg.success("成功");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//请求医信网标识id
|
|
|
|
|
public String getDepartId(Power_User user) {
|
|
|
|
|
// 创建OkHttpClient实例
|
|
|
|
|
OkHttpClient client = HttpClientUtil.getClient();
|
|
|
|
|
|
|
|
|
|
// 定义请求的URL
|
|
|
|
|
String url = synDepartUrl;
|
|
|
|
|
String dataId = "";
|
|
|
|
|
// 创建请求体
|
|
|
|
|
String json = "{"
|
|
|
|
|
+ "\"head\": {"
|
|
|
|
|
+ "\"clientId\": \"" + clientId + "\","
|
|
|
|
|
+ "\"clientSecret\": \"" + clientSecret + "\","
|
|
|
|
|
+ "},"
|
|
|
|
|
+ "\"body\": {"
|
|
|
|
|
+ "\"thirdDepartId\": \"3040000\","
|
|
|
|
|
+ "\"departName\": \"病案室\","
|
|
|
|
|
+ "\"departPhone\": \"" + user.getUserEmail() + "\","
|
|
|
|
|
+ "\"departPerson\": \"" + user.getUserPosition() + "\","
|
|
|
|
|
+ "\"clientOrgCode\": \"BAS\","
|
|
|
|
|
+ "\"clientOrgType\": \"ORG\""
|
|
|
|
|
+ "}"
|
|
|
|
|
+ "}";
|
|
|
|
|
|
|
|
|
|
// 创建RequestBody
|
|
|
|
|
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
|
|
|
|
|
|
|
|
|
|
// 创建Request
|
|
|
|
|
Request request = new Request.Builder()
|
|
|
|
|
.url(url)
|
|
|
|
|
.post(requestBody)
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 执行请求
|
|
|
|
|
Response response = client.newCall(request).execute();
|
|
|
|
|
|
|
|
|
|
// 检查响应状态码
|
|
|
|
|
if (response.isSuccessful()) {
|
|
|
|
|
// 获取响应体
|
|
|
|
|
String responseData = response.body().string();
|
|
|
|
|
|
|
|
|
|
// 解析JSON响应
|
|
|
|
|
JSONObject jsonResponse = new JSONObject(responseData);
|
|
|
|
|
|
|
|
|
|
// 获取返回的参数
|
|
|
|
|
dataId = jsonResponse.getJSONObject("data").getString("departId");
|
|
|
|
|
String message = jsonResponse.getString("message");
|
|
|
|
|
String status = jsonResponse.getString("status");
|
|
|
|
|
boolean successful = jsonResponse.getBoolean("successful");
|
|
|
|
|
|
|
|
|
|
// 输出解析结果
|
|
|
|
|
System.out.println("DepartId: " + dataId);
|
|
|
|
|
System.out.println("Message: " + message);
|
|
|
|
|
System.out.println("Status: " + status);
|
|
|
|
|
System.out.println("Successful: " + successful);
|
|
|
|
|
} else {
|
|
|
|
|
System.out.println("请求失败,状态码:" + response.code());
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
return dataId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @Description: updateCaFileState方法是更新ca签章
|
|
|
|
|
* @param: [idList, masterId]
|
|
|
|
|
* @return: void
|
|
|
|
|
* @author 曾文和
|
|
|
|
|
* @createTime 2023/7/25 16:19
|
|
|
|
|
*/
|
|
|
|
|
public void updateCaFileState(List<String> idList, List<String> failIdList, String masterId) {
|
|
|
|
|
if (!CollectionUtils.isEmpty(idList)) {
|
|
|
|
|
//先删除原有签章记录
|
|
|
|
|
archiveDetaiCaSignService.deletesFromMasterId(masterId);
|
|
|
|
|
//后新增
|
|
|
|
|
List<Archive_Detail_caSign> list = new ArrayList<>();
|
|
|
|
|
Date date = new Date();
|
|
|
|
|
for (String id : idList) {
|
|
|
|
|
Archive_Detail_caSign obj = new Archive_Detail_caSign();
|
|
|
|
|
obj.setArchiveDetailId(id);
|
|
|
|
|
obj.setMasterId(masterId);
|
|
|
|
|
obj.setSignTime(date);
|
|
|
|
|
obj.setCaStatic(1);
|
|
|
|
|
list.add(obj);
|
|
|
|
|
}
|
|
|
|
|
if (!CollectionUtils.isEmpty(failIdList)) {
|
|
|
|
|
for (String id : failIdList) {
|
|
|
|
|
Archive_Detail_caSign obj = new Archive_Detail_caSign();
|
|
|
|
|
obj.setArchiveDetailId(id);
|
|
|
|
|
obj.setMasterId(masterId);
|
|
|
|
|
obj.setSignTime(date);
|
|
|
|
|
obj.setCaStatic(2);
|
|
|
|
|
list.add(obj);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//批量新增
|
|
|
|
|
archiveDetaiCaSignService.insertBatchCaSign(list);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|