package open.dolphin.session;
import java.beans.XMLDecoder;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.inject.Named;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
//import javax.jms.QueueSession;
import javax.jms.Session;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import open.dolphin.infomodel.AttachmentModel;
import open.dolphin.infomodel.DocumentModel;
import open.dolphin.infomodel.HealthInsuranceModel;
import open.dolphin.infomodel.IInfoModel;
import open.dolphin.infomodel.KarteBean;
import open.dolphin.infomodel.ModuleModel;
import open.dolphin.infomodel.PVTHealthInsuranceModel;
import open.dolphin.infomodel.PatientModel;
import open.dolphin.infomodel.PatientVisitModel;
import open.dolphin.infomodel.ProgressCourse;
import open.dolphin.infomodel.SchemaModel;
import open.dolphin.infomodel.UserModel;
import open.dolphin.msg.ClaimSender;
import open.dolphin.touch.converter.IOSHelper;
/**
* (予定カルテ対応)
* @author kazushi Minagawa.
*/
@Named
@Stateless
public class ScheduleServiceBean {
private static final String QUERY_PVT_BY_FID_DATE
= "from PatientVisitModel p where p.facilityId=:fid and p.pvtDate like :date order by p.pvtDate";
private static final String QUERY_PVT_BY_FID_DID_DATE
= "from PatientVisitModel p where p.facilityId=:fid and p.pvtDate like :date and (doctorId=:did or doctorId=:unassigned) order by p.pvtDate";
private static final String QUERY_INSURANCE_BY_PATIENT_ID
= "from HealthInsuranceModel h where h.patient.id=:id";
private static final String QUERY_KARTE
= "from KarteBean k where k.patient.id=:patientPk";
private static final String QUERY_LASTDOC_DATE_BY_KARTEID_FINAL
//minagawa^ LSC Test
//= "select max(m.started) from DocumentModel m where m.karte.id=:karteId and (m.status='F' or m.status='T')";
= "select max(m.started) from d_document m where m.karte_id=:karteId and m.docType=:docType and (m.status = 'F' or m.status = 'T')";
//minagawa$
private static final String QUERY_DOCUMENT_BY_KARTEID_STARTDATE
= "from DocumentModel d where d.karte.id=:karteId and d.started=:started and (d.status='F' or d.status='T')";
private static final String QUERY_DOCUMENT_BY_LINK_ID
= "from DocumentModel d where d.linkId=:id";
private static final String QUERY_MODULE_BY_DOC_ID
= "from ModuleModel m where m.document.id=:id";
private static final String QUERY_SCHEMA_BY_DOC_ID
= "from SchemaModel i where i.document.id=:id";
private static final String QUERY_ATTACHMENT_BY_DOC_ID
= "from AttachmentModel a where a.document.id=:id";
@PersistenceContext
private EntityManager em;
//s.oh^ 2014/02/21 Claim送信方法の変更
//@Resource(mappedName = "java:/JmsXA")
//private ConnectionFactory connectionFactory;
//
//@Resource(mappedName = "java:/queue/dolphin")
//private javax.jms.Queue queue;
//s.oh$
public List<PatientVisitModel> getPvt(String fid, String did, String unassigned, String date) {
List<PatientVisitModel> result;
if (did==null && unassigned==null) {
result = (List<PatientVisitModel>) em.createQuery(QUERY_PVT_BY_FID_DATE)
.setParameter("fid", fid)
.setParameter("date", date+"%")
.getResultList();
} else {
result = (List<PatientVisitModel>) em.createQuery(QUERY_PVT_BY_FID_DID_DATE)
.setParameter("fid", fid)
.setParameter("did", did)
.setParameter("unassigned", unassigned)
.setParameter("date", date+"%")
.getResultList();
}
int len = result.size();
if (len == 0) {
return result;
}
// Dateへ変換
Date startDate = dateFromString(date);
// 来院情報と患者は ManyToOne の関係である
for (int i = 0; i < len; i++) {
PatientVisitModel pvt = result.get(i);
PatientModel patient = pvt.getPatientModel();
// 患者の健康保険を取得する
List<HealthInsuranceModel> insurances = (List<HealthInsuranceModel>)em.createQuery(QUERY_INSURANCE_BY_PATIENT_ID)
.setParameter("id", patient.getId()).getResultList();
patient.setHealthInsurances(insurances);
List<KarteBean> kartes = em.createQuery(QUERY_KARTE)
.setParameter("patientPk", patient.getId())
.getResultList();
KarteBean karte = kartes.get(0);
// この日のカルテが存在するか
List<DocumentModel> list = (List<DocumentModel>)em.createQuery(QUERY_DOCUMENT_BY_KARTEID_STARTDATE)
.setParameter("karteId", karte.getId())
.setParameter("started", startDate)
.getResultList();
if (list!=null && !list.isEmpty()) {
pvt.setLastDocDate(startDate);
}
}
return result;
}
public int makeScheduleAndSend(long pvtPK, long userPK, Date startDate, boolean send) {
try {
// 受付情報を取得する
PatientVisitModel pvt = (PatientVisitModel)em.find(PatientVisitModel.class, pvtPK);
PatientModel patient = pvt.getPatientModel();
// 患者の健康保険を取得する
List<HealthInsuranceModel> insurances = (List<HealthInsuranceModel>)em.createQuery(QUERY_INSURANCE_BY_PATIENT_ID)
.setParameter("id", patient.getId()).getResultList();
patient.setHealthInsurances(insurances);
// 受け付けた保険をデコードする
PVTHealthInsuranceModel pvtHealthInsurance=null;
for (HealthInsuranceModel m : insurances) {
XMLDecoder d = new XMLDecoder(
new BufferedInputStream(
new ByteArrayInputStream(m.getBeanBytes())));
pvtHealthInsurance = (PVTHealthInsuranceModel)d.readObject();
break;
}
// Creator
UserModel user = em.find(UserModel.class, userPK);
// 患者のカルテを取得する
List<KarteBean> kartes = em.createQuery(QUERY_KARTE)
.setParameter("patientPk", patient.getId())
.getResultList();
KarteBean karte = kartes.get(0);
// startDateに相当する日の文書があるか startDate(00:00:00)
List<DocumentModel> list = (List<DocumentModel>)em.createQuery(QUERY_DOCUMENT_BY_KARTEID_STARTDATE)
.setParameter("karteId", karte.getId())
.setParameter("started", startDate)
.getResultList();
if (!list.isEmpty()) {
// 当日のカルテがある場合は何もしない
Logger.getLogger("open.dolphin").log(Level.INFO, "{0} has karte at {1}", new Object[]{patient.getFullName(), startDate});
return 0;
}
// 当日のカルテがない場合
DocumentModel schedule;
try {
// Documentの最終日を得る
Date lastDocDate = (Date)
//minagawa^ LSC Test
em.createNativeQuery(QUERY_LASTDOC_DATE_BY_KARTEID_FINAL)
.setParameter("karteId", karte.getId())
.setParameter("docType", "karte")
.getSingleResult();
//minagawa$
// そのDocumentを得る ToDo
List<DocumentModel> list2 = (List<DocumentModel>)em.createQuery(QUERY_DOCUMENT_BY_KARTEID_STARTDATE)
.setParameter("karteId", karte.getId())
.setParameter("started", lastDocDate)
.getResultList();
DocumentModel latest = list2.get(0);
// 予定文書(カルテ)
schedule = latest.rpClone();
//s.oh^ 2014/02/06 iPadのFreeText対応
if(schedule.getModules() != null && !schedule.getModules().isEmpty()) {
// SOA
StringBuilder sb = new StringBuilder();
sb.append("<section>");
sb.append("<paragraph>");
sb.append("<content><text></text></content>");
sb.append("</paragraph>");
sb.append("</section>");
ProgressCourse soaProgress = new ProgressCourse();
soaProgress.setFreeText(sb.toString());
ModuleModel soaSpecModule = new ModuleModel();
soaSpecModule.setBeanBytes(IOSHelper.toXMLBytes(soaProgress));
soaSpecModule.setConfirmed(latest.getConfirmed());
soaSpecModule.setStarted(latest.getStarted());
soaSpecModule.setRecorded(latest.getRecorded());
soaSpecModule.setStatus(latest.getStatus());
soaSpecModule.setUserModel(latest.getUserModel());
soaSpecModule.setKarteBean(latest.getKarteBean());
soaSpecModule.getModuleInfoBean().setStampName("progressCourse");
soaSpecModule.getModuleInfoBean().setStampRole("soaSpec");
soaSpecModule.getModuleInfoBean().setEntity("progressCourse");
soaSpecModule.getModuleInfoBean().setStampNumber(0);
soaSpecModule.setDocumentModel(schedule);
schedule.addModule(soaSpecModule);
// P
int number = 0;
sb = new StringBuilder();
sb.append("<section>");
for(int i = 0; i < schedule.getModules().size(); i++) {
if(i != 0) {
sb.append("<paragraph>");
sb.append("<content><text>\n</text></content>");
sb.append("</paragraph>");
}
sb.append("<paragraph>");
sb.append("<component component=").append("\"").append(i).append("\"").append(" name=\"stampHolder\">").append("</component>");
sb.append("<content><text></text></content>");
sb.append("<content><text>\n</text></content>");
sb.append("</paragraph>");
}
sb.append("</section>");
ProgressCourse pProgress = new ProgressCourse();
pProgress.setFreeText(sb.toString());
ModuleModel pSpecModule = new ModuleModel();
pSpecModule.setBeanBytes(IOSHelper.toXMLBytes(pProgress));
pSpecModule.setConfirmed(latest.getConfirmed());
pSpecModule.setStarted(latest.getStarted());
pSpecModule.setRecorded(latest.getRecorded());
pSpecModule.setStatus(latest.getStatus());
pSpecModule.setUserModel(latest.getUserModel());
pSpecModule.setKarteBean(latest.getKarteBean());
pSpecModule.getModuleInfoBean().setStampName("progressCourse");
pSpecModule.getModuleInfoBean().setStampRole("pSpec");
pSpecModule.getModuleInfoBean().setEntity("progressCourse");
pSpecModule.getModuleInfoBean().setStampNumber(number++);
pSpecModule.setDocumentModel(schedule);
schedule.addModule(pSpecModule);
}
//s.oh$
Logger.getLogger("open.dolphin").info("did rpClone");
} catch (Exception e) {
Logger.getLogger("open.dolphin").info("lastDocDate dose not exist");
schedule = new DocumentModel();
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
schedule.getDocInfoModel().setDocId(uuid);
schedule.getDocInfoModel().setDocType(IInfoModel.DOCTYPE_KARTE);
schedule.getDocInfoModel().setTitle("予定");
schedule.getDocInfoModel().setPurpose(IInfoModel.PURPOSE_RECORD);
schedule.getDocInfoModel().setHasRp(false);
schedule.getDocInfoModel().setVersionNumber("1.0");
Logger.getLogger("open.dolphin").info("did create new karte");
}
// Confirmed
Date now = new Date();
// DocInfoを設定する
StringBuilder sb = new StringBuilder();
sb.append(pvt.getDeptName()).append(","); // 診療科名
sb.append(pvt.getDeptCode()).append(","); // 診療科コード : 受けと不一致、受信?
sb.append(user.getCommonName()).append(","); // 担当医名
if (pvt.getDoctorId()!=null) {
sb.append(pvt.getDoctorId()).append(","); // 担当医コード: 受付でIDがある場合
} else if (user.getOrcaId()!=null) {
sb.append(user.getOrcaId()).append(","); // 担当医コード: ORCA ID がある場合
} else {
sb.append(user.getUserId()).append(","); // 担当医コード: ログインユーザーID
}
sb.append(pvt.getJmariNumber()); // JMARI
schedule.getDocInfoModel().setDepartmentDesc(sb.toString()); // 上記をカンマ区切りで docInfo.departmentDesc へ設定
schedule.getDocInfoModel().setDepartment(pvt.getDeptCode()); // 診療科コード 01 内科等
// 施設名、ライセンス、患者情報
schedule.getDocInfoModel().setFacilityName(user.getFacilityModel().getFacilityName());
schedule.getDocInfoModel().setCreaterLisence(user.getLicenseModel().getLicense());
schedule.getDocInfoModel().setPatientId(patient.getPatientId());
schedule.getDocInfoModel().setPatientName(patient.getFullName());
schedule.getDocInfoModel().setPatientGender(patient.getGenderDesc());
// 健康保険を設定する-新規カルテダイアログで選択された保険をセットしている
schedule.getDocInfoModel().setHealthInsurance(pvtHealthInsurance.getInsuranceClassCode()); // classCode
schedule.getDocInfoModel().setHealthInsuranceDesc(pvtHealthInsurance.toString()); // 説明
schedule.getDocInfoModel().setHealthInsuranceGUID(pvtHealthInsurance.getGUID()); // UUID
schedule.getDocInfoModel().setPVTHealthInsuranceModel(pvtHealthInsurance); // 適用保険
// 基本属性
schedule.setStarted(startDate);
schedule.setConfirmed(now);
schedule.setRecorded(now);
schedule.setKarteBean(karte);
schedule.setUserModel(user);
schedule.setStatus("T");
// 関係構築
List<ModuleModel> modules = schedule.getModules();
if (modules!=null) {
for (ModuleModel module : modules) {
module.setStarted(schedule.getStarted());
module.setConfirmed(schedule.getConfirmed());
module.setRecorded(schedule.getRecorded());
module.setKarteBean(schedule.getKarteBean());
module.setUserModel(user);
module.setStatus(schedule.getStatus());
module.setDocumentModel(schedule);
}
}
// CLAIM送信
send = send && (modules!=null && !modules.isEmpty());
schedule.getDocInfoModel().setSendClaim(send);
// 永続化
em.persist(schedule);
// CLAIM送信
if (send) {
//s.oh^ 2014/01/23 ORCAとの接続対応
Properties config = new Properties();
sb = new StringBuilder();
sb.append(System.getProperty("jboss.home.dir"));
sb.append(File.separator);
sb.append("custom.properties");
File f = new File(sb.toString());
try {
FileInputStream fin = new FileInputStream(f);
InputStreamReader r = new InputStreamReader(fin, "JISAutoDetect");
config.load(r);
r.close();
} catch (IOException ex) {
ex.printStackTrace(System.err);
return 1;
}
String claimConn = config.getProperty("claim.conn");
if(claimConn != null && claimConn.equals("server")) {
//s.oh$
// DocInfoへ開始日等を設定する
schedule.toDetuch();
//s.oh^ 2014/02/21 Claim送信方法の変更
//Connection conn = null;
//try {
// conn = connectionFactory.createConnection();
// Session session = conn.createSession(false, QueueSession.AUTO_ACKNOWLEDGE);
// ObjectMessage msg = session.createObjectMessage(schedule);
// MessageProducer producer = session.createProducer(queue);
// producer.send(msg);
//} catch (Exception e) {
// e.printStackTrace(System.err);
//} finally {
// if(conn != null) {
// try {
// conn.close();
// } catch (JMSException e) {
// }
// }
//}
// ORCA CLAIM 送信パラメータ
String host = config.getProperty("claim.host");
int port = Integer.parseInt(config.getProperty("claim.send.port"));
String enc = config.getProperty("claim.send.encoding");
String facilityId = config.getProperty("dolphin.facilityId");
Logger.getLogger("open.dolphin").info("Schedule message has received. Sending ORCA will start(Not Que).");
ClaimSender sender = new ClaimSender(host, port, enc);
try {
sender.send(schedule);
} catch (Exception ex) {
ex.printStackTrace(System.err);
Logger.getLogger("open.dolphin").warning("Claim send error : " + ex.getMessage());
}
//s.oh$
}
}
return 1;
} catch (Exception e) {
e.printStackTrace(System.err);
}
return 0;
}
public int removePvt(long pvtPK, long ptPK, Date startDate) {
// 受付咲くジョン
PatientVisitModel exist = (PatientVisitModel)em.find(PatientVisitModel.class, new Long(pvtPK));
em.remove(exist);
// 患者のカルテを取得する
List<KarteBean> kartes = em.createQuery(QUERY_KARTE)
.setParameter("patientPk", ptPK)
.getResultList();
KarteBean karte = kartes.get(0);
// 当日のドキュメントを検索
List<DocumentModel> list = (List<DocumentModel>)em.createQuery(QUERY_DOCUMENT_BY_KARTEID_STARTDATE)
.setParameter("karteId", karte.getId())
.setParameter("started", startDate)
.getResultList();
if (list.isEmpty()) {
return 1;
}
// それを削除
int cnt=1;
for (DocumentModel d : list) {
List<String> l = deleteDocument(d.getId());
cnt+=l.size();
}
return cnt;
}
public List<String> deleteDocument(long id) {
//----------------------------------------
// 参照されているDocumentの場合は例外を投げる
//----------------------------------------
Collection refs = em.createQuery(QUERY_DOCUMENT_BY_LINK_ID)
.setParameter("id", id).getResultList();
if (refs != null && refs.size() >0) {
CanNotDeleteException ce = new CanNotDeleteException("他のドキュメントから参照されているため削除できません。");
throw ce;
}
// 終了日
Date ended = new Date();
// 削除件数
int cnt=0;
// 削除リスト 文書ID
List<String> list = new ArrayList<String>();
// Loop で削除
while (true) {
try {
//-----------------------
// 対象 Document を取得する
//-----------------------
DocumentModel delete = (DocumentModel)em.find(DocumentModel.class, id);
//------------------------
// 削除フラグをたてる
//------------------------
delete.setStatus(IInfoModel.STATUS_DELETE);
delete.setEnded(ended);
cnt++;
list.add(delete.getDocInfoModel().getDocId());
//------------------------------
// 関連するモジュールに同じ処理を行う
//------------------------------
Collection deleteModules = em.createQuery(QUERY_MODULE_BY_DOC_ID)
.setParameter("id", id).getResultList();
for (Iterator iter = deleteModules.iterator(); iter.hasNext(); ) {
ModuleModel model = (ModuleModel) iter.next();
model.setStatus(IInfoModel.STATUS_DELETE);
model.setEnded(ended);
}
//------------------------------
// 関連する画像に同じ処理を行う
//------------------------------
Collection deleteImages = em.createQuery(QUERY_SCHEMA_BY_DOC_ID)
.setParameter("id", id).getResultList();
for (Iterator iter = deleteImages.iterator(); iter.hasNext(); ) {
SchemaModel model = (SchemaModel) iter.next();
model.setStatus(IInfoModel.STATUS_DELETE);
model.setEnded(ended);
}
//------------------------------
// 関連するAttachmentに同じ処理を行う
//------------------------------
Collection deleteAttachments = em.createQuery(QUERY_ATTACHMENT_BY_DOC_ID)
.setParameter("id", id).getResultList();
for (Iterator iter = deleteAttachments.iterator(); iter.hasNext(); ) {
AttachmentModel model = (AttachmentModel)iter.next();
model.setStatus(IInfoModel.STATUS_DELETE);
model.setEnded(ended);
}
// 削除したDocumentのlinkID を 削除するDocument id(PK) にしてLoopさせる
id = delete.getLinkId();
} catch (Exception e) {
break;
}
}
return list;
}
private Date dateFromString(String str) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.parse(str);
} catch (Exception e) {
}
return null;
}
}