sales_tool/functions/create-log-sheet/source/main.py
2025-11-17 14:21:29 +09:00

218 lines
7.9 KiB
Python
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import functions_framework
from google.cloud import secretmanager
from google.oauth2 import service_account
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
import json
import os
from datetime import datetime, timezone, timedelta
sm_client = secretmanager.SecretManagerServiceClient()
SCOPES = ["https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/drive.file"]
HEADER_VALUES = ["タイムスタンプ","商談日", "タイトル", "登録先企業","担当者", "ミーティングURL", "議事録URL", "HubSpot会社概要URL"]
@functions_framework.http
def handle_request(request):
# POSTリクエストの処理
if request.method != 'POST':
return ('', 405, {'Allow': 'POST', 'Content-Type': 'application/json'}) # メソッドがPOSTでない場合は405エラーを返す
"""Shows basic usage of the Drive Activity API.
Prints information about the last 10 events that occured the user's Drive.
"""
try:
log_folder_id = os.getenv("LOG_FOLDER_ID") # 共有ドライブID
meeting_folder_id = os.getenv("MEETING_FOLDER_ID") # ミーティングフォルダID
mode = os.getenv("MODE") # モードdevまたはprod
service_account_info = get_service_account_info()
# 認証
credentials = get_credentials(service_account_info)
# APIクライアントの構築
drive_service = build("drive", "v3", credentials=credentials)
sheet_service = build("sheets", "v4", credentials=credentials)
# 現在日時をJSTに変換
jst_now = datetime.now(timezone.utc).astimezone(timezone(timedelta(hours=9)))
# JSTの現在日時を文字列に変換
ym_str = jst_now.strftime("%Y%m")
y_str = jst_now.strftime("%Y")
# 年別のフォルダを検索
target_folder = get_directory_files_dev(drive_service, log_folder_id, y_str) if mode == "dev" else get_directory_files_prod(drive_service, meeting_folder_id, log_folder_id, y_str)
print("target_folder", target_folder)
year_folder_id = None
if not target_folder:
# フォルダが存在しない場合は新規作成
year_folder_id = create_new_folder(drive_service, log_folder_id, y_str)
else:
# フォルダが存在する場合はそのIDを使用
year_folder_id = target_folder[0]['id']
print("年別のフォルダID:", year_folder_id)
# スプレッドシートを作成
spreadsheet_id = create_new_spreadsheet(drive_service, year_folder_id, ym_str)
print("スプレッドシートID:", spreadsheet_id)
# 注意事項追加
append_log_to_sheet(sheet_service, spreadsheet_id, ["※シート名変更厳禁"])
# ヘッダーを追加
append_log_to_sheet(sheet_service, spreadsheet_id, HEADER_VALUES)
return (json.dumps({"status": "success"}, ensure_ascii=False), 200, {"Content-Type": "application/json"})
except HttpError as error:
# TODO(developer) - Handleerrors from drive activity API.
print(f"An error occurred: {error}")
#
# SecretManagerから秘密鍵を取得
#
def get_service_account_info():
key_path = os.getenv('KEY_PATH') + "/versions/1"
# 秘密鍵取得
response = sm_client.access_secret_version(name=key_path)
# 秘密鍵の値をデコード
secret_key = response.payload.data.decode("UTF-8")
return json.loads(secret_key)
# Google Drive認証
def get_credentials(service_account_info):
credentials = service_account.Credentials.from_service_account_info(
service_account_info,
scopes=SCOPES
)
return credentials
# 開発用マイドライブからのファイルを取得
def get_directory_files_dev(service,shared_folder_id, filename):
"""
対象のディレクトリ配下からファイル名で検索した結果を配列で返す
:param filename: ファイル名
:param directory_id: ディレクトリID
:param pages_max: 最大ページ探索数
:return: ファイルリスト
"""
items = []
page = 0
pages_max = 10 # 最大ページ数
while True:
page += 1
if page == pages_max:
break
results = service.files().list(
corpora="user",
includeItemsFromAllDrives=True,
includeTeamDriveItems=True,
q=f"'{shared_folder_id}' in parents and name = '{filename}' and trashed = false",
supportsAllDrives=True,
pageSize=10,
fields="nextPageToken, files(id, name)").execute()
items += results.get("files", [])
page_token = results.get('nextPageToken', None)
if page_token is None:
break
return items
# 本番用共有ドライブからのファイルを取得
def get_directory_files_prod(service,shared_folder_id,sub_folder_id,filename):
"""
対象のディレクトリ配下からファイル名で検索した結果を配列で返す
:param filename: ファイル名
:param directory_id: ディレクトリID
:param pages_max: 最大ページ探索数
:return: ファイルリスト
"""
items = []
page = 0
pages_max = 10 # 最大ページ数
while True:
page += 1
if page == pages_max:
break
results = service.files().list(
corpora="drive",
driveId=shared_folder_id,
includeItemsFromAllDrives=True,
includeTeamDriveItems=True,
q=f"'{sub_folder_id}' in parents and name = '{filename}' and trashed = false",
supportsAllDrives=True,
pageSize=10,
fields="nextPageToken, files(id, name, parents)").execute()
items += results.get("files", [])
page_token = results.get('nextPageToken', None)
if page_token is None:
break
return items
def create_new_folder(service, sub_folder_id, title):
"""
Google Drive APIを使用して新しいフォルダを作成する
:param service: Google Drive APIのサービスオブジェクト
:param title: フォルダのタイトル
:return: 作成したフォルダのID
"""
file_metadata = {
"name": title,
"parents": [sub_folder_id], # 共有ドライブのIDを指定
"mimeType": "application/vnd.google-apps.folder",
}
result = service.files().create(body=file_metadata, fields="id", supportsAllDrives=True).execute()
return result.get('id')
def create_new_spreadsheet(service,folder_id,title):
"""
Google Sheets APIを使用して新しいスプレッドシートを作成する
:param service: Google Sheets APIのサービスオブジェクト
:param title: スプレッドシートのタイトル
:return: 作成したスプレッドシートのID
"""
file_metadata = {
'name': title,
'parents': [folder_id], # 作成したフォルダのIDを指定
'mimeType': 'application/vnd.google-apps.spreadsheet',
}
result = (
service.files()
.create(body=file_metadata, fields="id", supportsAllDrives=True)
.execute()
)
return result.get("id")
def append_log_to_sheet(service, spreadsheet_id, row_data):
"""
Google Sheets APIを使用してスプレッドシートにログを追加する
:param service: Google Sheets APIのサービスオブジェクト
:param spreadsheet_id: スプレッドシートのID
:param row_data: 追加するログデータ(リスト形式)
"""
body = {
'values': [row_data]
}
# スプレッドシートにログを追加
result = service.spreadsheets().values().append(
spreadsheetId=spreadsheet_id,
range='Sheet1',
valueInputOption="USER_ENTERED",
insertDataOption='INSERT_ROWS',
body=body,
).execute()
print(f"{result.get('updates').get('updatedCells')} cells appended.")