protae5544's picture
Update app.py
1ecca81 verified
raw
history blame
23.8 kB
import gradio as gr
import sqlite3
import json
from huggingface_hub import hf_hub_download, upload_file
import os
from pathlib import Path
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import cm
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
import qrcode
import zipfile
import io
from dotenv import load_dotenv
import time
import requests
# อ่าน .env (ถ้ามี)
load_dotenv()
REPO_ID = os.getenv("REPO_ID", "protae5544/WorkerManagement")
ORIGINAL_REPO_ID = os.getenv("ORIGINAL_REPO_ID", None)
# ดาวน์โหลดฟอนต์จาก Space อื่น
def download_fonts():
try:
# ดาวน์โหลดฟอนต์จาก protae5544/worberkit2024poe
font_urls = {
'THSarabunNew.ttf': 'https://huggingface.co/spaces/protae5544/worberkit2024poe/resolve/main/fontCSS/subset-THSarabunNew.woff2',
'THSarabunNew-Bold.ttf': 'https://huggingface.co/spaces/protae5544/worberkit2024poe/resolve/main/fontCSS/subset-THSarabunNew-Bold.woff2'
}
# ใช้ฟอนต์ที่มีอยู่แล้วในระบบ หรือดาวน์โหลดจาก Google Fonts
google_fonts = {
'THSarabunNew.ttf': 'https://fonts.gstatic.com/s/sarabun/v13/DtVjJx26TKEqsc-lWcmw-wKE7wM.ttf',
'THSarabunNew-Bold.ttf': 'https://fonts.gstatic.com/s/sarabun/v13/DtVmJx26TKEqsc-lWcmw5wq0hwOKBwXcb0A.ttf'
}
for filename, url in google_fonts.items():
if not os.path.exists(filename):
try:
response = requests.get(url, timeout=10)
if response.status_code == 200:
with open(filename, 'wb') as f:
f.write(response.content)
print(f"Downloaded font: {filename}")
except Exception as e:
print(f"Error downloading {filename}: {e}")
except Exception as e:
print(f"Error in download_fonts: {e}")
# ตั้งค่าฟอนต์
def setup_fonts():
try:
# ดาวน์โหลดฟอนต์ก่อน
download_fonts()
# ลงทะเบียนฟอนต์
if os.path.exists('THSarabunNew.ttf'):
pdfmetrics.registerFont(TTFont('THSarabun', 'THSarabunNew.ttf'))
print("Registered THSarabun font")
if os.path.exists('THSarabunNew-Bold.ttf'):
pdfmetrics.registerFont(TTFont('THSarabunBold', 'THSarabunNew-Bold.ttf'))
print("Registered THSarabunBold font")
return True
except Exception as e:
print(f"Warning: Could not load fonts: {e}")
return False
# เริ่มต้นฟอนต์
font_available = setup_fonts()
# ฟังก์ชันแปลงวันที่เป็นภาษาไทย
def thai_date_time(timestamp):
months = {
1: "มกราคม", 2: "กุมภาพันธ์", 3: "มีนาคม", 4: "เมษายน",
5: "พฤษภาคม", 6: "มิถุนายน", 7: "กรกฎาคม", 8: "สิงหาคม",
9: "กันยายน", 10: "ตุลาคม", 11: "พฤศจิกายน", 12: "ธันวาคม"
}
dt = time.localtime(timestamp)
day = dt.tm_mday
month = months[dt.tm_mon]
year = dt.tm_year + 543
hour = dt.tm_hour
minute = dt.tm_min
return f"{day:02d} {month} {year} {hour:02d}:{minute:02d} น."
# เริ่มต้นฐานข้อมูล
def init_db():
conn = sqlite3.connect("workers.db")
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS workers (
request_number TEXT PRIMARY KEY,
english_name TEXT,
foreign_reference_number TEXT,
id_number TEXT,
nationality TEXT,
receipt_number TEXT,
payment_number TEXT,
created_at TEXT
)''')
c.execute('''CREATE TABLE IF NOT EXISTS attachments (
request_number TEXT,
file_url TEXT,
FOREIGN KEY(request_number) REFERENCES workers(request_number)
)''')
c.execute('''CREATE TABLE IF NOT EXISTS pdfs (
request_number TEXT,
pdf_url TEXT,
FOREIGN KEY(request_number) REFERENCES workers(request_number)
)''')
conn.commit()
conn.close()
# สำรองฐานข้อมูล
def create_receipt_pdf(request_number, english_name, foreign_reference_number, id_number, nationality, receipt_number, payment_number):
filename = f"pdfs/receipt_{request_number}.pdf"
local_path = f"temp_{request_number}.pdf"
# สร้างโฟลเดอร์ pdfs ถ้าไม่มี
os.makedirs("pdfs", exist_ok=True)
c = canvas.Canvas(local_path, pagesize=A4)
width, height = A4
# กำหนดตำแหน่งและขนาดตามเอกสารต้นฉบับ
# ใช้ Helvetica สำหรับความเข้ากันได้
# หัวเอกสาร - กระทรวงแรงงาน
c.setFont("Helvetica-Bold", 20)
c.drawCentredText(width/2, height-80, "กระทรวงแรงงาน")
c.setFont("Helvetica-Bold", 16)
c.drawCentredText(width/2, height-110, "ใบเสร็จรับเงิน (ต้นฉบับ)")
# ข้อมูลส่วนหัว
c.setFont("Helvetica", 12)
y_pos = height - 150
c.drawString(50, y_pos, f"เลขที่: {receipt_number}")
c.drawString(350, y_pos, "แบบ ภ.1600-034")
y_pos -= 25
c.drawString(50, y_pos, "ที่ทำการ: สำนักบริหารแรงงานต่างด้าว")
y_pos -= 25
c.drawString(50, y_pos, "วันที่: 01 เมษายน 2568")
y_pos -= 25
c.drawString(50, y_pos, f"เลขที่ใบชำระเงิน: {payment_number}")
y_pos -= 25
c.drawString(50, y_pos, f"เลขรับคำขอที่: {request_number}")
# ข้อมูลผู้ชำระเงิน
y_pos -= 40
c.setFont("Helvetica-Bold", 12)
c.drawString(50, y_pos, "ข้อมูลผู้ชำระเงิน:")
y_pos -= 25
c.setFont("Helvetica", 12)
c.drawString(50, y_pos, f"ชื่อผู้ชำระเงิน: {english_name}")
y_pos -= 20
c.drawString(50, y_pos, f"สัญชาติ: {nationality}")
y_pos -= 20
c.drawString(50, y_pos, f"เลขอ้างอิงคนต่างด้าว: {foreign_reference_number}")
y_pos -= 20
c.drawString(50, y_pos, f"หมายเลขประจำตัวคนต่างด้าว: {id_number}")
# ข้อมูลนายจ้าง
y_pos -= 40
c.setFont("Helvetica-Bold", 12)
c.drawString(50, y_pos, "ข้อมูลนายจ้าง:")
y_pos -= 25
c.setFont("Helvetica", 12)
c.drawString(50, y_pos, "ชื่อนายจ้าง/สถานประกอบการ: บริษัท บาน กง เอ็นจิเนียริ่ง จำกัด")
y_pos -= 20
c.drawString(50, y_pos, "เลขประจำตัวนายจ้าง: 0415567000061")
# รายการค่าธรรมเนียม
y_pos -= 40
c.setFont("Helvetica-Bold", 14)
c.drawString(50, y_pos, "รายการค่าธรรมเนียม")
# วาดเส้นใต้หัวข้อ
c.line(50, y_pos-5, 500, y_pos-5)
y_pos -= 30
c.setFont("Helvetica", 12)
c.drawString(70, y_pos, "1. ค่าธรรมเนียมในการยื่นคำขอ ฉบับละ 100 บาท")
c.drawString(450, y_pos, "100.00")
y_pos -= 25
c.drawString(70, y_pos, "2. ค่าธรรมเนียมการพิจารณา")
c.drawString(450, y_pos, "900.00")
# เส้นคั่น
y_pos -= 15
c.line(400, y_pos, 500, y_pos)
y_pos -= 25
c.setFont("Helvetica-Bold", 12)
c.drawString(70, y_pos, "รวมเป็นเงินทั้งสิ้น (บาท): (หนึ่งพันบาทถ้วน)")
c.drawString(430, y_pos, "1,000.00")
# เส้นใต้ยอดรวม
c.line(400, y_pos-5, 500, y_pos-5)
c.line(400, y_pos-8, 500, y_pos-8)
# ข้อความรับรอง
y_pos -= 40
c.setFont("Helvetica", 12)
c.drawString(50, y_pos, "ได้รับเงินไว้เป็นการถูกต้องแล้ว")
# ลายเซ็น
y_pos -= 60
c.drawString(300, y_pos, "(ลงชื่อ) นางสาวอารีวรรณ โพธิ์นิ่มแดง")
c.drawString(350, y_pos-20, "(ผู้รับเงิน)")
y_pos -= 45
c.drawString(300, y_pos, "ตำแหน่ง: นักวิชาการแรงงานชำนาญการ")
# QR Code ที่มุมขวาล่าง
pdf_url = f"https://huggingface.co/spaces/{REPO_ID}/resolve/main/{filename}"
try:
qr = qrcode.QRCode(version=1, box_size=8, border=2)
qr.add_data(pdf_url)
qr.make(fit=True)
qr_img = qr.make_image(fill_color="black", back_color="white")
qr_img.save("temp_qr.png")
c.drawImage("temp_qr.png", width-150, 50, width=80, height=80)
except Exception as e:
print(f"Error creating QR code: {e}")
# Timestamp ที่ด้านล่าง
c.setFont("Helvetica", 8)
print_time = thai_date_time(time.time())
c.drawString(50, 30, f"พิมพ์เมื่อ: {print_time}")
# เส้นขอบกรอบเอกสาร
c.rect(30, 30, width-60, height-60, stroke=1, fill=0)
c.showPage()
c.save()
# เพิ่ม HTML version สำหรับ preview และ print
create_html_receipt(request_number, english_name, foreign_reference_number,
id_number, nationality, receipt_number, payment_number)
# อัพโหลด PDF
try:
upload_file(
path_or_fileobj=local_path,
path_in_repo=filename,
repo_id=REPO_ID,
repo_type="space"
)
print(f"PDF uploaded successfully: {filename}")
except Exception as e:
print(f"Error uploading PDF: {e}")
return None
# บันทึกข้อมูล PDF ในฐานข้อมูล
conn = sqlite3.connect("workers.db")
cursor = conn.cursor()
cursor.execute("INSERT OR REPLACE INTO pdfs (request_number, pdf_url) VALUES (?, ?)",
(request_number, pdf_url))
conn.commit()
conn.close()
return pdf_url
# เพิ่มฟังก์ชันสร้าง HTML version
def create_html_receipt(request_number, english_name, foreign_reference_number, id_number, nationality, receipt_number, payment_number):
html_filename = f"receipts/receipt_{request_number}.html"
local_html_path = f"temp_{request_number}.html"
os.makedirs("receipts", exist_ok=True)
pdf_url = f"https://huggingface.co/spaces/{REPO_ID}/resolve/main/pdfs/receipt_{request_number}.pdf"
print_time = thai_date_time(time.time())
html_content = f"""
<!DOCTYPE html>
<html lang="th">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ใบเสร็จรับเงิน - {request_number}</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/qrcode.min.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Sarabun:wght@400;600;700&display=swap');
* {{
margin: 0;
padding: 0;
box-sizing: border-box;
}}
body {{
font-family: 'Sarabun', Arial, sans-serif;
background: #f5f5f5;
padding: 20px;
}}
.receipt-container {{
max-width: 800px;
margin: 0 auto;
background: white;
border: 2px solid #000;
padding: 30px;
box-shadow: 0 0 20px rgba(0,0,0,0.1);
}}
.header {{
text-align: center;
margin-bottom: 30px;
border-bottom: 2px solid #000;
padding-bottom: 20px;
}}
.header h1 {{
font-size: 24px;
font-weight: 700;
margin-bottom: 10px;
}}
.header h2 {{
font-size: 18px;
font-weight: 600;
}}
.info-section {{
margin-bottom: 25px;
}}
.info-row {{
display: flex;
justify-content: space-between;
margin-bottom: 8px;
padding: 5px 0;
}}
.info-label {{
font-weight: 600;
}}
.section-title {{
font-size: 16px;
font-weight: 700;
margin: 20px 0 15px 0;
border-bottom: 1px solid #ccc;
padding-bottom: 5px;
}}
.fee-table {{
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}}
.fee-table th,
.fee-table td {{
border: 1px solid #000;
padding: 10px;
text-align: left;
}}
.fee-table th {{
background: #f0f0f0;
font-weight: 700;
}}
.amount {{
text-align: right;
font-weight: 600;
}}
.total-row {{
background: #f9f9f9;
font-weight: 700;
}}
.signature-section {{
margin-top: 40px;
display: flex;
justify-content: space-between;
align-items: flex-end;
}}
.signature-box {{
text-align: center;
}}
.qr-section {{
display: flex;
flex-direction: column;
align-items: center;
}}
.footer {{
margin-top: 30px;
text-align: center;
font-size: 12px;
color: #666;
border-top: 1px solid #ccc;
padding-top: 15px;
}}
.download-section {{
text-align: center;
margin: 20px 0;
padding: 15px;
background: #e3f2fd;
border-radius: 8px;
border: 1px solid #2196f3;
}}
.download-btn {{
background: #2196f3;
color: white;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
margin: 5px;
text-decoration: none;
display: inline-block;
}}
.download-btn:hover {{
background: #1976d2;
}}
/* Print Styles */
@media print {{
body {{
background: white;
padding: 0;
}}
.receipt-container {{
box-shadow: none;
border: 2px solid #000;
max-width: none;
width: 100%;
}}
.download-section {{
display: none;
}}
.no-print {{
display: none;
}}
/* ปรับขนาดสำหรับการพิมพ์ */
.header h1 {{
font-size: 22px;
}}
.header h2 {{
font-size: 16px;
}}
.info-row {{
font-size: 14px;
}}
.fee-table {{
font-size: 14px;
}}
}}
@page {{
margin: 1cm;
size: A4;
}}
</style>
</head>
<body>
<div class="receipt-container">
<!-- Header -->
<div class="header">
<h1>กระทรวงแรงงาน</h1>
<h2>ใบเสร็จรับเงิน (ต้นฉบับ)</h2>
</div>
<!-- Download Section (ไม่แสดงเวลาพิมพ์) -->
<div class="download-section no-print">
<h3>🔗 ดาวน์โหลดเอกสาร</h3>
<a href="{pdf_url}" class="download-btn" target="_blank">📄 ดาวน์โหลด PDF</a>
<button onclick="window.print()" class="download-btn">🖨️ พิมพ์เอกสาร</button>
</div>
<!-- Receipt Info -->
<div class="info-section">
<div class="info-row">
<span class="info-label">เลขที่:</span>
<span>{receipt_number}</span>
<span class="info-label">แบบ ภ.1600-034</span>
</div>
<div class="info-row">
<span class="info-label">ที่ทำการ:</span>
<span>สำนักบริหารแรงงานต่างด้าว</span>
</div>
<div class="info-row">
<span class="info-label">วันที่:</span>
<span>01 เมษายน 2568</span>
</div>
<div class="info-row">
<span class="info-label">เลขที่ใบชำระเงิน:</span>
<span>{payment_number}</span>
</div>
<div class="info-row">
<span class="info-label">เลขรับคำขอที่:</span>
<span>{request_number}</span>
</div>
</div>
<!-- Payer Info -->
<div class="section-title">ข้อมูลผู้ชำระเงิน</div>
<div class="info-section">
<div class="info-row">
<span class="info-label">ชื่อผู้ชำระเงิน:</span>
<span>{english_name}</span>
</div>
<div class="info-row">
<span class="info-label">สัญชาติ:</span>
<span>{nationality}</span>
</div>
<div class="info-row">
<span class="info-label">เลขอ้างอิงคนต่างด้าว:</span>
<span>{foreign_reference_number}</span>
</div>
<div class="info-row">
<span class="info-label">หมายเลขประจำตัวคนต่างด้าว:</span>
<span>{id_number}</span>
</div>
</div>
<!-- Employer Info -->
<div class="section-title">ข้อมูลนายจ้าง</div>
<div class="info-section">
<div class="info-row">
<span class="info-label">ชื่อนายจ้าง/สถานประกอบการ:</span>
<span>บริษัท บาน กง เอ็นจิเนียริ่ง จำกัด</span>
</div>
<div class="info-row">
<span class="info-label">เลขประจำตัวนายจ้าง:</span>
<span>0415567000061</span>
</div>
</div>
<!-- Fee Table -->
<div class="section-title">รายการค่าธรรมเนียม</div>
<table class="fee-table">
<thead>
<tr>
<th>รายการ</th>
<th class="amount">จำนวนเงิน (บาท)</th>
</tr>
</thead>
<tbody>
<tr>
<td>1. ค่าธรรมเนียมในการยื่นคำขอ ฉบับละ 100 บาท</td>
<td class="amount">100.00</td>
</tr>
<tr>
<td>2. ค่าธรรมเนียมการพิจารณา</td>
<td class="amount">900.00</td>
</tr>
<tr class="total-row">
<td><strong>รวมเป็นเงินทั้งสิ้น (บาท): (หนึ่งพันบาทถ้วน)</strong></td>
<td class="amount"><strong>1,000.00</strong></td>
</tr>
</tbody>
</table>
<div style="margin: 20px 0; font-weight: 600;">
ได้รับเงินไว้เป็นการถูกต้องแล้ว
</div>
<!-- Signature Section -->
<div class="signature-section">
<div class="signature-box">
<div style="margin-bottom: 50px;">_______________________</div>
<div>(ลงชื่อ) นางสาวอารีวรรณ โพธิ์นิ่มแดง</div>
<div>(ผู้รับเงิน)</div>
<div style="margin-top: 10px;">ตำแหน่ง: นักวิชาการแรงงานชำนาญการ</div>
</div>
<div class="qr-section">
<div id="qrcode"></div>
<div style="font-size: 12px; margin-top: 5px;">สแกนเพื่อตรวจสอบ</div>
</div>
</div>
<!-- Footer -->
<div class="footer">
<div>พิมพ์เมื่อ: {print_time}</div>
<div style="margin-top: 5px;">เอกสารนี้ออกโดยระบบอัตโนมัติ - บริษัท บาน กง เอ็นจิเนียริ่ง จำกัด</div>
</div>
</div>
<script>
// สร้าง QR Code
QRCode.toCanvas(document.getElementById('qrcode'), '{pdf_url}', {{
width: 80,
height: 80,
margin: 1,
color: {{
dark: '#000000',
light: '#FFFFFF'
}}
}}, function (error) {{
if (error) console.error(error);
console.log('QR Code generated successfully!');
}});
// Auto-focus สำหรับการพิมพ์
window.addEventListener('load', function() {{
console.log('Receipt loaded successfully');
}});
</script>
</body>
</html>
"""
# บันทึกไฟล์ HTML
with open(local_html_path, 'w', encoding='utf-8') as f:
f.write(html_content)
# อัพโหลด HTML
try:
upload_file(
path_or_fileobj=local_html_path,
path_in_repo=html_filename,
repo_id=REPO_ID,
repo_type="space"
)
print(f"HTML uploaded successfully: {html_filename}")
except Exception as e:
print(f"Error uploading HTML: {e}")