様々な表現で提供されるクレジットカードの利用履歴、あるいは複数のテーブルが一つのCSVで提供されることについて

## はじめに

データをコンピュータで処理するためにはコンピュータが扱いやすい形式でデータが提供されていることが必要であるということは誰にも納得していただけることだと思います。多くの場合、データを提供する形式としてCSVが使われるかと思いますが、データの構造に対してCSVの表現力が十分かというと、そうとは限らない場合が多いのではないかと思います。この記事ではクレジットカード会社が会員に提供している利用履歴データのCSVでの表現が多様性に富んでいることを紹介します。そしてCSVには収まらないデータが提供されていることを観察します。また、それに対して私がこうあってほしいと思っている表現を書きたいと思います。

最初にこのような記事を書くに至った経緯について触れておきましょう。私は[ledger](https://www.ledger-cli.org/)というソフトウェアで家計簿をつけていて、レシートから手入力で仕訳をした取引を記録しています。しかしそれでは多少の漏れが生じるので、クレジットカードに関しては利用履歴の突き合わせを定期的に行っています。しかし、この作業はそれなりに時間を使いますし、何より集中力を持っていかれます。毎月この作業を行うのは面倒なので、クレジットカード会社が提供している利用履歴CSVデータを使って自動で突き合わせることを思い立ちました。（Ledgerも転記した取引をCSVで出力できます。）

しかしながらここで問題が生じました。クレジットカード会社ごとに利用履歴の表現の仕方がバラバラなのです。単純に比較できなくて困りました。私は2週間かけてとりあえず[間に合わせのツール](https://github.com/ShotaroTsuji/compare-csv)を作りました。これでなんとか記録の比較はできるようになりました。しかし、よりよいデータの提供の仕方があるのではないかと思っています。あとで実際のCSVファイルを見てもらいますが、そこに現れている問題はそれぞれの会社が表現したいデータに対してCSVは表現力不足ではないかと思います。

この記事では4つのクレジットカード会社が提供する利用履歴CSVデータによる利用履歴の表現がそれぞれ異なることを観察します。それから、クレジットカードの利用履歴を表現するのにどのような構造があればよいのかを抽出し、ユーザーに提供される利用履歴データはこのような構造であれかしと私が思っているものを提案したいと思います。

## 各クレジットカード会社が提供するCSVの比較

CSVはよく知られている通り、カンマで区切られたフィールドからなるレコードが改行文字で区切られて格納されたテキスト形式のフォーマットです。シンプルな形式なので適当に処理されがちに思いますが、[RFC 4180](https://tools.ietf.org/html/rfc4180)でCSVのフォーマットが定義されています。

規格はあるといっても、レコードの並びからなるデータであることしか規定していないので、個別のデータの意味までは規定していません。ですから作る人によって自由にデータを整形することができます。フィールドの個数はいくつにしてもよいですし、各レコードが同じ数のフィールドを持たなくても構いません。

まずは4つのクレジットカード会社が提供している利用履歴CSVデータを紹介します。割とおとなしいものからはちゃめちゃなものまであり、それぞれの会社が思い思いの表現で利用履歴を提供していることがわかってもらえると思います。なお、プライバシーの観点から、利用履歴の具体的な内容はアルファベットに置き換えて伏せてあります。

### A社

最初に紹介するのはA社の利用履歴CSVデータです。A社は月別ではなく期間を指定して利用履歴を出力することができます。さっそく内容を見ていきましょう。

概ね大人しいCSVです。全てのレコードが8列からなります。ですが、1行目はヘッダとしての内容を持っておらず、実際には2行目がヘッダになっています。また、最後3行はコメントになっています。

```
月別ご利用明細 {{ ユーザー氏名 }}　様　ご利用期間：yyyy年mm月からyyyy年mm月　株式会社XXXXXX,,,,,,,
種別（ショッピング、キャッシング、その他）,ご利用年月日,ご利用場所,ご利用内容,ご利用金額（キャッシングでは元金になります）,支払区分,お支払開始月,備考
ショッピング,yyyy年mm月dd日,AAAAAA,－,nnnnn,3回払い　*2,2020年5月,"１回目　n,nnn円 ２回目以降　n,nnn円"
ショッピング,yyyy年mm月dd日,AAAAAA,－,nnnn,1回払い,yyyy年mm月,
ショッピング,yyyy年mm月dd日,AAAAAA,－,nnnn,1回払い,yyyy年mm月,
ショッピング合計,,,,nnnnnn,,,
その他ご利用,yyyy年mm月dd日,AAAAAA,BBBBBB,nnnn,1回払い,yyyy年mm月,
その他ご利用合計,,,,nnnn,,,
（＊１）リボ変更適用分　（＊２）分割変更適用分　（＊３）解約済分　（＊４）リボ未切替分,,,,,,,
※１　ショッピングでは、現在までのご利用で、売上データが到着していないご利用分は含みません。,,,,,,,
※２　解約済み分はご利用合計には含まれません,,,,,,,
```

### B社

次に紹介するのはB社の利用履歴CSVデータです。B社は月別に利用履歴を出力する形式です。また、カードでの決済とモバイルでの決済で履歴が分かれています。

CSVファイルの各レコードの列数は7で揃っています。ただし、ヘッダは存在しません。各列の内容は`日付,利用店名,利用金額,支払区分,今回回数,支払金額,備考`です。`支払区分`は支払回数などのことで、`今回回数`は今回の支払回数のことです。備考欄には外国通貨での支払の際の換算レートなどが記載されます。また、最後の行には合計支払金額が記載されています。

```
{{ ユーザー氏名 }}　様,xxxx-xxxx-xxxx-xxxx,{{ カードブランド }}
yyyy/mm/dd,AAAAAA,nnnn,１,１,nnnn,
yyyy/mm/dd,AAAAAA,nnnn,１,１,nnnn,
yyyy/mm/dd,AAAAAA,nnnn,１,１,nnnn,aaaa.aa　JPY　1.0000　mm dd
yyyy/mm/dd,AAAAAA,nnnn,１,１,nnnn,aaaa.aa　JPY　1.0000　mm dd
{{ ユーザー氏名 }}　様,xxxx-xxxx-xxxx-xxxx,{{ モバイル決済ブランド }}
yyyy/09/01,AAAAAA／BB,nnnn,１,１,nnnn,
,,,,,74515,
```

### C社

C社の利用履歴CSVデータを紹介しましょう。この会社も履歴の出力は月別です。

まず最初の3行は2列からなるレコードが並びます。それから空行を挟んで利用履歴のテーブルが続きます。そして利用履歴のテーブルは最初にヘッダが来ます。各レコードは7列からなります。このCSVデータは実質的に二つのテーブルを含んでいることになります。

```
カード名称,{{ カード名称 }}
お支払日,yyyy/mm/dd
今回ご請求額,00000nnnnn

利用日,ご利用店名及び商品名,本人・家族区分,支払区分名称,締前入金区分,利用金額,備考
yyyy/mm/dd,AAAAAA,,１回,,nnnn,
yyyy/mm/dd,AAAAAA,,１回,,nnnn,
```

### D社

D社の利用履歴CSVデータを紹介しましょう。D社も月別に取得する方式です。

このCSVデータは複数のテーブルを含んでいます。空行で区切ることでサイズの異なるテーブルをExcelの一枚のシートに並べたようなCSVになっています。一つ目のユーザー氏名は1列のテーブル、二つ目は6列からなるテーブル、三つ目は4列からなるテーブル、四つ目は見出しが1行と2列のテーブル、そして五つ目にようやく利用履歴が11列のテーブルとして記されています。六つ目以降は1列のテーブルですが実際の内容はコメントに近いものです。

また、利用履歴の今回請求額が3桁ごとにカンマで区切られているのも困り物です。

```
"ユーザー氏名"

"カード種類","カード名称","カード番号","ブランド",,"照会月","明細作成日"
"一般","XXXX","****-****-****-****","XXXX",,"yyyy年m月","yyyy年m月dd日"

"お支払日","今回ご請求合計額[(1)－(2)]","(1)今回ご請求額","(2)事前お支払額"
"mm月dd日","nn,nnn","nn,nnn","0"

"カード代金支払口座"
"お取引店","口座番号"
"XXXX銀行　YYY支店","普通　**********"

"利用日","利用者","利用区分","利用内容","新規利用額","今回請求額","支払回数","現地通貨額","通貨略称","換算レート","備考"
"yyyy/m/d","xxxxx","１回払い","AAAAAAAA","nnnnn","n,nnn","","","","",""
"yyyy/m/d","xxxxx","１回払い","BBBBBBBB","nnnnn","nn,nnn","","","","",""
"yyyy/m/d","xxxxx","１回払い","CCCCCCCC","nnnnn","nn,nnn","","","","",""

"遅延損害金について"
"-- 遅延損害金の説明 --"

"支払停止の抗弁について"
"-- 支払停止の抗弁の説明 --"

"-- 問い合わせ先 --"
"-- 会社名 --"
"-- 部署名 --"
"-- 電話番号 --"
```

## JSONによる表現の提案

それぞれのクレジットカード会社の利用履歴CSVデータを観察してわかる問題点は、ⅰ）取引を表現するレコードのどのフィールドにどんな情報が入っているかわからないことと、ⅱ）複数のテーブルを一つのCSVファイルに押し込めているということです。これらの問題点を解決するためにCSVより高い表現力を持つフォーマットを利用する必要があると思います。そこで、JSONで表現できるように各社の例から取引を表現するのに必要な情報を拾い集めましょう。各社の利用履歴CSVデータの取引レコードのフィールドを以下にまとめました。

- A社
    `種別（ショッピング、キャッシング、その他）,ご利用年月日,ご利用場所,ご利用内容,ご利用金額（キャッシングでは元金になります）,支払区分,お支払開始月,備考`

- B社
    `日付,利用店名,利用金額,支払区分,今回回数,支払金額,備考`

- C社
    `利用日,ご利用店名及び商品名,本人・家族区分,支払区分名称,締前入金区分,利用金額,備考`

- D社
    `利用日,利用者,利用区分,利用内容,新規利用額,今回請求額,支払回数,現地通貨額,通貨略称,換算レート,備考`

まずは共通のフィールドを抜き出しましょう。日付、利用金額、支払区分、備考は共通しています。利用場所と利用内容は両方含んでいるものと片方だけを含むものがあります。

支払金額のフィールドはC社とD社のものにあります。D社では今回請求額という名前になっています。利用金額と支払金額のフィールドが別々に存在するのは分割払いがあるためです。分割払いを表現するために合計の支払回数と現在の支払回数を記録するフィールドも必要そうです。

D社は利用時の通貨と換算レートのフィールドを備えていますが、他の会社はこの情報を備考欄に入れてしまいます。今回はこの項目は独立させて扱うことにしましょう。

以上をまとめると一つの取引は次のようなフィールドを持つレコードになります。コロンの右側は各フィールドの型だと思ってください。

- __利用日__: 日付
- __利用場所__: 文字列
- __利用内容__: 文字列
- __利用金額__: 数値
- __支払金額__: 数値
- __支払区分__: "一回" | "分割" | "リボルビング"
- __支払回数__: 自然数 | なし
- __今回回数__: 自然数 | なし
- __現地通貨額__: 数値 | なし
- __通貨__: 文字列 | なし
- __換算レート__: 数値 | なし

上記の構造を各項目名をキーとするJSONのオブジェクトとして表現してほしいと考えています。そして、JSON Pointerで`/利用履歴`となる位置に取引の配列が格納されていてほしいと考えています。また、利用履歴とは別のキーで支払日、合計支払金額、クレジットカード番号などの情報を格納するのがよいと思っています。

## まとめ

以上でクレジットカードの利用履歴を表現するのに最低限必要と思われる構造とそのJSONによる表現を考えました。会社ごとに付加される情報は異なりますが、取引を表現するのに必要な情報は共通していると思います。この記事でまとめたことがクレジットカード会社の責任者に届くことを願っています。そしてできれば共通の規格で表現方法が統一されてほしいと思っています。

もちろんCSVでデータを取れるのはありがたいのですが、やはり処理にいくつか手間がかかるので単一のテーブルを表現する以外の用途では使わない方がよいかと思います。今回はクレジットカード会社の利用履歴を題材に取りましたが、他のデータでもその構造に応じて適切なフォーマットを選んで提供すべきかと思われます。もし読者の中にデータを提供する側になる方がいるのであれば、コンピュータで処理しやすい形でデータを提供するようにお願いします。