diff --git a/lib/receiptisan/model/receipt_computer/master/loader/comment_loader.rb b/lib/receiptisan/model/receipt_computer/master/loader/comment_loader.rb index 86fc6c7..f01cf4e 100644 --- a/lib/receiptisan/model/receipt_computer/master/loader/comment_loader.rb +++ b/lib/receiptisan/model/receipt_computer/master/loader/comment_loader.rb @@ -36,7 +36,7 @@ def load(csv_paths) pattern: Treatment::Comment::Pattern.find_by_code( values[Treatment::Comment::Columns::C_パターン] ), - name: convert_kakkotsuki_mark( + name: replace_kakkotsuki_mark( convert_unit(convert_unit(values[Treatment::Comment::Columns::C_コメント文_漢字名称])) ), name_kana: convert_katakana(values[Treatment::Comment::Columns::C_コメント文_カナ名称]), diff --git a/lib/receiptisan/model/receipt_computer/master/loader/iyakuhin_loader.rb b/lib/receiptisan/model/receipt_computer/master/loader/iyakuhin_loader.rb index 4514681..2b11efa 100644 --- a/lib/receiptisan/model/receipt_computer/master/loader/iyakuhin_loader.rb +++ b/lib/receiptisan/model/receipt_computer/master/loader/iyakuhin_loader.rb @@ -16,7 +16,7 @@ def load(csv_paths) code = Treatment::Iyakuhin::Code.of(values[Treatment::Iyakuhin::Columns::C_コード]) hash[code.value] = Treatment::Iyakuhin.new( code: code, - name: convert_kakkotsuki_mark( + name: replace_kakkotsuki_mark( convert_unit(values[Treatment::Iyakuhin::Columns::C_医薬品名・規格名_漢字名称]) ), name_kana: convert_katakana(values[Treatment::Iyakuhin::Columns::C_医薬品名・規格名_カナ名称]), diff --git a/lib/receiptisan/model/receipt_computer/master/loader/loader_trait.rb b/lib/receiptisan/model/receipt_computer/master/loader/loader_trait.rb index d5dfce5..e5b20ef 100644 --- a/lib/receiptisan/model/receipt_computer/master/loader/loader_trait.rb +++ b/lib/receiptisan/model/receipt_computer/master/loader/loader_trait.rb @@ -32,7 +32,7 @@ def foreach(csv_paths) def_delegators Receiptisan::Util::Formatter, :convert_katakana, :convert_unit, - :convert_kakkotsuki_mark + :replace_kakkotsuki_mark end end end diff --git a/lib/receiptisan/model/receipt_computer/master/loader/shinryou_koui_loader.rb b/lib/receiptisan/model/receipt_computer/master/loader/shinryou_koui_loader.rb index 1b2a808..da19c2b 100644 --- a/lib/receiptisan/model/receipt_computer/master/loader/shinryou_koui_loader.rb +++ b/lib/receiptisan/model/receipt_computer/master/loader/shinryou_koui_loader.rb @@ -21,7 +21,7 @@ def load(version, csv_paths) code = Treatment::ShinryouKoui::Code.of(values[columns::C_コード]) hash[code.value] = Treatment::ShinryouKoui.new( code: code, - name: convert_kakkotsuki_mark( + name: replace_kakkotsuki_mark( convert_unit(values[columns::C_省略名称_漢字名称]) ), name_kana: convert_katakana(values[columns::C_省略名称_カナ名称]), diff --git a/lib/receiptisan/model/receipt_computer/master/loader/tokutei_kizai_loader.rb b/lib/receiptisan/model/receipt_computer/master/loader/tokutei_kizai_loader.rb index b7b6372..c88832a 100644 --- a/lib/receiptisan/model/receipt_computer/master/loader/tokutei_kizai_loader.rb +++ b/lib/receiptisan/model/receipt_computer/master/loader/tokutei_kizai_loader.rb @@ -16,7 +16,7 @@ def load(csv_paths) code = Treatment::TokuteiKizai::Code.of(values[Treatment::TokuteiKizai::Columns::C_コード]) hash[code.value] = Treatment::TokuteiKizai.new( code: code, - name: convert_kakkotsuki_mark( + name: replace_kakkotsuki_mark( convert_unit(values[Treatment::TokuteiKizai::Columns::C_特定器材名・規格名_漢字名称]) ), name_kana: convert_katakana(values[Treatment::TokuteiKizai::Columns::C_特定器材名・規格名_カナ名称]), diff --git a/lib/receiptisan/util/formatter.rb b/lib/receiptisan/util/formatter.rb index 28ef4d4..d96ddac 100644 --- a/lib/receiptisan/util/formatter.rb +++ b/lib/receiptisan/util/formatter.rb @@ -1,22 +1,23 @@ # frozen_string_literal: true +require_relative 'formatter/kakkotsuki_formatter' + module Receiptisan module Util module Formatter MARU_ICHI_CODEPOINT = 0x2460 # ①~⑳のコードポイント MARU_ICHI_CODEPOINT_21 = 0x3251 # ㉑以降のコードポイント MARU_ICHI_CODEPOINT_36 = 0x32b1 # ㊱以降のコードポイント - KAKKO_ICHI_CODEPOINT = 0x2474 # ⑴のコードポイント HANKAKU_CHARS = '−() A-Za-z0-9.' ZENKAKU_CHARS = '―() A-Za-z0-9.' # カンマ区切り表記にする # @param integer [Integer, nil] nilの場合は空文字列を返します # @return [String] - def to_currency(integer) - return '' if integer.nil? + def to_currency(value) + return '' unless value.respond_to?(:to_i) - integer.to_s.gsub(/(\d)(?=(\d{3})+(?!\d))/, '\1,') + value.to_i.to_s.gsub(/(\d)(?=(\d{3})+(?!\d))/, '\1,') end # マル付数字の文字を生成する @@ -39,14 +40,9 @@ def to_marutsuki_mark(zero_based_index) codepoint.chr('UTF-8') end - # カッコ付数字の文字を生成する - # @param zero_based_index [Integer] # @return [String] - def to_kakkotsuki_mark(zero_based_index) - # 用意されている文字はカッコ20まで - raise ArgumentError, "given index is out of range (0~19): '#{zero_based_index}'" if zero_based_index >= 20 - - (KAKKO_ICHI_CODEPOINT + zero_based_index).chr('UTF-8') + def replace_kakkotsuki_mark(string) + KakkotsukiFormatter.format(string) end # @param value [String, Symbol, Integer, nil] nilの場合は空文字列を返します @@ -73,10 +69,6 @@ def convert_katakana(hankaku) NKF.nkf('-wWX', hankaku) end - def convert_kakkotsuki_mark(string) - string.gsub(/(([0-9]{1,2}))/) { | m | to_kakkotsuki_mark(to_hankaku(m).to_i) } - end - def convert_unit(string) string .gsub('mLV', '㎖V') diff --git a/lib/receiptisan/util/formatter/kakkotsuki_formatter.rb b/lib/receiptisan/util/formatter/kakkotsuki_formatter.rb new file mode 100644 index 0000000..431f4b7 --- /dev/null +++ b/lib/receiptisan/util/formatter/kakkotsuki_formatter.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +module Receiptisan + module Util + module Formatter + module KakkotsukiFormatter + Formatter = ::Receiptisan::Util::Formatter + + KAKKO_ICHI_CODEPOINT = 0x2474 # ⑴のコードポイント + TARGET_RANGE = 1..20 + + # カッコ付数字の文字が含まれていたら置換する + # @return [String] + def format(string) + string.gsub(/(([1-9][0-9]*))/) do + matched_number = ::Regexp.last_match(1) + number = Formatter.to_hankaku(matched_number).to_i + convertable?(number) ? convert(number - 1) : matched_number + end + end + + # カッコ付数字の文字を生成する + # @param zero_based_index [Integer] + # @return [String] + def convert(zero_based_index) + # 用意されている文字はカッコ20まで + unless convertable?(zero_based_index + 1) + min = TARGET_RANGE.begin - 1 + max = TARGET_RANGE.end - 1 + + raise ArgumentError, "given index is out of range (#{min}~#{max}): '#{zero_based_index}'" + end + + (KAKKO_ICHI_CODEPOINT + zero_based_index).chr('UTF-8') + end + + def convertable?(number) + number.between?(TARGET_RANGE.begin, TARGET_RANGE.end) + end + + module_function :format, :convert, :convertable? + end + end + end +end diff --git a/spec/lib/receiptisan/util/formatter/kakkotsuki_formatter_spec.rb b/spec/lib/receiptisan/util/formatter/kakkotsuki_formatter_spec.rb new file mode 100644 index 0000000..8171046 --- /dev/null +++ b/spec/lib/receiptisan/util/formatter/kakkotsuki_formatter_spec.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require 'receiptisan' + +RSpec.describe Receiptisan::Util::Formatter::KakkotsukiFormatter do + describe '#convert' do + context '0を渡したとき' do + specify '⑴を返す' do + expect(described_class.convert(0)).to eq '⑴' + end + end + + context '1を渡したとき' do + specify '⑵を返す' do + expect(described_class.convert(1)).to eq '⑵' + end + end + + context '3を渡したとき' do + specify '⑶を返す' do + expect(described_class.convert(2)).to eq '⑶' + end + end + + context '19を渡したとき' do + specify '⒇を返す' do + expect(described_class.convert(19)).to eq '⒇' + end + end + + context '20を渡したとき' do + specify '(21)は表示不可能なので範囲外である旨例外を投げる' do + expect { described_class.convert(20) }.to raise_error(ArgumentError, "given index is out of range (0~19): '20'") + end + end + end + + describe '#format' do + context 'カッコ数字を含む文字列を渡したとき' do + context '「生化学的検査(1)判断料」を渡したとき' do + specify '「生化学的検査⑴判断料」を返す' do + expect(described_class.format('生化学的検査(1)判断料')).to eq '生化学的検査⑴判断料' + end + end + + context '「生化学的検査(2)判断料」を渡したとき' do + specify '「生化学的検査⑵判断料」を返す' do + expect(described_class.format('生化学的検査(2)判断料')).to eq '生化学的検査⑵判断料' + end + end + end + + context('カッコ数字を含まない文字列を渡したとき') do + context '「処方箋料(リフィル以外・その他)」を渡したとき' do + specify '何も変更せず「処方箋料(リフィル以外・その他)」を返す' do + expect(described_class.format('処方箋料(リフィル以外・その他)')).to eq '処方箋料(リフィル以外・その他)' + end + end + + context '「一般名処方加算2(処方箋料)」を渡したとき' do + specify '何も変更せず「一般名処方加算2(処方箋料)」を返す' do + expect(described_class.format('一般名処方加算2(処方箋料)')).to eq '一般名処方加算2(処方箋料)' + end + end + end + end +end diff --git a/spec/lib/receiptisan/util/formatter_spec.rb b/spec/lib/receiptisan/util/formatter_spec.rb new file mode 100644 index 0000000..926dba5 --- /dev/null +++ b/spec/lib/receiptisan/util/formatter_spec.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require 'receiptisan' + +RSpec.describe Receiptisan::Util::Formatter do + # TODO: Integer以外のパターン + + describe '#to_currency' do + context '正の整数' do + context '4桁のとき' do + specify '千の位と百の位の間にカンマを付した文字列を返すこと' do + expect(described_class.to_currency(1234)).to eq '1,234' + end + end + + context '6桁のとき' do + specify '千の位と百の位の間にカンマを付した文字列を返すこと' do + expect(described_class.to_currency(123_456)).to eq '123,456' + end + end + + context '7桁のとき' do + specify '百万の位と十万の位、千の位と百の位の間にそれぞれカンマを付した文字列を返すこと' do + expect(described_class.to_currency(1_234_567)).to eq '1,234,567' + end + end + + context '3桁のとき' do + specify 'カンマを付さず3桁の数値を文字列として返すこと' do + expect(described_class.to_currency(123)).to eq '123' + end + end + end + + context '負の整数' do + context '4桁のとき' do + specify 'マイナス符号つきの、千の位と百の位の間にカンマを付した文字列を返すこと' do + expect(described_class.to_currency(-1234)).to eq '-1,234' + end + end + + context '3桁のとき' do + specify 'カンマを付さず3桁の数値を文字列として返すこと' do + expect(described_class.to_currency(-123)).to eq '-123' + end + end + end + end +end