
途中まで書いて愚痴のブログになったので、
お時間の有る方のみお付き合いくださいm(_ _)m
その中でもAIについて記述している部分がありますので、
その内容が貴方の日々のビジネスやプライベートで有用になることを願います。
2週間ほど前からタイトルの課題に取り組んでいました。
我が社ではOrder Management System=OMSとしてネクストエンジン、
データの共有としてGoogleスプレッドシートを使用しておりますが、
その接続方法が課題でした。
と言っても、課題だと思うのは我が社で私だけ(-_-;)
人力でネクストエンジンからCSVをダウンロードして、
Googleスプレッドシートにアップロードするという方法が簡単に行えそうですが、
私からするとその作業を1日何回行うのですか?
例えば1日3回だとして360日稼働だとして1年で1080回ですよね?
10年行ったとしたら10800回ですよね?
その人件費は経費ベースだとそこまで多くないかもしれませんが、
人時生産性ベースだといくらかわかりますか?
そういうのがわからないのが我が社でとても残念な点だと思います。
ほんまたいがいやな~(-_-;)
楽天のとある部門で一位とか偉そうに言っていますが、
うちの会社はホンマに何も出来てませんよ。
なので私の仕事が無限にあるという(笑)
以前使用していたTepsは価格が暴騰して使用を止めました(-_-;)
Tepsも良かったのですが、
出来ないこともありましたんでGASでのスケジュールで実現したことはあります。
7月末に見つけて8月頭から少し使用したYoomは思う動作ではなかったので、
ネクストエンジン側の接続を遮断しました。
それよりまだ前に使用していたのは、
我が社にSFTPサーバーを立ち上げて、
(その中にNO-IPという技術が入っています)
ネクストエンジンからSFTPサーバーに対してCSVを時間指定で吐き出させる
という事をしていました。
そのCSVをGoogleドライブに連携させて、
GoogleスプレッドシートにGoogle Apps Script=GASでCSVを読み込ませる
というのを時間指定して処理させていました。
ですが、ネクストエンジンがCSVを吐き出させるスケジュールが
スケーラビリティに優れていない・・・(-_-;)
ということで、AIに
ネクストエンジンとGoogleスプレッドシートを接続する方法を教えてもらえますか?
と聞くと、
Yoomという回答もあったのですが、
ハードルは高くなるもののGASでの開発ならばスケーラビリティに優れている
という回答を得られましたのでGASでの開発にシフトしていきました。
と言うものの、
GASを最初から学ぶには今年49歳という年齢からあまりにも遅すぎる・・・
なので、令和の今どきであるコーディングが出来るAIに頼ることにしました(笑)
当然、我が社にはAIに払う予算なんてものは存在しませんし、
会議でAIは・・・
なんて言おうものなら上層部に頭の硬い連中がいるので、
AIというのも・・・
なんて超絶めんどくさい事を言う奴しか居ないので
報告無しで無料枠からAIを使うしかありませんでした。
私の人生のコンセプトは仕事の課題は仕事の時間中のみ。
ただし、プライベートでその課題が気になるのは仕方ない。
ですが、仕事とプライベートは基本的に割り切る。
コーディングは確かGemini 2.5 Flashから始めたのかな~?
ですが、上手く行かずにGPT-5に移行したように思います。
ですが、GPT-5でも上手く行かずにGemini 2.5 Proに移行したこともありますが、
それでも上手く行かずに無料枠の範囲内で
Gemini 2.5 ProとGPT-5とGemini 2.5 Flashを行き来しながら可決できず、
VS CodeのGithub Copilotに移行しました。
これで解決できるか?と思っていましたが、
無料枠では限界が来て開発が出来なくなり・・・
ということで、
開発を止めることは出来なかったのでググったら
AnthropicのClaude Codeにたどり着きました。
Claude Codeは何やらコーディングが強いとか・・・
アプリを100日の間毎日つくる100日チャレンジをした
大塚あみ
さんも有料枠で使っているとか・・・
この記事を2週間の間に見た記憶はあったのですが、
改めて見ると・・・
2週間でここまで来たか・・・
Claude Codeに話を戻して、
コーディングが出来るAIと言えども適切な質問をしなければ
曖昧な答えしか得られないというのは当たり前。
そのことが広く認知されていれれば
プロンプトエンジニアリング
という言葉も出来てこなかったのではないでしょうか?
ということで、Claude Codeにログインして最初にいくつか質問されましたので
それに答えたらチャット履歴として下記が残っていました。
--------------------------------------------------
こんにちは、Claudeさん!一緒にコーディングしましょうをお願いできますでしょうか?追加情報が必要な場合は、重要な質問を1~2つお聞かせください。より良い結果のために必要な資料がございましたら、お申し付けください。Google Driveやウェブ検索など、利用可能なツールを必要に応じてご活用ください。分析ツールのご使用はお控えください。ご回答は親しみやすく簡潔な形でお願いいたします。
できるだけ早めにタスクを実行していただき、可能であれば成果物を作成していただけると助かります。成果物を作成する場合は、このタスクに最適な形式(インタラクティブ、ビジュアル、チェックリストなど)をご検討ください。ご協力ありがとうございます。
--------------------------------------------------
すると下記の回答が得られました。
--------------------------------------------------
こんにちは!コーディングのお手伝いをさせていただきます。
どのようなプログラムやアプリケーションを作りたいか教えていただけますか?例えば:
何を作りたいですか?
Webアプリ、ゲーム、計算ツール、データ可視化など
どの技術を使いますか?
JavaScript/HTML、React、Python、特定のライブラリなど
具体的なアイデアがあれば、すぐに実用的な成果物を作成いたします。アイデアが漠然としている場合でも、ご希望に合わせて提案させていただきます!
どのようなものを作ってみましょうか?
--------------------------------------------------
ということで、プロンプトエンジニアリングを行うことにしました。
その回答内容は
--------------------------------------------------
ネクストエンジンとGoogleスプレッドシートをAPI接続するGASを作成したいと思います。
スクリプトはQiitaなどへの公開を考えてコンテナバインドではなくスタンドアロンを考えています。
また、設定項目は上記同様にコード内に記載するのではなくスクリプトプロパティを使用したいと思います。
在庫数の取得が目的ですが、最初から行いたいこと全部となると、今までいくつかのAIといっしょに作業してきましたが認証で躓いていますので、まずは認証ができることを目標としたいと思います。
注意書きにつきましてはGASのトップでコメントとしてこのスクリプトの説明文を記載したいと思います。
ネクストエンジンAPIのエンドポイントは下記が参考になりますか?
https://developer.next-engine.com/api
ネクストエンジンのテスト環境設定についてスクリーンショットを貼り付けますので参考にしてください。
他に必要な情報はありますか?
--------------------------------------------------
・・・
これによりClaudeはネクストエンジンAPIの認証フローを確認してくれて、
認証フローを確認するために、公式ドキュメントを見てくれました。
--------------------------------------------------
理解しました!ネクストエンジンAPIの認証フローとスクリーンショットの情報を基に、認証に特化したGASスクリプトを作成します。
--------------------------------------------------
なんとも頼もしい回答なのですが、
他社のAIでも似たような回答がありましたので、
過度な期待はありませんでした。
ですが、何度かやり取りを行ったところ無事認証が取れました(^^♪
Claude Code スゲ~
因みに下記が途中まで上手く行った全文です。
--------------------------------------------------
/**
* ネクストエンジンAPI認証テスト用スクリプト
*
* 【目的】
* ネクストエンジンAPIとの認証を確立し、アクセストークンの取得を行う
*
* 【機能】
* 1. OAuth2認証フローの実行
* 2. アクセストークンとリフレッシュトークンの取得・保存
* 3. トークンの有効性確認
*
* 【設定方法】
* スクリプトプロパティに以下の値を設定してください:
* - CLIENT_ID: ネクストエンジンのクライアントID
* - CLIENT_SECRET: ネクストエンジンのクライアントシークレット
* - REDIRECT_URI: リダイレクトURI(スクリーンショット参照)
*
* 【注意事項】
* - テスト環境での動作確認を前提としています
* - 本番環境での使用前に十分なテストを行ってください
* - アクセストークンは安全に管理してください
*/
// ネクストエンジンAPIのエンドポイント
const NE_BASE_URL = 'https://base.next-engine.org';
const NE_API_URL = 'https://api.next-engine.org';
/**
* WebアプリとしてのGETリクエスト処理
* ネクストエンジンからのリダイレクト時にuidとstateを受け取る
*/
function doGet(e) {
const uid = e.parameter.uid;
const state = e.parameter.state;
if (uid && state) {
try {
// 自動的にアクセストークンを取得
const result = getAccessToken(uid, state);
return HtmlService.createHtmlOutput(`
ネクストエンジン認証完了
✅ 認証成功!
ネクストエンジンAPIの認証が完了しました。
取得した情報:
UID: ${uid}
State: ${state}
Access Token: ${result.access_token.substring(0, 20)}...
Refresh Token: ${result.refresh_token.substring(0, 20)}...
次のステップ:
GASエディタに戻り、testApiConnection()
を実行してAPI接続をテストしてください。
このページを閉じて構いません。
`);
} catch (error) {
return HtmlService.createHtmlOutput(`
認証エラー
❌ 認証エラー
認証処理中にエラーが発生しました:
${error.message}
GASエディタでログを確認してください。
`);
}
} else {
return HtmlService.createHtmlOutput(`
パラメータエラー
❌ パラメータエラー
必要なパラメータ(uid、state)が見つかりません。
認証URLから正しくリダイレクトされていない可能性があります。
GASエディタで generateAuthUrl()
を実行して、正しい認証URLを取得してください。
`);
}
}
/**
* スクリプトプロパティから設定値を取得
*/
function getScriptProperties() {
const properties = PropertiesService.getScriptProperties();
const clientId = properties.getProperty('CLIENT_ID');
const clientSecret = properties.getProperty('CLIENT_SECRET');
const redirectUri = properties.getProperty('REDIRECT_URI');
if (!clientId || !clientSecret || !redirectUri) {
throw new Error('必要なスクリプトプロパティが設定されていません。CLIENT_ID, CLIENT_SECRET, REDIRECT_URIを設定してください。');
}
return {
clientId,
clientSecret,
redirectUri
};
}
/**
* ステップ1: 認証URLを生成してログ出力
* 手動でブラウザでアクセスして認証を行う
*/
function generateAuthUrl() {
try {
const config = getScriptProperties();
// ネクストエンジンの認証URL
const authUrl = `${NE_BASE_URL}/users/sign_in?client_id=${config.clientId}&redirect_uri=${encodeURIComponent(config.redirectUri)}`;
console.log('=== ネクストエンジン認証URL ===');
console.log(authUrl);
console.log('');
console.log('上記URLをブラウザでアクセスしてください');
console.log('認証後、リダイレクトURLに uid と state パラメータが付与されて戻ってきます');
console.log('例: https://your-redirect-uri?uid=XXXXX&state=YYYYY');
return authUrl;
} catch (error) {
console.error('認証URL生成エラー:', error.message);
throw error;
}
}
/**
* ステップ2: uidとstateを使用してアクセストークンを取得
* @param {string} uid - 認証後に取得されるuid
* @param {string} state - 認証後に取得されるstate
*/
function getAccessToken(uid, state) {
try {
if (!uid || !state) {
throw new Error('uid と state が必要です');
}
const config = getScriptProperties();
// アクセストークン取得のリクエスト
const url = `${NE_API_URL}/api_neauth`;
const payload = {
'uid': uid,
'state': state,
'client_id': config.clientId,
'client_secret': config.clientSecret
};
const options = {
'method': 'POST',
'headers': {
'Content-Type': 'application/x-www-form-urlencoded'
},
'payload': Object.keys(payload).map(key =>
encodeURIComponent(key) + '=' + encodeURIComponent(payload[key])
).join('&')
};
console.log('アクセストークン取得リクエスト送信中...');
console.log('使用URL:', url);
console.log('ペイロード:', payload);
const response = UrlFetchApp.fetch(url, options);
const responseText = response.getContentText();
console.log('レスポンス:', responseText);
if (response.getResponseCode() !== 200) {
throw new Error(`APIリクエストが失敗しました。ステータス: ${response.getResponseCode()}`);
}
const responseData = JSON.parse(responseText);
if (responseData.result === 'success') {
// トークンをスクリプトプロパティに保存
const properties = PropertiesService.getScriptProperties();
properties.setProperties({
'ACCESS_TOKEN': responseData.access_token,
'REFRESH_TOKEN': responseData.refresh_token,
'TOKEN_OBTAINED_AT': new Date().getTime().toString()
});
console.log('=== 認証成功 ===');
console.log('アクセストークン:', responseData.access_token);
console.log('リフレッシュトークン:', responseData.refresh_token);
console.log('トークンをスクリプトプロパティに保存しました');
return responseData;
} else {
throw new Error(`認証失敗: ${JSON.stringify(responseData)}`);
}
} catch (error) {
console.error('アクセストークン取得エラー:', error.message);
throw error;
}
}
/**
* ステップ3: 保存されたトークンでAPI接続をテスト
* ユーザー情報を取得して認証が正常に動作しているか確認
*/
function testApiConnection() {
try {
const properties = PropertiesService.getScriptProperties();
const accessToken = properties.getProperty('ACCESS_TOKEN');
const refreshToken = properties.getProperty('REFRESH_TOKEN');
if (!accessToken || !refreshToken) {
throw new Error('アクセストークンが見つかりません。先にgetAccessToken()を実行してください。');
}
// ログインユーザー情報取得APIでテスト
const url = `${NE_API_URL}/api_v1_login_user/info`;
const payload = {
'access_token': accessToken,
'refresh_token': refreshToken
};
const options = {
'method': 'POST',
'headers': {
'Content-Type': 'application/x-www-form-urlencoded'
},
'payload': Object.keys(payload).map(key =>
encodeURIComponent(key) + '=' + encodeURIComponent(payload[key])
).join('&')
};
console.log('API接続テスト実行中...');
console.log('使用URL:', url);
console.log('ペイロード:', payload);
const response = UrlFetchApp.fetch(url, options);
const responseText = response.getContentText();
console.log('レスポンスコード:', response.getResponseCode());
console.log('API レスポンス:', responseText);
const responseData = JSON.parse(responseText);
if (responseData.result === 'success') {
console.log('=== API接続テスト成功 ===');
console.log('ユーザー情報:', responseData.data);
// トークンが更新された場合は保存
if (responseData.access_token && responseData.refresh_token) {
properties.setProperties({
'ACCESS_TOKEN': responseData.access_token,
'REFRESH_TOKEN': responseData.refresh_token,
'TOKEN_UPDATED_AT': new Date().getTime().toString()
});
console.log('トークンが更新されました');
}
return responseData.data;
} else {
throw new Error(`API接続テスト失敗: ${JSON.stringify(responseData)}`);
}
} catch (error) {
console.error('API接続テストエラー:', error.message);
throw error;
}
}
/**
* デバッグ用: 手動でuid/stateを入力してテスト
* 認証URLにアクセス後、リダイレクトURLのuid/stateを手動で入力
*/
function debugAuth() {
// ここにブラウザのリダイレクトURLから取得したuid/stateを入力してテスト
const uid = 'ここにuidを入力';
const state = 'ここにstateを入力';
if (uid === 'ここにuidを入力' || state === 'ここにstateを入力') {
console.log('uid と state を実際の値に変更してから実行してください');
return;
}
try {
const result = getAccessToken(uid, state);
console.log('デバッグテスト成功:', result);
} catch (error) {
console.error('デバッグテストエラー:', error.message);
}
}
/**
* 保存されているトークン情報を表示
*/
function showStoredTokens() {
const properties = PropertiesService.getScriptProperties();
console.log('=== 保存されているトークン情報 ===');
console.log('ACCESS_TOKEN:', properties.getProperty('ACCESS_TOKEN') || '未設定');
console.log('REFRESH_TOKEN:', properties.getProperty('REFRESH_TOKEN') || '未設定');
console.log('TOKEN_OBTAINED_AT:', properties.getProperty('TOKEN_OBTAINED_AT') || '未設定');
console.log('TOKEN_UPDATED_AT:', properties.getProperty('TOKEN_UPDATED_AT') || '未設定');
}
/**
* スクリプトプロパティをクリア(テスト用)
*/
function clearProperties() {
const properties = PropertiesService.getScriptProperties();
properties.deleteProperty('ACCESS_TOKEN');
properties.deleteProperty('REFRESH_TOKEN');
properties.deleteProperty('TOKEN_OBTAINED_AT');
properties.deleteProperty('TOKEN_UPDATED_AT');
console.log('トークン情報をクリアしました');
}
/**
* 認証フロー全体のガイド表示
*/
function showAuthGuide() {
console.log('=== ネクストエンジンAPI認証ガイド ===');
console.log('');
console.log('【事前準備】');
console.log('1. スクリプトプロパティに以下を設定:');
console.log(' - CLIENT_ID: あなたのクライアントID');
console.log(' - CLIENT_SECRET: あなたのクライアントシークレット');
console.log(' - REDIRECT_URI: リダイレクトURI');
console.log('');
console.log('2. スクリプトをWebアプリとしてデプロイ:');
console.log(' - 「デプロイ」→「新しいデプロイ」');
console.log(' - 種類: ウェブアプリ');
console.log(' - 実行者: 自分');
console.log(' - アクセス: 全員');
console.log(' - デプロイ後のURLをREDIRECT_URIに設定');
console.log('');
console.log('【認証手順】');
console.log('1. generateAuthUrl() を実行して認証URLを取得');
console.log('2. ブラウザで認証URLにアクセス');
console.log('3. ネクストエンジンにログイン');
console.log('4. 自動的にアクセストークンが取得されます');
console.log('5. testApiConnection() で動作確認');
console.log('');
console.log('【その他の関数】');
console.log('- showStoredTokens(): 保存済みトークン情報表示');
console.log('- clearProperties(): トークン情報クリア');
}
--------------------------------------------------
ネクストエンジン側で操作する点は色々ありますが、
Qiitaで記事をUpしたいと思います。
プロンプトエンジニアリングを行ったとは言え、
数度のやり取りでここまでのコーディングが出来る
Claude Code・・・やばい(-_-;)
みんカラユーザーには興味ない内容でしたね^^;