Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Yokenzan/manage daily kaisuu #37

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lib/receiptisan/cli/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ module Cli
class Application
def initialize
@commandset = Commandset
@commandset.register('--preview', Command::PreviewCommand, aliases: ['-p'])
@commandset.register('--version', Command::VersionCommand, aliases: ['-v'])
@commandset.register('--preview', Command::PreviewCommand, aliases: ['-p'])
@commandset.register('--version', Command::VersionCommand, aliases: ['-v'])
@commandset.register('--checklist', Command::ReceiptChecklistCommand, aliases: ['-c'])
end

def run
Expand Down
1 change: 1 addition & 0 deletions lib/receiptisan/cli/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@

require_relative 'command/preview_command'
require_relative 'command/version_command'
require_relative 'command/receipt_checklist_command'
96 changes: 96 additions & 0 deletions lib/receiptisan/cli/command/receipt_checklist_command.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# frozen_string_literal: true

require 'logger'
require 'dry/cli'

module Receiptisan
module Cli
module Command
# Command to preview RECEIPTC.UKE files
#
# given arguments and parameters patterns:
#
# 1. by giving UKE file paths
# 2. by giving stdin
class ReceiptChecklistCommand < Dry::CLI::Command
include Receiptisan::Model::ReceiptComputer

Parser = DigitalizedReceipt::Parser
Options = Parser::SupplementalOptions

argument :uke_file_paths, required: false, type: :array, desc: 'paths of RECEIPTC.UKE files to create checklist'
# hospitals
option :hospitals, type: :json, desc: 'parameters for hospitals(each hospital has location, code, bed_count)'

# check rules
option :check_naifuku_tazai, type: :boolean, desc: '内服他剤投与に該当する可能性があるが他剤投与逓減が適用されていないレセプトを抽出します'
option :check_cholesterol, type: :boolean, desc: 'Tcho, LDL-コレステロール, HDL-コレステロールを併算定しているレセプトを抽出します'
option :check_influenza, type: :boolean, desc: 'インフルエンザウイルス抗原訂正, Sars-Cov-2抗原検出, 抗原同時検出を併算定しているレセプトを抽出します'
option :check_sm, type: :boolean, desc: 'S−M, S−蛍光M、位相差M、暗視野Mを併算定しているレセプトを抽出します'
option :check_es_xylocaine, type: :boolean, desc: '内視鏡検査でキシロカインゼリーを使用しているレセプトを抽出します'
option :check_yakujou, type: :boolean, desc: '薬剤情報提供料を月に2回以上算定しているレセプトを抽出します'
option :check_dimethicone, type: :boolean, desc: 'ジメチコンを使用しているが胃カメラを実施していないレセプトを抽出します'
option :check_tanki_taizai3, type: :boolean, desc: '短期滞在手術等基本料算定時に包括される診療行為を算定しているレセプトを抽出します'
option :check_metgluco, type: :boolean, desc: 'メトグルコ錠500mgを1日あたり6錠以上処方しているレセプトを抽出します'
option :check_tokubetsushoku, type: :boolean, desc: '特別食加算と食事療養数量の不一致しているレセプトを抽出します'
option :check_shubyou_tokutei, type: :boolean, desc: '主病がない状態で特定疾患療養管理料・特定疾患処方管理加算を算定しているレセプトを抽出します'
option :check_tokusho2_nissuu, type: :boolean, desc: '特定疾患処方管理加算2を算定しているレセプトを抽出します'

# @param [Array<String>] uke_file_paths
# @param [Hash] options
def call(uke_file_paths: [], **options)
initialize_parser
initialize_check_rules(options)

digitalized_receipts = parse(uke_file_paths, options)
checklist = check(digitalized_receipts)

puts checklist
end

private

def initialize_parser
@parser = DigitalizedReceipt::Parser.new(
DigitalizedReceipt::Parser::MasterHandler.new(Master::Loader.new(Master::ResourceResolver.new)),
Logger.new($stderr)
)
end

def initialize_check_rules(options)
@check_executor = Reporting::ReceiptCheckExecutor.new

options[:check_cholesterol] && @check_executor.add_rule(Reporting::Rule::CholesterolRule.new)
options[:check_dimethicone] && @check_executor.add_rule(Reporting::Rule::DimethiconeRule.new)
options[:check_es_xylocaine] && @check_executor.add_rule(Reporting::Rule::ESWithXylocaineRule.new)
options[:check_influenza] && @check_executor.add_rule(Reporting::Rule::InfluenzaRule.new)
options[:check_naifuku_tazai] && @check_executor.add_rule(Reporting::Rule::NaifukuTazaiRule.new)
options[:check_sm] && @check_executor.add_rule(Reporting::Rule::SMRule.new)
options[:check_yakujou] && @check_executor.add_rule(Reporting::Rule::YakujouRule.new)
options[:check_tanki_taizai3] && @check_executor.add_rule(Reporting::Rule::TankiTaizai3Rule.new)
options[:check_metgluco] && @check_executor.add_rule(Reporting::Rule::MetglucoRule.new)
options[:check_tokubetsushoku] && @check_executor.add_rule(Reporting::Rule::TokubetsushokuRule.new)
options[:check_shubyou_tokutei] && @check_executor.add_rule(Reporting::Rule::TokuteiShikkanShubyouRule.new)
options[:check_tokusho2_nissuu] && @check_executor.add_rule(Reporting::Rule::Tokusho2NissuuRule.new)

raise unless @check_executor.any_rules?
end

# @param uke_file_paths [Array<String>]
# @return [Array<Model::ReceiptComputer::DigitalizedReceipt>]
def parse(uke_file_paths, options)
supplemental_options = Options.from(options[:hospitals])
parse_proc = proc { | io | @parser.parse(io, supplemental_options) }

(uke_file_paths.empty? ?
parse_proc.call($stdin) :
uke_file_paths.map { | path | File.open(path) { | io | parse_proc.call(io) } }).flatten
end

def check(digitalized_receipts)
digitalized_receipts.map { | digitalized_receipt | @check_executor.check(digitalized_receipt) }.flatten
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/receiptisan/model/receipt_computer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
require_relative 'receipt_computer/tag'
require_relative 'receipt_computer/abbrev'
require_relative 'receipt_computer/util'
require_relative 'receipt_computer/reporting'
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class DigitalizedReceipt
class Parser # rubocop:disable Metrics/ClassLength
include Parser::Context::ErrorContextReportable
using Receiptisan::Util::IOWithEncoding
using Receiptisan::Util::MonthExtention

ReceiptType = DigitalizedReceipt::Receipt::Type
Comment = Receipt::Tekiyou::Comment
Expand Down Expand Up @@ -202,12 +203,21 @@ def process_sj(values)
end

def wrap_as_cost(resource, column_definition, values)
daily_kaisuu_range = column_definition::C_算定日_1日..column_definition::C_算定日_31日
daily_kaisuus = values[daily_kaisuu_range].map.with_index do | daily_kaisuu, index |
daily_kaisuu.nil? ? nil : Receipt::Tekiyou::DailyKaisuu.new(
date: buffer.current_shinryou_ym.of_date(index + 1),
kaisuu: daily_kaisuu.to_i
)
end.reject(&:nil?)

cost = Receipt::Tekiyou::Cost.new(
resource: resource,
shinryou_shikibetsu: Receipt::ShinryouShikibetsu.find_by_code(values[column_definition::C_診療識別]),
futan_kubun: Receipt::FutanKubun.find_by_code(values[column_definition::C_負担区分]),
tensuu: values[column_definition::C_点数]&.to_i,
kaisuu: values[column_definition::C_回数]&.to_i
kaisuu: values[column_definition::C_回数]&.to_i,
daily_kaisuus: daily_kaisuus
)

comment_range = column_definition::C_コメント_1_コメントコード..column_definition::C_コメント_3_文字データ
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,26 @@ def nyuuin?
@type.nyuuin?
end

def dates
@tekiyou.map do | _, ichirens |
ichirens.map do | ichiren |
ichiren.map do | santei |
santei.each_date.map(&:date)
end
end
end.flatten.uniq.sort
end

def each_date
dates.each do | date |
tekiyou_on_date = @tekiyou.map do | _, ichirens |
[ichirens.first.shinryou_shikibetsu, ichirens.select { | ichiren | ichiren.on_date(date) }]
end.to_h

yield date, tekiyou_on_date
end
end

# @return [void]
def fix!
@tekiyou = @tekiyou.sort_by { | shinryou_shikibetsu, _ | shinryou_shikibetsu.to_s.to_i }.to_h
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ def initialize(
shinryou_shikibetsu:,
futan_kubun:,
tensuu:,
kaisuu:
kaisuu:,
daily_kaisuus:
)
@resource = resource
@shinryou_shikibetsu = shinryou_shikibetsu
@futan_kubun = futan_kubun
@tensuu = tensuu&.to_i
@kaisuu = kaisuu&.to_i
@daily_kaisuus = daily_kaisuus
@comments = []
end

Expand All @@ -51,6 +53,14 @@ def kaisuu?
!kaisuu.nil?
end

def kaisuu_on?(date)
!@daily_kaisuus.find { | it | it.date == date }.nil?
end

def kaisuu_on(date)
@daily_kaisuus.find { | it | it.date == date }&.kaisuu
end

def comment?
false
end
Expand All @@ -76,9 +86,23 @@ def each_comment(&block)
# @return [Integer, nil] 算定回数
# @!attribute [r] shinryou_shikibetsu
# @return [ShinryouShikibetsu] 診療識別
attr_reader :resource, :futan_kubun, :tensuu, :kaisuu, :shinryou_shikibetsu
attr_reader :resource, :futan_kubun, :tensuu, :kaisuu, :shinryou_shikibetsu, :daily_kaisuus

def_delegators :futan_kubun, :uses?
def_delegators :resource, :name, :code
end

class DailyKaisuu
def initialize(date:, kaisuu:)
@date = date
@kaisuu = kaisuu
end

def on?(date)
@date == date
end

attr_reader :date, :kaisuu
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,26 @@ def futan_kubun
@santei_units.first.futan_kubun
end

# @return [self, nil]
def on_date(date)
return nil unless @santei_units.any? { | santei | santei.on_date?(date) }

copied = self.class.new(shinryou_shikibetsu: shinryou_shikibetsu)

@santei_units.each do | santei |
if new_santei = santei.on_date(date)
copied.add_santei_unit(new_santei)
end
end

copied.empty? ? nil : copied
end

# @!attribute [r] shinryou_shikibetsu
# @return [ShinryouShikibetsu]
attr_reader :shinryou_shikibetsu

def_delegators :@santei_units, :each, :map
def_delegators :@santei_units, :each, :map, :empty?
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def initialize
@kaisuu = nil
# @type tekiyou_items [Array<Cost, Comment>]
@tekiyou_items = []
@daily_kaisuus = []
end

# @param tekiyou_item [Cost, Comment]
Expand All @@ -32,8 +33,9 @@ def fix!
bottom_cost = tekiyou_items.reverse.find(&:tensuu?)
return unless bottom_cost

@tensuu = bottom_cost.tensuu
@kaisuu = bottom_cost.kaisuu
@tensuu = bottom_cost.tensuu
@kaisuu = bottom_cost.kaisuu
@daily_kaisuus = bottom_cost.daily_kaisuus
end

# @return [Symbol, nil] returns nil when only costists of comments.
Expand All @@ -47,6 +49,46 @@ def each_cost(&block)
block_given? ? enum.each(&block) : enum
end

# @return [Enumnerator]
def each_date
Enumerator.new { | y | @daily_kaisuus.each { | it | y << it } }
end

def on_date?(date)
@daily_kaisuus.any? { | daily_kaisuu | daily_kaisuu.on?(date) }
end

# @return [self, nil]
def on_date(date)
daily_kaisuu = @daily_kaisuus.find { | dk | dk.on?(date) }

return nil unless daily_kaisuu

new_unit = self.class.new

tekiyou_items.each do | cost_or_comment |
if cost_or_comment.comment?
new_unit.add_tekiyou(cost_or_comment)
else
cost = cost_or_comment
new_cost = Cost.new(
resource: cost.resource,
shinryou_shikibetsu: cost.shinryou_shikibetsu,
futan_kubun: cost.futan_kubun,
tensuu: cost.tensuu,
kaisuu: daily_kaisuu.kaisuu,
daily_kaisuus: [daily_kaisuu]
)
cost.each_comment { | c | new_cost.add_comment(c) }

new_unit.add_tekiyou(new_cost)
end
end

new_unit.fix!
new_unit
end

# @return [Integer, nil]
def calculate
tensuu && kaisuu ? tensuu * kaisuu : nil
Expand All @@ -58,7 +100,7 @@ def calculate
# @return [Integer, nil]
attr_reader :tensuu, :kaisuu

def_delegators :@tekiyou_items, :each, :map
def_delegators :@tekiyou_items, :each, :map, :reduce
def_delegators :first_item, :futan_kubun, :uses?

private
Expand Down
4 changes: 4 additions & 0 deletions lib/receiptisan/model/receipt_computer/reporting.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# frozen_string_literal: true

require_relative 'reporting/receipt_check_executor'
require_relative 'reporting/rule'
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true

module Receiptisan
module Model
module ReceiptComputer
module Reporting
class ReceiptCheckExecutor
def initialize
@check_rules = []
end

def add_rule(rule)
@check_rules << rule
end

def any_rules?
@check_rules.empty?.!
end

def check(digitalized_receipt)
reports = []

@check_rules.each do | rule |
reports << rule.check(digitalized_receipt)
end

reports.reject(&:empty?).join("\n")
end
end
end
end
end
end
14 changes: 14 additions & 0 deletions lib/receiptisan/model/receipt_computer/reporting/rule.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

require_relative 'rule/cholesterol_rule'
require_relative 'rule/dimethicone_rule'
require_relative 'rule/es_with_xylocaine_rule'
require_relative 'rule/influenza_rule'
require_relative 'rule/naifuku_tazai_rule'
require_relative 'rule/sm_rule'
require_relative 'rule/yakujou_rule'
require_relative 'rule/tanki_taizai3_rule'
require_relative 'rule/metgluco_rule'
require_relative 'rule/tokubetsushoku_kasan_rule'
require_relative 'rule/tokutei_shikkan_shubyou_rule'
require_relative 'rule/tokusho2_nissuu_rule'
Loading