kintone
投稿日:

イベント会社の案件進行管理をkintoneで一元化 ― 会場・機材・スタッフの同時手配とダブルブッキング防止

皆さんこんにちは。kintoneアプリエンジニアのtomiokaです。

先日、年間150件ほどのイベントを手がけているイベント会社のお客様から「会場と機材とスタッフの手配がバラバラで、ダブルブッキングが起きてしまう」と相談がありました。

社員25名、協力スタッフ約40名という体制で、展示会やセミナー、企業パーティーなど多種多様なイベントを回しているそうです。案件数が増えるにつれて、どのリソースがいつ空いているのかが把握しきれなくなってきた、と。イベント業界ではわりとよく聞く悩みですよね。

こんな方に読んでほしい記事です

この記事は、以下のような方を想定して書いています。

  • 年間100件以上のイベントを運営していて、会場・機材・スタッフの手配が複雑になっている会社の方
  • 社員20〜30名規模のイベント会社で、進行管理を担当しているディレクターやPMの方
  • 「Excelでなんとか回しているけど、そろそろ限界かも」と感じている方

Excelで管理していたときの課題

お客様の話を詳しく聞いてみると、管理の仕組みにいくつかの問題がありました。

まず、会場の予約状況を管理するExcel、機材の貸出状況を管理するExcel、スタッフのシフトを管理するExcelがそれぞれ別ファイルで存在していました。案件ごとの進行管理はさらに別のExcelです。つまり、1つのイベントに対して最低4つのファイルを確認しないと全体像がつかめない状態だったんです。

具体的に起きていた問題は次のとおりです。

  • 同じ日に同じ会場を2件の案件で予約してしまい、直前に発覚して慌てて別会場を手配した(年に2〜3件発生)
  • 大型プロジェクターなどの数量限定の機材が足りなくなり、当日にレンタルで急遽対応した
  • スタッフの予定がExcelに反映されるのが遅く、すでに別案件に入っているスタッフをアサインしてしまった
  • 案件の進捗が担当者の頭の中にしかなく、急な担当変更時に引き継ぎが大変だった

年間150件も回していると、こういった問題がほぼ必ずと言っていいほど発生します。特にダブルブッキングは信用問題に直結するので、なんとか防ぎたいですよね。

kintoneで構築したアプリ構成

今回、以下の3つのアプリを連携させる形で構築しました。

アプリ名役割主な管理内容
案件管理アプリイベント案件の進行管理案件名、クライアント、開催日、ステータス、担当者
リソース管理アプリ会場・機材・スタッフの予約管理リソース種別、リソース名、予約期間、紐づく案件
リソースマスタアプリ会場・機材・スタッフの台帳リソース種別、名称、数量上限、備考

ポイントは、リソース管理アプリを会場・機材・スタッフで共通にしたことです。最初はそれぞれ別アプリにしようかとも考えたのですが、ダブルブッキングチェックのロジックが3つに分散すると保守が大変になります。リソース種別をドロップダウンで切り替える設計にして、1つのアプリに集約しました。

フィールド構成

案件管理アプリ

フィールド名フィールドタイプフィールドコード備考
案件名文字列(1行)projectName必須
クライアント名文字列(1行)clientName
開催日日付eventDate
開催終了日日付eventEndDate複数日イベント対応
会場文字列(1行)venueリソース管理から自動反映
ステータスドロップダウンstatus企画中/準備中/当日/完了/中止
担当者ユーザー選択manager
備考文字列(複数行)notes

リソース管理アプリ

フィールド名フィールドタイプフィールドコード備考
リソース種別ドロップダウンresourceType会場/機材/スタッフ
リソース名ルックアップresourceNameリソースマスタから取得
利用開始日日付startDate必須
利用終了日日付endDate必須
案件名ルックアップrelatedProject案件管理アプリから取得
数量数値quantity機材の場合に使用
ステータスドロップダウンreservationStatus仮予約/確定/キャンセル
登録者作成者creator

ダブルブッキングを防ぐJavaScriptカスタマイズ

今回のカスタマイズで一番重要だったのが、リソース管理アプリでレコードを保存する際に、同じリソースが同じ期間に予約されていないかをチェックする処理です。

リソース管理アプリの新規追加画面・編集画面で、保存ボタンを押したタイミングでREST APIを使って既存の予約を検索し、重複があればエラーを表示します。

(function() {
  'use strict';

  // 新規追加・編集画面の保存前イベント
  var events = [
    'app.record.create.submit',
    'app.record.edit.submit'
  ];

  kintone.events.on(events, function(event) {
    var record = event.record;
    var resourceName = record.resourceName.value;
    var startDate = record.startDate.value;
    var endDate = record.endDate.value;
    var recordId = record.$id ? record.$id.value : null;

    if (!resourceName || !startDate || !endDate) {
      return event;
    }

    // 日付の重複を検出するクエリを組み立てる
    // 既存予約の開始日 <= 新規の終了日 AND 既存予約の終了日 >= 新規の開始日
    var query = 'resourceName = "' + resourceName + '"' +
      ' and startDate <= "' + endDate + '"' +
      ' and endDate >= "' + startDate + '"' +
      ' and reservationStatus != "キャンセル"';

    // 編集時は自分自身のレコードを除外する
    if (recordId) {
      query += ' and $id != ' + recordId;
    }

    var params = {
      app: kintone.app.getId(),
      query: query,
      fields: ['resourceName', 'startDate', 'endDate', 'relatedProject']
    };

    return kintone.api(kintone.api.url('/k/v1/records.json', true), 'GET', params)
      .then(function(resp) {
        if (resp.records.length > 0) {
          var conflicting = resp.records[0];
          var msg = '【ダブルブッキング検出】\n' +
            resourceName + ' は ' +
            conflicting.startDate.value + ' 〜 ' +
            conflicting.endDate.value + ' の期間、' +
            '案件「' + conflicting.relatedProject.value + '」で予約済みです。';
          event.error = msg;
        }
        return event;
      })
      .catch(function(err) {
        console.error('予約チェックでエラーが発生しました:', err);
        event.error = '予約の重複チェック中にエラーが発生しました。管理者に連絡してください。';
        return event;
      });
  });
})();

このコードは、リソース管理アプリの新規追加画面と編集画面で動作します。保存ボタンを押すと、REST APIで同じリソース名・重複する期間の予約を検索し、見つかった場合は event.error にメッセージを設定してエラーとして表示します。キャンセル済みの予約は検索対象から除外しています。

ハマりどころ

実装を進める中で、いくつかハマったポイントがあります。

日付の重複判定ロジック

最初は「開始日が同じかどうか」だけで判定していたのですが、、、、それだと「7月1日〜3日」と「7月2日〜4日」のような部分的な重複を検出できません。日付範囲の重複判定は「既存の開始日 <= 新規の終了日 AND 既存の終了日 >= 新規の開始日」という条件が正解です。これはイベント業界に限らず、予約系のシステムでは定番のロジックなのですが、最初にシンプルに書いてしまうと見落としがちなんです。

フィールドコードの大文字小文字

kintoneのREST APIで日付フィールドを比較するとき、値は "2026-07-15" のようにISO形式の文字列で渡す必要があります。ここは問題なかったのですが、、、、ハマったのはフィールドコードの大文字小文字です。フィールドコードを StartDate と書いてしまい、実際のコードは startDate だったので、クエリがヒットしなくて30分くらい原因を探しました。kintoneのフィールドコードは大文字小文字を区別するので、コピペするのが一番確実です。

ルックアップフィールドの値取得タイミング

ルックアップフィールドは、ユーザーが「取得」ボタンを押した後でないと値が入りません。保存前イベントの時点でルックアップの値が空の場合は、チェックをスキップするようにしています。もしルックアップ未取得のまま保存できてしまうと、ダブルブッキングチェックが機能しないことになるので、、、、リソース名フィールドは必須にしておくのがおすすめです。

導入した結果

この仕組みを導入してから約3ヶ月後にお客様にヒアリングしたところ、以下のような変化があったそうです。

  • ダブルブッキングの発生件数が年間2〜3件からゼロになった
  • 案件ごとのリソース手配状況を一覧で確認できるようになり、会議の準備時間が半分以下になった
  • 新しいスタッフが入っても、どの案件にどのリソースが割り当てられているかすぐに把握できるようになった
  • 会場の空き状況を確認するために複数のExcelを開く必要がなくなり、1つの画面で完結するようになった

特に「ダブルブッキングがゼロになった」という点はお客様にも喜んでいただけました。イベント業界では当日の変更や急な追加が多いので、リアルタイムで予約状況が確認できるのは大きいですよね。

まとめ

今回は、イベント会社の案件進行管理をkintoneで構築した事例をご紹介しました。会場・機材・スタッフという3種類のリソースを1つのアプリで管理し、ダブルブッキングをシステムで防ぐ仕組みです。

イベント業界の手配業務では、リソースの種類が多く、期間も案件ごとに異なるため、Excelでの管理には限界があります。特に案件数が年間100件を超えてくると、人の注意力だけでは重複を防ぎきれません。

今回の構築で押さえておきたいポイントは以下の3つです。

  • 会場・機材・スタッフを1つのリソース管理アプリに集約することで、チェックロジックの保守性を高める
  • 日付範囲の重複判定は「既存開始日 <= 新規終了日 AND 既存終了日 >= 新規開始日」で正確に行う
  • フィールドコードの大文字小文字やルックアップの取得タイミングなど、kintone固有の挙動を把握しておく

実際にこの仕組みを導入したことで、ダブルブッキングの発生がゼロになり、手配業務にかかる確認時間も大幅に短縮されました。kintoneの標準機能とJavaScriptカスタマイズの組み合わせで、ここまで業務改善ができるという実例です。

株式会社ファストコーディングでは、kintoneのカスタマイズや業務アプリの構築を承っています。「うちのリソース管理もkintoneでなんとかしたい」「ダブルブッキングを仕組みで防ぎたい」といったご要望がありましたら、お問い合わせフォームからお気軽にご連絡ください。