« 2010年6月 | トップページ | 2010年8月 »

2010年7月

2010年7月29日 (木)

生年月日検索

患者検索のキーワード入力で,検索キーワードの頭にアルファベット+スペースを付けると,それぞれ下記のような検索ができるようになっている。この機能を拡張して,B 年-月-日 で生年月日検索ができるようにした。なお,年号で入力する場合は,最初の B を省略できるようにした。
例)B H12-3-4 または H12-3-4 または B 2000-03-04 などと入力する。
N 名前検索
K カナ検索
A 住所検索
Z 郵便番号検索
T 電話番号検索
I ID 検索
E メールアドレス検索
O その他 ID 検索(コーディングされていない)
B 生年月日検索(今回作成)

 

dto/PatientSearchSpec.java

//pns^
public static final int BIRTHDAY_SEARCH         = 12;
private String birthday;

public void setBirthday(String birthday) {
  this.birthday = birthday;
}
public String getBirthday() {
  return birthday;
}
//pns$

ejb/RemotePatientServiceImpl.java

public Collection getPatients(PatientSearchSpec spec) {
 ・
 ・
//pns^
  case PatientSearchSpec.BIRTHDAY_SEARCH:
    String birthday = spec.getBirthday();
    if (!birthday.endsWith("%")) {
      birthday += "%";
    }
    ret = em.createQuery("from PatientModel p where p.facilityId = :fid and p.birthday like :birthday")
    .setMaxResults(50)
    .setParameter("fid", fid)
    .setParameter("birthday", birthday)
    .getResultList();
//pns$

infomodel/ModelUtils.java

/** 年号=>西暦変換 H22-7-26 => 2010-07-26 by pns
 * @param nengoBirthday
 * @return mmlBirthday
 */
public static String toSeireki(String nengoBirthday) {

  try {
    StringTokenizer st = new StringTokenizer(nengoBirthday, "-");
    String yearStr = st.nextToken();
    String monthStr = st.nextToken();
    String dateStr = st.nextToken();

    String nengo = yearStr.substring(0,1);
    int year = Integer.valueOf(yearStr.substring(1));

    if ("M".equals(nengo) || "m".equals(nengo)) year = year + 1867;
    else if ("T".equals(nengo) || "t".equals(nengo)) year = year + 1911;
    else if ("S".equals(nengo) || "s".equals(nengo)) year = year + 1925;
    else if ("H".equals(nengo) || "h".equals(nengo)) year = year + 1988;
    else year = Integer.valueOf(yearStr); // 西暦で入ってきた場合

    if (monthStr.length() == 1) monthStr = "0" + monthStr;
    if (dateStr.length() == 1) dateStr = "0" + dateStr;

    StringBuilder mmlBirthday = new StringBuilder();
    mmlBirthday.append(Integer.toString(year));
    mmlBirthday.append("-");
    mmlBirthday.append(monthStr);
    mmlBirthday.append("-");
    mmlBirthday.append(dateStr);

    return mmlBirthday.toString();

  } catch (Exception ex) {
    System.out.println("ModelUtils.java: " + ex);
    return null;
  }
}

plugin/PatientSearchImpl.java

private void find(String text) {
 ・
 ・
  } else if (text.startsWith("O ") || text.startsWith("o ")) {
    spec.setCode(PatientSearchSpec.OTHERID_SEARCH);
    text = text.substring(2);
    spec.setOtherId(text);
//pns^      誕生日検索
  } else if (text.startsWith("B ") || text.startsWith("b ")) {
    spec.setCode(PatientSearchSpec.BIRTHDAY_SEARCH);
    text = text.substring(2);
    spec.setBirthday(ModelUtils.toSeireki(text));

  } else if (isNengoDate(text)) {
    spec.setCode(PatientSearchSpec.BIRTHDAY_SEARCH);
    spec.setBirthday(ModelUtils.toSeireki(text));
//pns$
 ・
 ・
private boolean isNengoDate(String text) {
  return text==null? false: text.matches("[MmTtSsHh][0-9]+-[0-9]+-[0-9]+");
}

2010年7月 3日 (土)

byomeiCount の永続化

受付リストが増えると,DocumentPeeker の病名数カウントにけっこう時間がかかり,立ち上げ時や更新ボタンを押した後しばらく待たされてしまっていたので,病名数のカウントを PatientVisitModel 内に永続化して早くできるようにした。試しに受付患者数 150 にしてみたところ,以前の方式だと 20秒くらいかかったが,永続化後は 5 秒程度でカウント終了した。もちろん実際にそんなに患者さんが来ているわけではない。

delegater/PVTDelegater

public int setByomeiCount(long pk, int total, int today) {
  try {
    return getService().setByomeiCount(pk, total, today);
  } catch (NamingException e) {
    e.printStackTrace();
    processError(e);
  }
  return 0;
}

ejb/RemotePvtService.java

/**
 * 付いている病名数を書き込む
 * @param pk
 * @param total 総病名数
 * @param today 今日付いた病名数
 * @return
 */
public int setByomeiCount(long pk, int total, int today);

ejb/RemotePvtServiceImpl.java

public Collection getPvt(PatientVisitSpec spec) {
 ・
 ・
//pns^      病名数をセットする
  // カルテの PK を得る
  KarteBean karte = (KarteBean)em.createQuery("from KarteBean k where k.patient.id = :pk")
    .setParameter("pk", patient.getId())
    .getSingleResult();
  long karteId = karte.getId();

  // トータルの病名数
  String byomeiCountQuery = "select count(*) from RegisteredDiagnosisModel r where r.karte.id = :karteId and r.started >= :fromDate";
  int totalCount = ((Long) em.createQuery(byomeiCountQuery)
    .setParameter("karteId", karteId)
    .setParameter("fromDate", new Date(0L))
    .getSingleResult()).intValue();
  pvt.setByomeiCount(totalCount);

  // 今日の病名数
  GregorianCalendar yesterday = new GregorianCalendar();
  yesterday.add(GregorianCalendar.DATE, -1);
  yesterday.set(Calendar.HOUR_OF_DAY, 23);
  int todayCount = ((Long)em.createQuery(byomeiCountQuery)
    .setParameter("karteId", karteId)
    .setParameter("fromDate", yesterday.getTime())
    .getSingleResult()).intValue();
  pvt.setByomeiCountToday(todayCount);
//pns$
 ・
 ・
public int setByomeiCount(long pk, int total, int today) {
  PatientVisitModel exist = em.find(PatientVisitModel.class, pk);
  exist.setByomeiCount(total);
  exist.setByomeiCountToday(today);
  return 1;
}

client/DiagnosisDocument.java

class DiagnosisPutTask extends DBTask> {
 ・
 ・
  @Override
  protected List doInBackground() throws Exception {
 ・
 ・
  // ByomeiCount の永続化
  PatientVisitModel pvt = getContext().getPatientVisit();
  if (pvt.getPvtDate() != null) { // 今日の受診がなければ pvtDate == null
    PVTDelegater pdl = new PVTDelegater();
    pdl.setByomeiCount(pvt.getId(), pvt.getByomeiCount(), pvt.getByomeiCountToday());
  }

infomodel/PatientVisitModel.java

//pns^  pvt model の項目を増やす
/** 今まで付いた病名の総数 */
@Column(nullable=false)
private int byomeiCount;
/** 今日付いた病名の数 */
@Column(nullable=false)
private int byomeiCountToday;
/** カルテ記載があるかどうか */
@Transient
private boolean karteEmpty;
/** ORCA から送られる「診療内容」 */
private String memo;
//pns$
nullable=false を書いても,以前に作られた pvt の byomeiCount が全部 null になってしまい,以下のエラーが出る。
Null value was assigned to a property of primitive type setter of byomeicount
データベースを書き換えて対応する。
# update d_patient_visit set byomeicount=0;
# update d_patient_visit set byomeicounttoday=0;
 

2010年7月 1日 (木)

待ち時間表示

受付リストに,待ち人数と待ち時間(次に診察する患者さんが待っていた時間)を表示するようにした。インスペクタにはその患者さんの待ち時間が出るようにした。

Waiting1

Waiting2

plugin/WatingListImpl.java

 ・
 ・
public void updateState(final PatientVisitModel updated) {
 ・
 ・
//pns
  setPvtCount(pvtTableModel.getObjectCount());
}
 ・
 ・
//pns^
/**
 * 来院数を設定する。
 * @param cnt 来院数
 */
public void setPvtCount(int cnt) {
  pvtCount = cnt;
  //String text = ClientContext.getString("watingList.state.pvtCountText");
  //text += String.valueOf(pvtCount); // 来院数:20
  //view.getCountLbl().setText(text);
  setPvtCount();
}
/**
 * 来院数,待人数,待時間表示
 */
private void setPvtCount() {
  int waitingCount = 0;
  String waitingTime = "00:00";
  List dataList = pvtTableModel.getObjectList();

  if (pvtCount > 0) {
    boolean found = false;
    for (int i = 0; i < pvtCount; i++) {
      PatientVisitModel pvt = (PatientVisitModel) dataList.get(i);
      int state = pvt.getState();
      if (state == ChartImpl.CLOSE_NONE || state == ChartImpl.OPEN_NONE) {
        // 診察未終了レコードをカウント,最初に見つかった未終了レコードの時間から待ち時間を計算
        waitingCount++;
        if (!found) {
          Date pvtDate = ModelUtils.getDateTimeAsObject(pvt.getPvtDate());
          waitingTime = DurationFormatUtils.formatPeriod(pvtDate.getTime(), new Date().getTime(), "HH:mm");
          found = true;
        }
      }
    }
  }
  StringBuilder sb = new StringBuilder();
  sb.append("来院数");
  sb.append(String.valueOf(pvtCount));
  sb.append("人,待ち");
  sb.append(String.valueOf(waitingCount));
  sb.append("人,待ち時間 ");
  sb.append(waitingTime);
  view.getCountLbl().setText(sb.toString());
}
//pns$

plugin/RowTipsTable.java

public String getToolTipText(MouseEvent e) {
        
  ObjectReflectTableModel model = (ObjectReflectTableModel) getModel();
  int row = rowAtPoint(e.getPoint());
  PatientVisitModel pvt = (PatientVisitModel) model.getObject(row);

//pns^  待ち時間表示
  Date pvtDate = ModelUtils.getDateTimeAsObject(pvt.getPvtDate());
  int pvtState = pvt.getState();
  String waitingTime = "";
  if (pvtDate != null &&
    (pvtState == ChartImpl.CLOSE_NONE || pvtState ==ChartImpl.OPEN_NONE)) {
    waitingTime = " - 待ち時間 " + DurationFormatUtils.formatPeriod(pvtDate.getTime(), new Date().getTime(), "HH:mm");
  }

  String patientName = pvt != null ? pvt.getPatient().getKanaName() : null;
  return patientName + waitingTime;
//pns$

// return pvt != null ? pvt.getPatient().getKanaName() : null;
}

client/ChartImpl.java

public void initComponents() {
 ・
 ・
  statusPanel.setRightInfo(rdPrifix + created); // カルテ登録日:yyyy/mm/dd
//pns^待ち時間表示
  Date pvtDate = ModelUtils.getDateTimeAsObject(pvt.getPvtDate());
  if (pvtDate != null && pvt.getState() == CLOSE_NONE) { // window open 前に呼ばれる
    String waitingTime = DurationFormatUtils.formatPeriod(pvtDate.getTime(), new Date().getTime(), "HH:mm");
  statusPanel.setRightInfo(rdPrifix + created + "待ち時間 " + waitingTime);
  }
//pns$

« 2010年6月 | トップページ | 2010年8月 »