Webの技術でレジ(POS) を開発・運用する

当社TORICOは、主にインターネット上での書籍の販売サービス、つまりECサイトを自社開発して展開しています。

その他に、自社でイベント会場(実店舗)を営業しており、そこではお客様に会場に来てもらうことでのサービスやグッズ販売を提供しています。

実店舗を営業するにあたり、レジ(POSシステム) が必要となります。TORICOでは、POSシステムもWeb技術で自社開発し運用しています。当社と同様に Web技術で POSを開発される方に向けて、私が対応したいくつかの経験を書き残します。

サーバサイドのシステム

当社の POS システムは、40万点以上の商品を扱う必要があり、そのDBとリアルタイムに連携する必要があるのでクラウド上でのサーバサイドアプリを開発運用しています。バーコードを元に商品DBからの商品検索を行ったり、売上をDBに記録するなどの機能を担っています。一般的にECサイト開発で書くようなコードとほぼ違いはありません。通常の開発と同様に、WebセキュリティとACIDを意識して書けば問題ありません。

当社では、Django + Django Rest Framework が鉄板構成のため、今回の POSシステムのサーバサイドも Django で開発しました。

クライアントサイドのシステム

クライアント側は、大きく分けてブラウザかモバイルアプリかを使うことになります。社内スタッフしか使わないという限定的なアプリであるため、SEOやアプリストアへのレギュレーション等は考える必要が無く、コンシューマ向けアプリを作るより開発は単純化できます。

Webブラウザかモバイルアプリか。どちらにも一長一短あり、展開したい構成によってどちらが適しているか変わってきます。展開規模が多ければ、両方を作ってみるのも良いですね。

結局、当社は最初は Webブラウザで作り実運用しています。現在はモバイルアプリでの研究開発も開始しています。
Webブラウザかモバイルアプリか、両者の長所や違いについては、この後のシステム構成案の個所で再度書きます。

レシート出力方法の選択

POSシステムである以上、会計レシートの出力が必須となります。

レシートプリンタは各社から市販されていますが、主に3通りの使い方が存在します。

1. Windows のプリンタドライバ・プリントキューで印刷する

通常のプリンタと同じように、Windows のプリンタドライバとプリントキュー経由でプリントする方法です。各社から市販されているレシートプリンタは、ほとんどに Windows 用のプリンタドライバも配布されており、これを使うことで OS やブラウザの印刷機能で幅広い表現のレシートをプリントできます。

特にブラウザを使う場合、HTMLでレシートがデザインできますので、高い表現力のレシートを素早く開発することができます。レシートカッターのついているプリンタにレシートカット指示を明示的に出すことはできませんが、大抵はプリント終了時に自動でカットされます。

通常の用紙設定と違い、設定には一工夫必要ですし、ソフトウェアによっては印刷の制限があったりします。例えば Chrome では最少文字サイズが決められていたり、マージンやヘッダーのレイアウトに限界があるため、ブラウザからのレシート出力をするのであれば Firefox がおすすめです。

パソコンの中でも Window と限定しているのは、Linux, Chromebook はプリンタドライバを提供しているメーカーが少ないため除外、Mac はレジに向いている端末が無いため POSレジの候補とならないためです。

2. プリントSDK を使う

主に iOS・Android 等のモバイルアプリOSでレシートを出力するには、プリントメーカーから公開されているSDK をアプリ内に組み込んで使うのが一般的で、これ以外の方法は難しいです。Windows用のSDKを公開しているメーカーも多いです。表現力は、HTMLより数段劣りますが、応答が早く、またレシートカッターやレジドロワーなどプリント以外の機能も柔軟に使えます。

3. シリアル通信で使う

プリンタメーカーによってはシリアル通信の仕様書が公開されていますので、SDKが無い場合やSDKを使いたく無い場合には、直接シリアル通信してプリントすることになります。例えば、スター精密のプリント仕様書はこのようになります: StarPRNT 仕様書 。通信仕様を把握しないといけないため大変ですが、Python, Ruby, NodeJS, PHP など比較的モダンな言語での開発はドライバは用意されていないと思いますので、実質シリアル通信コードを書くしか方法がありません。Bluetooth 対応のレシートプリンタは、Bluetoothでペアリングを確立した後、その TTYに向けてシリアル通信を行います。

実際に書いてみると、レシートへの出力パターンはそれほど多く無く、軽量言語からシリアル通信をするのはそれほど複雑コードにはなりません。つまりどころとしては、1行の中に左寄せと右寄せの文字を同時に出したり、表を出力する時に困るぐらいでしょうか。

購入レシートなので表っぽい形式での出力は必須となるため、ここが技術的にクリアできれば問題無いといえます。

それ以外

プリンタによっては、HTTPサーバが内蔵されており、そのHTTPサーバに向かって印刷内容をリクエストすると印刷できる機能を持ったものがあります。システムを ブラウザだけで完結させるこができ、使い勝手は良いのですが、通信インフラの設置制限などを受けます。

スター精密の機種は、WebPRNT というブランド名でこの機能が搭載されています。使いたかったのですが、当社にある「mC-Print3」は無線Lanインターフェイスがなく有線LANのみ搭載で、設置環境は有線LANのケーブリングは無理だったため今回は採用できませんでした。

また、プリンタによってはクラウド経由のプリントをサポートしているものもあるようです。

バーコードリーダーとの接続方法の選択

バーコードリーダーの接続方法は、大きく分けて2つあります。

「キーボード」として認識させるもの

大抵は、バーコードリーダは「キーボード」として扱います。

バーコードを読み取ると、そのコードがキーボードの打鍵としてOSに入ってきます。これはソフトを選ばず使えるため、使い勝手は良く、大抵この方法で問題ありません。

シリアルポート接続

バーコードリーダーによっては、シリアルポートとして接続させることもできます。Bluetoothで接続でき、市販のモバイルのレジアプリとの対応を謳っている製品にはこの機能が入っていると思います。キー入力に影響が無いためアプリの自由度は高まりますが、入力を受け付けるサービスを別途用意しなければいけないので、開発が少し手間です。

クライアントシステム構成の例

当社で運用している(検討している)具体的なハードウェア構成パターンを2つ書きます。

構成1. Windows + Firefox + OSのプリントキューでレシート印刷

当社で実際の販売点で使っている構成です。

Webブラウザを使ったレジアプリの場合、ハードウェアを Windows にすると、WIndows 特有の恩寵も多く受けられる非常に低コストで素早い開発が行えます。

利点

利点としてはこのような点があげられます。

  • 機能リリース(アップデート)が簡単。ブラウザをリロードするだけで良い。
  • プリンタドライバが豊富。間違い無く用意されている。
  • レシートを HTMLでレイアウトができるため、表現力が豊富で開発も早い。

特に、アップデートが早くて簡単なのは非常に高い優位があります。

フレームワーク

Webサイトのフロントエンドフレームワークとして、Vue, React, Angular 等のモダンなフレームワークを使うことで、レスポンスの良く体験に優れた POS アプリが簡単に作れます。CSSフレームワークも、Tailwind や Bootstrap等を用いることで美しいものが手軽に作れます。

弊社の鉄板構成は、Nuxt + TypeScript + Bootstrap です。

タッチ前提のUIにすると良い

開発中は、トラックパッドやマウスなどのポインティングデバイスでの利用を考えてしまいますが、実際のレジ現場ではタッチパネルを使ったほうが断然使いやすいので、タッチを前提としたUIにした方が良いです。ハードウェアも、Windowsタブレットを採用するのが良いでしょう。

Firefoxに限定している理由

ブラウザを Firefox に限定しているのは、Chrome の場合は最少フォント制限がありレシート印刷が難しいのと、Firefox はプリント時の余白設定も柔軟に行えるためです。

Firefoxでのプリント設定例

レシートプリント時、以下の設定を行うことで、専用システムのレシート出力に比べて遜色ないプリントができます。

  1. 余白を「なし」に設定する
  2. 倍率を「100%」に固定する
  3. ヘッダー・フッターはプリントしない
  4. プリントプレビューを表示しなくする

1〜3は、メニュー内の「プリント」をクリックすることで設定できます。

倍率を100% とし、横幅の制限は HTML上で作ります。例えば80mmプリンタを使うのであれば、レシートの内容は width: 70mm 程度にしたdiv の中に組んでいき、それをプリントさせるということです。

Firefoxでプリントプレビューを表示しない

Firefoxで プリントプレビューを表示しないようにするには、

about:config を開いて、print.always_print_silent を検索し、false となっているのを true にします。

ちなみにこの設定は、プラグインで簡単に設定できないかと思ったのですが、プラグインから about:config を操作するのは無理みたいで、実現できるものは存在しませんでした。

USB電源管理を無効化する

プリンタは USBで接続することになると思いますが、Windowsは使用方法によっては USBの仮想プリンタポート番号がいつの間にか変わってしまう場合があります。それを防ぐため、下記の記事を参考に、USBでの電源管理を無効化しておくとトラブルを防げます。

Windows10 (1803) USBの仮想プリンターポートを固定化する

デバイスマネージャの「ユニバーサル シリアル バス コントローラー」の中のUSB Root HubもしくはUSB ルート ハブ(USB 3.0)のプロパティを開き 「電源の管理」タブの「電力の節約のために、コンピューターでこのデバイスの電源をオフにできるようにする(A)」のチェックを外します。 

バーコードリーダ対応ライブラリ

Vue.js でキーボードとして認識されたバーコードリーダーからのバーコード入力を読み取る用途に

vue-barcode-scanner というライブラリが開発されており、これを使うと何の問題も無くバーコードリーダーとの連携ができます。

お客様ディスプレイ

レジスタッフだけではなく、お客様にも金額を確認してもらうため、お客様用のディスプレイの用意が必要になります。

ディスプレイ自体は、1万円弱でラズパイ用のディスプレイが多く出回っているのでそれを購入し、ブラウザから window.open() 等でお客様ディスプレイ用のウインドウを出します。

レジで打っている内容を、お客様ディスプレイに反映させる方法としては、ローカルストレージを使うのが一番手軽で良いと思います。

レジでバーコードをスキャンした時、その商品名や金額、合計金額をブラウザのローカルストレージに入れる。

お客様用ディスプレイのブラウザウィンドウで稼働しているJSコードは、ローカルストレージを500msとかでポーリングして監視し、変更があったらブラウザウィンドウに描画する。

プッシュ通知や PubSub, ウェブソケット等使うより素朴ですが、ローカルストレージをポーリングする方法は構成要素も少なく、安定して稼働できると考えています。

構成2. Android + Flutter + 専用プリンタドライバ

現在、研究開発段階でまだ実用化はできていません。

Sunmi というメーカーの POS 用品が美しく、今後は使っていきたいと思っているため、Flutter でアプリ開発を初めています。

レシート出力については、flutter_sunmi_printer というライブラリが pub で公開されており、これを使うと sunmi の内蔵プリンタへの出力が容易に行えます。

テーブル出力についても、このライブラリは 「Bootstrap のように 1行を12カラムに分けてレイアウトする」という方式を取っており、比較的容易に表組みを作れました。

実は、Windows POSシステムを作ると、開発は楽なのですがセットアップの工程が多かったりトラブルも多く、あまり安定稼働に向かないと考えています。その点、Android 主体のシステムは、アプリさえしっかり書いておけば安定動作はさせやすい(機材トラブルが少ない) と考えています。

Currently unrated

コメント

コメントを投稿
コメントするには TORICO-ID にログインしてください。
ログイン コメント利用規約

Recent Tweets

  • ytyng

    ytyng @ytyng

    @linear_pulse 同様の現象が出てました。
    4 days, 16 hours ago

  • ytyng

    ytyng @ytyng

    django-allauth 0.45 の 昨日のリリースで Python3系からの Apple Signin できない不具合直ってる https://t.co/JHcM3g2GCT
    1 week, 4 days ago

  • ytyng

    ytyng @ytyng

    あんまりPC詳しくない人とか普通に踏んじゃうと思うので、キヤノン製品は控えることにする
    1 month, 2 weeks ago

  • ytyng

    ytyng @ytyng

    ダメサイトっぽい https://t.co/GBlGq9T3Oe 公式はこちらでした https://t.co/sPvhEowLdt
    1 month, 2 weeks ago

  • ytyng

    ytyng @ytyng

    whoisも怪しすぎるんだけど
    1 month, 2 weeks ago