1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

GASやらスプレッドシートやらNuxtjsでなんとかしたイベント予約の設計の話

Last updated at Posted at 2020-11-09

知り合いからの依頼で作って運用した、
小規模イベント用の予約システムを
設計メモだけでも残して供養します。

要望

  • イベント内でブースは複数且つ席数上限あり、参加者はあらかじめ**「ユーザー登録」「見たいブースの予約」**をする
  • 公開は基本的にLPページのみ。(ユーザーページ? 作ってもいいよ!)
  • 予約は「フォーム送信で仮登録」「ユーザー動作で登録有効化」と段階を踏むこと
  • 一定時間は仮予約状態でもブースの席を押さえられるように!
  • 仮予約のフォームはLPに埋め込むこと。また、「入力・確認・修正・送信」できるように!

ユーザーシナリオ

  1. ユーザーがLPページにアクセスし、フォームから「ユーザー登録」「イベント予約」を実行
  2. バックエンド側で仮登録処理→本登録用リンクをメール送信
  3. ユーザー側で本登録用リンクをクリック(ページにアクセス)
  4. ページが開かれた際にバックエンドにユーザー有効化をリクエスト
  5. 本登録完了

使用したサービス

  • Firebase …… ホスティング、運営側の認証で利用。小規模サービスで便利すぎる。
  • Nuxtjs …… ページ作成・処理で利用。
  • Google Apps Script …… doGet、doPostを用いたNuxtjsのバックエンド処理。
  • スプレッドシート …… DBの代わり。また、一部クエリ処理的なものをスプレッドシート関数で代用。
  • googleフォーム …… スプレッドシートに新規登録する際の排他処理代わり兼データバックアップ

※当初バックエンドはLaravelで作ることも考えたが、規模が大きくなるのが嫌だったので上記の構成に。
 それに、**スプレッドシートでデータも見えるから、エクセルにコピペもできて便利でしょ?**とか考えてた。

どう作っていったか

前後するので、各サービスの役割だけ。

Firebase

hosting機能はほぼそのまま使った。
せいぜいhostingの設定で、firebase.jsonの「trailingSlash」をfalseにしてURL末尾のスラッシュを失くしたこと、
headersでキャッシュの設定をしたことくらいか。

Authenticationは運営側のみの利用のため今回は割愛。

google apps script

色んなサービス連携で便利。
おおまかには以下の内容で処理を行い、データを返す形とした。
また、仮登録・本登録時は「gmailapp」を用いて
本登録用リンク記載メール(仮登録有効時間内アクセスで本登録化)、
本登録完了メールを送信した。

  • doGet
    • 予約状況のjson
  • doPost
    • ユーザー重複登録チェックのvalidate(OK/ErrorMessage)
    • 予約可否のvalidate(OK/ErrorMessage)
    • ユーザー、ユーザーブース予約の仮登録(true/false)
    • 本登録(true/false)

スプレッドシート

googleフォームの保存先をひとつのスプレッドシートにまとめること、
また、VLOOKUPかCOUTIFS等を用いることで
データの集約と、大幅な処理コードの削減ができる。

今回以下のシートを準備した。

  1. 席数上限(定数)、仮登録の有効時間の計算用タイマーなどを書いた「設定シート」
  2. ユーザー情報、自動作成する識別のための固有ID、登録時の時間、登録時の時間と上記仮登録タイマーを照合する「有効な仮登録」、本予約状態の可否を書いた「ユーザーシート」
  3. ユーザーIDと予約ブースの紐づけ。&そのユーザーが有効(仮登録有効時間内 or 有効化済み)かどうかを書いた「予約シート」
  4. (仮登録有効時間内 or 有効化済みの)ユーザーの予約から算出する「予約状況シート」

googleフォーム

スプレッドシートへの情報入力時、gasを使って入力処理を行うが、
単純に「最終行+1に新規データを追加」とした場合、
タイミングによっては上書きされる形で処理が終わってしまう。

防ぐためには、登録中は他者の処理にストップをかける
「排他処理」が必要だが、gasのロックでは
複数台でいっせーのーせっでやるとタイムラグがモロにでる……。

代替案で使ったのがgoogleフォーム。
あらかじめスプレッドシートの内容に合致する形でフォームを作成。
フォームの項目のID、また、フォームのpost先URLを調べ、
google apps scriptのfetchを用いて情報をpostする。

フォームの保存先を「既存のスプレッドシート」とし、
上記のスプレッドを選択したらOK。

(現状は)処理もれや同一行登録を防ぐことができた。

Nuxtjs

LP(兼仮予約)ページでは
参加ブース指定、ユーザー登録という2つのフォームの
「入力・確認・修正・送信」をまとめるために、
以下の4つのコンポーネントを作成、
データ入力の進捗、操作によってコンポーネントを切り替えた。

  1. 参加ブース指定
  2. ユーザー登録のための情報入力
  3. 確認(修正ボタンあり。操作で1or2に戻る)
  4. 送信

また、本予約確定ページでは、アクセスした段階で本予約確定とするため、
mounted時にバックエンドにURLのパラメータをポストする処理を書いた。
(あとはバックエンド側で照合、該当ユーザーを有効化)

※余談だけど、gasとの連携で大分躓いた。
 axiosとgasが絶妙にマッチしない……というより使い方に合致してないのか。
 ちょっと詰まったと思ったら、やり方ごそっと切り替えるのオススメです。
 axiosで書いていたのをfetch apiにしたり
「heroku cors」とか検索してみたりすると幸運があるかもです。

評価

スピード重視しようと色んなサービス使った結果、
変に複雑化&処理の低速なサービスになってしまった。
小規模サービスなら、もっとシンプルに、もしくは定型のものを使うべきだった。

ちょっとした推しだった**「データの可視化」「エクセルとの互換」も
「え、自分でやるの?」と不評**だったので
今度からはこのやり方は採用しません。
(美味しいコーヒー奢ってもらったから変な顔はしないけど)

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?