import sqlite3 import csv from io import StringIO from datetime import datetime, timedelta from flask import Flask, request, render_template_string, redirect, Response, session app = Flask(__name__) app.secret_key = 'super_secret_key_netmarble' DB_PATH = '/home/ajw103/mysite/visitors.db' def get_kst_now(): return datetime.utcnow() + timedelta(hours=9) # ๐Ÿ› ๏ธ 1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ค€๋น„ (๋ฐฉ๋ฌธ๋ชฉ์ , ์ถœ์ฐจ์‹œ๊ฐ„ ์ถ”๊ฐ€!) def init_db(): conn = sqlite3.connect(DB_PATH) c = conn.cursor() c.execute('''CREATE TABLE IF NOT EXISTS visitors (name TEXT, visitor_company TEXT, car_number TEXT, host_info TEXT, purpose TEXT, visit_date TEXT, visit_time TEXT, status TEXT DEFAULT '๋Œ€๊ธฐ์ค‘', parking_time TEXT, entry_time TEXT, exit_time TEXT)''') # ์˜ˆ์ „ ๊ธˆ๊ณ ์— ์—†๋Š” ์นธ ์ž๋™ ์ถ”๊ฐ€ ๋งˆ๋ฒ• new_columns = ['visitor_company', 'host_info', 'purpose', 'visit_date', 'visit_time', 'parking_time', 'entry_time', 'exit_time'] for col in new_columns: try: c.execute(f"ALTER TABLE visitors ADD COLUMN {col} TEXT") except: pass conn.commit() conn.close() init_db() # ๐Ÿ” ๊ด€๋ฆฌ์ž ๋กœ๊ทธ์ธ ํ™”๋ฉด login_html = """

๐Ÿ”’ ๊ด€๋ฆฌ์ž ๋กœ๊ทธ์ธ

{% if error %}

{{ error }}

{% endif %}
""" # ๐Ÿ‘จโ€๐Ÿ’ผ ๋‹ด๋‹น์ž ํ™”๋ฉด staff_html = """

๐Ÿ‘จโ€๐Ÿ’ผ ๋‹ด๋‹น์ž: ๋ฐฉ๋ฌธ๊ฐ ์ดˆ๋Œ€

โžก๏ธ ์ธํฌ๋ฐ์Šคํฌ ๋ชจ๋‹ˆํ„ฐ ๊ฐ€๊ธฐ
""" # ๐Ÿ“ฑ ๋ฐฉ๋ฌธ๊ฐ ํผ ํ™”๋ฉด (๋ฐฉ๋ฌธ ๋ชฉ์  ์ถ”๊ฐ€!) visitor_html = """

๐Ÿข {% if v %}๋ฐฉ๋ฌธ ์ผ์ • ๋ณ€๊ฒฝ{% else %}์‚ฌ์ „ ๋ฐฉ๋ฌธ์‹ ์ฒญ{% endif %}

[๊ฐœ์ธ์ •๋ณด ์ˆ˜์ง‘ ๋ฐ ์ด์šฉ ๋™์˜]
- ์ˆ˜์ง‘ ํ•ญ๋ชฉ: ์„ฑ๋ช…, ์†Œ์†, ์ฐจ๋Ÿ‰๋ฒˆํ˜ธ
- ์ˆ˜์ง‘ ๋ชฉ์ : ๋ฐฉ๋ฌธ๊ฐ ์‹๋ณ„ ๋ฐ ์ฃผ์ฐจ ๋“ฑ๋ก
- ๋ณด์œ  ๊ธฐ๊ฐ„: ๋ฐฉ๋ฌธ ์ข…๋ฃŒ ํ›„ 1๊ฐœ์›” ๋’ค ํŒŒ๊ธฐ
""" # โœ… ์‹ ์ฒญ ์™„๋ฃŒ ํ™”๋ฉด success_html = """

โœ… ๋ฐฉ๋ฌธ ์‹ ์ฒญ์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค

์ž…๋ ฅํ•˜์‹  ์ •๋ณด๋Š” ์•ˆ์ „ํ•˜๊ฒŒ ์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
๋ฐฉ๋ฌธ ๋‹น์ผ ์กฐ์‹ฌํžˆ ์˜ค์„ธ์š”!

โœ๏ธ ๋ฐฉ๋ฌธ ์ผ์ • ๋ณ€๊ฒฝ / ํ™•์ธํ•˜๊ธฐ

๐Ÿ“ ์˜ค์‹œ๋Š” ๊ธธ

๐Ÿข ์„œ์šธ ๊ตฌ๋กœ๊ตฌ ๋””์ง€ํ„ธ๋กœ26๊ธธ 38 ์ง€ํƒ€์›Œ
""" # ๐Ÿข 4. ์ธํฌ๋ฐ์Šคํฌ ํ™”๋ฉด (์ถœ์ฐจ ์‹œ๊ฐ„, ๋ฐฉ๋ฌธ ๋ชฉ์  ์—ด ์ถ”๊ฐ€) desk_html = """

๐Ÿข ๊ด€๋ฆฌ์ž ๋Œ€์‹œ๋ณด๋“œ

๋กœ๊ทธ์•„์›ƒ

| ๐Ÿ”„ ์ดˆ๊ธฐํ™”
๊ฒ€์ƒ‰๋œ ๋ฐฉ๋ฌธ ์˜ˆ์ •๊ฐ: {{ visitor_count }} ๋ช…
{% if visitors %} {% for v in visitors %} {% endfor %} {% else %} {% endif %}
์˜ˆ์ • ์‹œ๊ฐ„์ž…์ฐจ ์‹œ๊ฐ„์ถœ์ฐจ ์‹œ๊ฐ„๋ฐฉ๋ฌธ์ž ์„ฑํ•จ (์†Œ์†)์ฐจ๋Ÿ‰ ๋ฒˆํ˜ธ๋ฐฉ๋ฌธ ๋Œ€์ƒ๋ฐฉ๋ฌธ ๋ชฉ์ ์ƒํƒœ์ฃผ์ฐจ์‹œ๊ฐ„ ๋“ฑ๋ก๊ด€๋ฆฌ
โฐ {{ v['visit_time'] }} {% if not v['entry_time'] %} ์ž…์ฐจ ์ „
{% else %} {{ v['entry_time'] }} {% endif %}
{% if not v['exit_time'] %} ์ถœ์ฐจ ์ „
{% if v['entry_time'] %}
{% endif %} {% else %} {{ v['exit_time'] }} {% endif %}
{{ v['name'] }}
({{ v['visitor_company'] }})
{{ v['car_number'] }} {{ v['host_info'] }} {{ v['purpose'] }} {% if not v['parking_time'] %}๋ฏธ๋“ฑ๋ก {% else %}๋ˆ„์ : {{ v['parking_time'] }}{% endif %}
ํ•ด๋‹น ์กฐ๊ฑด์— ์ผ์น˜ํ•˜๋Š” ๋ฐฉ๋ฌธ๊ฐ์ด ์—†์Šต๋‹ˆ๋‹ค.
๐Ÿ“ฅ ์—‘์…€(CSV) ๋‹ค์šด๋กœ๋“œ

โฌ…๏ธ ๋‹ด๋‹น์ž ํ™”๋ฉด์œผ๋กœ ๋Œ์•„๊ฐ€๊ธฐ
""" # --- ๋ผ์šฐํŒ… (์„œ๋ฒ„ ๊ธฐ๋Šฅ) --- @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': if request.form.get('admin_id') == 'netmarble' and request.form.get('admin_pw') == 'netmarble1!': session['logged_in'] = True return redirect('/desk') return render_template_string(login_html, error="์•„์ด๋”” ๋˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ํ‹€๋ ธ์Šต๋‹ˆ๋‹ค.") return render_template_string(login_html) @app.route('/logout') def logout(): session.pop('logged_in', None) return redirect('/login') @app.route('/') def staff_home(): return staff_html @app.route('/register') def register_form(): return render_template_string(visitor_html, v=None) @app.route('/submit', methods=['POST']) def submit(): conn = sqlite3.connect(DB_PATH) c = conn.cursor() # ๋ฐฉ๋ฌธ ๋ชฉ์ (purpose)์„ ์ €์žฅํ•˜๋Š” ์ฟผ๋ฆฌ๋กœ ์—…๋ฐ์ดํŠธ c.execute("""INSERT INTO visitors (name, visitor_company, car_number, host_info, purpose, visit_date, visit_time) VALUES (?, ?, ?, ?, ?, ?, ?)""", (request.form.get("name"), request.form.get("visitor_company"), request.form.get("car_number"), request.form.get("host_info"), request.form.get("purpose"), request.form.get("visit_date"), request.form.get("visit_time"))) visitor_id = c.lastrowid conn.commit() conn.close() return render_template_string(success_html, visitor_id=visitor_id) @app.route('/edit_visitor/') def edit_visitor(vid): conn = sqlite3.connect(DB_PATH) conn.row_factory = sqlite3.Row c = conn.cursor() c.execute("SELECT rowid, * FROM visitors WHERE rowid = ?", (vid,)) v = c.fetchone() conn.close() return render_template_string(visitor_html, v=v) @app.route('/update_visitor/', methods=['POST']) def update_visitor(vid): conn = sqlite3.connect(DB_PATH) c = conn.cursor() c.execute("""UPDATE visitors SET name=?, visitor_company=?, car_number=?, host_info=?, purpose=?, visit_date=?, visit_time=? WHERE rowid=?""", (request.form.get("name"), request.form.get("visitor_company"), request.form.get("car_number"), request.form.get("host_info"), request.form.get("purpose"), request.form.get("visit_date"), request.form.get("visit_time"), vid)) conn.commit() conn.close() return render_template_string(success_html, visitor_id=vid) @app.route('/desk') def desk(): if not session.get('logged_in'): return redirect('/login') selected_date = request.args.get('date') or get_kst_now().strftime('%Y-%m-%d') search_keyword = request.args.get('search', '') conn = sqlite3.connect(DB_PATH) conn.row_factory = sqlite3.Row c = conn.cursor() if search_keyword: c.execute("SELECT rowid, * FROM visitors WHERE visit_date = ? AND (name LIKE ? OR car_number LIKE ?) ORDER BY visit_time ASC", (selected_date, f"%{search_keyword}%", f"%{search_keyword}%")) else: c.execute("SELECT rowid, * FROM visitors WHERE visit_date = ? ORDER BY visit_time ASC", (selected_date,)) visitor_list = c.fetchall() conn.close() return render_template_string(desk_html, visitors=visitor_list, selected_date=selected_date, search_keyword=search_keyword, visitor_count=len(visitor_list)) @app.route('/delete_visitor', methods=['POST']) def delete_visitor(): if not session.get('logged_in'): return redirect('/login') rowid = request.form.get('rowid') conn = sqlite3.connect(DB_PATH) c = conn.cursor() c.execute("DELETE FROM visitors WHERE rowid = ?", (rowid,)) conn.commit() conn.close() return redirect(f'/desk?date={request.form.get("date")}&search={request.form.get("search")}') # ๐Ÿš€ 5. ์นด๋ฉ”๋ผ๊ฐ€ ์ž…์ฐจ๋ฅผ ์ฐ๋Š” ์‹œ๋ฎฌ๋ ˆ์ด์…˜ @app.route('/simulate_entry', methods=['POST']) def simulate_entry(): if not session.get('logged_in'): return redirect('/login') rowid = request.form.get("rowid") now_time = get_kst_now().strftime('%H:%M') conn = sqlite3.connect(DB_PATH) c = conn.cursor() c.execute("UPDATE visitors SET entry_time = ? WHERE rowid = ?", (now_time, rowid)) conn.commit() conn.close() return redirect(f'/desk?date={request.form.get("date")}&search={request.form.get("search")}') # ๐Ÿš€ 6. ์นด๋ฉ”๋ผ๊ฐ€ ์ถœ์ฐจ๋ฅผ ์ฐ๋Š” ์‹œ๋ฎฌ๋ ˆ์ด์…˜ (์ƒˆ๋กœ ์ถ”๊ฐ€๋จ!) @app.route('/simulate_exit', methods=['POST']) def simulate_exit(): if not session.get('logged_in'): return redirect('/login') rowid = request.form.get("rowid") now_time = get_kst_now().strftime('%H:%M') conn = sqlite3.connect(DB_PATH) c = conn.cursor() c.execute("UPDATE visitors SET exit_time = ? WHERE rowid = ?", (now_time, rowid)) conn.commit() conn.close() return redirect(f'/desk?date={request.form.get("date")}&search={request.form.get("search")}') @app.route('/approve', methods=['POST']) def approve(): if not session.get('logged_in'): return redirect('/login') rowid = request.form.get("rowid") added_time = request.form.get("parking_time") conn = sqlite3.connect(DB_PATH) c = conn.cursor() c.execute("SELECT parking_time FROM visitors WHERE rowid = ?", (rowid,)) result = c.fetchone() current_time = result[0] if result and result[0] else "" new_time = added_time if current_time == "์ข…์ผ๊ถŒ" or added_time == "์ข…์ผ๊ถŒ": new_time = "์ข…์ผ๊ถŒ" elif current_time: try: curr_h = int(current_time.replace('์‹œ๊ฐ„', '')) add_h = int(added_time.replace('์‹œ๊ฐ„', '')) new_time = f"{curr_h + add_h}์‹œ๊ฐ„" except: new_time = added_time c.execute("UPDATE visitors SET status = '์Šน์ธ์™„๋ฃŒ', parking_time = ? WHERE rowid = ?", (new_time, rowid)) conn.commit() conn.close() return redirect(f'/desk?date={request.form.get("date")}&search={request.form.get("search")}') @app.route('/download') def download(): if not session.get('logged_in'): return redirect('/login') selected_date = request.args.get('date') or get_kst_now().strftime('%Y-%m-%d') search_keyword = request.args.get('search', '') conn = sqlite3.connect(DB_PATH) c = conn.cursor() # ์—‘์…€ ๋‹ค์šด๋กœ๋“œ ์ฟผ๋ฆฌ์—๋„ purpose(๋ชฉ์ ), exit_time(์ถœ์ฐจ์‹œ๊ฐ„) ์ถ”๊ฐ€ if search_keyword: c.execute("SELECT visit_time, entry_time, exit_time, name, visitor_company, car_number, host_info, purpose, status, parking_time FROM visitors WHERE visit_date = ? AND (name LIKE ? OR car_number LIKE ?) ORDER BY visit_time ASC", (selected_date, f"%{search_keyword}%", f"%{search_keyword}%")) else: c.execute("SELECT visit_time, entry_time, exit_time, name, visitor_company, car_number, host_info, purpose, status, parking_time FROM visitors WHERE visit_date = ? ORDER BY visit_time ASC", (selected_date,)) rows = c.fetchall() conn.close() si = StringIO() si.write('\ufeff') cw = csv.writer(si) cw.writerow(['๋ฐฉ๋ฌธ ์˜ˆ์ • ์‹œ๊ฐ„', '์ž…์ฐจ ์‹œ๊ฐ„', '์ถœ์ฐจ ์‹œ๊ฐ„', '๋ฐฉ๋ฌธ์ž ์„ฑํ•จ', '์†Œ์†', '์ฐจ๋Ÿ‰ ๋ฒˆํ˜ธ', '๋ฐฉ๋ฌธ ๋Œ€์ƒ', '๋ฐฉ๋ฌธ ๋ชฉ์ ', '์ƒํƒœ', '์ฃผ์ฐจ์‹œ๊ฐ„(๋ˆ„์ )']) cw.writerows(rows) return Response(si.getvalue(), mimetype="text/csv", headers={"Content-Disposition": f"attachment;filename=visitors_{selected_date}.csv"})