こんにちは!
Yuki (@yukibnb) です。
今回はBeds24を使用している民泊運営者の方向けに、チェックアウトの部屋一覧を毎朝自動でLINE通知する方法を紹介します。
自社の清掃部門責任者や外部の清掃業者に自動連絡することができるようになるので、運営者の手間削減や清掃の抜け漏れ防止につながります。
では早速見ていきましょう!
チェックアウトとチェックインの一覧をLINEしたい方は以下の記事をご覧ください。
【【Beds24のAPI連携シリーズ】チェックアウト&イン一覧を毎朝自動LINE通知するGAS
はじめに
実現したいこと
この画像のようにその日にチェックアウトがある部屋の一覧を毎朝自動でLINE通知します。
通知する部屋情報は施設名 - 部屋名(ユニット名)
としています。
なお同日にチェックインがある場合★施設名 - 部屋名(ユニット名)《チェックイン予定時刻》
と表記して目立たせています。
チェックイン予定時刻はBeds24の予約詳細画面の[Arrival Time]の値を取得しています。もし[Arrival Time]に何も入力されていない場合、チェックイン予定時刻は《未定》
と表示されます。
同日にチェックインがある部屋を目立たせ、且つチェックイン予定時刻を表記することで清掃順の優先順位付けに役立ちます。
使用するもの
主に以下3つのサービスを使って実現します。
- Beds24のAPI
- Google Apps Script (GAS)
- LINE Notify
当記事で紹介する通知内容を独自にカスタマイズしたい場合Google Apps Scriptの知識が必要ですが、そのまま使うだけでしたら予備知識がなくても設定できるように紹介しますのでご安心ください。
大半は過去に当ブログで紹介した各種方法の組み合わせで実現できます。
コピペでOK!チェックアウト一覧を毎朝自動LINE通知するGAS
GASのスクリプトエディタを開く
まずGoogle Apps Script (GAS) のスクリプトエディタを開いてください。
スタンドアロンでも大丈夫ですが、空のスプレッドシートを作成してスクリプトエディタを開く(コンテナバインド)方が後々カスタマイズしやすいのでおすすめします。
スクリプトエディタの開き方がわからない場合、以下記事で方法を解説していますのでご覧ください。
【Beds24のAPI連携シリーズ】Google Apps Scriptを開こう
Moment.jsライブラリを追加する
今回紹介するGoogle Apps ScriptではMoment.jsというライブラリを使用します。
以下記事を参考にMoment.jsライブラリを導入してください。記事内の手順に沿って頂くと簡単に導入できます。
Moment.jsを使うとGoogle Apps Script内で日付や時間を簡単に記述することができます。
今回は「本日チェックアウトがある部屋のみ抽出」「本日チェックアウトがあり、且つチェックインもある部屋を目立たせる」など日付に関する処理を多数実施します。Moment.jsを使うことでそれらの処理をよりシンプルに記述できます。
スクリプトエディタにスクリプトをコピペする
スクリプトエディタに以下をまるごとコピペしてください。
//★★★ Beds24のログインIDを記入 ★★★ const USERID = "Beds24のログインID"; //★★★ Beds24のAPIキーを記入 ★★★ const APIKEY = "Beds24のAPIキー"; //★★★ LINE Notifyのアクセストークンを記入 ★★★ const LINETOKEN = "LINE Notifyのアクセストークン"; function checkOut() { //本日の日付を取得する let today = Moment.moment(); let todayFormatted = today.format("YYYY/MM/DD"); //3ヶ月前の日付を"YYYY-MM-DD"で抽出する let datefrom = today.clone().subtract(3, "months"); let datefrom_formatted = datefrom.format("YYYY-MM-DD"); //1ヶ月後の日付を"YYYY-MM-DD"で抽出する let dateto = today.clone().add(1, "months"); let dateto_formatted = dateto.format("YYYY-MM-DD"); //POST先のURL let url = "https://www.beds24.com/api/csv/getbookingscsv" let options = { "method": "post", "followRedirects": false, "payload": { "username": USERID, "password": APIKEY, "datefrom": datefrom_formatted, "dateto": dateto_formatted } } //CSVをBeds24からダウンロード let csv = UrlFetchApp.fetch(url,options); //ダウンロードしたCSVを二次元配列に変換する let csvContents = Utilities.parseCsv(csv); //必要な情報のインデックスを調べる //※今回使用していないものもあります //カスタマイズしたい場合参考にしてください let property = csvContents[0].indexOf("Property"); let room = csvContents[0].indexOf("Room"); let roomId = csvContents[0].indexOf("Roomid"); let unit = csvContents[0].indexOf("Unit"); let unitId = csvContents[0].indexOf("Unitid"); let bookingId = csvContents[0].indexOf("Ref") //Beds24の予約番号 let status = csvContents[0].indexOf("Status"); let checkIn = csvContents[0].indexOf("FirstNight"); //チェックイン日 let checkOut = csvContents[0].indexOf("CheckOut"); //チェックアウト日 let firstName = csvContents[0].indexOf("First Name"); //名 let lastName = csvContents[0].indexOf("Name"); //姓 let balance = csvContents[0].indexOf("Balance"); //バランス (残高) let originalReferer = csvContents[0].indexOf("Original Referer"); //予約元 let adultNum = csvContents[0].indexOf("Adult"); let childNum = csvContents[0].indexOf("Child"); let arrivalTime = csvContents[0].indexOf("Arrival"); let notes = csvContents[0].indexOf("Notes"); //本日チェックインの予約情報を格納するための空配列を宣言する let checkInToday = []; //本日チェックアウトとチェックインの両方がある部屋を判別するための情報確報用の空配列を宣言する let checkOutAndInToday = []; //本日チェックインがある部屋のチェックイン時間を判別するための情報確報用の空配列を宣言する let checkInTime = []; //本日チェックインの予約を抽出する for(let i = 1; i < csvContents.length; i++) { let checkInDate = Moment.moment(csvContents[i][checkIn], "YYYY-MM-DD"); //ステータスが"Cancelled"の予約は除外する if(today.isSame(checkInDate, "day") && csvContents[i][status] !== "Cancelled") { checkInToday.push(csvContents[i]); checkOutAndInToday.push("" + csvContents[i][roomId] + csvContents[i][unitId]); if(csvContents[i][arrivalTime] == "") { checkInTime.push(["" + csvContents[i][roomId] + csvContents[i][unitId], "未定"]); } else { checkInTime.push(["" + csvContents[i][roomId] + csvContents[i][unitId], csvContents[i][arrivalTime]]); } } } //本日チェックアウトの予約情報を格納するための空配列を宣言する let checkOutToday = []; //本日チェックアウトの予約を抽出する for(let i = 1; i < csvContents.length; i++) { let checkOutDate = Moment.moment(csvContents[i][checkOut], "YYYY-MM-DD"); //ステータスが"Cancelled"の予約は除外する if(today.isSame(checkOutDate, "day") && csvContents[i][status] !== "Cancelled") { checkOutToday.push(csvContents[i]); } } //通知文章の一部を格納するための空配列を宣言する let checkOutList = []; for(let j = 0; j < checkOutToday.length; j++) { let checkOutRoomAndUnit = "" + checkOutToday[j][roomId] + checkOutToday[j][unitId]; //チェックアウトとチェックインの両方ある部屋は頭に★を付与する if(checkOutAndInToday.indexOf(checkOutRoomAndUnit) >= 0){ //チェックイン時間を格納するための空配列を宣言する let checkInTimeToday = []; //チェックイン時間をcheckInTimeTodayに格納する for(let k = 0; k < checkInTime.length; k++) { if(checkInTime[k].indexOf(checkOutRoomAndUnit) >= 0) { checkInTimeToday.push(checkInTime[k][1]); } } //当日チェックインがある部屋の文面 checkOutList.push("★" + checkOutToday[j][property] + " - " + checkOutToday[j][room] + "(" + checkOutToday[j][unit] + ")" + " 《" + checkInTimeToday[0] + "》" ); } else { //当日チェックインがない部屋の文面 checkOutList.push(checkOutToday[j][property] + " - " + checkOutToday[j][room] + "(" + checkOutToday[j][unit] + ")" ); } } //通知文章を格納するための変数を宣言する let content; if(checkOutToday.length > 0) { content = "\n【本日のチェックアウト】\n" + "日付: " + todayFormatted + "\n" + "合計: " + checkOutList.length + "件" + "\n\n" + checkOutList.join("\n"); } else { content = "\n【本日チェックアウト】\n" + "日付: " + todayFormatted + "\n" + "合計: " + checkOutList.length + "件" + "\nチェックアウトはありません。" } sendLine(content); } // LINE notifyへの通知 function sendLine(content){ //「&」が文章に含まれると「&」以降の文章が通知されないため、 //「&」を「%26」で置き換えます //実際のライン上では「%26」は「&」と表示されます let contentLine = content.replace(/&/g, "%26"); let options = { "method" : "post", "payload" : "message=" + contentLine, "headers" : {"Authorization" : "Bearer "+ LINETOKEN} }; UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options); }
コピペすると以下のようになります。
一部情報を置き換える
先程ペーストしたスクリプトの中の3か所をみなさん自身のものに置き換えてください。
Beds24のログインID
//★★★ Beds24のログインIDを記入 ★★★ const USERID = "Beds24のログインID";
ご自身のBeds24のログインIDに置き換えてください。
ログインIDは以下箇所のことです。
Beds24のAPIキー
//★★★ Beds24のAPIキーを記入 ★★★ const APIKEY = "Beds24のAPIキー";
ご自身のBeds24のAPIキーに置き換えてください。
APIキーの取得方法は以下記事をご覧ください。
www.yukibnb.com
APIキーはBeds24のログインパスワードではありません。
LINE Notifyのアクセストークン
//★★★ LINE Notifyのアクセストークンを記入 ★★★ const LINETOKEN = "LINE Notifyのアクセストークン";
ご自身のLINE Notifyのアクセストークンに置き換えてください。
アクセストークンの取得方法は以下記事をご覧ください。
www.yukibnb.com
スクリプトを保存する
スクリプトエディタの画面上部の[保存]アイコンをクリックして、スクリプトを保存してください。
これで本日チェックアウトする部屋一覧をLINE通知するするスクリプトの記述が完了しました。
スクリプトを手動実行しよう
スクリプトを選択する
スクリプトエディタの画面上部のプルダウンから[checkOut]を選択してください。
スクリプトの初回承認を行う
スクリプトエディタの画面上部の[実行]をクリックしてください。
すると以下のようなポップアップが表示されます。
これは[checkOut]を実行するための初回承認です。承認しないとスクリプトを実行できないため、[権限を確認]をクリックし承認を行ってください。
なお[権限を確認]をクリックした後の詳しい承認方法については以下記事に画像や動画付きで詳しく紹介していますので、そちらをご覧ください。
www.yukibnb.com
[checkOut]を手動実行する
初回承認が完了すると自動的に[checkOut]が実行されます。
もし何も動きがなければ、画面上部の[実行]をクリックすると[checkOut]を実行できます。
数秒でスクリプトの実行が完了し、LINE通知が届きます。
毎朝自動的にLINE通知されるようにトリガーを設定する
無事スクリプトの初回承認が完了し、手動実行することができました。
ただし毎朝[実行]をクリックして手動実行するのは面倒なので、毎日決まった時間帯に自動でLINE通知されるように設定します。
この設定のことを「トリガーを設定する」と言います。
トリガーの設定画面を開く
スクリプトエディタの画面左側の[時計]アイコンをクリックしてください。
するとトリガーの設定画面が開きます。
[トリガーを追加]をクリックする
画面右下の[トリガーを追加]をクリックしてください。
するとポップアップが表示されます。
トリガーを設定する
上記画像のように各項目の選択肢を選択してください。
- 実行する関数を選択: checkOut
- 実行するデプロイを選択: Head
- イベントのソースを選択: 時間主導型
- 時間ベースのトリガーのタイプを選択: 日付ベースのタイマー
- 時刻を選択: 自動LINE通知したい時間帯
- [保存]をクリック
(5)は画像内では「午前8時~9時」としていますが、自由に時間帯を選択ください。
ここで選択した時間帯に毎日自動LINE通知されます。
トリガーを設定完了!
トリガーを保存すると、このように画面上に設定済みのトリガーが表示されます。
これで毎日決まった時間帯に[checkOut]が自動実行され、自動LINE通知されるようになりました。
GASのポイントを解説
「使えたら問題がない」という方は読み飛ばして頂いて問題ありません。
今回紹介したスクリプトをカスタマイズして独自の通知を作成したい方向けに、Google Apps Scriptのポイントを解説します。
Beds24からCSVを取得し、二次元配列に変換する
//CSVをBeds24からダウンロード let csv = UrlFetchApp.fetch(url,options); //ダウンロードしたCSVを二次元配列に変換する let csvContents = Utilities.parseCsv(csv);
UrlFetchApp.fetch(url,options)
を使いBeds24からCSVを取得し、変数csv
に格納します。
そして変数csv
に対してUtilities.parseCsv
を使用することで、取得したCSVを二次元配列に変換し変数csvContents
に格納します。
変数csvContents
の中には様々な予約情報が二次元配列形式で格納されています。
どのような情報が格納されているか確認したい場合、Logger.log(csvContents)
を記述すれば確認できます。
取り出したい情報のインデックスを調べる
let property = csvContents[0].indexOf("Property"); let room = csvContents[0].indexOf("Room"); let roomId = csvContents[0].indexOf("Roomid"); let unit = csvContents[0].indexOf("Unit"); let unitId = csvContents[0].indexOf("Unitid"); let bookingId = csvContents[0].indexOf("Ref") //Beds24の予約番号 let status = csvContents[0].indexOf("Status"); let checkIn = csvContents[0].indexOf("FirstNight"); //チェックイン日 let checkOut = csvContents[0].indexOf("CheckOut"); //チェックアウト日 let firstName = csvContents[0].indexOf("First Name"); //名 let lastName = csvContents[0].indexOf("Name"); //姓 let balance = csvContents[0].indexOf("Balance"); //バランス (残高) let originalReferer = csvContents[0].indexOf("Original Referer"); //予約元 let adultNum = csvContents[0].indexOf("Adult"); let childNum = csvContents[0].indexOf("Child"); let arrivalTime = csvContents[0].indexOf("Arrival"); let notes = csvContents[0].indexOf("Notes");
csvContents[0]
の要素はProperty、Room、Roomid、Unit、Unitidなど数十個あります。
PropertyはcsvContents[0][0]
、RoomはcsvContents[0][1]
、RoomidはcsvContents[0][2]
...というように指定することができます。
スプレッドシートで例えるとA列にProperty、B列にRoom、C列にRoomid....というイメージです。
「A列にProperty」のように何列目に何があるかは、Beds24に新しい項目が追加されれば将来変わる可能性があります。例えばSub Status
という項目は昔のBeds24ではありませんでしたが現在はH列に存在しています。
取得したい要素の列(インデックス)が将来変わっても問題なくスクリプトが動くように、indexOf
メソッドを使ってcsvContents[0]
から必要な要素のインデックスを動的に取得しています。
なお変数bookingId
やfirstName
、balance
などは今回のLINE通知では使用していませんが、みなさんがカスタマイズする際にわかりやすいように変数だけ作成しておきました。
キャンセル予約を除外する
//ステータスが"Cancelled"の予約は除外する if(today.isSame(checkInDate, "day") && csvContents[i][status] !== "Cancelled") { checkInToday.push(csvContents[i]); checkOutAndInToday.push("" + csvContents[i][roomId] + csvContents[i][unitId]);
//ステータスが"Cancelled"の予約は除外する if(today.isSame(checkOutDate, "day") && csvContents[i][status] !== "Cancelled") { checkOutToday.push(csvContents[i]);
変数csvContents
にはキャンセル予約の情報も含まれているため、ステータスが"Cancelled"になっている予約を除外しました。
LINE通知の文章を変数contentに格納する
//通知文章を格納するための変数を宣言する let content; if(checkOutToday.length > 0) { content = "\n【本日のチェックアウト】\n" + "日付: " + todayFormatted + "\n" + "合計: " + checkOutList.length + "件" + "\n\n" + checkOutList.join("\n"); } else { content = "\n【本日チェックアウト】\n" + "日付: " + todayFormatted + "\n" + "合計: " + checkOutList.length + "件" + "\nチェックアウトはありません。" }
変数content
に格納した文章が実際にLINE通知される文章です。
そのため通知内容をカスタマイズしたい場合、変数content
の中身を調整すればOKです。
「&」のエラーを回避する
//「&」が文章に含まれると「&」以降の文章が通知されないため、 //「&」を「%26」で置き換えます //実際のライン上では「%26」は「&」と表示されます let contentLine = content.replace(/&/g, "%26");
LINE Notifyでは文章内に「&」が含まれると、「&」以降の文章が途切れてしまい全文が通知されないことがあります。
「&」を「%26」に置き換えることでLINE通知内で「&」を表示することができるため、replace
メソッドを使って変数content
内の「&」をすべて「%26」に置き換えます。
まとめ
今回はBeds24を使用している民泊運営者の方向けに、チェックアウトの部屋一覧を毎朝自動でLINE通知する方法を紹介しました。
自社の清掃部門責任者や外部の清掃業者に自動連絡などに活用ください。
次回記事もご期待ください!