0
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?

プログラミングで作る清掃スケジューラ自動化ガイド

Posted at

カレンダーを見て「え、今週もう終わったの?」って思ったことありませんか?…私もです。
私はかつて友人と小さな清掃業をやっていました。初めはホワイトボード、次にスプレッドシート…
でも、手作業では限界があり、ミスやダブルブッキングが多発。そこでソフトウェアに助けを求めました。

developer.jpg

目次

  1. 自動化のメリット
  2. 基本アーキテクチャ
  3. バックエンド:REST API
  4. フロントエンド:React コンポーネント
  5. データベース設計
  6. 外部連携:Google Calendar API
  7. 自動リマインダー:Twilio で SMS
  8. デプロイと Docker
  9. セキュリティと ベストプラクティス
  10. まとめ

1. 自動化のメリット

  • ダブルブッキング防止:予約ロジックで時間衝突を検知。
  • 効率化:スタッフへの自動リマインダーでミス激減。
  • スケーラビリティ:ビジネス拡大時も設定の調整だけで対応可能。
  • 顧客満足度向上:ウェブポータルで手軽に再予約やキャンセル操作が可能。

2. 基本アーキテクチャ

[Browser] ←→ [React SPA] ←→ [Node.js/Express API] ←→ [PostgreSQL]
                                       ↓
                                [Twilio API]
                                       ↓
                           [Google Calendar API]

3. バックエンド:REST API

Node.js + Express サンプル:

// server.js
import express from 'express';
import bodyParser from 'body-parser';
import { Pool } from 'pg';
import dotenv from 'dotenv';
dotenv.config();

const app = express();
app.use(bodyParser.json());

const pool = new Pool({ connectionString: process.env.DATABASE_URL });

// 予約作成エンドポイント
app.post('/api/bookings', async (req, res) => {
  const { clientName, startTime, duration } = req.body;
  const endTime = new Date(new Date(startTime).getTime() + duration * 3600000);
  const conflict = await pool.query(
    'SELECT * FROM bookings WHERE NOT($1 >= end_time OR $2 <= start_time)',
    [endTime.toISOString(), new Date(startTime).toISOString()]
  );
  if (conflict.rows.length) {
    return res.status(409).json({ error: '時間が重複しています。' });
  }
  const result = await pool.query(
    'INSERT INTO bookings(client_name, start_time, end_time) VALUES($1, $2, $3) RETURNING *',
    [clientName, startTime, endTime]
  );
  res.status(201).json(result.rows[0]);
});

// ポート起動
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

4. フロントエンド:React コンポーネント

// BookingForm.jsx
import React, { useState } from 'react';
import axios from 'axios';

export default function BookingForm() {
  const [date, setDate] = useState('');
  const [duration, setDuration] = useState(2);

  const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      const res = await axios.post('/api/bookings', {
        clientName: 'User',
        startTime: date,
        duration
      });
      alert(`予約完了: ${res.data.start_time} から ${res.data.end_time}`);
    } catch (err) {
      alert(err.response.data.error);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>日付・時刻:</label>
      <input type="datetime-local" value={date} onChange={e => setDate(e.target.value)} required />
      <label>所要時間 (h):</label>
      <input type="number" value={duration} onChange={e => setDuration(+e.target.value)} min="1" />
      <button type="submit">予約</button>
    </form>
  );
}

5. データベース設計 (PostgreSQL)

CREATE TABLE bookings (
  id SERIAL PRIMARY KEY,
  client_name VARCHAR(100) NOT NULL,
  start_time TIMESTAMP NOT NULL,
  end_time TIMESTAMP NOT NULL,
  created_at TIMESTAMP DEFAULT NOW()
);

6. 外部連携:Google Calendar API

import { google } from 'googleapis';
const calendar = google.calendar('v3');

async function addEvent(auth, booking) {
  const event = {
    summary: '清掃サービス',
    start: { dateTime: booking.start_time },
    end: { dateTime: booking.end_time },
  };
  await calendar.events.insert({
    auth,
    calendarId: 'primary',
    resource: event,
  });
}

7. 自動リマインダー:Twilio で SMS

import Twilio from 'twilio';
const client = new Twilio(process.env.TWILIO_SID, process.env.TWILIO_TOKEN);

function sendReminder(phone, message) {
  return client.messages.create({
    body: message,
    from: process.env.TWILIO_FROM,
    to: phone,
  });
}

8. デプロイと Docker

# Dockerfile
FROM node:16
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
CMD ["node", "server.js"]

9. セキュリティと ベストプラクティス

  • 環境変数で機密情報を管理(.env ファイルは .gitignore に追加)。
  • SQL インジェクション防止のため、パラメータライズドクエリを使用。
  • HTTPS 対応(Let’s Encrypt などで SSL 化)。
  • ユーザー認証・認可(JWT など)。

10. まとめ

清掃業のスケジューリング自動化は、技術を活用することで

  • 作業効率
  • 顧客満足度
  • ビジネスの拡張性
    を飛躍的に向上させます。
    ぜひこのテンプレートを参考に、自分だけの最適なスケジューラを構築してください!

エピソードひとつ。聞いてください。

高齢のお客様「Doris」さんがいて、「掃除後にバスルームが変な匂いする」と言われました。
調べたら、スタッフが漂白剤を使っていて、実は彼女アレルギーだったんです…。
でもその情報、どこにも記録してなかったんですよね。今は、顧客ごとの好みや注意点をアプリにタグ付けしています。
Dorisさんの健康のために、これは大事な一歩でした。

0
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
0
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?