Firebaseを利用して金融機関のスマホ・アプリのシンプルなものを作ってみることにした。ヒントを与えてくれたのは、このYouTube ビデオ。
Let's code a beginner Python BANKING PROGRAM
今回の設定は、
1. Kanoo Bankという架空の銀行
2. 同銀行に2人が口座を保有
3. それぞれの入金、出金およびその2人の間での送金をトレースする
このアプリでは、データベースを扱うときの基本CRUD(Create/Read/Update/Delete)の内、CRを実装。
アプリ実行のビデオの通り、「取引実行」ボタンをタップするとWarningが表示されたり、残高がリアルタイムに変更されないなどまだまだ、問題多いが、このアプリを作り始めて随分時間も経過したので、この段階で一旦アップするもの。引き続き改善していく予定。Warning後、Reloadボタンをタップしたら表示できた。
今回はミラリング・ソフトがうまく作動したので、Firebase側のページとアプリの画面を同時録画。
アプリ実行のビデオ:
ビデオが長いためか、gooへのリンクを取得できなかったが、リンクが取得できた。
スクリーン・デザイン:
右側画面下部にあるテスト用のLabelは「Test Label3」までしか見えないが、計4つあり。
Test Label1=>データのIDリスト(tag list)
Test Label2=>全データのJSON File
Test Label3=>ログインした預金者のデータの日付リスト+取引内容(入金or出金)+入金or出金の金額(数字)のリスト
Test Label4=>出金可能金額合計額

以下はアプリ実行時の画面について、私の備忘録的にまとめたもの。全てのデータからログインしているKanooKanaの口座内容のみがListView(左端の画面の緑の四角内)に表示されている。(ちょっと日付は古いが、このアプリを作ってすぐにスクリーンショットしたもので、アプリ実行のビデオはこれに新たにデータを加えたもの)

ブロック・コーディング:
<Screen1>(スクリーン・デザインの左のランディング・ページ)
お客のお客様番号をキーに、ログインパスワードをその値としてDictionary型の変数customerDetailsを設定

画面が初期化される際に、openingClock1を有効にする。

ランディング・ページが表示されたら、若干間(ま)を置いてから、お客様番号の入力を促すポップアップを表示する。その間(ま)を格納する変数countIndexForOpeningを初期化。

countIndexForOpeningの interval は、1000ミリ秒にセットしてある。2回ループするので2秒の間をおくことになる。2秒経過するとelse以下が実行され、お客様番号の入力を促すポップアップが表示される。

変数customerNumberInput:上記ポップアップで入力される数字を格納

入力された数字を変数customerNumberInputにセットする。(この変数に格納されたデータは後で利用)=>入力されたお客様番号がcustomerDetailsのキー(お客様番号)に存在する場合は、「ログイン・パスワード」入力を促すポップアップが表示。ない場合は、再度お客様番号の入力を促すポップアップが表示。ただし、cancelボタンをタップした時の動作がまだ実装されていない。

変数customerPasswordを設定

変数customerDetailsよりcustomerNumInputをキーにしてパスワードを取り出し、customerPasswordに格納。
customerPasswordの値が入力の値とマッチすればtransitionClock1を有効にする。

変数countIndexToTransition:この値が2超となったら、すなわち2秒経過したら「mainScreen」へ遷移させる。その際、お客様番号を渡す。


<mainScreen>(スクリーン・デザインの右側の画面)
変数customerNameList:Screen1と同様の顧客情報をDictionary形式で格納。お客様番号をキーとして、値はお客様の名前と口座番号。Screen1にも似たような変数customerDetailsがあるので、一つにしてFirebase内で管理すべきかもしれないが、複雑になるので現段階ではそれぞれの画面で変数で対応。

変数transactionList:取引内容をlist形式で格納

関数init:リストの初期化

変数customerNameとcustomerAccountNumberをブランクで初期化。内容は変数の名前の通り。


mainScreenの初期化:
関数initを実行し、変数を初期化 => Layout用ブロック(HorizontalArrangement)であり、TextBoxの「入金額」と「引出し額」を格納しているdepositHAとwithdrawalHAを非表示とする。選択された取引内容が「入金」または「出金」であればいずれかを表示=>Screen1より渡された値を基に、dictionary型のcustomerNameListより値を取り出し、変数customerNameとcustomeracountNumberに格納。=>それぞれ、customerNameLabelとcustomerAccountNumberLabelに表示。=>transactionListPickerに取引種類(transationList)をセット。=>fetchingDataClockを有効にして動かす。

fetchingDataClockでは、データをFirebaseより取得するための関数(関数init、関数getTagList、関数getData)を2回実行させる。もちろん、1回実行させたら、うまくデータを取得できることもあるが、不安定であり、2回実行するとデータ取得を失敗することが少なくなったので、この方法を採用。(この方法は、以前マリオの時にも、背景をセットする際に利用)でも、成功率は低い。


なお、以下は、1回のみこれら3つの関数を実行する最初に試したブロック。(今回はこのブロックではなく、上記ブロックを使用)

関数initTextBox:depositTextboxとwithdrawlTextBoxをブランクで初期化する。

今回は、取引内容を「入金」と「出金」に限って作成。「送金」と「残高」は今後実装を検討予定。なお、「残高」は今回ほぼ実現しているので不要かもしれないが。
変数transactionType:「入金」か「出金」のいずれが選択されたかを格納するもの。「入金」=1、「出金」=2。

取引内容の選択後、
1. 「入金」の場合は、depositHA(入金額入力用TextBoxを内包)とexecutionButton「取引実行」を有効にする
2. 「出金」の場合は、withdrawlHA(出金額入力用TextBoxを内包)とexecutionButton「取引実行」を有効にする。

「取引実行」ボタンをタップした際の動作を設定。
取引内容リストより「1 入金」あるいは「2 出金」を選択した場合、関数makeCurrentDateおよび関数makeDepositWithdrawlTransactionを実行。

関数makeCurrentDate:
現在の日付を設定したフォーマットに変換の上変数currentDateに格納。フォーマットは こちらのサイト を参照にした。


関数makeDepositWithdrawlTransaction:
Firebaseに対しアップロードするデータを格納する変数postDataを初期化。
Firebaseには、このアプリ用にあらかじめサブフォルダー「PlayBank」を設定済み。
depositTextBoxまたはwithdrawTextBoxに何らかの入力がある場合は、POST先のURLをセットし、それぞれのデータをpostDataに格納。=>セットされたURLに対しPOST requestを行う。=>この際、金額については、「Amount」と「AmountForCalculation」の二つのデータをアップロードしている。「出金」の場合は残高より差し引く必要があるため、「AmountForCalculation」は Amount X -1 として負の数字としている。後で残高などを計算する時は、この「AmountForCalculation」の数字のみを対象に行なっている。
なお、depositTextBoxおよびwithdrawTextBoxが空白の場合は、金額の入力を促すポップアップを表示。


関数getTagList:
これは、Firebaseを利用するときにいつも行なっている各データのIDを取り出すもの。パラメーター「?shallow=true」を追加すれば取得できる。
所定のURLをセットして、GET requestを行う。

データが取得できれば、変数tagListにIDのリストを格納。なお、取得したそれぞれのデータのindexが1のデータを取り出しているが、[["-ojds983rlrlkas_xVFW", "TRUE"], ......]のようなリスト形式で、最初のIDのみを取り出すため。(Mit App Inventor の場合、index は 0 ではなく1 )



関数getData:
データの詳細を取得するため、所定のURLをセットし、GET requestを行う。

データ取得に成功すれば、取得データをデコードの上変数responseJSONに格納。
その後、各データアイテムごとにリストを作成するため、関数makeDateList、makeAmountList、makeTransactionTypeListを実行し、最後にListViewに表示するデータを作成するmakeDataForListViewを実行する。
なお、それぞれの結果は、testLabel2 ~ 4 に表示させている。
accountBalanceLabelは残高を表示するもので、3桁ごとに区切り、末尾に「円」を追加。


以下は、データリストを作成する関数のブロックで、関数getTagListで取得したIDをキーにして各アイテムごとに順番にデータを取り出してリスト形式で変数に保存している。
想定では、このFirebaseのデータベースは銀行のデータベースであり、すべての客のデータを保存している。したがって、現在このアプリにログインしているお客様のデータを取り出す必要がある。そのため、ログインしたお客様の名前と各データのお客様の名前をチェックし、合致すればリストに追加していく。(最初のif statementの部分)



関数makeAmountList:ほぼ上記と同様。




関数makeTransactionTypeList:ほぼ、上記と同様。



関数makeDataForListView:
上記関数実行により取得した当該お客様のアイテムごとのデータ(リスト形式)を表示形式を整え統合してListView用のリストを作成。



Reloadボタンをタップした時の動作を設定。基本的に変数の初期化と再度Firebaseよりデータを取得し表示する関数を実行している。


FirebaseやPublic APIを利用した場合、どうしても長くなってしまう。
まだまだ、問題が多いが、色々試行錯誤を行なっていきたい。