はじめに
初めまして、私たちはテクノロジー戦略本部の23卒エンジニアです。
バイセルでは、入社後に毎年新卒エンジニアが協力してプロダクト開発研修を行っています。
新卒11人はAチームとBチームに分けられ、私たちの所属するAチームは、「店舗買取時に作成される契約書の不備による差し戻し」を減らすことをテーマに契約書作成をサポートする拡張機能を開発しました。
プロダクト開発研修とは
まず、バイセルのテクノロジー戦略本部の新卒研修であるプロダクト開発研修について説明します。
新卒エンジニア研修というと、コードの書き方を学んだりGitを使ってみたりするものや、チームでのハッカソンなど何か手を動かしてものを作るもの、という印象を持たれる方もいるかと思われます。
バイセルのプロダクト開発研修は、業務の課題解決や全社を巻き込んだ新たなプロジェクトを立ち上げる、という形で行います。
プロダクト開発研修の目的は次の2点です。
ユーザの課題を解決するまでのプロセスを学ぶ
エンジニアの仕事は、技術の力でユーザーの課題を解決することです。 ユーザーが抱える本質的な課題を発見し、どのような課題をどのようなプロダクトで解決するべきか、解決までのプロセスを理解することが大切です。リーダーシップとチームワークの重要性を学ぶ
会社において仕事はチームですすめるものであり、一人で仕事はできません。 チームの中でどのような役割分担をし、どのようなリーダーシップを発揮するべきか、そして協力して課題解決する重要性を学びます。
プロダクト開発研修ではまず初めにテーマが与えられ、ゼロから要件定義をして、開発、ユーザーフィードバックの収集、それを受けてのロードマップ作成などを行います。
新卒でプロダクト開発を初期段階から経験したことのあるメンバーは少ないので、もちろん進めていく上で多くの先輩エンジニアから助言を貰いつつ開発していきます。
また、テーマの深掘りや課題の発見はエンジニアだけで行うのではなく、バイセルグループ内の事業部のメンバーにヒアリングやアンケートで情報をもらいつつ行っていきます。
さらに、期間内だけ取り組んで終わりではなく、プロダクト開発研修期間の2週間が終わった後もフィードバックを貰いながら開発は続いていきます。
「業務に活かせるものを作る」という目的と、作って終わりではなくそれがスタートラインである、というエンジニアとしての心構えを学べるものとなっています。
この記事を読むことで、バイセルで行う新卒エンジニア研修への解像度を高め、バイセルが大切にするエンジニア像について知ってもらえれば幸いです。
背景
契約書の差し戻しについて見ていく前に、バイセルにおける店舗買取のフローを簡単にご紹介します。
まず、来店されたお客様から商品をお預かりし査定いたします。その後、査定額に応じてお売りいただく商品を選択していただき、売買契約へと進みます。本人確認等を済ませ、お客様情報やお売りいただく商品を契約書にまとめます。この売買契約書を作成することでお客様からの買取が正式に成立するという流れです。
売買契約書には古物営業法に基づいたフォーマットや記載ルール、バイセル独自の記法が存在しており、不備がないかを契約ごとにセールスコンプライアンス課(以下、SC課)が確認しています。
売買契約書をSC課に確認を依頼するフローを「決裁申請」と呼び、契約書の内容に後述する不備が存在した場合は、店舗スタッフに対して修正を依頼する形で契約書の差し戻しが発生します。これが「決裁申請の差し戻し」です。
決裁申請の差し戻しがもたらす課題
バイセルでの店舗買取は、Storeというバイセル独自のWebサービスを利用しています(詳細は後述します)。
決裁申請時に提出される売買契約書の不備は2種に大別され、「古物営業法で作成するべき契約書形態に反しているもの」「バイセルとしての買取商材記法に違反しているもの」に分けられます。
具体的な不備例としては、
- 添付する本人確認書類(保険証)の写真の特定部分にマスキングがない
- 貴金属を買い取る際の備考欄に特定の記述がない など
店舗スタッフが契約書の作成時に不備を減らすことが、SC課の負担軽減から店舗回転率の向上、ひいては顧客満足度の向上につながります。
Store について
バイセルグループで導入が進む店舗買取向けシステムです。iPadのSafariで利用するWebアプリケーションであり、Next.jsで開発されているSPA(Single Page Application)になっています。
バイセルでは出張訪問買取が主流ですが、近年では店舗での買取も増加しています。Storeの導入により査定時間の短縮やスタッフの操作負担が軽減されています。
契約書作成時のミスを減らすために
調査
まずは現状の確認のために以下の2つを行いました。
差し戻しについてのヒアリング
実際に店舗に足を運び、差し戻し事例やその背景についてのヒアリングを行いました。併せて、SC課や関連部署にも現場スタッフ以外の視点を得るためにヒアリングしました。差し戻し事例のデータ分析
毎月バイセルグループの各店舗では差し戻し件数やその不備事例のデータを取っています。それらを集計し、どのような理由・項目で差し戻しが発生しているのかを分析しました。
調査結果
以上の調査から、決裁申請の差し戻し理由の傾向やそれが起きる理由を洗い出し、それを踏まえてどうするべきかを整理しました。
差し戻し理由として、本人確認書類に関するものと商材登録に関するものがほとんどを占めていました。
- 本人確認書類の登録に関するミス
- 運転免許証と運転経歴証明書を間違えて登録する
- 健康保険証の登録時に撮影した写真に対するマスキング忘れ など
- 商材登録に関するミス
- 一部の商材を買い取る場合には備考欄に記載が必要である
- 商材登録時の写真に全部の商材が写っていない など
また、これらが起きてしまう原因として、古物営業法を含めた買取ルール自体が複雑であることも挙げられました。
研修期間でやるべきこと
調査をもとにして3つのアプローチ方法を考え、最終的に3つ目の方法を選択しました。
(1) 自身や店舗の差し戻し事例の振り返りアプリ
個人のミス事例だけでなく、店舗やテナント単位で発生した差し戻し事例を確認できるアプリケーションを考案しました。一方で、実施してもらう時間の確保など業務オペレーションへの介入が必要であること、効果が出るまで長期的なアプローチとなり、即時効果があるものと併用する必要があることなどの課題がありました。
(2) 契約書の内容と買取商品の写真の内容が一致するかチェックするシステム
商材登録ミス削減を目的としたシステムとして提案しました。現場の商材登録フローや写真撮影環境を考えた際、ルールベースなどで機械的にアプローチできるポイントが少ないことが問題となりました。AIによる画像認識という意見も出ましたが、ファインチューニングが必要であることやそのための工数や費用対効果の観点から断念しています。
(3) Storeの画面上にアラートを出す機能
差し戻しの原因となりそうな入力項目(備考欄、本人確認書類の選択)にアラートを表示する機能を実装するものです。こちらは、何らかの形でStore上に直接実装する必要があり、連携面やそれによる開発業務への影響の高さが課題となりました。
研修期間や私たちのできることを考慮した結果、3つ目の案をベースにブラウザ拡張機能によって実現する方向で進めました。
Storeに直接組み込む必要がなく小回りも効きやすいこと、バイセル内で拡張機能のノウハウが少なく技術的な挑戦にもなることから採用しました。
開発したもの
今回は、以下の3点に絞って開発しました。
- 本人確認書類の選択時に類似する別の書類種別ではないかを問うアラート
- 必要な健康保険証の登録時に必要なマスキング箇所の例を示すアラート
- 商材の登録時に必要な記述を促すアラート
これらは、実際にStoreを導入している店舗の差し戻し事例のデータから、頻出かつ注意喚起の実装が容易で費用対効果が高いものとして選択しています。
使用技術
- React
- TypeScript
- MUI
- Plasmo
今回拡張機能を導入するStoreはReact + MUIで作成されているため、Storeとのデザインの一貫性を持たせつつ、開発効率を上げるために拡張機能でも同様の技術スタックを採用しました。
また、拡張機能のフレームワークとしてPlasmoを利用しました。ゼロコンフィグでReact+TypeScriptをサポートしていること、ホットリロードを利用できることが選定の理由です。ただ後述しますが、今回SPAであるStoreで拡張機能を利用するという要件にはあまり合致しない選定となってしまいました。 Plasmo自体は大変便利なフレームワークで、以下の記事でも詳しく紹介されているので参考にしてください。
画面上へのアラートの表示の仕組みは単純で、Reactで作成したコンポーネントをReactDOMのcreateRoot
を利用してDOMに埋め込んでいきました。
SPAで拡張機能を利用する
ブラウザ拡張機能は、webページの読み込み時にJSやCSSファイルが読み込まれることで実行されます。通常の拡張機能では再読み込みやページ遷移ごとにJSが再実行されるので、エントリポイントでページを判定し、適切な処理を行うことになります。
// イメージ switch (location.pathname) { case "appraisal": appraisalPage(); break; case "/contract": contractPage(); break; }
一方、StoreはNext.jsで開発されているSPAです。SPAのルーティングではページ全体の再読み込みが行われないため、上記のコードは初回のStoreアクセス時にしか実行されず、ページ遷移後に再実行されなくなってしまいます。
そこで、tabs.onUpdatedを利用します。ページの再読み込みやSPAのルーティングが行われるとonUpdated
イベントが発火されるので、発行されるchangeInfo
やtab
を見てエントリポイントであるmain.ts
の実行をトリガーする処理を書きました。
※今回はSafari用に作成しているのでbrowser
APIを利用しています。Chrome拡張機能であればchrome
APIを利用する必要があります。また、onUpdatedイベントの発火タイミングや、取得できるchangeInfo
などの形もChromeとSafariで異なるためご注意ください。
import filePath from "url:./main.ts"; browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { if (changeInfo.status) return; if (tab.url.indexOf(process.env.PLASMO_PUBLIC_STORE_URL) > -1) { const contentFile = filePath.split("/").pop().split("?")[0]; browser.scripting.executeScript({ target: { tabId }, files: [contentFile], }); } });
技術選定の反省
今回フレームワークとして採用したPlasmoはゼロコンフィグで拡張機能を開発できることがウリの技術ですが、SPAではこうしたページ遷移検出の処理が必要になってしまいました。
また、Plasmoではdevサーバーを立ち上げることでホットリロードが利用できるという特徴があるのですが、devサーバーではページ遷移検出で参照する上記コードのfilePathがうまく解決されず、ホットリロードが効かないという問題もありました。SPAで利用する拡張機能の開発では、Plasmoから受けられる恩恵はあまり多くはなかったです。
Safariで利用する
店舗買取で使用するStoreの推奨環境はChromeではなくSafariです。実際に店舗でもSafariを使用してStoreを操作しているため、拡張機能をiPadのSafariで利用できるようにする必要があります。
ここまでで作成した拡張機能はChrome等のwebブラウザでは動作しますが、実はSafariではXcodeを利用してビルドする必要があり、そのままで使用できません。
そこで、以下で紹介されている通り、xcrun safari-web-extension-converter
コマンドに、Plasmoでビルドした拡張機能のパスを渡し、Safari用の拡張機能に変換します。このコマンドによって、Xcodeプロジェクトが作成されます。Xcode上でビルドすることで、Safariで拡張機能を利用できるようになります。
インタビュー
開発したSafariの拡張機能のプロトタイプについてStoreの開発チームや店舗の方にヒアリングしました。店舗スタッフの方からは「保険証のマスキング例の表示はすぐに欲しい」という旨の好意的なフィードバックを、Store開発チームからも差し戻し改善に有効でありStoreの店舗導入の後押しになる、といった高い評価をいただきました。
以上のフィードバックを踏まえ、プロトタイプの方向性やアプローチは問題なく、今後ブラッシュアップしてテストを実施するという合意が取れたと判断しました。
おわりに
他部署の方や店舗スタッフからのヒアリングを経て、そのフィードバックを開発に活用する経験を積むことができました。研修期間という限られた時間内で、自分たちが具体的に何ができるかを見極め、それを実行に移すことができたのは大きな進歩です。さらには、Storeチームと協力して拡張機能の導入調整を行ったり、実際の業務で求められる様々なことを経験できました。これらの経験は、私たちのスキルを磨き、業務に活かすための貴重なものとなりました。
最後に、バイセルでは新卒エンジニアを募集しております。興味のある方はぜひ以下のリンクからご応募ください。