🦔

GENDAインターン体験記(鰭崎):外貨両替機の警送コスト削減に向けたDX化

に公開

はじめに

はじめまして!株式会社GENDAインターン生の鰭崎です。
東京大学工学部に所属している4年生です。

今回は、9ヶ月ほど長期インターン生として携わらせていただきました業務をインターン体験記として共有させていただこうと思います。

インターン参加のきっかけ

去年の9月から東京大学発のエンジニアサークルUTokyo Tech Clubに6期生として加わり、ゼロからWeb開発の知識を身につけ、実際にアプリ開発を行いハッカソンを修了しました。その後、同サークルのインターン紹介を通じてGENDAに出会いました。
https://www.uttc.dev/
GENDAを選んだ理由は、

  • 勢いがある会社で、スピード感を体験してみたかった
  • 他のインターン生の方々が楽しく業務をされていた

と、楽しみながら成長できる環境だと感じたためです。

業務内容

インターンでは、外貨両替機に日本円を補充するという警送工程において、補充台の選定やルートの自動化を行いました。本記事では背景や具体的な実装方法をご紹介します。

背景

グループ会社であるアクトプロの外貨両替機「SMARTEXCHANGE」は、主に訪日外国人を対象とした海外の現金通貨を日本円に両替する自動外貨両替機です。

これまで、外貨両替機に日本円を補充する際の警送台の選定や巡回ルートの作成は、担当者が手作業で行っていました。
しかしこの方法にはいくつかの課題がありました。

まず、経験や勘に基づく判断によって補充台が選ばれるため、実際にはまだ十分な残高がある台まで補充対象になってしまうケースがありました。これにより、現金が過剰に機械内に滞留し、結果として利息負担の増加につながっていました。
一方で、反対に補充が後回しになったことで「エンプティ台(日本円が不足し、取引が停止してしまう台)」が発生するケースもありました。これによって本来得られるはずの両替機会を逃し、売上機会損失が発生してしまうという課題も存在しました。
また、ルートの設計も人手で行われていたため、効率の悪い経路が選ばれてしまうこともあり、移動距離の増加による人件費の増大が課題でした。

そこで、これらの問題を解決するために、私は補充台の自動選定とルート最適化のシステム化に取り組みました。

この問題は一般的に「巡回セールスマン問題(Travelling Salesman Problem, TSP)」と呼ばれ、すべての地点を最短で回る経路を求めるという組合せ最適化問題に分類されます。
理論的には「厳密解」を求めるのは計算的に困難ですが、最近ではAIや機械学習を用いた近似最適化手法によって、現実的な時間で高精度な解を導くことが可能になっています。

本プロジェクトでは、これらの手法を応用し、警送台の補充効率を最大化しつつ、ルートの最短化を図る自動化システムを実装しました。

プロジェクトの全体像

本プロジェクトでは、「どの台に補充に行くべきか」 と 「その台をどの順番で回るべきか」 を一体として最適化する仕組みを構築しました。

この最適化には Google Maps Platform の Route Optimization API を活用し、各台の位置情報と優先度(コスト)を入力として、AI が自動的に最適な巡回順序と訪問対象を算出する仕組みを実装しました。これにより、限られた時間内で効率的かつ無駄のない補充ルートを実現しています。

google map表示

警送計画の例

1. 各台ごとの「empty までの日数」を推定

まずは、どの台がどれくらい危険(empty が近い)かを定量的に評価するところから始めました。

  • 台ごとの過去の両替金額 / day(1日あたりの両替ペース)
  • 台ごとの現在の日本円残高

をもとに、「あと何日で empty になるか?」を計算し、empty までの日数をシミュレーションします。
この値が小さい台ほど、「早く補充に行かないと危ない台」とみなせます。

2. empty が近い台ほど「コスト(優先度)」を大きくする

次に、その「empty までの日数」から、Route Optimization API に渡すpenaltyCostを設計しました。

Route Optimization API では、各訪問先ごとにpenaltyCostを設定でき、「そのポイントをスキップしたときにどれだけコストがかかったとみなすか」を指定できます。
最適化エンジンは、

  • その地点を回るための移動コスト・時間コスト
  • スキップしたときの penaltyCost

を比較しながら、「どの地点に行くか/行かないか」を判断します。

ここで、
1.empty が近い台 → penaltyCost を大きく
2.余裕がある台 → penaltyCost を小さく

というルールでコストを設定することで、
「empty が近い台は、多少遠回りでも極力行く」
「余裕のある台は、ルートや時間に余裕があれば行く」

という挙動を実現しました。

3. 位置情報+コストを Route Optimization API に投入

各台について、

1.緯度・経度(位置情報)
2.ペナルティコスト
3.作業時間
4.その日の警送車両の稼働時間・開始/終了地点 など

をまとめて Route Optimization API に渡します。
Route Optimization 側では、全ての候補台を一度に見たうえで、
訪問コスト+移動距離(時間)の合計が最小になるように
「どの台に行くか/行かないか」と「どの順番で回るか」
を同時に最適化してくれます。

結果として、

  • その日は絶対に行くべき台(emptyが近い・ペナルティ大)
  • 余裕があれば行く台(ペナルティ中)
  • 今日はスキップしてよい台(ペナルティ小)

が自動的に振り分けられ、それらを 時間内におさまるようなルートに落とし込めるようになりました。

4. kintone で作業時間を蓄積し、ルート精度を改善

さらに、実際の運用では、各台での実際の作業時間をkintoneに記録し、日々データを蓄積していきました。
このデータをもとに、次回以降の Route Optimization 呼び出し時に より現実に近い作業時間として反映させています。

これにより、実績との誤差を埋めるようにパラメータを調整していく
というフィードバックループを回せるようになりました。

実装・技術スタック

実装はすべて Google Apps Script(GAS) で行いました。
スプレッドシートをデータベース代わりに使い、各両替台の残高や両替実績などの情報を取得して処理します。スクリプトはこれらのデータをもとに Route Optimization API にリクエストを送り、最適な警送ルートを計算します。

返ってきたルート情報(訪問順・移動時間・対象台など)は再びスプレッドシートに書き込み、現場担当者がそのまま参照できるようにしました。
また、実際の作業時間や移動時間を kintone に記録し、日々更新される実績データを次回以降のルート計算に反映することで、より精度の高い補充計画を実現しています。

苦労した点・工夫した点

開発の中で最も大変だったのは、Google Apps Script (GAS) の管理トラブルでした。
当初は複数人で同じスクリプトプロジェクトを編集していたのですが、ある日、同時に作業した際に変更のコンフリクト(競合)が発生し、コードがほぼすべて消えてしまうという事故が起きました。GASはリアルタイム共同編集が可能な反面、バージョン管理の仕組みが弱く、編集の衝突や誤保存によって簡単に上書きが起こってしまいます。

この出来事をきっかけに、開発体制を一から見直しました。まず、処理をライブラリ化し、機能ごとに独立したスクリプトに分割することで、編集範囲を明確にしました。
たとえば、

  • スプレッドシートの読み書き処理
  • Route Optimization API への通信部分
  • データ整形・結果出力部分

といった機能をモジュール単位で分け、それぞれを別ファイルまたは独立ライブラリとして管理するようにしました。これにより、複数人が同時に作業しても衝突しにくくなり、変更の追跡も容易になりました。

さらに、clasp(Command Line Apps Script Projects) を導入して、スクリプトをローカル環境でも管理できるようにしました。これによって、コードを GitHub にバックアップしたり、過去バージョンに戻したりできるよう整備しました。

結果として、トラブルは痛手ではありましたが、ライブラリ化とバージョン管理の導入を通じて、チーム開発に耐えうる堅牢な構成に進化しました。今では、誰がどの処理を触っても安全に動かせる体制が整い、長期運用を見据えた開発基盤として安定しています。

終わりに

今回のインターンでは、実際の業務課題を自分の手でシステムとして解決するという、非常に貴重な経験をさせていただきました。
当初は「警送ルートの自動化」という一見シンプルなテーマでしたが、実際に取り組んでみると、データの扱い方やAPIの制約、現場での運用とのギャップなど、多くの課題がありました。それらを一つひとつ乗り越える中で、「システムを作ること」と「業務を良くすること」は別物であり、両者をどうつなぐかが本当の開発だということを学びました。

また、GAS や kintone といった身近なツールでも、設計次第で十分に高度な自動化や最適化が実現できるという実感も得られました。単に動くものを作るだけでなく、「誰が使っても運用できる仕組み」に仕上げる重要性を、痛いトラブルとともに身をもって体験できたのは大きな財産です。

今後もこの経験を活かし、技術を使って現場の課題を解決し、人の仕事をより創造的な方向へ導けるようなエンジニアを目指していきたいと思います。

Discussion