「拡張機能」→「Apps Script」を開く以下のコードを貼り付けて保存してください。さらに「プロジェクトの設定」→「スクリプト プロパティ」で API_TOKEN にお店の合言葉を設定してください。
// ソナレア補聴器 顧客管理 GAS v4
// v4: 合言葉(トークン)を必ず確認するようにした。
// 「プロジェクトの設定」→「スクリプト プロパティ」で API_TOKEN にお店の合言葉を設定してください。
// v3: 全項目を「書式なしテキスト」で書き込み、電話番号の先頭0や
// 日付の形式がシートの自動変換で壊れないようにした。
// 複数端末の同時書き込みはロックで保護。
const SHEET_NAME = '顧客情報';
function tokenOk_(tok) {
const t = PropertiesService.getScriptProperties().getProperty('API_TOKEN') || '';
return t !== '' && tok === t;
}
function doPost(e) {
const lock = LockService.getScriptLock();
lock.waitLock(30000);
try {
const data = JSON.parse(e.postData.contents);
if (!tokenOk_(data.token)) return json_({ok:false, error:'unauthorized'});
if (data.action === 'ping') return json_({ok:true, pong:true});
return handle_(data);
} finally {
lock.releaseLock();
}
}
function handle_(data) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName(SHEET_NAME);
const action = data.action;
const HEADERS = [
'ID','氏名','フリガナ','生年月日','性別',
'補聴器への意欲','性格メモ',
'KPあり','KP続柄','KP氏名','KP携帯','KPその他',
'自宅電話','携帯電話','メール','郵便番号','住所',
'右耳機種','右耳購入日','右耳価格','右耳助成金',
'左耳機種','左耳購入日','左耳価格','左耳助成金',
'メモ','来店履歴','登録日','顧客番号','店舗'
];
if (sheet.getLastRow() === 0 || sheet.getLastColumn() < HEADERS.length) {
sheet.getRange(1,1,1,HEADERS.length).setValues([HEADERS]);
}
if (action === 'getAll') {
const rows = sheet.getDataRange().getValues();
return json_({ok:true, data:rows});
}
if (action === 'save') {
const c = data.customer;
const row = [
c.id, c.name, c.kana, c.dob, c.gender,
c.attitude, c.personality,
c.kpExists?'あり':'', c.kpRelation, c.kpName, c.kpMobile, c.kpOther,
c.phoneHome, c.phoneMobile, c.email, c.zip, c.address,
c.rModel, c.rDate, c.rPrice, c.rSubsidy?'対象':'',
c.lModel, c.lDate, c.lPrice, c.lSubsidy?'対象':'',
c.memo, JSON.stringify(c.visits), c.createdAt, c.custNo, c.store
].map(function(v){ return v == null ? '' : String(v); });
const allData = sheet.getDataRange().getValues();
let rowIndex = -1;
for (let i = 1; i < allData.length; i++) {
if (allData[i][0] === c.id) { rowIndex = i+1; break; }
}
if (rowIndex < 0) rowIndex = sheet.getLastRow()+1;
sheet.getRange(rowIndex,1,1,row.length).setNumberFormat('@').setValues([row]);
return json_({ok:true});
}
if (action === 'delete') {
const allData = sheet.getDataRange().getValues();
for (let i = 1; i < allData.length; i++) {
if (allData[i][0] === data.id) { sheet.deleteRow(i+1); break; }
}
return json_({ok:true});
}
return json_({ok:false, error:'unknown action'});
}
function json_(obj) {
return ContentService.createTextOutput(JSON.stringify(obj))
.setMimeType(ContentService.MimeType.JSON);
}