StailerとPOS連携

はじめに

こんにちは! お会計チームのyamakazuです。

ドメインベースの開発体制に移行して以来、お会計チームに所属し、主に金銭に関わるドメインでの開発を担当しています。

「お会計」と呼ぶと勘定仕分け的なことを想像されるかもしれませんが、自分たちが「お会計」と呼ぶ領域は、決済やポイント、店舗売上といった金銭に深く関係する領域を指します。

今回はそんなお会計チームが受け持つドメインの中でも「店舗売上」に焦点を当てて、Stailerにおける店舗売上データの扱い方、記事タイトルでも示す POS連携 (Point of Sales 連携) をStailerを例に取って紹介します。

目次

多様な解釈がなされるPOS連携

ECサービスを運営する人が高確率で遭遇するデータ連携がPOS連携です。

「POS連携」や「POS連携 開発」とGoogle 検索すると色々な角度でPOS連携の是非が語られている通り、多様な解釈が存在することがわかります。

POS連携

最初にこの事実を知ると混乱しますが、「そういうものだ」と割り切って理解しましょう。

POS連携という広義のデータ連携の概念と考えがあり、その部分集合として、多様な連携手段や連携フォーマット、ツールセットやプロダクトが存在します。

この特異なデータ連携の領域だけで一定の商売が成り立ってしまう (ex: 受託開発など) のが、おもしろいところだったりします。すごい世界ですね。

POS連携が多様な解釈で溢れている要因は色々と考えられますが、自分は「扱う商材の特性,多様な連携形態,多数の連携手段 の3つによるものからだ」という仮説を持っています。

例として、筆者が考えうるケースをいくつか挙げてみました。

ケース 商材 連携形態 連携手段
ケース1 衣類雑貨EC Web ECサービス → 自社POSシステム API連携
ケース2 飲食店 物理営業端末 → クラウドPOSシステム 独自システム連携
ケース3 小売EC アプリ ECサービス → 委託POSシステム ファイル連携
ケース4 医療機関 物理端末 → 委託POSシステム ファイル連携

パッと考えただけでも4つのパターンが出てきます。理解深めるために比較してみましょう。

衣類や雑貨をEC販売した場合のPOS連携と、実店舗での飲食営業した場合のPOS連携は「POS連携」という括りでは一緒ですが、連携内容と形態が異なります。

前者は1度の注文で2~3点の商品で収まるかもしれませんが、後者は1注文で10~20点ほどの商品を扱うことがあります。また、連携の対象がWeb ECサービスから自社のPOSシステムが前者で、営業の物理端末から他社のクラウドPOSシステムへの連携というケースもありえます。

達成したいことは ”販売情報の連携” ですが、商材によって扱う点数と営業形態が違うためそれに合わせてシステムも最適化された結果、全く違うアプローチ (規模, 頻度, 形態) での連携が行われます。

単純な比較例になりますが、POS連携の広さと違いが生まれるイメージはつくのではないでしょうか。このPOS連携の世界の特徴を掴んでもらった上で、StailerのPOS連携の特徴をみてみます。

StailerにおけるPOS連携

Stailerはネットスーパーやネットドラッグストアを運営可能にするEnterprise EC SaaS Platformです。Stailer自体の紹介はこれまであらゆる場所で行われているので割愛します。

StailerももちろんPOS連携に対応しています。特徴を列挙してみましょう。

  • 1注文あたり、20~30点の商品を扱う
  • 1店舗あたり、毎日数十注文を扱う
  • 1パートナーあたり、数百店舗で営業する
  • 連携仕様がパートナーごとに存在する
  • 店舗の営業サイクルに合わせて連携を行う
  • 連携内容の過不足は許されない
  • 上記を人のオペレーションを介さずに実現する

一言で言えば「大規模な独自データ連携」になっているのが、StailerのPOS連携です。

ネットスーパーやネットドラックストアというサービス形態上、1度の注文で扱われる商品点数が平均的に見ても多いのが特徴的です。

「店舗の営業サイクルに合わせて連携を行う」や「連携の過不足は許されない」といったシビアな側面もあり、まさにインフラ的で、ソフトウェアエンジニアリング方面に存在する「System of Engagement」「System of Record」という考え方で捉えると、典型的なSoRのシステムになります。

POS連携の実装と運用

特徴を踏まえた上で、実態としての実装と運用は以下のような構成で実現しています。

連携の概要

先の連携の特徴で「店舗の営業サイクルに合わせて連携を行う」という点を挙げました。

これは店舗の1日の営業活動が終了した時点で連携を実施するということで、おおよそ毎日19時~20時に連携されることが期待されています。営業活動の終了を待たずに連携が開始されることは期待されていないため、店舗担当者に営業活動終了の判断を委ね、その終了判断に合わせて操作を行ってもらい、POS連携を開始できる様な仕様にしています。

具体的には、Stailer管理画面から営業終了操作を行なってもらい、その操作をトリガーとしてWorkerにイベントを渡して非同期で連携処理を行う構成です。

これを選択した理由は、特にネットスーパーの場合、注文を配達した時点で売上計上ができる状態ではありますが、配達後に商品不備などによって返品などを実施するケースがあるからです。

POS連携を終えた後に注文内容を修正したいといった可能性も考えられ、そういった運用の不確実性を考慮すると、現場の店舗締めのサイクルに合わせてPOS連携を実施した方が扱いやすくなるため、運用容易性を尊重して仕様と構成を選択しました。

POS連携を実装する難しさ

StailerのPOS連携の特徴、そしてその実装と運用を取り上げてきました。これらに取り組んできた中で感じた難しさと対応策を紹介します。

今後何らかのPOS連携開発を推進していく方には、実装の方針を決める上でのヒントになるかもしれません。

共通仕様が存在しない

Stailerが関わる小売パートナーとの間で行う連携では、共通仕様は存在しません。

これは "大規模な小売業である" という前提の元、どの企業も独自に進化したPOSシステムを持っているからです。

統一規格に揃えるような標準化を進めて欲しいなと開発者としては思っていますが、仕様規格を揃える動機を各社間で揃えることが困難なため、独自のPOS仕様に発展させて活用していると推察しています。

共通仕様がないので、Stailerの導入にあたっては必ず開発が発生することになります。

仕様の把握が難しい

POS連携の開発は頻繁に発生するものではなく、1度開発しきれば以降は運用業務に徹するのみで、継続的な変更が加わることは多くありません。

数年に1度社会ルールの変更、直近だとインボイス制度に追従するための修正対応がありましたが、そういったケースも稀でしょう。

変更頻度が少ないシステムを長く運用すると仕様を理解把握する価値が薄れるため、結果的にシステムの全貌を把握できる人はいなくなります。

連携の仕様書は存在しますが、高頻度に連携開発が発生することを想定してドキュメントが整備されているわけではないので、情報として充足しているとは言い難く、開発者が一定の労力を割いて仕様整理や論点整理に力を注がなければいけない状況になります。

運用のインセティブ構造上、こうなってしまうのは止むを得ないと受け入れていますが、新規で連携開発を始める際には、開発者側に仕様把握や確認が任される様になり、実装に落とし込むための一定の時間と労力が必要 になってしまいます。

文脈が異なる中で開発を推進しなければいけない

POS連携は外部システムとの接続であるため、異なるシステムを運用する者同士が相対して開発を推進しなければいけません。

文脈が異なる中で共通の言葉とコミュニケーションスタイルを確立させて推進することはそれ自体が1つの開発推進スキルです。言葉の定義や段取り整理や論点の扱いなど、単純な実装力とはまた違った開発者スキルが求められます。

幸いにも10XにはBizDevという推進のプロがいるため、コミュニケーション面でサポートをもらいながら開発推進できるため、開発者に求められることは仕様把握と論点整理だけになっています。

難しさに対処するための考え

POS連携の開発を複数回実施してきた中で見えてきた困難な点を挙げましたが、同時によりリーズナブルに開発運用していくために見出した自分たちなりの工夫と考えがあります。

インターフェースの共通仕様を諦める

POS連携の開発でインターフェース(ファイルフォーマット / 連携手法) を完全に共通化することは諦めました。

全てのパートナーで統一の規格を持つのではなく、自分たちが推奨する規格を持ちながらパートナーの意思を尊重するスタンスを取っています。

ここでの意思とは、どこが連携開発の主体を持つのか or どういった形式手法の連携を選択するのか という選択肢を複数提示して決めることです。

必ずしも10Xが全て開発するだけでなく、場合によっては部分的に10Xが開発する or 10Xがリーズナブルだと考える連携手段に合わせてもらうといった、手段候補にグラデーションを持たせて、可能な限りより良い選択肢が取れる様な努力をする様にしています。

部分的な抽象化と断片化の許容

抽象化と部分的な断片化

実装としてインターフェースの共通仕様を持つことは諦めているものの、部分的な抽象化を行なって汎用性を保ちつつ、実装の断片化を最小限に抑えるような工夫は施してあります。

POS連携の処理を分解すると以下の手続きで構成されます。

  1. 書き込みデータの選別
  2. データ整形
  3. 書き込み
  4. ファイルアップロード

連携で発生する一連の手続き処理は抽象化して揃えることができ、単純なインターフェースにしています。例えば、書き込みの writeFile やファイルアップロードの upload など。

データ選別とデータ整形には共通で利用するインターフェースを持ちながらも、断片的な処理 (≒パートナー固有の処理) が入ることを ”前向きに許容” し、独自の拡張実装になるものの、その範囲を限定化することで認知負荷を一定に保つ構成を取っています。

全てが共通化できるのが一番の理想ですが、時には妥協せざる得ない状況もあります。そうなった場合でも、諦めずに最小の労力で開発運用し続けられる様に断片化を極小化し、実装構造レベルでの共通化 (抽象化) を取ることで、可能な限り運用し続けられる様な努力をしています。

段階的なテスト実施 (開発テスト / 型テスト / 受け入れテスト)

ファイル連携 × 仕様の把握が難しい × 外部連携での開発推進 という文脈で苦労するのがテスト実施です。

ファイル連携はテスト容易性が低いので、自分たちは以下の様に段階を設けてテストを実施しています。

開発テスト : テストコードを書いて振る舞いを守るテスト。単体テストと結合テストのカバレッジはおおよそ80%程度の厚さで整備しています。必ずしもカバレッジを満たすことで振る舞いを守り切れるものでもないため、そこにこだわりは持っていません。結合テストでは期待ファイルと生成ファイルを突合してテストしており、期待通りにファイルが作られているかを守ります。

型テスト : 仕様書に従って作ったファイルが取り込む側のシステムで ”取り込めるか” を確認するテスト。取り込みにフォーカスをしているため、ファイルに書き込まれている内容はテストデータで良いとしています。このテストを実施することで、曖昧な仕様書定義に存在する定義漏れや、解釈の誤りを明らかにすることができ、正しい仕様で実装されていることが保証されます。次に行う受け入れテストでの出戻り発生を防ぐことや、早い段階で仕様定義を確定させること(Shift Left)することで、後続の修正対応負荷を落とす狙いがあります。なお「型テスト」というのは独自の定義で一般名称ではありません。

受け入れテスト : 本番運用を始める前に実施する最終テスト。前提として型テストをパスしているので、型関連の振る舞いで例外が生まれることは想定していません。受け入れテストでは実際の運用で使われるデータを扱って、取り込み実施から取り込み完了までを含めてテストを行います。文字通り、システムとして連携データを受け入れられるかを最終確認します。

まとめ

  • POS連携には多様な解釈と多様な表現が多くある。
  • POS連携だけで商売が成り立ってしまうほどマーケットが大きい。
  • StailerのPOS連携は「大規模な独自データ連携」となっている。
  • 小売のPOS連携特有の困難さがあり、対応策を講じて取り組んでいる。

最後に

StailerのPOS連携を取り上げて紹介しました。

企業に実装されたPOSシステムに対して外部から新たに連携することで価値を生む開発は事例もなく、最初はとても苦労しました。

初期は手探り的に進めていましたが、今では組織に蓄積されたナレッジを活かしてイニシアチブを取りながらリーズナブルに開発を推進し始めており、最初の頃と比べれば見違えるほど組織の進化を感じています。実装上の課題はゼロとは言い難いですが、長く付き合っていくことになりそうなので、適宜リファクタリングを加えながら、保守性の高い連携基盤の構築をしていきたいです。

お会計チームではSystem of Recordの特徴を強く持つ機能開発を多く推進しています。今回話に取り上げた様な外部連携を必要とするシーンがたくさんあり、そういったシビアな開発で腕を振いたい方には絶好の機会を提供できると思っています。

もし興味を持っていただけたらカジュアルにお話ししましょう。🤝 ぜひお気軽に応募してください。

open.talentio.com

関連して

追記となりますが、合わせて違う角度でPOS連携の開発している記事があります。より解像度高く開発への理解が進むかと思うので、ぜひ読んでみてください。

note.com

note.com

note.com