feat: invoice_fetcher

setting DB connection
This commit is contained in:
2026-03-18 01:44:24 +08:00
parent c4f64bed75
commit 73ec39daa6

View File

@@ -30,6 +30,17 @@ EINVOICE_USER = os.getenv("EINVOICE_USER")
EINVOICE_PASS = os.getenv("EINVOICE_PASS") EINVOICE_PASS = os.getenv("EINVOICE_PASS")
GROQ_API_KEY = os.getenv("GROQ_API_KEY") GROQ_API_KEY = os.getenv("GROQ_API_KEY")
MY_USER_ID = os.getenv("LINE_USER_ID") MY_USER_ID = os.getenv("LINE_USER_ID")
DB_HOST = os.getenv("DB_HOST")
DB_NAME = os.getenv("DB_NAME")
DB_USER = os.getenv("DB_USER")
DB_PASSWORD = os.getenv("DB_PASSWORD")
DB_CONFIG = {
"host": DB_HOST,
"database": DB_NAME,
"user": DB_USER,
"password": DB_PASSWORD
}
cloudinary.config( cloudinary.config(
cloud_name=os.getenv("CLOUDINARY_CLOUD_NAME"), cloud_name=os.getenv("CLOUDINARY_CLOUD_NAME"),
@@ -38,19 +49,20 @@ cloudinary.config(
) )
# 本地直接連 localhost # 本地直接連 localhost
# DATABASE_URL = os.getenv("LOCAL_DATABASE_URL") DATABASE_URL = f"postgresql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}/{DB_NAME}"
# engine = create_engine(DATABASE_URL) engine = create_engine(DATABASE_URL)
# SessionLocal = sessionmaker(bind=engine) SessionLocal = sessionmaker(bind=engine)
Base = declarative_base() Base = declarative_base()
# class Transaction(Base): class Transaction(Base):
# __tablename__ = "transactions" __tablename__ = "transactions"
# id = Column(Integer, primary_key=True, index=True) id = Column(Integer, primary_key=True)
# user_id = Column(String) date = Column(DateTime, nullable=False)
# category = Column(String) description = Column(String)
# amount = Column(Float) amount = Column(Float, nullable=False)
# note = Column(String, nullable=True) category = Column(String)
# created_at = Column(DateTime, default=datetime.now) invoice_number = Column(String, unique=True)
created_at = Column(DateTime, server_default=text("CURRENT_TIMESTAMP"))
async def solve_captcha(img_b64: str) -> str: async def solve_captcha(img_b64: str) -> str:
@@ -267,41 +279,44 @@ async def fetch_invoices(token: str, days: int = 7) -> list:
return invoice_list return invoice_list
def save_invoices(invoices: list): def save_invoices(invoices: list):
# db = SessionLocal() db = SessionLocal()
saved = 0 saved = 0
skipped = 0
try: try:
for inv in invoices: for inv in invoices:
inv_date = inv.get("invoiceDate", "未知日期") inv_num = inv.get("invoiceNumber")
# 檢查是否已存在 (避免重複)
existing = db.query(Transaction).filter(Transaction.invoice_number == inv_num).first()
if existing:
skipped += 1
continue
# 簡單分類
seller = inv.get("sellerName", "未知店家") seller = inv.get("sellerName", "未知店家")
amount = inv.get("totalAmount", 0) category = "其他"
inv_num = inv.get("invoiceNumber", "無號碼") if "統一超商" in seller or "全家" in seller: category = "餐飲/超商"
# existing = db.query(Transaction).filter( elif "和德昌" in seller: category = "外食"
# Transaction.note == inv["invoiceNumber"]
# ).first() # 建立新資料列
# if existing: new_inv = Transaction(
# continue date=datetime.fromtimestamp(inv.get("invoiceDate") / 1000),
# db.add(Transaction( description=seller,
# user_id="auto_import", amount=float(inv.get("totalAmount", 0)),
# category=inv["sellerName"], category=category,
# amount=inv["totalAmount"], invoice_number=inv_num
# note=inv["invoiceNumber"], )
# created_at=datetime.fromisoformat( db.add(new_inv)
# inv["invoiceDate"].replace("Z", "+00:00")
# )
# ))
# 美化輸出格式
print(f"新增發票 | 日期: {inv_date[:10]} | 店家: {seller[:15]:<15} | 金額: {amount:>6} | 號碼: {inv_num}")
saved += 1 saved += 1
# db.commit()
db.commit()
print("-" * 30) print("-" * 30)
print(f"模擬處理完成:預計新增 {saved} 筆,總計來源 {len(invoices)}") print(f"存入完成:新增 {saved} 筆,略過 {skipped} 筆 (已存在)總計來源 {len(invoices)}")
except Exception as e: except Exception as e:
print("❌ 儲存發票失敗:", e) print("❌ 儲存發票至資料庫失敗:", e)
if 'inv' in locals(): db.rollback()
print(f"錯誤發票內容: {inv}") finally:
# db.rollback() db.close()
# finally:
# db.close()
async def main(): async def main():
print("開始抓取發票...") print("開始抓取發票...")