diff --git a/main.py b/main.py index abc4ab7..7c9a88e 100644 --- a/main.py +++ b/main.py @@ -214,12 +214,20 @@ templates = Jinja2Templates(directory="templates") # Globals SMS_HISTORY_FILE = 'sms_history.dat' +SMS_HISTORY_HEADERS = ["일시", "주문유형", "입금액", "주문아이템", "메시지 내용", "이름", "연락처", "주소"] GSPREAD_CRED_FILE = 'manual-ordering.json' MANUAL_SPREADSHEET_ID = '1QxFtjDurPPZd8NmtXBy4XEUIzkf93aXD5Mlx5kB33xw' SETTINGS_SPREADSHEET_ID = '1k7SNEdIaRtGXzQNdJSQAiNSDRwzOePDRTLHY_mNCO8M' MANUAL_HISTORY_FILE = 'manual_history.dat' # ----- Utility Functions ----- +def first_nonempty(data: dict, *keys: str) -> str: + for key in keys: + value = data.get(key) + if value is not None and str(value).strip(): + return str(value) + return "" + def read_config(force_refresh=False): global _CONFIG_ROWS_CACHE, _CONFIG_ROWS_CACHE_TIME @@ -508,7 +516,7 @@ def get_sms_history_worksheet(): worksheet_sms_history_global = ss.worksheet("문자내역") except gspread.exceptions.WorksheetNotFound: worksheet_sms_history_global = ss.add_worksheet(title="문자내역", rows=1000, cols=10) - worksheet_sms_history_global.append_row(["일시", "주문유형", "입금액", "주문아이템", "메시지 내용"]) + worksheet_sms_history_global.append_row(SMS_HISTORY_HEADERS) return worksheet_sms_history_global def get_manual_history_worksheet(): @@ -647,6 +655,16 @@ async def download_and_clear_sheet(): @app.get("/api/sms/history") async def get_history(): local_history = {} + def merge_history_item(sheet_item, local_item): + if not local_item: + return sheet_item + merged = dict(sheet_item) + merged.update(local_item) + for key in ("custName", "custPhone", "custAddress", "customer_name", "phone", "address"): + if not merged.get(key) and sheet_item.get(key): + merged[key] = sheet_item[key] + return merged + if os.path.exists(SMS_HISTORY_FILE): with open(SMS_HISTORY_FILE, 'r', encoding='utf-8') as f: for line in f: @@ -657,7 +675,7 @@ async def get_history(): local_history[item["timestamp"]] = item except: pass - + history = [] try: ws = get_sms_history_worksheet() @@ -667,23 +685,30 @@ async def get_history(): if not row or not row[0].strip(): continue timestamp = row[0] - - if timestamp in local_history: - history.append(local_history[timestamp]) - else: - order_type = row[1] if len(row) > 1 else "" - deposit_amt = row[2] if len(row) > 2 else "" - items_str = row[3] if len(row) > 3 else "" - preview_text = row[4] if len(row) > 4 else "" - preview_text = preview_text.replace(" ", "\n") - - history.append({ - "timestamp": timestamp, - "orderType": order_type, - "deposit_amount_str": deposit_amt, - "items_str": items_str, - "previewText": preview_text - }) + + order_type = row[1] if len(row) > 1 else "" + deposit_amt = row[2] if len(row) > 2 else "" + items_str = row[3] if len(row) > 3 else "" + preview_text = row[4] if len(row) > 4 else "" + cust_name = row[5] if len(row) > 5 else "" + cust_phone = row[6] if len(row) > 6 else "" + cust_address = row[7] if len(row) > 7 else "" + preview_text = preview_text.replace(" ", "\n") + + sheet_item = { + "timestamp": timestamp, + "orderType": order_type, + "deposit_amount_str": deposit_amt, + "items_str": items_str, + "previewText": preview_text, + "custName": cust_name, + "custPhone": cust_phone, + "custAddress": cust_address, + "customer_name": cust_name, + "phone": cust_phone, + "address": cust_address + } + history.append(merge_history_item(sheet_item, local_history.get(timestamp))) return history except Exception as e: print(f"구글 시트에서 기록을 읽어오는 중 에러: {e}") @@ -710,15 +735,22 @@ async def add_history(data: dict): # 행 높이가 길어지지 않도록 줄바꿈을 띄어쓰기로 변경 preview_text = data.get("previewText", "").replace("\n", " ").replace("\r", "") - + customer_name = first_nonempty(data, "custName", "customer_name", "customerName", "name") + customer_phone = first_nonempty(data, "custPhone", "phone", "customer_phone", "customerPhone") + customer_address = first_nonempty(data, "custAddress", "address", "customer_address", "customerAddress") + row = [ data.get("timestamp", ""), data.get("orderType", ""), data.get("deposit_amount_str", ""), items_str, - preview_text + preview_text, + customer_name, + customer_phone, + customer_address ] - ws.append_row(row, value_input_option='USER_ENTERED') + next_row = len(ws.col_values(1)) + 1 + ws.update(values=[row], range_name=f"A{next_row}:H{next_row}", value_input_option='USER_ENTERED') except Exception as e: print(f"구글 시트 문자내역 기록 실패: {e}") diff --git a/static/js/app.js b/static/js/app.js index bee253f..0be619e 100644 --- a/static/js/app.js +++ b/static/js/app.js @@ -1201,12 +1201,19 @@ document.addEventListener('DOMContentLoaded', () => { }); + const custName = document.getElementById('cust-name').value.trim(); + const custPhone = document.getElementById('cust-phone').value.trim(); + const custAddress = document.getElementById('cust-address').value.trim(); + const histData = { timestamp: stamp, deposit_amount_str: finalPayable.toLocaleString() + "원", - custName: document.getElementById('cust-name').value.trim(), - custPhone: document.getElementById('cust-phone').value.trim(), - custAddress: document.getElementById('cust-address').value.trim(), + custName: custName, + custPhone: custPhone, + custAddress: custAddress, + customer_name: custName, + phone: custPhone, + address: custAddress, orderType: document.querySelector('input[name="order-type"]:checked').value, noLid: document.getElementById('chk-no-lid').checked, items: savedItems, @@ -1224,7 +1231,14 @@ document.addEventListener('DOMContentLoaded', () => { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(histData) - }).then(() => loadSmsHistory()); + }).then(() => { + writeSmsCustomerCache(stamp, { + custName: custName, + custPhone: custPhone, + custAddress: custAddress + }); + loadSmsHistory(); + }); }); @@ -1232,6 +1246,32 @@ document.addEventListener('DOMContentLoaded', () => { // ============================================ // SMS HISTORY // ============================================ + const SMS_CUSTOMER_CACHE_KEY = 'smsCustomerHistoryByTimestamp'; + + function readSmsCustomerCache() { + try { + return JSON.parse(localStorage.getItem(SMS_CUSTOMER_CACHE_KEY) || '{}'); + } catch (e) { + return {}; + } + } + + function writeSmsCustomerCache(timestamp, customer) { + if (!timestamp) return; + const cache = readSmsCustomerCache(); + cache[timestamp] = customer; + localStorage.setItem(SMS_CUSTOMER_CACHE_KEY, JSON.stringify(cache)); + } + + function firstNonEmpty(...values) { + for (const value of values) { + if (value !== undefined && value !== null && String(value).trim() !== '') { + return value; + } + } + return ''; + } + function loadSmsHistory() { const u = document.getElementById('sms-history-list'); u.innerHTML = ''; @@ -1338,9 +1378,13 @@ document.addEventListener('DOMContentLoaded', () => { document.getElementById('btn-reset').click(); - if (d.custName !== undefined) document.getElementById('cust-name').value = d.custName; - if (d.custPhone !== undefined) document.getElementById('cust-phone').value = d.custPhone; - if (d.custAddress !== undefined) document.getElementById('cust-address').value = d.custAddress; + const cachedCustomer = readSmsCustomerCache()[d.timestamp] || {}; + const savedCustName = firstNonEmpty(d.custName, d.customer_name, cachedCustomer.custName, cachedCustomer.customer_name); + const savedCustPhone = firstNonEmpty(d.custPhone, d.phone, cachedCustomer.custPhone, cachedCustomer.phone); + const savedCustAddress = firstNonEmpty(d.custAddress, d.address, cachedCustomer.custAddress, cachedCustomer.address); + document.getElementById('cust-name').value = savedCustName; + document.getElementById('cust-phone').value = savedCustPhone; + document.getElementById('cust-address').value = savedCustAddress; if (d.orderType !== undefined) { const rb = document.querySelector(`input[name="order-type"][value="${d.orderType}"]`); if (rb) rb.checked = true; diff --git a/templates/index.html b/templates/index.html index 2c98abf..24c7c0a 100644 --- a/templates/index.html +++ b/templates/index.html @@ -46,10 +46,10 @@
CS 통합 관리