LoginSignup
4
2

会社のプロダクトに自作プログラムを活用した経緯と、その功罪

Last updated at Posted at 2023-12-20

この記事は、株式会社ヘンリー アドベントカレンダー2023の21日目の記事です。昨日の記事は @agatan さんの Henry の開発はなにが楽しい?ソフトウェアエンジニアにとっての魅力と挑戦をご紹介します! でした。

はじめに

株式会社ヘンリーのエンジニアの小貫です。私は病院で医療事務として5年ほど働いていたことがあり、その知見もあって主にレセコンまわりの開発をしています。
ヘンリーに入社してから、個人的につくったプログラムが会社のプロダクトのいち機能になったという体験をしまして、なかなかできない経験だったなーと思い、この件についてお話したいと思います。

個人的にプログラムを書くまで

私は開発でレセコンまわりを担当することが多く、業務に役立てようと個人的にプログラムを書いていました。

レセコンとは「レセプトコンピュータシステム」のことで、医療機関の診療報酬の計算やレセプト(診療報酬請求明細書)請求をおこなうためのシステムです。

患者さんが診療所や病院にかかった際の医療費は、厚生労働大臣が定める診療報酬点数表という算定ルールにのっとり、まず点数として算出されます。点数は「1点=10円」として金額になり、患者さんの保険証を適用して患者が支払う自己負担額が決まります。

患者さんが窓口で自己負担を支払ったあとの残りの医療費は、保険証を発行している保険者に請求されます。このときに使われる様式が診療報酬請求明細書、通称「レセプト」で、次のようなフォーマットになっています。

レセプトプレビュー _ 国R4-01.png

レセプトはこのイメージのようにかつては用紙で請求していましたが、現在では「電子レセプトファイル」と呼ばれるテキストファイルによって請求します。電子レセプトファイルは UKE という拡張子をもつので、弊社では「UKEファイル」と呼んでいます。

UKEファイルをエディタで開いたところ.png

UKEファイルはコンピュータで処理するためのCSVであるため、エディタで開いて目視で確認するのはなかなか骨が折れます。見慣れた紙レセプトでのプレビューも併用して確認することになります。

以下の文章に「プレビュー」や「表示」という表現が繰り返し出きますが、これは「UKEファイルを何かしらの human-readable なフォーマットに変換する、あるいは画面に表示する」くらいの意味で使っています。

フリーウェアとして公開されているビューワアプリを利用することで、紙レセプトのフォーマットでプレビューを閲覧できますが、ビューワアプリは主に医療事務による利用を想定しているため、例えば次のような課題がありました:

  • レセプトの内容を見るためのフォーマットは、必ずしも紙レセプトがベストではない
    確かに紙レセプトは病院時代からの見慣れたフォーマットであるものの、目的や用途に応じて必要な情報にしぼったり、載せる情報を追加するなど工夫することで利便性が増す余地があります。
  • 読込ませるのは完全なUKEファイルである必要がある
    実はUKEファイルにはひとつではなく多数のレセプトが記録されており、レセプトそのもののほかにヘッダ行や集計行も記録されます。
    通常、ビューワは完全なUKEファイルをその入力として期待しますが、例えば「UKEファイルの特定のレセプトだけ、あるいはレセプトのなかの数行だけ読込ませたい」という場合に、ヘッダ行や集計行まで完備したUKEファイルを用意するのは少々面倒です。
  • もっと気軽にプレビューを見たい
    「ビューワを立上げる→UKEファイルを読込む→目的のレセプトを探す」とい手順は少し煩わしく感じます。また、GUIなので少し効率が落ちます。

いくつか挙げましたが、早い話が「使い慣れたエディタでUKEファイルを開き、欲しいところだけかいつまんでレセプトを閲覧したい」と思ったのでした。

というわけでつくりました

このような考えのもとつくったのが receiptisan でした。コマンド実行で次のようなフォーマットでレセプトを表示できます:

receiptisanを実行したところ.gif

私は普段Vimを使っているので、 vim-quickrun を設定してVimからも実行もできるようにしました:

Vimでレセプトを閲覧しているところ.gif

これでだいぶ楽ができるようになり、いまでも大いに活躍してくれています。

UKEファイルを紙レセプトのフォーマットで表示する機能は個人的には特に必要がなかったのですが、せっかくレセプトの便利ツールをつくったんだし、ということで続いて開発していました。

Henryの一機能として転用することに

一方、当時のHenryには、紙レセプトのフォーマットでレセプトを表示する機能が備わっていませんでした。諸々の事情で開発に着手できずにいたのですが、プロダクトとして「Henryから出力したUKEをビューワアプリに読込んでレセプトをプレビューする」という方法の不便さがだんだん際立つようになり、看過できない状況でした。
当時の私は、エンジニアに職種をコンバートしたタイミングでした。そういうわけで私のエンジニアタスクは手空きだったので、つくりかけのreceiptisanの紙レセプト表示機能をこのまま私が最後まで実装し、Henryから利用するようにすればいいのではという案がもちあがり、とり急ぎこの方法でHenryのレセプトプレビュー機能(紙レセプトのフォーマットでレセプトを表示する機能)を実現することになりました。

実現にあたってはMVPで実装するという意思決定をしたため、技術的には「レセコン機能を担うサーバからの外部コマンド実行でreceiptisanを呼出す」という単純な仕組みで用意しました。
サーバをビルドするDockerfileのなかで、Rubyとreceiptisanも一緒のコンテナにインストールして同居させるようにしました。一見とんでもない話ですが、特段テクニカルなところもなく、ササッと実現できました。

処理のフローとしては、

  • ユーザがレセプトプレビューを実行し、
  • HenryがUKEファイルを生成し、
  • receiptisanがUKEファイルを標準入力から受取り、紙レセプトのプレビューをHTMLで標準出力に出力し、
  • henryがHTMLファイルをクラウドストレージにアップロードし、ブラウザ上で表示する

といった流れになっています。

一方、紙レセプトの仕様は『診療報酬請求書等の記載要領等について』に記載されています。

開いてみていただけるとわかりますが、記載要領は長大で、公文書ということもあってなかなかとっつきづらい文章になっています。
例えば、紙レセプトの下部に位置する一部負担金の記載は次のように述べられています(抜粋):

Ⅱ 診療報酬請求書及び診療報酬明細書の記載要領 - 第3. 診療報酬明細書の記載要領(様式第2) - 2. 診療報酬明細書の記載要領に関する事項 - (21)「療養の給付」欄について より抜粋

オ 「公費①」及び「公費②」の項には、それぞれ第1公費及び第2公費に係る医療券等に記入されている公費負担医療に係る患者の負担額(一部負担金(食事療養標準負担額及び生活療養標準負担額を含む。)の額が医療券等に記載されている公費負担医療に係る患者の負担額を下回る場合で、「負担金額」の項又は「一部負担金額」の項に金額を記載するものの場合はウの(ア)又は(イ)により記載した額(食事療養標準負担額及び生活療養標準負担額を含む。)を、金額の記載を要しないものの場合は10円未満の端数を四捨五入する前の一部負担金の額(食事療養標準負担額及び生活療養標準負担額を含む。))を記載すること。
ただし、障害者総合支援法による精神通院医療、更生医療、育成医療、療養介護医療及び基準該当療養介護医療、児童福祉法による小児慢性特定疾病医療支援、肢体不自由児通所医療及び障害児入所医療並びに難病法による特定医療に係る患者の負担額(一部負担金)については、食事療養標準負担額及び生活療養標準負担額を含まない額とすること。なお、後期高齢者医療又は医療保険(高齢受給者及び高齢受給者以外であって限度額適用認定証又は限度額適用・標準負担額減額認定証の提示があった者で高額療養費が現物給付された者に係るものに限る。)と感染症法による結核患者の適正医療との併用の場合(入院の場合及び入院外分であって、高額療養費が現物給付された場合に限る。)には、一部負担金から同負担金のうち当該公費負担医療が給付する額を控除した額(即ち、窓口で徴収した額)を記載すること。
また、障害者総合支援法による精神通院医療、更生医療、..(略)

この調子で説明が続くので、やはり公文書というのは読解に根性が欠かせませんね笑

記載要領はページ数も多くボリューム十分ですが、レセプトに記録される内容は多岐にわたっていて記録のパターンの分岐も多いため、記載要領にすべての仕様が網羅されている、というわけでもありません。
仕様が不明瞭だった点も少なくありませんでしたが、既存のビューワを参考にする、関係機関に問合わせる、ドメインに詳しいメンバーと相談する、エッジケースなのであればスコープから落とす、といった方法で解消していきました。

また、紙レセプトのフォーマットは先に示したような様式なのですが、実際にはビューワアプリによってレイアウトや細部の表示内容は異なっており、医療事務時代の経験も踏まえ、見やすさと実装コストのバランスをとって決定していきました。

こうして無事Henryにレセプトプレビュー機能が搭載されました。

実際にやってみての感想と課題

振り返ると次の点はよかったなと思います。

  • 実装や仕組みは最小限の構成にして、顧客の体験改善を最優先とした意思決定ができた
    開発リソース的にやむを得ないという現実的な都合もありましたが、システム構成・アーキテクチャにはこだわらずに、とにもかくにもまずは機能をリリースすることを目指したため、よそ見もなく早く価値提供できたと思います。
    個人的にも、「社内でレセプトに比較的詳しい」という元医療事務である強みをいかした開発ができたと思っています。
  • レセプトのプレビュー機能という医療事務にとってクリティカルな機能の実装に、自作の個人プログラムを活用できた
    元医療事務としても現エンジニアとしても、どっちとも冥利に尽きます。
  • 業務の時間を使ってOSS(receiptisanですね)を書くという経験ができた
    ユースケースの限られた非常にニッチなソフトウェアですが、仕事で書という経験はなかなかできない貴重なものだったなと思います。
    むしろニッチな領域で選択肢が少ないからこそ、このような経験ができたとも言えそうです。

一方で、次のような課題・負債がいまでも残っています。

  • プレビュー機能だけのためにRuby実行環境が必要になっている
    HenryのサーバはKotlin/JVM製なので、サーバのコンテナも本来JVM環境を用意するだけですむはずのところ、レセプトのプレビュー機能だけのためにRubyの実行環境もセットアップする必要があります。コンテナサイズが肥大化し、またビルドも時間がかかってしまいます。
  • レセプトに関連するマスタはHenry本体とは別に独自に用意しており、保守管理の非効率が生じている
    レセプトに関連するマスタは、例えばこちらのHPで公開されています。Henryは内部で公式のマスタを加工した独自のものを使っています。一方、receiptisanは公式のマスタをそのまま同梱して利用しています。いずれも個別にマスタ管理をしている状態で、全体をひとつのプロダクトとして見ると歪みが生じています。
  • レセプトのプレビューのインプットにUKEファイルを使っているが、これがあまり適切ではなかった
    UKEファイルの生成がそもそも高コストな処理なのですが、その上でプレビューを生成するという処理になっているため、プレビューが画面に表示されるまで長く待されます。
    また、UKEファイルは紙レセプトを電子化したものではあるものの、実は紙レセプトの内容がすべてUKEファイルに記録されるというわけではなく、例えば医療機関所在地のような一部の情報はUKEファイルには記録されません。そのため追加のインプットを渡すことを考える必要があります。
  • 一部保守作業をのぞいて、保守や改修は事実上、私個人に属人化している
    receiptisanがOSSとして管理されるべきか、Henryの一部として管理されるべきかという分界はなかなか悩ましいものがあります。Henryでのreceiptisanの利用はあくまで一時しのぎであり、最終的にはHenryのコードベースで実現したいものなので、このことも課題を難しくしています。
  • 未熟なOSSを利用して機能が実現されており、機能として成熟しづらい
    上の点とも関連しますが、属人化の課題を解決しなければ私個人からプレビュー機能が手離れしないため、機能としても継続的な改善が難しくなります。

よくも悪くも、最小工数でリリースまで突進んだことの影響と言えそうです。

おわりに

以上、簡単にご紹介させていただきました。

今後のやりたいこととしてはやはり課題の解消ですが、そのためにはレセプトプレビュー機能をHenryで内製し、receiptisanからリプレースすることが必要だと考えています。
receiptisanが担っている処理の段階的なリプレースの手順もぼんやり考えているので、負債の解消をすすめつつ、時機を見計らって対処していきたいと思っています。

最後までお読みいただきありがとうございました。明日もお楽しみに!

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2