Javeとシェルスクリプトでセルフメディケーション税制合計額を算出する。

# はじめに

皆さんは確定申告をされたことはあるでしょうか？

今回はセルフメディケーション税制の合計額をいくら使ったかを見ていきたいと思います。

確定申告されている方なら知っていると思いますが、セルフメディケーション税制とは年間12000円以上第2類医薬品を買うと、確定申告の時に控除されるというものです。

ドラッグストアで該当医薬品(風邪薬や頭痛薬など対象)を買うとレシートの商品名の横辺りに◆マークがついていると思います。

レシートをファイルに見立てて、購入日付、商品名、税抜き額をJavaでファイルを作成し、軽減税率を加味して、税率と税込額をシェルスクリプトで算出します。
そして最後にセルフメディケーション税制の合計額を算出したいと思います。

セルフメディケーション税制対象は商品名の頭に◆、軽減税率では消費税8％対象が商品名の頭に*を付けます。

因みに、今回の購入商品はあくまでも一例であり、設定はフィクションです。

## Javaのプログラムから見ていきましょう。
```Java:Medicine.java

import java.io.*;

class Receipt {
    //privateフィールド
	private int date;
    private String merchandise;
    private int price;
    
	//コンストラクタ
    public Receipt(int d, String m, int p) {
        date = d;
        merchandise = m;
        price = p;
    }
    
	//日付を取得
    public int getDate() {
        return date;
    }
    
	//商品名を取得
    public String getMerchandise() {
        return merchandise;
    }
    
	//価格を取得
    public int getPrice() {
        return price;
    }
    
	//ファイル書き込み用
    public String getFile() {
        return date + "," + merchandise + "," + price;
    }
}

class Medicine {
    public static void main(String[] args) {
        //オブジェクト生成
    	Receipt[] receipt = {
            new Receipt(20230102, "◆パブロンゴールド", 1280),
            new Receipt(20230102, "*キリン生茶", 433),
            new Receipt(20230107, "*キリン生茶", 433),
            new Receipt(20230107, "*シマダヤ流水麺", 218),
            new Receipt(20230107, "キレイキレイ", 498),
            new Receipt(20230107, "キュキュット詰め替え用", 297),
            new Receipt(20230207, "◆パブロンゴールド", 1280),
            new Receipt(20230207, "キレイキレイ", 498),
            new Receipt(20230207, "*サントリクラフトボス", 218),
            new Receipt(20230207, "キュキュット詰め替え用", 297),
            new Receipt(20230211, "*アサヒ三ツ矢サイダー", 137),
            new Receipt(20230227, "キュキュット詰め替え用", 297),
            new Receipt(20230227, "キレイキレイ", 498),
            new Receipt(20230307, "◆パブロン鼻炎カプセル", 1280),
            new Receipt(20230307, "*サントリクラフトボス", 218),
            new Receipt(20230312, "◆パブロンゴールド", 1280),
            new Receipt(20230319, "◆パブロン鼻炎カプセル", 1280),
            new Receipt(20230319, "キュキュット詰め替え用", 297),
            new Receipt(20230319, "キレイキレイ", 498),
            new Receipt(20230325, "◆パブロン鼻炎カプセル", 1280),
            new Receipt(20230331, "◆パブロン鼻炎カプセル", 1280),
            new Receipt(20230403, "キュキュット詰め替え用", 297),
            new Receipt(20230403, "キレイキレイ", 498),
            new Receipt(20230411, "◆パブロン鼻炎カプセル", 1280),
            new Receipt(20230411, "*サントリクラフトボス", 218),
            new Receipt(20230415, "◆パブロンゴールド", 1280),
            new Receipt(20230419, "◆パブロン鼻炎カプセル", 1280),
            new Receipt(20230419, "キュキュット詰め替え用", 297),
            new Receipt(20230419, "キレイキレイ", 498),
            new Receipt(20230423, "◆パブロン鼻炎カプセル", 1280),
            new Receipt(20230429, "◆パブロン鼻炎カプセル", 1280)
        };
        
    	// ファイル指定
        String Filename = "/mnt/dev8/FILE/Medicine1";
        try {
            // ファイルへの書き込み
            BufferedWriter out = new BufferedWriter(new FileWriter(Filename));
            String lf = System.getProperty("line.separator");
            for(Receipt reｃ : receipt) {
                out.write(rec.getFile() + lf);
            }
            out.close();
            
            // ファイルからの読み取り
            FileReader in = new FileReader(Filename);
            BufferedReader br = new BufferedReader(in);
            System.out.println("領収書ファイル");
        	String line;
            while ((line = br.readLine()) != null) {
            	System.out.println(line);
            }
            br.close();
            
        } catch (IOException e) {
            System.out.println("ファイルが書き込み中にエラーが発生しました。");
        }
    }
}

```
クラスReceiptから見ていくと、

date(日付)、merchandise(商品名)、price(価格)をprivateフィールドにて定義しています。

それをコンストラクタを利用することにより、クラスMedicineで一括にデータを入れることができます。

日付取得、商品名を取得、価格を取得、ファイル書き込み用の戻り値で使用するメソッドも合わせて記述します。

オブジェクト生成のところでは配列としてまとめてデータ入力しています。

次にファイルを書き込んで、実行結果としてファイルを読み込みます。

ファイル指定でファイルの格納先を指定しています。

##### ファイルの書き込み:

・BufferedWriterを使用して指定されたファイルに書き込みます。

・for文のループ処理を使ってreceipt配列内の各Receiptオブジェクトの情報をファイルに書き込みます。
  ファイル書き込み用のgetFile()メソッドがReceiptオブジェクトのファイル形式の文字列を返します。

##### ファイルからの読み取り:

・FileReaderとBufferedReaderを使用してファイルから読み取ります。
・while文のループ処理を使ってファイルの各行を読み取り、それをターミナル上に出力します。

FileWriterだと一文字ずつ書き込むため、今回のようにまとめてデータを出力する場合、
非効率なのでBufferedWriterと合わせて使います。

FileReaderの場合も同様で一文字ずつ読み込みますが、BufferedReaderが効率的に読み込む事ができます。
readLineメソッドは1行ずつ読み込みを行い読み込み完了時点で”null”を返すため、
while文を使い、ファイル全体を行がなくなるまでループ処理させます。

実行すると次のようになります。

```Medicine.java実行結果
領収書ファイル

20230102,◆パブロンゴールド,1280

20230102,*キリン生茶,433

20230107,*キリン生茶,433

20230107,*シマダヤ流水麺,218

20230107,キレイキレイ,498

20230107,キュキュット詰め替え用,297

20230207,◆パブロンゴールド,1280

20230207,キレイキレイ,498

20230207,*サントリクラフトボス,218

20230207,キュキュット詰め替え用,297

20230211,*アサヒ三ツ矢サイダー,137

20230227,キュキュット詰め替え用,297

20230227,キレイキレイ,498

20230307,◆パブロン鼻炎カプセル,1280

20230307,*サントリクラフトボス,218

20230312,◆パブロンゴールド,1280

20230319,◆パブロン鼻炎カプセル,1280

20230319,キュキュット詰め替え用,297

20230319,キレイキレイ,498

20230325,◆パブロン鼻炎カプセル,1280

20230331,◆パブロン鼻炎カプセル,1280

20230403,キュキュット詰め替え用,297

20230403,キレイキレイ,498

20230411,◆パブロン鼻炎カプセル,1280

20230411,*サントリクラフトボス,218

20230415,◆パブロンゴールド,1280

20230419,◆パブロン鼻炎カプセル,1280

20230419,キュキュット詰め替え用,297

20230419,キレイキレイ,498

20230423,◆パブロン鼻炎カプセル,1280

20230429,◆パブロン鼻炎カプセル,1280
```

## セルフメディケーション税制の合計額を算出するシェルスクリプトを見ます。

```bash:Medicine.sh
#!/bin/bash
#カレントディレクトリを設定する。
cd /mnt/dev8 && pwd

# Medicineを実行。
java Medicine

# Javaファイルを指定する。
INFILE="/mnt/dev8/FILE/Medicine1"

# 税率と税込額を算出する。
OUTFILE1="/mnt/dev8/FILE/Medicine2"
cat "${INFILE}" | awk -v  OFS=, -F, '{tax = ($1<"20191001"||$2~"^*") ? 1.08 : 1.1; print $0,tax ;}' |
 awk -v OFS=, -F, '{print $0, int($3*$4)}{a+=int($3*$4)}END{print "合計額",a}' > "${OUTFILE1}"

# 税率・税込額ファイルを表示する。
echo "税率・税込額ファイル"
cat "${OUTFILE1}"

# セルフメディケーション税制合計額を算出する。
OUTFILE2="/mnt/dev8/FILE/SELF-MED-1"
cat "${OUTFILE1}" | awk -v OFS=, -F, '$2 ~ /^◆/' |
 awk -v OFS=, -F, '{print $0}{b+=$5}END{print "セルフメディケーション税制合計額",b}' > "${OUTFILE2}"

# セルフメディケーション税制合計額ファイルを表示する。
echo 'セルフメディケーション税制合計額ファイル'
cat "${OUTFILE2}"

exit 0
```

java Medicineを実行して上記Medicine.java実行結果が出ます。
読み込まれたファイルが実行結果としてターミナル上に映るでしょう。

### 税率と税込額を算出するコマンドを見ていきます。
```bash:Medicine.sh抜粋
# 税率と税込額を算出する。
OUTFILE1="/mnt/dev8/FILE/Medicine2"
cat "${INFILE}" | awk -v  OFS=, -F, '{tax = ($1<"20191001"||$2~"^*") ? 1.08 : 1.1; print $0,tax ;}' |
 awk -v OFS=, -F, '{print $0, int($3*$4)}{a+=int($3*$4)}END{print "合計額",a}' > "${OUTFILE1}"

# 税率・税込額ファイルを表示する。
echo "税率・税込額ファイル"
cat "${OUTFILE1}"
```

### 税率のところを見ていきます。
```bash:Medicine.sh抜粋
cat "${INFILE}" | awk -v  OFS=, -F, '{tax = ($1<"20191001"||$2~"^*") ? 1.08 : 1.1; print $0,tax ;}'
```
catコマンドをJavaで作成されるファイルをパイプでawkに引き渡して「-v 変数名」と「‐F 区切り文字」でawkを出力するときにフィールドを区切るのにカンマ区切りする意味です。
tax = (＄1<"20191001"||＄2~"^\*") ? 1.08 : 1.1は三項演算子と呼ばれるもので、軽減税率が始まった2019月10月01日より前の日付で、||(or演算子)で「または」を意味して、~演算子は商品名の先頭に\*がつくパターンマッチした場合の正規表現で、真の処理で税率が1.08になるという意味です。
条件として整理すると＄1(日付のフィールド)が20191001より前または、＄2(商品名のフィールド)の先頭に*がつくと税率が8％という意味です。
後続の print $0,taxまでやってINFILEの結果に加えて4列目に税率(tax)が加わりました。

```bash:Medicine.shのここまでの実行結果
20230102,◆パブロンゴールド,1280,1.1

20230102,*キリン生茶,433,1.08

20230107,*キリン生茶,433,1.08

20230107,*シマダヤ流水麺,218,1.08

20230107,キレイキレイ,498,1.1

20230107,キュキュット詰め替え用,297,1.1

20230207,◆パブロンゴールド,1280,1.1

20230207,キレイキレイ,498,1.1

…一部抜粋
```
```cmd:awkコマンドまとめ
awk -v 変数名  ・・・変数に値を代入します。

awk ‐F 区切り文字  ・・・フィールドの区切り文字を指定します。デフォルトはスペースとタブです。

三項演算子(条件演算子)
条件式 ? 真の処理 : 偽の処理
```
### 次に税込額と合計額を見ていきます
```bash:Medicine.sh抜粋
awk -v OFS=, -F, '{print $0, int($3*$4)}{a+=int($3*$4)}END{print "合計額",a}' > "${OUTFILE1}"
```
Javaで作成した領収書ファイルに税率と税込額と合計額を合わせたファイルをOUTFILE1として作成したいため、
税率の結果をパイプで引き渡して、ここでも「-v 変数名」と「‐F 区切り文字」を使ってます。
int関数で3列目の値段と4列目の税率を掛け算した結果を小数点以下切り捨てに出来ます。
合計額のところはAWKのENDパターンといわれるので、awkが最終行の処理を終えた後の処理になります。
a+=int(＄3\*＄4)で税込額をそれぞれ行を合算して合計額を算出しています。
ENDパターンがあるということはもちろんBEGINパターンもあります。
a+=int(＄3\*＄4)が実行される直前に整数0で初期化されるため、BEGIN{a=0}を書くのを省略することが出来ます。

税率・税込額ファイルの実行結果は以下の通りになります。

```bash:Medicine.shのここまでの実行結果
税率・税込額ファイル

20230102,◆パブロンゴールド,1280,1.1,1408

20230102,*キリン生茶,433,1.08,467

20230107,*キリン生茶,433,1.08,467

20230107,*シマダヤ流水麺,218,1.08,235

20230107,キレイキレイ,498,1.1,547

20230107,キュキュット詰め替え用,297,1.1,326

20230207,◆パブロンゴールド,1280,1.1,1408

20230207,キレイキレイ,498,1.1,547

20230207,*サントリクラフトボス,218,1.08,235

20230207,キュキュット詰め替え用,297,1.1,326

20230211,*アサヒ三ツ矢サイダー,137,1.08,147

20230227,キュキュット詰め替え用,297,1.1,326

20230227,キレイキレイ,498,1.1,547

20230307,◆パブロン鼻炎カプセル,1280,1.1,1408

20230307,*サントリクラフトボス,218,1.08,235

20230312,◆パブロンゴールド,1280,1.1,1408

20230319,◆パブロン鼻炎カプセル,1280,1.1,1408

20230319,キュキュット詰め替え用,297,1.1,326

20230319,キレイキレイ,498,1.1,547

20230325,◆パブロン鼻炎カプセル,1280,1.1,1408

20230331,◆パブロン鼻炎カプセル,1280,1.1,1408

20230403,キュキュット詰め替え用,297,1.1,326

20230403,キレイキレイ,498,1.1,547

20230411,◆パブロン鼻炎カプセル,1280,1.1,1408

20230411,*サントリクラフトボス,218,1.08,235

20230415,◆パブロンゴールド,1280,1.1,1408

20230419,◆パブロン鼻炎カプセル,1280,1.1,1408

20230419,キュキュット詰め替え用,297,1.1,326

20230419,キレイキレイ,498,1.1,547

20230423,◆パブロン鼻炎カプセル,1280,1.1,1408

20230429,◆パブロン鼻炎カプセル,1280,1.1,1408

合計額,24155

```

```cmd:awkコマンドまとめ
int  ・・・小数点以下切り捨てします。

STARTパターン  ・・・awkが1行目の処理を始める前の処理。

ENDパターン  ・・・awkが最終行の処理を終えた後の処理。
```

###  セルフメディケーション税制合計額を見ていきます。

```bash:Medicine.sh抜粋
# セルフメディケーション税制額を算出する。
OUTFILE2="/mnt/dev8/FILE/SELF-MED-1"
cat "${OUTFILE1}" | awk -v OFS=, -F, '$2 ~ /^◆/' |
 awk -v OFS=, -F, '{print $0}{b+=$5}END{print "セルフメディケーション税制合計額",b}' > "${OUTFILE2}"

# セルフメディケーション税制合計額ファイルを表示する。
echo 'セルフメディケーション税制合計額ファイル'
cat "${OUTFILE2}"
```
税率・税込額ファイルを使ってセルフメディケーション税制の対象の先頭に◆が来るものを
awkコマンドで抽出します。
ここでも「-v 変数名」と「‐F 区切り文字」を使ってます。
税率・税込額ファイルでもやった合計額を算出するENDパターンを使います。
今回は5列目が税込額なので、先頭に◆が抽出できていれば、セルフメディケーション税制合計額が算出されます。

```bash:Medicine.shのここまでの実行結果
セルフメディケーション税制合計額ファイル

20230102,◆パブロンゴールド,1280,1.1,1408

20230207,◆パブロンゴールド,1280,1.1,1408

20230307,◆パブロン鼻炎カプセル,1280,1.1,1408

20230312,◆パブロンゴールド,1280,1.1,1408

20230319,◆パブロン鼻炎カプセル,1280,1.1,1408

20230325,◆パブロン鼻炎カプセル,1280,1.1,1408

20230331,◆パブロン鼻炎カプセル,1280,1.1,1408

20230411,◆パブロン鼻炎カプセル,1280,1.1,1408

20230415,◆パブロンゴールド,1280,1.1,1408

20230419,◆パブロン鼻炎カプセル,1280,1.1,1408

20230423,◆パブロン鼻炎カプセル,1280,1.1,1408

20230429,◆パブロン鼻炎カプセル,1280,1.1,1408

セルフメディケーション税制合計額,16896

```

正常に行けば以下の様に出力されます。
```bash:Medicine.shの実行結果
$ bash Medicine.sh

/mnt/dev8

領収書ファイル

20230102,◆パブロンゴールド,1280

20230102,*キリン生茶,433

20230107,*キリン生茶,433

20230107,*シマダヤ流水麺,218

20230107,キレイキレイ,498

20230107,キュキュット詰め替え用,297

20230207,◆パブロンゴールド,1280

20230207,キレイキレイ,498

20230207,*サントリクラフトボス,218

20230207,キュキュット詰め替え用,297

20230211,*アサヒ三ツ矢サイダー,137

20230227,キュキュット詰め替え用,297

20230227,キレイキレイ,498

20230307,◆パブロン鼻炎カプセル,1280

20230307,*サントリクラフトボス,218

20230312,◆パブロンゴールド,1280

20230319,◆パブロン鼻炎カプセル,1280

20230319,キュキュット詰め替え用,297

20230319,キレイキレイ,498

20230325,◆パブロン鼻炎カプセル,1280

20230331,◆パブロン鼻炎カプセル,1280

20230403,キュキュット詰め替え用,297

20230403,キレイキレイ,498

20230411,◆パブロン鼻炎カプセル,1280

20230411,*サントリクラフトボス,218

20230415,◆パブロンゴールド,1280

20230419,◆パブロン鼻炎カプセル,1280

20230419,キュキュット詰め替え用,297

20230419,キレイキレイ,498

20230423,◆パブロン鼻炎カプセル,1280

20230429,◆パブロン鼻炎カプセル,1280

税率・税込額ファイル

20230102,◆パブロンゴールド,1280,1.1,1408

20230102,*キリン生茶,433,1.08,467

20230107,*キリン生茶,433,1.08,467

20230107,*シマダヤ流水麺,218,1.08,235

20230107,キレイキレイ,498,1.1,547

20230107,キュキュット詰め替え用,297,1.1,326

20230207,◆パブロンゴールド,1280,1.1,1408

20230207,キレイキレイ,498,1.1,547

20230207,*サントリクラフトボス,218,1.08,235

20230207,キュキュット詰め替え用,297,1.1,326

20230211,*アサヒ三ツ矢サイダー,137,1.08,147

20230227,キュキュット詰め替え用,297,1.1,326

20230227,キレイキレイ,498,1.1,547

20230307,◆パブロン鼻炎カプセル,1280,1.1,1408

20230307,*サントリクラフトボス,218,1.08,235

20230312,◆パブロンゴールド,1280,1.1,1408

20230319,◆パブロン鼻炎カプセル,1280,1.1,1408

20230319,キュキュット詰め替え用,297,1.1,326

20230319,キレイキレイ,498,1.1,547

20230325,◆パブロン鼻炎カプセル,1280,1.1,1408

20230331,◆パブロン鼻炎カプセル,1280,1.1,1408

20230403,キュキュット詰め替え用,297,1.1,326

20230403,キレイキレイ,498,1.1,547

20230411,◆パブロン鼻炎カプセル,1280,1.1,1408

20230411,*サントリクラフトボス,218,1.08,235

20230415,◆パブロンゴールド,1280,1.1,1408

20230419,◆パブロン鼻炎カプセル,1280,1.1,1408

20230419,キュキュット詰め替え用,297,1.1,326

20230419,キレイキレイ,498,1.1,547

20230423,◆パブロン鼻炎カプセル,1280,1.1,1408

20230429,◆パブロン鼻炎カプセル,1280,1.1,1408

合計額,24155

セルフメディケーション税制合計額ファイル

20230102,◆パブロンゴールド,1280,1.1,1408

20230207,◆パブロンゴールド,1280,1.1,1408

20230307,◆パブロン鼻炎カプセル,1280,1.1,1408

20230312,◆パブロンゴールド,1280,1.1,1408

20230319,◆パブロン鼻炎カプセル,1280,1.1,1408

20230325,◆パブロン鼻炎カプセル,1280,1.1,1408

20230331,◆パブロン鼻炎カプセル,1280,1.1,1408

20230411,◆パブロン鼻炎カプセル,1280,1.1,1408

20230415,◆パブロンゴールド,1280,1.1,1408

20230419,◆パブロン鼻炎カプセル,1280,1.1,1408

20230423,◆パブロン鼻炎カプセル,1280,1.1,1408

20230429,◆パブロン鼻炎カプセル,1280,1.1,1408

セルフメディケーション税制合計額,16896

```

余談ですが、16000円くらいで12000円を超えているのでセルフメディケーション税制で確定申告出来ますね。

## 最後に
今回、Javaで入力ファイルを作って、それを基にシェルスクリプトで税率と税込額とその合計額、セルフメディケーション税制の
合計額を算出出来ました。
今まではCOBOLをメインにやっていきましたが、Javaを学んでいって今までCOBOLでやってきた処理とかをJavaでコーディングしてみるのも
いいなと感じます。

セルフメディケーション税制の入力ファイルですがCOBOLでも作成していましたが、opensource COBOLの場合、レコードが改行されない
事象と桁数を余分に定義したりするので空白行などが入り、上記の手順と合わせてそれらを対処する説明を書かないと行けない為、
かなり冗長な説明になってしまう為、今回、Javaで説明させていただきました。

最後までご覧いただきありがとうございました。