◇ GAC #2: クレジットカード使用管理アプリの作成 1

2026年10月4日日曜日

Google Apps Script

t f B! P L

構想: メモ: クレジットカード使用管理アプリの作成
このアプリをGoogle Apps Scriptで作成してみる。

テストアプリの作成

以下のソースをGACに張り付け、メソッド名に"テスト実行" (test_run) を選択して実行

// ==========================================
// 設定項目(マイカレンダーでの表示名)
// ==========================================
const CALENDAR_NAME_UNPROCESSED = '未処理'; // 未処理用カレンダーの名前
const CALENDAR_NAME_PROCESSED   = '処理済'; // 処理済用カレンダーの名前

// ステータス定義
const STATUS_UNPROCESSED = '未処理';
const STATUS_PROCESSED   = '処理済';

/**
 * カレンダー名からCalendarオブジェクトを取得するヘルパー関数
 */
function getCalendarByName(name) {
  const calendars = CalendarApp.getCalendarsByName(name);
  if (calendars.length === 0) {
    throw new Error(`カレンダー「${name}」が見つかりませんでした。「マイカレンダー」に存在する形式を確認してください。`);
  }
  return calendars[0];
}

/**
 * 1. カード利用時の登録関数(「未処理」カレンダーに登録)
 */
function recordCardUsage(cardCode, amount, dateStr, timeStr = '00:00', location = '', note = '') {
  const calUnprocessed = getCalendarByName(CALENDAR_NAME_UNPROCESSED);
  
  const title = `${cardCode}${amount}`;
  const startTime = new Date(`${dateStr}T${timeStr}:00`);
  const endTime = new Date(startTime.getTime() + 30 * 60 * 1000); // 30分枠
  
  const description = `【ステータス】: ${STATUS_UNPROCESSED}\n【メモ】: ${note}`;
  
  // 「未処理」カレンダーに作成
  const event = calUnprocessed.createEvent(title, startTime, endTime, {
    location: location,
    description: description
  });
  
  Logger.log(`[未処理カレンダーに登録完了] ID: ${event.getId()} / タイトル: ${title}`);
  return event;
}

/**
 * 2. カード請求時の処理(照合&「処理済」カレンダーへ移動 / 新規「処理済」登録)
 */
function processCardBilling(cardCode, amount, dateStr, location = '', note = '') {
  const calUnprocessed = getCalendarByName(CALENDAR_NAME_UNPROCESSED);
  const calProcessed   = getCalendarByName(CALENDAR_NAME_PROCESSED);
  const targetTitle = `${cardCode}${amount}`;
  
  // 対象日の範囲指定
  const targetDate = new Date(dateStr);
  const startOfDay = new Date(targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate(), 0, 0, 0);
  const endOfDay   = new Date(targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate(), 23, 59, 59);
  
  // 「未処理」カレンダーから対象イベントを検索
  const events = calUnprocessed.getEvents(startOfDay, endOfDay);
  let matchedEvent = null;
  
  for (const event of events) {
    if (event.getTitle() === targetTitle) {
      matchedEvent = event;
      break;
    }
  }
  
  if (matchedEvent) {
    // 【パターンA】「未処理」カレンダーにあった場合 -> 「処理済」へ複製後、未処理側を削除
    const title = matchedEvent.getTitle();
    const startTime = matchedEvent.getStartTime();
    const endTime = matchedEvent.getEndTime();
    const loc = matchedEvent.getLocation();
    
    // 説明文のステータスを更新
    let desc = matchedEvent.getDescription();
    desc = desc.replace(`【ステータス】: ${STATUS_UNPROCESSED}`, `【ステータス】: ${STATUS_PROCESSED}`);
    
    // 処理済カレンダーに新規作成
    const newProcessedEvent = calProcessed.createEvent(title, startTime, endTime, {
      location: loc,
      description: desc
    });
    
    // 未処理カレンダー側のイベントを削除
    matchedEvent.deleteEvent();
    
    Logger.log(`[カレンダー移動完了] ID: ${newProcessedEvent.getId()} を「処理済」カレンダーへ作成し、未処理側を削除しました。`);
  } else {
    // 【パターンB】「未処理」カレンダーに無かった場合 -> 直接「処理済」カレンダーに新規登録
    const startTime = new Date(`${dateStr}T00:00:00`);
    const endTime = new Date(startTime.getTime() + 30 * 60 * 1000);
    const description = `【ステータス】: ${STATUS_PROCESSED}\n【メモ】: ${note}`;
    
    const newEvent = calProcessed.createEvent(targetTitle, startTime, endTime, {
      location: location,
      description: description
    });
    
    Logger.log(`[新規処理済登録] 未登録の明細だったため、「処理済」カレンダーに新規追加しました。`);
  }
}

// ==========================================
// 動作確認用テスト関数
// ==========================================
function test_run() {
  // ① マスターカードで1,200円の利用を「未処理」カレンダーに登録
  recordCardUsage('M', 1200, '2026-10-02', '12:30', 'スターバックス 渋谷店', 'ランチ代');
  
  // ② ビューカードで3,000円の利用を「未処理」カレンダーに登録(00:00)
  recordCardUsage('V', 3000, '2026-10-02', '00:00', '新宿駅', 'チャージ');
  
  // ③ 請求処理テスト(①の M1200 を「未処理」から「処理済」カレンダーへ移動)
  processCardBilling('M', 1200, '2026-10-02');
  
  // ④ 請求処理テスト(未登録の J5000 を直接「処理済」カレンダーに登録)
  processCardBilling('J', 5000, '2026-10-02', 'セブンイレブン', '未登録明細の補填');
}

Googleカレンダーに反映できた。


公開:2026.10.04(日) 02:23 くもり 19℃

QooQ