物品管理システムをChatGPTと作ってみた。

はじめに

物品管理システムがつくりたい!

こんばんはお久しぶりです。物品管理が必要になったので最近話題のチャットGPTを使って一緒にシステムを開発してみました。その過程を一部紹介できればと思います。

ChatGPTって?

最近流行りのAIです。簡単に言うといっぱい言語を学ばせているのでこの言葉の次ってこれ来るだろうなーっていう予測で考えてるふりをしているツールです。
結構とんちんかんなことも言うので、使い方は難しいです。

適切な指示が必要

指示の仕方がちょっと癖があります。言語AIなので基本的に普通に喋っている言葉を理解してくれます。ただし空気が読めないのでしっかりと前提を説明してあげたり最終的な表現をどのようにするかが大事です。
以下よくする指示を書き出してみます。

  1. 〇〇形式で教えて
  2. 箇条書きで教えて
  3. 概要を簡単に分かりやすく教えて
  4. 表の形で教えて
  5. 前提、お願い、出力の形をしっかりと教えてあげる

ChatGPTの得意なこと、ニガテなこと

Google検索ではないので「織田信長について教えて」であったり「1990年にあったことを教えて」のようなインプットなしで何かを出してもらうような作業はとても苦手です。
基本的には何か指示をしてそれを別の形式でアウトプットする大きな意味での翻訳のような作業が得意です。実際の作業工程を見ながら感じ取っていただけると幸いです。

早速システムをつくりたい、けど概要が定まっていない

システムの骨子を詰めていきましょう。
実際の指示はこちら

現在展示台の管理システムを制作しています私は美術大学に勤めているので講評会のたびに展示台が学生によって作られます。
そのため学内に展示台が増えすぎてしまっています既存の展示台をオンライン上に登録して貸出の際には QR コードなどで読み取り貸出期間を選択します。私はプログラミングができないため、できるだけ既存のサービスの組み合わせでできる方法を模索してください。新規展示台の登録も生徒が簡単に行える必要があります。

提案された情報は以下です。

  • QRコード: 展示台の詳細情報が記載されたGoogleフォームまたはスプレッドシートへのリンクが含まれています。スキャンするだけで、貸出者が簡単に展示台の詳細を確認できます。
  • 展示台ID: 展示台を一意に識別するためのID番号です。QRコードが読み取れない場合や、フォームで手動で入力する際に使用できます。
  • 展示台名: 展示台に固有の名前です。これにより、学生や教員が簡単に展示台を特定できます。
  • サイズ: 展示台の寸法を記載します(例:幅x奥行x高さ)。これにより、利用者がどの程度のスペースが必要かを把握できます。
  • オプション:

  • 貸出ルール: 展示台の使用に関する簡単なルールを記載することができます(例:貸出期間、禁止事項など)。
  • 連絡先情報: 管理者や担当者の連絡先情報を記載することができます。これにより、利用者が問題が発生した際に迅速に対応できます。

    という内容でした。しかし1つずつ印刷する方法は印刷のために人手が必要だったり印刷を自動化するために外部のシステムを使う必要がありますそのため共通の一つのシールで完結させられる方法をAIと考えました。このような仕様になりました。

    QRコードを活用することで、一つの共通のシールで展示台管理システムを完結させる方法を提案します。

    共通QRコードの作成: すべての展示台に共通のQRコードを作成します。このQRコードは、展示台の一覧が表示されるGoogleスプレッドシートや、展示台を選択するためのGoogleフォームにリンクします。

    シールの作成: 共通QRコードと、簡単な説明文(例: 「QRコードをスキャンして展示台を選択し、貸出手続きを行ってください」)を記載したシールを作成します。

    展示台へのシール貼付: 作成したシールを各展示台に貼り付けます。

    利用者が共通QRコードをスキャンすると、展示台の一覧が表示されるGoogleスプレッドシートやGoogleフォームにアクセスできます。利用者は、目の前の展示台を選択し、貸出手続きを行うことができます。

    ただし、この方法では展示台ごとに個別の情報(展示台名、サイズなど)がシールに記載されていないため、利用者が展示台を選択する際に、スプレッドシートやフォーム上で展示台の詳細情報を確認する必要があります。そのため、展示台の詳細情報が直接目に入るよう、Googleスプレッドシートやフォームを工夫してわかりやすく表示することが重要です。

    新しい展示台が追加される度にシールを印刷する必要がなくなりますが、共通のシールを使用することで展示台の詳細情報がすぐにはわからないというデメリットが生じます。どちらの方法を採用するかは、利便性と情報のアクセシビリティを総合的に検討して決定してください。

    システム内容をチャットGPTと詰めていく

    印刷するシールの内容を決めてもらったのですがその内容はこんな感じでした。

    仕様が決まったので実装していく

    QRコードを活用することで、一つの共通のシールで展示台管理システムを完結させる方法を提案します。

    共通QRコードの作成: すべての展示台に共通のQRコードを作成します。このQRコードは、展示台の一覧が表示されるGoogleスプレッドシートや、展示台を選択するためのGoogleフォームにリンクします。

    シールの作成: 共通QRコードと、簡単な説明文(例: 「QRコードをスキャンして展示台を選択し、貸出手続きを行ってください」)を記載したシールを作成します。

    展示台へのシール貼付: 作成したシールを各展示台に貼り付けます。

    利用者が共通QRコードをスキャンすると、展示台の一覧が表示されるGoogleスプレッドシートやGoogleフォームにアクセスできます。利用者は、目の前の展示台を選択し、貸出手続きを行うことができます。

    ただし、この方法では展示台ごとに個別の情報(展示台名、サイズなど)がシールに記載されていないため、利用者が展示台を選択する際に、スプレッドシートやフォーム上で展示台の詳細情報を確認する必要があります。そのため、展示台の詳細情報が直接目に入るよう、Googleスプレッドシートやフォームを工夫してわかりやすく表示することが重要です。

    新しい展示台が追加される度にシールを印刷する必要がなくなりますが、共通のシールを使用することで展示台の詳細情報がすぐにはわからないというデメリットが生じます。どちらの方法を採用するかは、利便性と情報のアクセシビリティを総合的に検討して決定してください。

    とのことでした。実際のフォームの例までたどり着くのはすこし長くなるので最終の質問事項まで割愛します。

    システムができた!

    実際のシステムがこちら

    ざっくり全体像

    グーグルフォームで貸出管理、新規登録、スプレッドシートで閲覧をします。
    グーグルのホームページを作るサービスにQRコードから飛ばす感じです。
    シールに書かれている展示台番号を撃ち込んで貸し出しをする感じです。

    使ったシールはこちら

    水に強めのものを使いました。木材の展示台に貼り付けましたが問題なく使えそうです。
    新規登録で物品追加を行います。以下グーグルフォームの質問事項です。

    貸出管理


    メールアドレス
    *
    展示台ID
    *
    学籍番号
    *
    出席番号を数字6桁で入力してください。(123456)
    氏名
    *
    スペースを開けずに入力ください。(山田太郎)
    借りますか?返しますか?
    *
    いつから借りますか
    返却時は入力不要
    日付
    いつまで借りますか
    返却時は入力不要
    日付
    使用場所または返却場所
    *

    新規登録


    新規展示台登録フォーム
    新しい展示台を作った際に入力ください。

    ファイルをアップロードしてこのフォームを送信すると、Google アカウントに関連付けられている名前と写真が記録されます. メールアドレスは回答に含まれません。
    * 必須の質問です
    姓名(アルファベット表記)
    *
    アルファベット大文字表記 例:YAMADATARO
    学籍番号
    *
    出席番号を数字6桁で入力してください。(123456)
    メールアドレス
    *
    学生のメールアドレスを入力してください。展示台IDやサイズ情報が送信されます。
    展示台のサイズ1(短辺)
    *
    新しい展示台の短い辺のサイズを入力してください。単位(cm)
    展示台のサイズ2(長辺)
    *
    新しい展示台の長い辺のサイズを入力してください。単位(cm)
    展示台のサイズ(高さ)
    *
    新しい展示台の高さを入力してください。単位(cm)
    展示台の色
    制作した展示台の写真を添付してください

    アップスクリプト

    Google Apps Script(グーグルアップスクリプト)は、Googleのオンラインサービスを簡単に操作・拡張するためのツールです。このツールを使うと、Googleのさまざまなサービス(Gmail、Googleスプレッドシート、Googleドキュメントなど)を連携させたり、独自の機能を追加できます。
    今回はアップスクリプトを使って少し難しい入力などを自動化させます。関数でできないことだったり、外部システムにリンクさせる際に使いやすいツールです。今回はgmailを連携させるために使用しています。
    以下スクリプトです。

    貸出用スクリプト

    行われていることはこんな感じです。

  • onRentalFormSubmit(e) 関数: Google フォームからの送信イベントがトリガーされると、この関数が実行されます。この関数は、フォームから送信された情報を処理し、展示台の貸出・返却の状態を更新します。
  • sendLoanSuccessEmail(email, displayId) 関数: 貸出・返却手続きが正常に完了した場合、この関数を使ってユーザーに成功メールを送信します。
  • sendLoanFailureEmail(email) 関数: 貸出・返却手続きが失敗した場合、この関数を使ってユーザーに失敗メールを送信します。
  • createRentalFormSubmitTrigger() 関数: この関数は、Google フォームの送信イベントに対応するトリガーを作成します。フォームが送信されるたびに、onRentalFormSubmit(e) 関数が実行されるようになります。
  • 具体的には、以下の処理が行われます:

    フォームから送信されたデータを取得します(メールアドレス、展示台ID、貸出/返却アクションなど)。
    「展示台ID管理」シートを検索し、送信された展示台IDが存在するかどうかを確認します。
    展示台IDが存在し、貸出/返却アクションが有効な場合、展示台の状態を更新し、成功メールを送信します。
    展示台IDが存在しない場合、または貸出/返却アクションが無効な場合(例: すでに貸出中の展示台を再度貸出しようとする)、失敗メールを送信します。

    function onRentalFormSubmit(e) {
      var loanFormSheet = e.source.getSheetByName("貸出フォーム");
      var idManagementSheet = e.source.getSheetByName("展示台ID管理");
      var loanFormRow = e.range.getRow();
    
      var email = e.namedValues['メールアドレス'][0];
      var displayId = e.namedValues['展示台ID'][0];
      var action = e.namedValues['借りますか?返しますか?'][0];
    
      var idManagementData = idManagementSheet.getRange("H3:H").getValues();
      var displayIdFound = false;
    
      for (var i = 0; i < idManagementData.length; i++) {
        if (idManagementData[i][0] == displayId) {
          displayIdFound = true;
          var managementRow = i + 3;
          var loanStatus = idManagementSheet.getRange(managementRow, 10).getValue();
    
          if ((action == "返却" && loanStatus != "貸出") || (action == "貸出" && loanStatus == "貸出")) {
            sendLoanFailureEmail(email);
          } else {
            idManagementSheet.getRange(managementRow, 9).setValue(e.namedValues['メールアドレス'][0]);
            idManagementSheet.getRange(managementRow, 10).setValue(e.namedValues['借りますか?返しますか?'][0]);
            idManagementSheet.getRange(managementRow, 11).setValue(e.namedValues['氏名'][0]);
            idManagementSheet.getRange(managementRow, 12).setValue(e.namedValues['学籍番号'][0]);
            idManagementSheet.getRange(managementRow, 13).setValue(e.namedValues['使用場所または返却場所'][0]);
            idManagementSheet.getRange(managementRow, 14).setValue(e.namedValues['いつから借りますか'][0]);
            idManagementSheet.getRange(managementRow, 15).setValue(e.namedValues['いつまで借りますか'][0]);
    
            // Send success email
            sendLoanSuccessEmail(email, displayId);
          }
          break;
        }
      }
    
      if (!displayIdFound) {
        // Send failure email
        sendLoanFailureEmail(email);
      }
    }
    
    function sendLoanSuccessEmail(email, displayId) {
      var subject = '貸出手続きの完了';
      var body = '展示台ID: ' + displayId + '\n\n' +
                 '貸出,返却手続きが完了しました。';
      MailApp.sendEmail(email, subject, body);
    }
    
    function sendLoanFailureEmail(email) {
      var subject = '貸出手続きの失敗';
      var body = '申し訳ありませんが、貸出手続きが失敗しました。\n\n' +
                 '正しい展示台IDを入力するか、貸出情報を確認し、もう一度お試しください。';
      MailApp.sendEmail(email, subject, body);
    }
    
    function createRentalFormSubmitTrigger() {
      var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
      var formSheet = spreadsheet.getSheetByName("貸出フォーム");
      ScriptApp.newTrigger("onRentalFormSubmit")
        .forSpreadsheet(spreadsheet)
       
    .onFormSubmit()
    .create();
    }

    新規登録用スクリプト

    このコードは、展示台の登録情報を管理する Google スプレッドシートとフォームを使用しています。主な機能は以下の通りです。

  • createFormSubmitTrigger() 関数: この関数は、Google フォームの送信イベントに対応するトリガーを作成します。フォームが送信されるたびに、onFormSubmit(e) 関数が実行されるようになります。
  • onFormSubmit(e) 関数: Google フォームからの送信イベントがトリガーされると、この関数が実行されます。この関数は、フォームから送信された情報を処理し、展示台IDを生成し、展示台ID管理シートに情報を追加します。
  • sendEmail(email, displayId) 関数: 展示台IDが生成されたら、この関数を使ってユーザーに展示台IDを通知するメールを送信します。
  • 具体的には、以下の処理が行われます:

    フォームから送信されたデータを取得します(メールアドレス、姓名、展示台のサイズと色など)。
    タイムスタンプからプレフィックスを生成し、展示台IDを生成します。
    生成した展示台IDをメールで送信し、送信が成功したら展示台ID管理シートに情報を追加します。
    このコードにより、ユーザーがフォームに展示台の情報を入力すると、展示台IDが自動的に生成され、管理シートに追加されるようになります。

    function createFormSubmitTrigger() {
      var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
      var formSheet = spreadsheet.getSheetByName("登録フォーム");
      ScriptApp.newTrigger("onFormSubmit")
        .forSpreadsheet(spreadsheet)
        .onFormSubmit()
        .create();
    }
    
    function onFormSubmit(e) {
      var formSheet = e.source.getSheetByName("登録フォーム");
      var idManagementSheet = e.source.getSheetByName("展示台ID管理");
      var row = e.range.getRow();
      
      var timestamp = new Date(e.namedValues['タイムスタンプ'][0]);
      var prefix = ('00' + timestamp.getSeconds()).slice(-2);
      
      var email = e.namedValues['メールアドレス'][0];
      var name = e.namedValues['姓名(アルファベット表記)'][0];
      var size1 = e.namedValues['展示台のサイズ1(短辺)'][0];
      var size2 = e.namedValues['展示台のサイズ2(長辺)'][0];
      var height = e.namedValues['展示台のサイズ(高さ)'][0];
      var color = e.namedValues['展示台の色'][0];
      
      var displayId = prefix + name.charAt(0).toUpperCase() + name.charAt(name.length - 1).toUpperCase() + size1 + size2 + height;
    
      if (sendEmail(email, displayId)) {
        var newRow = idManagementSheet.getLastRow() + 1;
        idManagementSheet.getRange(newRow, 1).setValue(size1 + 'x' + size2 + 'x' + height);
        idManagementSheet.getRange(newRow, 2).setValue(size1);
        idManagementSheet.getRange(newRow, 3).setValue(size2);
        idManagementSheet.getRange(newRow, 4).setValue(height);
        idManagementSheet.getRange(newRow, 5).setValue(name);
        idManagementSheet.getRange(newRow, 6).setValue(Utilities.formatDate(timestamp, Session.getScriptTimeZone(), 'yyyy-MM-dd'));
        idManagementSheet.getRange(newRow, 7).setValue(color);
        idManagementSheet.getRange(newRow, 8).setValue(displayId);
        idManagementSheet.getRange(newRow, 9).setValue(email);
      }
    }
    
    function sendEmail(email, displayId) {
      var subject = '展示台IDのお知らせ';
      var body = '展示台ID: ' + displayId + '\n\n' +
                 'この情報をシールに記入し、展示台に貼り付けてください。';
      
      try {
        MailApp.sendEmail(email, subject, body);
        return true;
      } catch (error) {
        Logger.log('Failed to send email: ' + error);
        return false;
      }
    }
    

    スクリプトをアクティブにする

    コードをコピペしただけでは動かないみたいです。
    この二つのトリガーを追加してください。

    こんな感じにトリガーの設定をしてみてください。

    アクセスして、編集をさせるので編集権限を与えてあげてください。

    以上で使えるはずです。
    ソースはコピー、ChatGPTに読ませる等自由にしてみてください。