From dde278db7f0149e2f323d8bf68a07b07d77828b9 Mon Sep 17 00:00:00 2001 From: yokenzan <31175068+yokenzan@users.noreply.github.com> Date: Sun, 5 Mar 2023 03:28:59 +0900 Subject: [PATCH 1/5] add DailyKaisuu --- .../digitalized_receipt/parser.rb | 12 +++++++++- .../receipt/tekiyou/cost.rb | 23 +++++++++++++++++-- .../receipt/tekiyou/santei_unit.rb | 11 +++++++-- .../output/preview/parameter/common.rb | 3 ++- .../santei_unit_convertor.rb | 9 +++++--- lib/receiptisan/util.rb | 1 + lib/receiptisan/util/month_extention.rb | 17 ++++++++++++++ 7 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 lib/receiptisan/util/month_extention.rb diff --git a/lib/receiptisan/model/receipt_computer/digitalized_receipt/parser.rb b/lib/receiptisan/model/receipt_computer/digitalized_receipt/parser.rb index 4fb355f..73324b2 100644 --- a/lib/receiptisan/model/receipt_computer/digitalized_receipt/parser.rb +++ b/lib/receiptisan/model/receipt_computer/digitalized_receipt/parser.rb @@ -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 @@ -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_文字データ diff --git a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/cost.rb b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/cost.rb index 5fe1023..94333cd 100644 --- a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/cost.rb +++ b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/cost.rb @@ -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 @@ -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 @@ -76,10 +86,19 @@ 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? end + + class DailyKaisuu + def initialize(date:, kaisuu:) + @date = date + @kaisuu = kaisuu + end + + attr_reader :date, :kaisuu + end end end end diff --git a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/santei_unit.rb b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/santei_unit.rb index b10cdeb..f4de6eb 100644 --- a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/santei_unit.rb +++ b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/santei_unit.rb @@ -19,6 +19,7 @@ def initialize @kaisuu = nil # @type tekiyou_items [Array] @tekiyou_items = [] + @daily_kaisuus = [] end # @param tekiyou_item [Cost, Comment] @@ -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. @@ -47,6 +49,11 @@ 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 + # @return [Integer, nil] def calculate tensuu && kaisuu ? tensuu * kaisuu : nil diff --git a/lib/receiptisan/output/preview/parameter/common.rb b/lib/receiptisan/output/preview/parameter/common.rb index 3ecd852..85a25a3 100644 --- a/lib/receiptisan/output/preview/parameter/common.rb +++ b/lib/receiptisan/output/preview/parameter/common.rb @@ -408,7 +408,8 @@ class ShinryouShikibetsu < CodedItem extend CodedItemFactory end IchirenUnit = Struct.new(:futan_kubun, :santei_units, keyword_init: true) - SanteiUnit = Struct.new(:tensuu, :kaisuu, :items, keyword_init: true) + SanteiUnit = Struct.new(:tensuu, :kaisuu, :items, :daily_kaisuus, keyword_init: true) + DailyKaisuu = Struct.new(:date, :kaisuu, keyword_init: true) Cost = Struct.new( :type, diff --git a/lib/receiptisan/output/preview/parameter/generator/tekiyou_convertor/santei_unit_convertor.rb b/lib/receiptisan/output/preview/parameter/generator/tekiyou_convertor/santei_unit_convertor.rb index c4b865e..4d9c5f0 100644 --- a/lib/receiptisan/output/preview/parameter/generator/tekiyou_convertor/santei_unit_convertor.rb +++ b/lib/receiptisan/output/preview/parameter/generator/tekiyou_convertor/santei_unit_convertor.rb @@ -18,9 +18,12 @@ def initialize(tekiyou_item_convertor) # @return [Common::SanteiUnit] def convert(santei_unit) parameterized_santei_unit = Common::SanteiUnit.new( - tensuu: santei_unit.tensuu, - kaisuu: santei_unit.kaisuu, - items: [] + tensuu: santei_unit.tensuu, + kaisuu: santei_unit.kaisuu, + items: [], + daily_kaisuus: santei_unit + .each_date + .map { | it | Common::DailyKaisuu.new(date: it.date, kaisuu: it.kaisuu) } ) santei_unit.each do | tekiyou_item | diff --git a/lib/receiptisan/util.rb b/lib/receiptisan/util.rb index 5c42e08..cb4cd46 100644 --- a/lib/receiptisan/util.rb +++ b/lib/receiptisan/util.rb @@ -2,6 +2,7 @@ require_relative 'util/formatter' require_relative 'util/date_util' +require_relative 'util/month_extention' require_relative 'util/wareki_extension' require_relative 'util/recursively_hash_convertable' require_relative 'util/io_with_encoding' diff --git a/lib/receiptisan/util/month_extention.rb b/lib/receiptisan/util/month_extention.rb new file mode 100644 index 0000000..3b40ae6 --- /dev/null +++ b/lib/receiptisan/util/month_extention.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'date' + +module Receiptisan + module Util + module MonthExtention + refine Month do + # @param [Integer] day + # @return [Date] + def of_date(day) + Date.new(year, number, day) + end + end + end + end +end From 98c78fa88eaf35d4059db82740c6546eba33b9a4 Mon Sep 17 00:00:00 2001 From: yokenzan <31175068+yokenzan@users.noreply.github.com> Date: Sun, 12 Mar 2023 17:35:09 +0900 Subject: [PATCH 2/5] add methods about date --- .../digitalized_receipt/receipt.rb | 19 +++++++++++++++++++ .../receipt/tekiyou/ichiren_unit.rb | 9 +++++++++ .../receipt/tekiyou/santei_unit.rb | 11 ++++++++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt.rb b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt.rb index 8f3c041..6087ebd 100644 --- a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt.rb +++ b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt.rb @@ -80,6 +80,25 @@ 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.each_value do | ichirens | + ichirens = ichirens.select { | ichiren | ichiren.on_date(date) }.group_by(&:shinryou_shikibetsu) + yield date, ichirens + end + end + end + # @return [void] def fix! @tekiyou = @tekiyou.sort_by { | shinryou_shikibetsu, _ | shinryou_shikibetsu.to_s.to_i }.to_h diff --git a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/ichiren_unit.rb b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/ichiren_unit.rb index b5aa3a5..e61264f 100644 --- a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/ichiren_unit.rb +++ b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/ichiren_unit.rb @@ -34,6 +34,15 @@ def futan_kubun @santei_units.first.futan_kubun end + # @return [self, nil] + def on_date(date) + return unless @santei_units.any? { | santei | santei.on_date?(date) } + + self.class.new(shinryou_shikibetsu: shinryou_shikibetsu).tap do | copied | + @santei_units.each { | santei | copied.add_santei_unit(santei) if santei.on_date(date) } + end + end + # @!attribute [r] shinryou_shikibetsu # @return [ShinryouShikibetsu] attr_reader :shinryou_shikibetsu diff --git a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/santei_unit.rb b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/santei_unit.rb index f4de6eb..d11c945 100644 --- a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/santei_unit.rb +++ b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/santei_unit.rb @@ -54,6 +54,15 @@ def each_date Enumerator.new { | y | @daily_kaisuus.each { | it | y << it } } end + def on_date?(date) + @daily_kaisuus.any? { | daily_kaisuu | daily_kaisuu.date == date } + end + + # @return [self, nil] + def on_date(date) + on_date?(date) ? self : nil + end + # @return [Integer, nil] def calculate tensuu && kaisuu ? tensuu * kaisuu : nil @@ -65,7 +74,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 From 8191947428c4d305d628e58abd1807a4d0327157 Mon Sep 17 00:00:00 2001 From: yokenzan <31175068+yokenzan@users.noreply.github.com> Date: Sun, 12 Mar 2023 17:36:07 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat(checklist):=20=E3=83=81=E3=82=A7?= =?UTF-8?q?=E3=83=83=E3=82=AF=E3=83=AA=E3=82=B9=E3=83=88=E3=82=92=E4=BB=AE?= =?UTF-8?q?=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/receiptisan/cli/application.rb | 5 +- lib/receiptisan/cli/command.rb | 1 + .../cli/command/receipt_checklist_command.rb | 86 ++++++++++++++++++ lib/receiptisan/model/receipt_computer.rb | 1 + .../model/receipt_computer/reporting.rb | 4 + .../reporting/receipt_check_executor.rb | 33 +++++++ .../model/receipt_computer/reporting/rule.rb | 9 ++ .../reporting/rule/cholesterol_rule.rb | 55 ++++++++++++ .../reporting/rule/dimethicone_rule.rb | 57 ++++++++++++ .../reporting/rule/es_with_xylocaine_rule.rb | 89 +++++++++++++++++++ .../reporting/rule/influenza_rule.rb | 71 +++++++++++++++ .../reporting/rule/naifuku_tazai_rule.rb | 69 ++++++++++++++ .../reporting/rule/sm_rule.rb | 52 +++++++++++ .../reporting/rule/yakujou_rule.rb | 38 ++++++++ 14 files changed, 568 insertions(+), 2 deletions(-) create mode 100644 lib/receiptisan/cli/command/receipt_checklist_command.rb create mode 100644 lib/receiptisan/model/receipt_computer/reporting.rb create mode 100644 lib/receiptisan/model/receipt_computer/reporting/receipt_check_executor.rb create mode 100644 lib/receiptisan/model/receipt_computer/reporting/rule.rb create mode 100644 lib/receiptisan/model/receipt_computer/reporting/rule/cholesterol_rule.rb create mode 100644 lib/receiptisan/model/receipt_computer/reporting/rule/dimethicone_rule.rb create mode 100644 lib/receiptisan/model/receipt_computer/reporting/rule/es_with_xylocaine_rule.rb create mode 100644 lib/receiptisan/model/receipt_computer/reporting/rule/influenza_rule.rb create mode 100644 lib/receiptisan/model/receipt_computer/reporting/rule/naifuku_tazai_rule.rb create mode 100644 lib/receiptisan/model/receipt_computer/reporting/rule/sm_rule.rb create mode 100644 lib/receiptisan/model/receipt_computer/reporting/rule/yakujou_rule.rb diff --git a/lib/receiptisan/cli/application.rb b/lib/receiptisan/cli/application.rb index 2d12cb2..f566539 100644 --- a/lib/receiptisan/cli/application.rb +++ b/lib/receiptisan/cli/application.rb @@ -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 diff --git a/lib/receiptisan/cli/command.rb b/lib/receiptisan/cli/command.rb index 59fc0aa..128d5d1 100644 --- a/lib/receiptisan/cli/command.rb +++ b/lib/receiptisan/cli/command.rb @@ -2,3 +2,4 @@ require_relative 'command/preview_command' require_relative 'command/version_command' +require_relative 'command/receipt_checklist_command' diff --git a/lib/receiptisan/cli/command/receipt_checklist_command.rb b/lib/receiptisan/cli/command/receipt_checklist_command.rb new file mode 100644 index 0000000..ded847a --- /dev/null +++ b/lib/receiptisan/cli/command/receipt_checklist_command.rb @@ -0,0 +1,86 @@ +# 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: 'ジメチコンを使用しているが胃カメラを実施していないレセプトを抽出します' + + # @param [Array] 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) + + raise unless @check_executor.any_rules? + end + + # @param uke_file_paths [Array] + # @return [Array] + 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 diff --git a/lib/receiptisan/model/receipt_computer.rb b/lib/receiptisan/model/receipt_computer.rb index fe9936e..fe5630a 100644 --- a/lib/receiptisan/model/receipt_computer.rb +++ b/lib/receiptisan/model/receipt_computer.rb @@ -5,3 +5,4 @@ require_relative 'receipt_computer/tag' require_relative 'receipt_computer/abbrev' require_relative 'receipt_computer/util' +require_relative 'receipt_computer/reporting' diff --git a/lib/receiptisan/model/receipt_computer/reporting.rb b/lib/receiptisan/model/receipt_computer/reporting.rb new file mode 100644 index 0000000..630d270 --- /dev/null +++ b/lib/receiptisan/model/receipt_computer/reporting.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +require_relative 'reporting/receipt_check_executor' +require_relative 'reporting/rule' diff --git a/lib/receiptisan/model/receipt_computer/reporting/receipt_check_executor.rb b/lib/receiptisan/model/receipt_computer/reporting/receipt_check_executor.rb new file mode 100644 index 0000000..810e327 --- /dev/null +++ b/lib/receiptisan/model/receipt_computer/reporting/receipt_check_executor.rb @@ -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 diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule.rb new file mode 100644 index 0000000..baac50a --- /dev/null +++ b/lib/receiptisan/model/receipt_computer/reporting/rule.rb @@ -0,0 +1,9 @@ +# 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' diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/cholesterol_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/cholesterol_rule.rb new file mode 100644 index 0000000..377c5a2 --- /dev/null +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/cholesterol_rule.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +module Receiptisan + module Model + module ReceiptComputer + module Reporting + module Rule + # コレステロール + class CholesterolRule + Util = Receiptisan::Model::ReceiptComputer::Util + Master = Receiptisan::Model::ReceiptComputer::Master + ShinryouShikibetsu = Receiptisan::Model::ReceiptComputer::DigitalizedReceipt::Receipt::ShinryouShikibetsu + + def check(digitalized_receipt) + digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?) + end + + def check_receipt(receipt) + tcho = Master::Treatment::ShinryouKoui::Code.of('160022410') + ldl = Master::Treatment::ShinryouKoui::Code.of('160167250') + hdl = Master::Treatment::ShinryouKoui::Code.of('160023410') + + reports = [] + + receipt.each_date do | date, ichirens | + has_tcho = false + has_ldl = false + has_hdl = false + + kensa_ichirens = ichirens[ShinryouShikibetsu.find_by_code(60)] + kensa_ichirens&.each do | ichiren | + ichiren.each do | santei | + next unless santei.resource_type == :shinryou_koui + + santei.each_cost do | cost | + has_tcho = true if cost.resource.master_item.code == tcho + has_ldl = true if cost.resource.master_item.code == ldl + has_hdl = true if cost.resource.master_item.code == hdl + end + end + end + + if has_tcho && has_hdl && has_ldl + reports << [receipt.audit_payer.short_name, receipt.patient.id, receipt.patient.name, date].join("\t") + end + end + + reports + end + end + end + end + end + end +end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/dimethicone_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/dimethicone_rule.rb new file mode 100644 index 0000000..ab7cc54 --- /dev/null +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/dimethicone_rule.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module Receiptisan + module Model + module ReceiptComputer + module Reporting + module Rule + # ジメチコン × 胃カメラなし + class DimethiconeRule + Util = Receiptisan::Model::ReceiptComputer::Util + Master = Receiptisan::Model::ReceiptComputer::Master + + def check(digitalized_receipt) + digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?) + end + + def check_receipt(receipt) + # | 620422003 | ジメチコン錠40mg「YD」 | + # | 620423501 | ジメチコン内用液2%「FSK」 | + code_fs = Master::Treatment::ShinryouKoui::Code.of('160093810') + code_of_dimechicones = [ + Master::Treatment::Iyakuhin::Code.of('620422003'), + Master::Treatment::Iyakuhin::Code.of('620423501'), + ] + + has_fs = false + used_dimechicone = nil + + Util::ReceiptEnumeratorGenerator.each_cost_for( + receipt: receipt, + resource_types: %i[shinryou_koui iyakuhin] + ).each do | cost | + case cost.resource_type + when :shinryou_koui + has_fs = true if cost.resource.code == code_fs + when :iyakuhin + used_dimechicone = cost.resource if code_of_dimechicones.any? { | c | c == cost.resource.code } + end + end + + return '' if has_fs || used_dimechicone.nil? + + [ + receipt.audit_payer.short_name, + receipt.patient.id, + receipt.patient.name, + used_dimechicone.code.value, + used_dimechicone.name, + '%s%s' % [used_dimechicone.shiyouryou, used_dimechicone.unit.name], + ].join("\t") + end + end + end + end + end + end +end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/es_with_xylocaine_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/es_with_xylocaine_rule.rb new file mode 100644 index 0000000..89159bf --- /dev/null +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/es_with_xylocaine_rule.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +module Receiptisan + module Model + module ReceiptComputer + module Reporting + module Rule + # 内視鏡 × キシロカインゼリー + class ESWithXylocaineRule + Util = Receiptisan::Model::ReceiptComputer::Util + Master = Receiptisan::Model::ReceiptComputer::Master + ShinryouShikibetsu = Receiptisan::Model::ReceiptComputer::DigitalizedReceipt::Receipt::ShinryouShikibetsu + + def check(digitalized_receipt) + digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?) + end + + def check_receipt(receipt) + code_fs = Master::Treatment::ShinryouKoui::Code.of('160093810') + code_poripeku_less = Master::Treatment::ShinryouKoui::Code.of('150285010') + code_poripeku_more = Master::Treatment::ShinryouKoui::Code.of('150183410') + code_cs_s = Master::Treatment::ShinryouKoui::Code.of('160094710') + code_cs_down_hr = Master::Treatment::ShinryouKoui::Code.of('160094810') + code_cs_up = Master::Treatment::ShinryouKoui::Code.of('160094910') + code_xylocaine = Master::Treatment::Iyakuhin::Code.of('620003852') + + code_of_shugis = [ + code_fs, + code_poripeku_less, + code_poripeku_more, + code_cs_s, + code_cs_down_hr, + code_cs_up, + ] + + shinryou_shikibetsu = ShinryouShikibetsu.find_by_code(60) + + reports = [] + + receipt.each_date do | date, ichirens | + shugis = {} + xylocaine_shiyouryou = nil + + kensa_ichirens = ichirens[shinryou_shikibetsu] + kensa_ichirens&.each do | ichiren | + ichiren.each do | santei | + case santei.resource_type + when :shinryou_koui + santei.each_cost do | cost | + if (code = code_of_shugis.find { | s | s == cost.resource.master_item.code }) + shugis[code.value] = true + end + end + when :iyakuhin + santei.each_cost do | cost | + if cost.resource.master_item.code == code_xylocaine + xylocaine_shiyouryou = cost.resource.shiyouryou + end + end + end + end + end + + next unless shugis.any? { | _k, v | v == true } && !xylocaine_shiyouryou.nil? + + reports << [ + receipt.audit_payer.short_name, + receipt.nyuuin?, + receipt.patient.id, + receipt.patient.name, + date, + shugis[code_fs.value], + shugis[code_poripeku_less.value], + shugis[code_poripeku_more.value], + shugis[code_cs_s.value], + shugis[code_cs_down_hr.value], + shugis[code_cs_up.value], + xylocaine_shiyouryou, + ].join("\t") + end + + reports + end + end + end + end + end + end +end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/influenza_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/influenza_rule.rb new file mode 100644 index 0000000..a9e44c6 --- /dev/null +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/influenza_rule.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +module Receiptisan + module Model + module ReceiptComputer + module Reporting + module Rule + # 同日にSARS−CoV−2・インフルエンザウイルス抗原同時検出(定性)とインフルエンザウイルス抗原定性又は + # SARS−CoV−2抗原検出が算定されています。別に算定できないと定められていますのでご留意願います。 + class InfluenzaRule + Util = Receiptisan::Model::ReceiptComputer::Util + Master = Receiptisan::Model::ReceiptComputer::Master + ShinryouShikibetsu = Receiptisan::Model::ReceiptComputer::DigitalizedReceipt::Receipt::ShinryouShikibetsu + + def check(digitalized_receipt) + digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?) + end + + def check_receipt(receipt) + code_of_インフルエンザウイルス抗原定性 = Master::Treatment::ShinryouKoui::Code.of('160169450') + code_of_SARS_CoV_2抗原検出(定性) = Master::Treatment::ShinryouKoui::Code.of('160229850') + code_of_SARS_CoV_2抗原検出(定量) = Master::Treatment::ShinryouKoui::Code.of('160229950') + code_of_SARS_CoV_2・インフルエンザウイルス抗原同時検出 = Master::Treatment::ShinryouKoui::Code.of('160230050') + + reports = [] + + receipt.each_date do | date, ichirens | + has_インフルエンザウイルス抗原定性 = false + has_SARS_CoV_2抗原検出 = false + has_SARS_CoV_2・インフルエンザウイルス抗原同時検出 = false + + kensa_ichirens = ichirens[ShinryouShikibetsu.find_by_code(60)] + kensa_ichirens&.each do | ichiren | + ichiren.each do | santei | + next unless santei.resource_type == :shinryou_koui + + santei.each_cost do | cost | + has_インフルエンザウイルス抗原定性 = true if code_of_インフルエンザウイルス抗原定性 == cost.resource.master_item.code + has_SARS_CoV_2抗原検出 = true if code_of_SARS_CoV_2抗原検出(定量) == cost.resource.master_item.code + has_SARS_CoV_2抗原検出 = true if code_of_SARS_CoV_2抗原検出(定性) == cost.resource.master_item.code + if code_of_SARS_CoV_2・インフルエンザウイルス抗原同時検出 == cost.resource.master_item.code + has_SARS_CoV_2・インフルエンザウイルス抗原同時検出 = true + end + end + end + end + + hass = [ + has_インフルエンザウイルス抗原定性, + has_SARS_CoV_2抗原検出, + has_SARS_CoV_2・インフルエンザウイルス抗原同時検出, + ] + + if hass.select { | a | a == true }.length > 1 + reports << [ + receipt.audit_payer.short_name, + receipt.patient.id, + receipt.patient.name, + date + ].join("\t") + end + end + + reports + end + end + end + end + end + end +end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/naifuku_tazai_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/naifuku_tazai_rule.rb new file mode 100644 index 0000000..6b29a87 --- /dev/null +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/naifuku_tazai_rule.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +module Receiptisan + module Model + module ReceiptComputer + module Reporting + module Rule + class NaifukuTazaiRule + Util = Receiptisan::Model::ReceiptComputer::Util + Master = Receiptisan::Model::ReceiptComputer::Master + ShinryouShikibetsu = Receiptisan::Model::ReceiptComputer::DigitalizedReceipt::Receipt::ShinryouShikibetsu + + def check(digitalized_receipt) + digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?) + end + + def check_receipt(receipt) + return [] if receipt.nyuuin? + + reports = [] + + receipt.each_date do | date, ichirens | + count = 0 + is_teigened = false + yakuzais = [] + naifuku_ichirens = ichirens[ShinryouShikibetsu.find_by_code(21)] + naifuku_ichirens&.each do | ichiren | + ichiren.each do | santei | + next unless santei.resource_type == :iyakuhin + + santei_kaisuuu_suuryou = '' + santei.each.with_index do | cost, idx | + prefix = idx.zero? ? '*' : ' ' + if cost.comment? + yakuzais << "#{prefix}#{cost.format}" + else + yakuzais << '%s%s %d%s' % [prefix, cost.resource.master_item.name, cost.resource.shiyouryou, + cost.resource.unit&.name,] + isnt_teigen = cost.resource.master_item.code != Master::Treatment::Iyakuhin::Code.of('630010002') + is_iyakuhin = cost.resource_type == :iyakuhin + is_teigened = true unless isnt_teigen + count += 1 if is_iyakuhin && isnt_teigen + + santei_kaisuuu_suuryou = "\t%d x %d" % [santei.tensuu, santei.kaisuu] + end + + yakuzais << santei_kaisuuu_suuryou unless santei_kaisuuu_suuryou.empty? + end + end + end + + return [] if is_teigened || count < 7 + + result = [ + '-' * 50, + '%s%s - %s日' % [receipt.patient.id, receipt.patient.name, date.day] + ] + yakuzais + + reports << result + end + + reports + end + end + end + end + end + end +end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/sm_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/sm_rule.rb new file mode 100644 index 0000000..20b3729 --- /dev/null +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/sm_rule.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +module Receiptisan + module Model + module ReceiptComputer + module Reporting + module Rule + # 160057710 S−M 160057510 S−蛍光M、位相差M、暗視野M の同日算定 + class SMRule + Util = Receiptisan::Model::ReceiptComputer::Util + Master = Receiptisan::Model::ReceiptComputer::Master + ShinryouShikibetsu = Receiptisan::Model::ReceiptComputer::DigitalizedReceipt::Receipt::ShinryouShikibetsu + + def check(digitalized_receipt) + digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?) + end + + def check_receipt(receipt) + code_sm = Master::Treatment::ShinryouKoui::Code.of('160057710') + code_keikou = Master::Treatment::ShinryouKoui::Code.of('160057510') + + reports = [] + + receipt.each_date do | date, ichirens | + has_sm = false + has_keikou = false + + kensa_ichirens = ichirens[ShinryouShikibetsu.find_by_code(60)] + kensa_ichirens&.each do | ichiren | + ichiren.each do | santei | + next unless santei.resource_type == :shinryou_koui + + santei.each_cost do | cost | + has_sm = true if cost.resource.master_item.code == code_sm + has_keikou = true if cost.resource.master_item.code == code_keikou + end + end + end + + if has_sm && has_keikou + reports << [receipt.audit_payer.short_name, receipt.patient.id, receipt.patient.name, date].join("\t") + end + end + + reports + end + end + end + end + end + end +end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/yakujou_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/yakujou_rule.rb new file mode 100644 index 0000000..a1969fb --- /dev/null +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/yakujou_rule.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +module Receiptisan + module Model + module ReceiptComputer + module Reporting + module Rule + # 薬情月2回以上 + class YakujouRule + Util = Receiptisan::Model::ReceiptComputer::Util + Master = Receiptisan::Model::ReceiptComputer::Master + + def check(digitalized_receipt) + digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?) + end + + def check_receipt(receipt) + return [] if receipt.nyuuin? + + code_yakujou = Master::Treatment::ShinryouKoui::Code.of('120002370') + yakujou_count = 0 + + Util::ReceiptEnumeratorGenerator.each_cost_for( + receipt: receipt, + shinryou_shikibetsu_codes: ['13'], + resource_types: [:shinryou_koui] + ).each { | cost | yakujou_count += cost.kaisuu if cost.resource.code == code_yakujou } + + yakujou_count > 1 ? + [receipt.audit_payer.short_name, receipt.patient.id, receipt.patient.name, yakujou_count].join("\t") : + [] + end + end + end + end + end + end +end From 115f567ed3c392a307d656530d77cead4d894a71 Mon Sep 17 00:00:00 2001 From: yokenzan <31175068+yokenzan@users.noreply.github.com> Date: Wed, 29 Mar 2023 11:49:59 +0900 Subject: [PATCH 4/5] =?UTF-8?q?fix(receipt=5Fcheck):=20=E8=A8=BA=E7=99=82?= =?UTF-8?q?=E6=97=A5=E3=81=94=E3=81=A8=E3=81=AB=E7=AE=97=E5=AE=9A=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E3=82=92=E6=8A=BD=E5=87=BA=E3=81=99=E3=82=8B=E3=83=AD?= =?UTF-8?q?=E3=82=B8=E3=83=83=E3=82=AF=E3=81=A7=E6=AD=A3=E3=81=97=E3=81=8F?= =?UTF-8?q?=E6=8A=BD=E5=87=BA=E3=81=95=E3=82=8C=E3=81=AA=E3=81=84=E4=B8=8D?= =?UTF-8?q?=E5=85=B7=E5=90=88=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../digitalized_receipt/receipt.rb | 9 +++--- .../receipt/tekiyou/cost.rb | 5 ++++ .../receipt/tekiyou/ichiren_unit.rb | 14 ++++++--- .../receipt/tekiyou/santei_unit.rb | 30 +++++++++++++++++-- 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt.rb b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt.rb index d086d35..4b0bbf0 100644 --- a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt.rb +++ b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt.rb @@ -92,10 +92,11 @@ def dates def each_date dates.each do | date | - @tekiyou.each_value do | ichirens | - ichirens = ichirens.select { | ichiren | ichiren.on_date(date) }.group_by(&:shinryou_shikibetsu) - yield date, ichirens - end + 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 diff --git a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/cost.rb b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/cost.rb index 94333cd..3493c36 100644 --- a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/cost.rb +++ b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/cost.rb @@ -89,6 +89,7 @@ def each_comment(&block) attr_reader :resource, :futan_kubun, :tensuu, :kaisuu, :shinryou_shikibetsu, :daily_kaisuus def_delegators :futan_kubun, :uses? + def_delegators :resource, :name, :code end class DailyKaisuu @@ -97,6 +98,10 @@ def initialize(date:, kaisuu:) @kaisuu = kaisuu end + def on?(date) + @date == date + end + attr_reader :date, :kaisuu end end diff --git a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/ichiren_unit.rb b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/ichiren_unit.rb index e61264f..798b1a3 100644 --- a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/ichiren_unit.rb +++ b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/ichiren_unit.rb @@ -36,18 +36,24 @@ def futan_kubun # @return [self, nil] def on_date(date) - return unless @santei_units.any? { | santei | santei.on_date?(date) } + return nil unless @santei_units.any? { | santei | santei.on_date?(date) } - self.class.new(shinryou_shikibetsu: shinryou_shikibetsu).tap do | copied | - @santei_units.each { | santei | copied.add_santei_unit(santei) if 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 diff --git a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/santei_unit.rb b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/santei_unit.rb index d11c945..b8068a9 100644 --- a/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/santei_unit.rb +++ b/lib/receiptisan/model/receipt_computer/digitalized_receipt/receipt/tekiyou/santei_unit.rb @@ -55,12 +55,38 @@ def each_date end def on_date?(date) - @daily_kaisuus.any? { | daily_kaisuu | daily_kaisuu.date == date } + @daily_kaisuus.any? { | daily_kaisuu | daily_kaisuu.on?(date) } end # @return [self, nil] def on_date(date) - on_date?(date) ? self : nil + 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] From 38f1284b39402145a686f6e3672ba08ceacbcfc6 Mon Sep 17 00:00:00 2001 From: yokenzan <31175068+yokenzan@users.noreply.github.com> Date: Thu, 30 Mar 2023 03:15:35 +0900 Subject: [PATCH 5/5] feat(check): addd receipt-check rules --- .../cli/command/receipt_checklist_command.rb | 38 +++-- .../model/receipt_computer/reporting/rule.rb | 5 + .../reporting/rule/cholesterol_rule.rb | 10 +- .../reporting/rule/dimethicone_rule.rb | 14 +- .../reporting/rule/es_with_xylocaine_rule.rb | 25 ++- .../reporting/rule/influenza_rule.rb | 10 +- .../reporting/rule/metgluco_rule.rb | 62 ++++++++ .../reporting/rule/naifuku_tazai_rule.rb | 10 +- .../reporting/rule/sm_rule.rb | 10 +- .../reporting/rule/tanki_taizai3_rule.rb | 82 ++++++++++ .../rule/tokubetsushoku_kasan_rule.rb | 57 +++++++ .../reporting/rule/tokusho2_nissuu_rule.rb | 121 +++++++++++++++ .../rule/tokutei_shikkan_shubyou_rule.rb | 143 ++++++++++++++++++ .../reporting/rule/yakujou_rule.rb | 10 +- 14 files changed, 573 insertions(+), 24 deletions(-) create mode 100644 lib/receiptisan/model/receipt_computer/reporting/rule/metgluco_rule.rb create mode 100644 lib/receiptisan/model/receipt_computer/reporting/rule/tanki_taizai3_rule.rb create mode 100644 lib/receiptisan/model/receipt_computer/reporting/rule/tokubetsushoku_kasan_rule.rb create mode 100644 lib/receiptisan/model/receipt_computer/reporting/rule/tokusho2_nissuu_rule.rb create mode 100644 lib/receiptisan/model/receipt_computer/reporting/rule/tokutei_shikkan_shubyou_rule.rb diff --git a/lib/receiptisan/cli/command/receipt_checklist_command.rb b/lib/receiptisan/cli/command/receipt_checklist_command.rb index ded847a..68f192f 100644 --- a/lib/receiptisan/cli/command/receipt_checklist_command.rb +++ b/lib/receiptisan/cli/command/receipt_checklist_command.rb @@ -23,13 +23,18 @@ class ReceiptChecklistCommand < Dry::CLI::Command 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_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] uke_file_paths # @param [Hash] options @@ -55,13 +60,18 @@ def initialize_parser 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_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 diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule.rb index baac50a..0bb373c 100644 --- a/lib/receiptisan/model/receipt_computer/reporting/rule.rb +++ b/lib/receiptisan/model/receipt_computer/reporting/rule.rb @@ -7,3 +7,8 @@ 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' diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/cholesterol_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/cholesterol_rule.rb index 377c5a2..b7ed891 100644 --- a/lib/receiptisan/model/receipt_computer/reporting/rule/cholesterol_rule.rb +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/cholesterol_rule.rb @@ -12,7 +12,7 @@ class CholesterolRule ShinryouShikibetsu = Receiptisan::Model::ReceiptComputer::DigitalizedReceipt::Receipt::ShinryouShikibetsu def check(digitalized_receipt) - digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?) + append_header(digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?)) end def check_receipt(receipt) @@ -47,6 +47,14 @@ def check_receipt(receipt) reports end + + private + + def append_header(reports) + header = %w[請求先 患者番号 患者氏名 診療日].join("\t") + + reports.empty? ? reports : ['コレステロール検査同日併算定', header, *reports] + end end end end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/dimethicone_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/dimethicone_rule.rb index ab7cc54..689acb8 100644 --- a/lib/receiptisan/model/receipt_computer/reporting/rule/dimethicone_rule.rb +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/dimethicone_rule.rb @@ -11,19 +11,19 @@ class DimethiconeRule Master = Receiptisan::Model::ReceiptComputer::Master def check(digitalized_receipt) - digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?) + append_header(digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?)) end def check_receipt(receipt) # | 620422003 | ジメチコン錠40mg「YD」 | # | 620423501 | ジメチコン内用液2%「FSK」 | - code_fs = Master::Treatment::ShinryouKoui::Code.of('160093810') + code_fs = Master::Treatment::ShinryouKoui::Code.of('160093810') code_of_dimechicones = [ Master::Treatment::Iyakuhin::Code.of('620422003'), Master::Treatment::Iyakuhin::Code.of('620423501'), ] - has_fs = false + has_fs = false used_dimechicone = nil Util::ReceiptEnumeratorGenerator.each_cost_for( @@ -49,6 +49,14 @@ def check_receipt(receipt) '%s%s' % [used_dimechicone.shiyouryou, used_dimechicone.unit.name], ].join("\t") end + + private + + def append_header(reports) + header = %w[請求先 患者番号 患者氏名 診療日].join("\t") + + reports.empty? ? reports : ['胃カメラ未実施でジメチコン使用', header, *reports] + end end end end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/es_with_xylocaine_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/es_with_xylocaine_rule.rb index 89159bf..01d8595 100644 --- a/lib/receiptisan/model/receipt_computer/reporting/rule/es_with_xylocaine_rule.rb +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/es_with_xylocaine_rule.rb @@ -12,7 +12,7 @@ class ESWithXylocaineRule ShinryouShikibetsu = Receiptisan::Model::ReceiptComputer::DigitalizedReceipt::Receipt::ShinryouShikibetsu def check(digitalized_receipt) - digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?) + append_header(digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?)) end def check_receipt(receipt) @@ -65,7 +65,7 @@ def check_receipt(receipt) reports << [ receipt.audit_payer.short_name, - receipt.nyuuin?, + receipt.nyuuin? ? '入院' : '入院外', receipt.patient.id, receipt.patient.name, date, @@ -81,6 +81,27 @@ def check_receipt(receipt) reports end + + private + + def append_header(reports) + header = %w[ + 請求先 + 入外 + 患者番号 + 患者氏名 + 診療日 + 胃カメラ実施 + ポリペク2cm未満実施 + ポリペク2cm以上実施 + 大腸カメラ(S状結腸)実施 + 大腸カメラ(下行・横行結腸)実施 + 大腸カメラ(上行結腸)実施 + キシロカイン使用量 + ].join("\t") + + reports.empty? ? reports : ['内視鏡のキシロカインゼリー使用量要確認リスト', header, *reports] + end end end end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/influenza_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/influenza_rule.rb index a9e44c6..cb2541a 100644 --- a/lib/receiptisan/model/receipt_computer/reporting/rule/influenza_rule.rb +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/influenza_rule.rb @@ -13,7 +13,7 @@ class InfluenzaRule ShinryouShikibetsu = Receiptisan::Model::ReceiptComputer::DigitalizedReceipt::Receipt::ShinryouShikibetsu def check(digitalized_receipt) - digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?) + append_header(digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?)) end def check_receipt(receipt) @@ -63,6 +63,14 @@ def check_receipt(receipt) reports end + + private + + def append_header(reports) + header = %w[請求先 患者番号 患者氏名 診療日].join("\t") + + reports.empty? ? reports : ['インフルエンザ系検査併算定', header, *reports] + end end end end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/metgluco_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/metgluco_rule.rb new file mode 100644 index 0000000..4122025 --- /dev/null +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/metgluco_rule.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +module Receiptisan + module Model + module ReceiptComputer + module Reporting + module Rule + # メトグルコ錠500mgを1日6錠以上処方するレセプトを抽出する + class MetglucoRule + Util = Receiptisan::Model::ReceiptComputer::Util + Master = Receiptisan::Model::ReceiptComputer::Master + ShinryouShikibetsu = Receiptisan::Model::ReceiptComputer::DigitalizedReceipt::Receipt::ShinryouShikibetsu + + def check(digitalized_receipt) + append_header(digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?)) + end + + def check_receipt(receipt) + metgluco = Master::Treatment::Iyakuhin::Code.of('622242501') + + reports = [] + + receipt.each_date do | date, ichirens | + + ichirens = ichirens[ShinryouShikibetsu.find_by_code(21)] + ichirens&.each do | ichiren | + ichiren.each do | santei | + next unless santei.resource_type == :iyakuhin + + santei.each_cost do | cost | + if cost.resource.code == metgluco && cost.resource.shiyouryou >= 6 + reports << [ + receipt.audit_payer.short_name, + receipt.patient.id, + receipt.patient.name, + date, + metgluco.value, + cost.resource.name, + '%d錠' % cost.resource.shiyouryou, + ].join("\t") + end + end + end + end + end + + reports + end + + private + + def append_header(reports) + header = %w[請求先 患者番号 患者氏名 診療日 医薬品コード 医薬品名 使用量].join("\t") + + reports.empty? ? reports : ['メトグルコ錠の使用量が6錠以上のレセプト', header, *reports] + end + end + end + end + end + end +end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/naifuku_tazai_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/naifuku_tazai_rule.rb index 6b29a87..6542243 100644 --- a/lib/receiptisan/model/receipt_computer/reporting/rule/naifuku_tazai_rule.rb +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/naifuku_tazai_rule.rb @@ -11,7 +11,7 @@ class NaifukuTazaiRule ShinryouShikibetsu = Receiptisan::Model::ReceiptComputer::DigitalizedReceipt::Receipt::ShinryouShikibetsu def check(digitalized_receipt) - digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?) + append_header(digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?)) end def check_receipt(receipt) @@ -61,6 +61,14 @@ def check_receipt(receipt) reports end + + private + + def append_header(reports) + header = %w[患者番号 患者氏名 診療日].join("\t") + + reports.empty? ? reports : ['内服他剤の可能性がある患者リスト', header, *reports] + end end end end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/sm_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/sm_rule.rb index 20b3729..517f75e 100644 --- a/lib/receiptisan/model/receipt_computer/reporting/rule/sm_rule.rb +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/sm_rule.rb @@ -12,7 +12,7 @@ class SMRule ShinryouShikibetsu = Receiptisan::Model::ReceiptComputer::DigitalizedReceipt::Receipt::ShinryouShikibetsu def check(digitalized_receipt) - digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?) + append_header(digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?)) end def check_receipt(receipt) @@ -44,6 +44,14 @@ def check_receipt(receipt) reports end + + private + + def append_header(reports) + header = %w[請求先 患者番号 患者氏名 診療日].join("\t") + + reports.empty? ? reports : ['S-M同日併算定', header, *reports] + end end end end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/tanki_taizai3_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/tanki_taizai3_rule.rb new file mode 100644 index 0000000..0cde799 --- /dev/null +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/tanki_taizai3_rule.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +module Receiptisan + module Model + module ReceiptComputer + module Reporting + module Rule + # 短期滞在3 + class TankiTaizai3Rule + Util = Receiptisan::Model::ReceiptComputer::Util + Master = Receiptisan::Model::ReceiptComputer::Master + ShinryouShikibetsu = Receiptisan::Model::ReceiptComputer::DigitalizedReceipt::Receipt::ShinryouShikibetsu + + def check(digitalized_receipt) + append_header(digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?)) + end + + def check_receipt(receipt) + haihan_codes = [ + Master::Treatment::ShinryouKoui::Code.of('160061810'), # 血液学的検査判断料 + Master::Treatment::ShinryouKoui::Code.of('160061910'), # 生化学的検査(1)判断料 + Master::Treatment::ShinryouKoui::Code.of('160062110'), # 免疫学的検査判断料 + Master::Treatment::ShinryouKoui::Code.of('120001710'), # 調基(入院) + Master::Treatment::ShinryouKoui::Code.of('120001810'), # 調基(その他) + Master::Treatment::ShinryouKoui::Code.of('170000210'), # 電子画像管理加算(単純撮影) + Master::Treatment::ShinryouKoui::Code.of('170016910'), # 電子画像管理加算(特殊撮影) + Master::Treatment::ShinryouKoui::Code.of('170017010'), # 電子画像管理加算(造影剤使用撮影) + Master::Treatment::ShinryouKoui::Code.of('170026710'), # 電子画像管理加算(乳房撮影) + Master::Treatment::ShinryouKoui::Code.of('170026810'), # 電子画像管理加算(核医学診断料) + Master::Treatment::ShinryouKoui::Code.of('170028810'), # 電子画像管理加算(コンピューター断層診断料) + ] + + reports = [] + + return reports unless tanki3?(receipt) + + Util::ReceiptEnumeratorGenerator.each_cost_for( + receipt: receipt, + resource_types: [:shinryou_koui] + ).each do | cost | + haihan_codes.each do | code | + cost.resource.code == code && reports << [ + receipt.audit_payer.short_name, + receipt.patient.id, + receipt.patient.name, + cost.daily_kaisuus.map(&:date).map(&:day).join(', '), + code.value, + cost.resource.name, + ].join("\t") + end + end + + reports + end + + private + + def append_header(reports) + header = %w[請求先 患者番号 患者氏名 診療日 診療行為コード 診療行為].join("\t") + + reports.empty? ? reports : ['短期滞在手術等基本料に包括される診療行為', header, *reports] + end + + def tanki3?(receipt) + has_tanki3 = false + + Util::ReceiptEnumeratorGenerator.each_cost_for( + receipt: receipt, + shinryou_shikibetsu_codes: ['92'], + resource_types: [:shinryou_koui] + ).each do | cost | + has_tanki3 = true if cost.resource.name.start_with?('短手3') + end + + has_tanki3 + end + end + end + end + end + end +end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/tokubetsushoku_kasan_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/tokubetsushoku_kasan_rule.rb new file mode 100644 index 0000000..b31fc45 --- /dev/null +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/tokubetsushoku_kasan_rule.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module Receiptisan + module Model + module ReceiptComputer + module Reporting + module Rule + # 特別食加算と食事療養数量の不一致を検出するルール + class TokubetsushokuRule + Util = Receiptisan::Model::ReceiptComputer::Util + Master = Receiptisan::Model::ReceiptComputer::Master + ShinryouShikibetsu = Receiptisan::Model::ReceiptComputer::DigitalizedReceipt::Receipt::ShinryouShikibetsu + + def check(digitalized_receipt) + append_header(digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?)) + end + + def check_receipt(receipt) + reports = [] + + receipt.each_date do | date, ichirens | + + ichirens = ichirens[ShinryouShikibetsu.find_by_code(97)] + ichirens&.each do | ichiren | + ichiren.each do | santei | + next unless santei.resource_type == :shinryou_koui + + santei.each_cost do | cost | + reports << [ + receipt.audit_payer.short_name, + receipt.patient.id, + receipt.patient.name, + date, + cost.resource.code.value, + cost.resource.name, + '%d食' % cost.resource.shiyouryou, + ].join("\t") + end + end + end + end + reports + end + + private + + def append_header(reports) + header = %w[請求先 患者番号 患者氏名 診療日 診療行為コード 名称 食数].join("\t") + + reports.empty? ? reports : ['特別食加算と食事療養数量の不一致を検出するルール', header, *reports] + end + end + end + end + end + end +end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/tokusho2_nissuu_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/tokusho2_nissuu_rule.rb new file mode 100644 index 0000000..62a31cb --- /dev/null +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/tokusho2_nissuu_rule.rb @@ -0,0 +1,121 @@ +# frozen_string_literal: true + +module Receiptisan + module Model + module ReceiptComputer + module Reporting + module Rule + class Tokusho2NissuuRule + Util = Receiptisan::Model::ReceiptComputer::Util + Master = Receiptisan::Model::ReceiptComputer::Master + ShinryouShikibetsu = Receiptisan::Model::ReceiptComputer::DigitalizedReceipt::Receipt::ShinryouShikibetsu + + def check(digitalized_receipt) + append_header(digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?)) + end + + def check_receipt(receipt) + return [] if receipt.nyuuin? + + reports = [] + + shubyous = receipt.shoubyoumeis.select(&:main?) + + receipt.each_date do | date, ichirens | + # 院内 + + innai_shohou_ichirens = ichirens[ShinryouShikibetsu.find_by_code(25)] + + if kanri_cost = pick_kanri_kasan(innai_shohou_ichirens || []) + reports << '----------------------------------------' + reports << receipt.audit_payer.short_name + reports << [receipt.patient.id, receipt.patient.name] + reports << [date, kanri_cost.resource.name, kanri_cost.resource.code.value].join("\t") + end + + # 院外 + + ingai_shohou_ichirens = ichirens[ShinryouShikibetsu.find_by_code(80)] + + if kanri_cost_ingai = pick_kanri_kasan(ingai_shohou_ichirens || []) + reports << '----------------------------------------' + reports << receipt.audit_payer.short_name + reports << receipt.patient.id + reports << receipt.patient.name + reports << [date, kanri_cost_ingai.resource.name, kanri_cost_ingai.resource.code.value].join("\t") + end + + next if kanri_cost.nil? && kanri_cost_ingai.nil? + + yakuzais = [] + naifuku_ichirens = ichirens[ShinryouShikibetsu.find_by_code(21)] + + naifuku_ichirens&.each do | ichiren | + ichiren.each do | santei | + next unless santei.resource_type == :iyakuhin + + santei_kaisuuu_suuryou = '' + santei.each.with_index do | cost, idx | + prefix = idx.zero? ? '*' : ' ' + if cost.comment? + yakuzais << "#{prefix}\t#{cost.format}" + else + yakuzais << "%s\t%s %d%s" % [ + prefix, + cost.resource.name, + cost.resource.shiyouryou || 0, + cost.resource.unit&.name || '', + ] + + santei_kaisuuu_suuryou = "\t%d x %d" % [santei.tensuu, santei.kaisuu] + end + + yakuzais << santei_kaisuuu_suuryou unless santei_kaisuuu_suuryou.empty? + end + end + end + + reports << yakuzais + end + + reports + end + + private + + def append_header(reports) + header = %w[患者番号 患者氏名 診療日].join("\t") + + reports.empty? ? reports : ['内服他剤の可能性がある患者リスト', header, *reports] + end + + # @param shohou_ichirens [Array] + def pick_kanri_kasan(shohou_ichirens) + shohou_ichirens.each do | ichiren | + ichiren.each do | santei | + next unless santei.resource_type == :shinryou_koui + + santei.each_cost do | cost | + return cost if self.class.kanri_kasan_codes.include?(cost.resource.code) + end + end + end + + nil + end + + class << self + def kanri_kasan_codes + [ + Master::Treatment::ShinryouKoui::Code.of('120003170'), # 特定疾患処方管理加算2(処方料) + Master::Treatment::ShinryouKoui::Code.of('120003270'), # 特定疾患処方管理加算2(処方箋料) + Master::Treatment::ShinryouKoui::Code.of('120003270'), # 特定疾患処方管理加算2(処方箋料) + ] + end + end + end + end + end + end + end +end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/tokutei_shikkan_shubyou_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/tokutei_shikkan_shubyou_rule.rb new file mode 100644 index 0000000..0b34998 --- /dev/null +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/tokutei_shikkan_shubyou_rule.rb @@ -0,0 +1,143 @@ +# frozen_string_literal: true + +module Receiptisan + module Model + module ReceiptComputer + module Reporting + module Rule + # 特定疾患処方管理加算・特定疾患療養管理料 + class TokuteiShikkanShubyouRule + Util = Receiptisan::Model::ReceiptComputer::Util + Master = Receiptisan::Model::ReceiptComputer::Master + ShinryouShikibetsu = Receiptisan::Model::ReceiptComputer::DigitalizedReceipt::Receipt::ShinryouShikibetsu + + def check(digitalized_receipt) + append_header(digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?)) + end + + # @param receipt [DigitalizedReceipt::Receipt] + def check_receipt(receipt) + reports = [] + + shubyous = receipt.shoubyoumeis.select(&:main?) + + receipt.each_date do | date, ichirens | + next if shubyou_exists?(shubyous, date) + + igaku_kanri_ichirens = ichirens[ShinryouShikibetsu.find_by_code(13)] + + if kanri_cost = pick_kanriryou(igaku_kanri_ichirens || []) + reports << [ + receipt.audit_payer.short_name, + receipt.patient.id, + receipt.patient.name, + date, + kanri_cost.resource.code.value, + kanri_cost.resource.name, + ].join("\t") + end + + innai_shohou_ichirens = ichirens[ShinryouShikibetsu.find_by_code(25)] + + if kanri_cost = pick_kanri_kasan(innai_shohou_ichirens || []) + reports << [ + receipt.audit_payer.short_name, + receipt.patient.id, + receipt.patient.name, + date, + kanri_cost.resource.code.value, + kanri_cost.resource.name, + ].join("\t") + end + + ingai_shohou_ichirens = ichirens[ShinryouShikibetsu.find_by_code(80)] + + if kanri_cost = pick_kanri_kasan(ingai_shohou_ichirens || []) + reports << [ + receipt.audit_payer.short_name, + receipt.patient.id, + receipt.patient.name, + date, + kanri_cost.resource.code.value, + kanri_cost.resource.name, + ].join("\t") + end + end + + reports + end + + private + + def append_header(reports) + header = %w[請求先 患者番号 患者氏名 診療日 診療行為コード 名称].join("\t") + + reports.empty? ? reports : ['主病がない状態で特定疾患療養管理料・特定疾患処方管理加算を算定しているレセプトを検出するルール', header, *reports] + end + + # @param shubyous [Array] + # @param date [Date] + def shubyou_exists?(shubyous, date) + shubyous.any? { | shubyou | shubyou.start_date <= date } + end + + # @param igaku_kanri_ichirens [Array] + def pick_kanriryou(igaku_kanri_ichirens) + igaku_kanri_ichirens.each do | ichiren | + ichiren.each do | santei | + next unless santei.resource_type == :shinryou_koui + + santei.each_cost do | cost | + return cost if self.class.kanriryou_codes.include?(cost.resource.code) + end + end + end + + nil + end + + # @param shohou_ichirens [Array] + def pick_kanri_kasan(shohou_ichirens) + shohou_ichirens.each do | ichiren | + ichiren.each do | santei | + next unless santei.resource_type == :shinryou_koui + + santei.each_cost do | cost | + return cost if self.class.kanri_kasan_codes.include?(cost.resource.code) + end + end + end + + nil + end + + class << self + def kanriryou_codes + [ + Master::Treatment::ShinryouKoui::Code.of('113001810'), # 特定疾患療養管理料(診療所) + Master::Treatment::ShinryouKoui::Code.of('113001910'), # 特定疾患療養管理料(100床未満) + Master::Treatment::ShinryouKoui::Code.of('113001910'), # 特定疾患療養管理料(100床以上200床未満) + Master::Treatment::ShinryouKoui::Code.of('113029010'), # 特定疾患療養管理料(情報通信機器) + Master::Treatment::ShinryouKoui::Code.of('113034010'), # 特定疾患療養管理料(診療所・情報通信機器) + Master::Treatment::ShinryouKoui::Code.of('113034110'), # 特定疾患療養管理料(100床未満の病院・情報通信機器) + Master::Treatment::ShinryouKoui::Code.of('113034210'), # 特定疾患療養管理料(100床以上200床未満病院・情報通信機器) + ] + end + + def kanri_kasan_codes + [ + Master::Treatment::ShinryouKoui::Code.of('120002270'), # 特定疾患処方管理加算1(処方料) + Master::Treatment::ShinryouKoui::Code.of('120002570'), # 特定疾患処方管理加算1(処方箋料) + Master::Treatment::ShinryouKoui::Code.of('120002570'), # 特定疾患処方管理加算1(処方箋料) + Master::Treatment::ShinryouKoui::Code.of('120003170'), # 特定疾患処方管理加算2(処方料) + Master::Treatment::ShinryouKoui::Code.of('120003270'), # 特定疾患処方管理加算2(処方箋料) + Master::Treatment::ShinryouKoui::Code.of('120003270'), # 特定疾患処方管理加算2(処方箋料) + ] + end + end + end + end + end + end + end +end diff --git a/lib/receiptisan/model/receipt_computer/reporting/rule/yakujou_rule.rb b/lib/receiptisan/model/receipt_computer/reporting/rule/yakujou_rule.rb index a1969fb..ef331b0 100644 --- a/lib/receiptisan/model/receipt_computer/reporting/rule/yakujou_rule.rb +++ b/lib/receiptisan/model/receipt_computer/reporting/rule/yakujou_rule.rb @@ -11,7 +11,7 @@ class YakujouRule Master = Receiptisan::Model::ReceiptComputer::Master def check(digitalized_receipt) - digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?) + append_header(digitalized_receipt.map { | receipt | check_receipt(receipt) }.reject(&:empty?)) end def check_receipt(receipt) @@ -30,6 +30,14 @@ def check_receipt(receipt) [receipt.audit_payer.short_name, receipt.patient.id, receipt.patient.name, yakujou_count].join("\t") : [] end + + private + + def append_header(reports) + header = %w[請求先 患者番号 患者氏名 薬情算定回数].join("\t") + + reports.empty? ? reports : ['薬情月内複数回算定', header, *reports] + end end end end