1223
This commit is contained in:
342
database.py
Normal file
342
database.py
Normal file
@@ -0,0 +1,342 @@
|
||||
"""
|
||||
数据库连接和初始化模块
|
||||
"""
|
||||
|
||||
import sqlite3
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def get_db_connection(db_path):
|
||||
"""获取数据库连接"""
|
||||
return sqlite3.connect(db_path, timeout=30)
|
||||
|
||||
|
||||
class DatabaseManager:
|
||||
"""数据库管理类"""
|
||||
|
||||
def __init__(self, db_path):
|
||||
self.db_path = db_path
|
||||
self.init_db()
|
||||
|
||||
def get_conn(self):
|
||||
"""获取数据库连接"""
|
||||
return get_db_connection(self.db_path)
|
||||
|
||||
def init_db(self):
|
||||
"""初始化数据库表结构"""
|
||||
try:
|
||||
with self.get_conn() as conn:
|
||||
# 原料表
|
||||
conn.execute('''
|
||||
CREATE TABLE IF NOT EXISTS fabrics (
|
||||
model TEXT PRIMARY KEY,
|
||||
category TEXT DEFAULT '未分类',
|
||||
supplier TEXT,
|
||||
color TEXT,
|
||||
width REAL,
|
||||
gsm REAL,
|
||||
retail_price REAL,
|
||||
bulk_price REAL,
|
||||
unit TEXT DEFAULT '米',
|
||||
timestamp TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
''')
|
||||
|
||||
# 为fabrics表添加索引
|
||||
conn.execute('CREATE INDEX IF NOT EXISTS idx_fabrics_category ON fabrics(category)')
|
||||
conn.execute('CREATE INDEX IF NOT EXISTS idx_fabrics_supplier ON fabrics(supplier)')
|
||||
|
||||
# 衣服款号表
|
||||
conn.execute('''
|
||||
CREATE TABLE IF NOT EXISTS garments (
|
||||
style_number TEXT PRIMARY KEY,
|
||||
image_path TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
''')
|
||||
|
||||
# 衣服材料用量表
|
||||
conn.execute('''
|
||||
CREATE TABLE IF NOT EXISTS garment_materials (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
style_number TEXT,
|
||||
category TEXT,
|
||||
fabric_type TEXT,
|
||||
usage_per_piece REAL,
|
||||
unit TEXT DEFAULT '米',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (style_number) REFERENCES garments(style_number)
|
||||
)
|
||||
''')
|
||||
|
||||
# 为garment_materials表添加索引
|
||||
conn.execute('CREATE INDEX IF NOT EXISTS idx_garment_materials_style ON garment_materials(style_number)')
|
||||
conn.execute('CREATE INDEX IF NOT EXISTS idx_garment_materials_category ON garment_materials(category)')
|
||||
|
||||
# 添加新字段(如果不存在)
|
||||
try:
|
||||
conn.execute("ALTER TABLE garment_materials ADD COLUMN fabric_type TEXT")
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
conn.execute("ALTER TABLE fabrics ADD COLUMN created_at DATETIME DEFAULT CURRENT_TIMESTAMP")
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
conn.execute("ALTER TABLE fabrics ADD COLUMN updated_at DATETIME DEFAULT CURRENT_TIMESTAMP")
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
conn.execute("ALTER TABLE garments ADD COLUMN created_at DATETIME DEFAULT CURRENT_TIMESTAMP")
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
conn.execute("ALTER TABLE garments ADD COLUMN updated_at DATETIME DEFAULT CURRENT_TIMESTAMP")
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
conn.execute("ALTER TABLE garment_materials ADD COLUMN created_at DATETIME DEFAULT CURRENT_TIMESTAMP")
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
conn.execute("ALTER TABLE garment_materials ADD COLUMN updated_at DATETIME DEFAULT CURRENT_TIMESTAMP")
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
conn.execute("ALTER TABLE admin_settings ADD COLUMN created_at DATETIME DEFAULT CURRENT_TIMESTAMP")
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
conn.execute("ALTER TABLE admin_settings ADD COLUMN updated_at DATETIME DEFAULT CURRENT_TIMESTAMP")
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
conn.execute("ALTER TABLE fabric_stock_in ADD COLUMN created_at DATETIME DEFAULT CURRENT_TIMESTAMP")
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
conn.execute("ALTER TABLE fabric_stock_in ADD COLUMN updated_at DATETIME DEFAULT CURRENT_TIMESTAMP")
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
conn.execute("ALTER TABLE fabric_consumption ADD COLUMN created_at DATETIME DEFAULT CURRENT_TIMESTAMP")
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
conn.execute("ALTER TABLE fabric_consumption ADD COLUMN updated_at DATETIME DEFAULT CURRENT_TIMESTAMP")
|
||||
except:
|
||||
pass
|
||||
|
||||
# 管理员设置表
|
||||
conn.execute('''
|
||||
CREATE TABLE IF NOT EXISTS admin_settings (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
''')
|
||||
|
||||
# 原料入库表
|
||||
conn.execute('''
|
||||
CREATE TABLE IF NOT EXISTS fabric_stock_in (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
model TEXT,
|
||||
quantity REAL,
|
||||
unit TEXT,
|
||||
purchase_date TEXT,
|
||||
note TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (model) REFERENCES fabrics(model)
|
||||
)
|
||||
''')
|
||||
|
||||
# 为fabric_stock_in表添加索引
|
||||
conn.execute('CREATE INDEX IF NOT EXISTS idx_fabric_stock_in_model ON fabric_stock_in(model)')
|
||||
conn.execute('CREATE INDEX IF NOT EXISTS idx_fabric_stock_in_date ON fabric_stock_in(purchase_date)')
|
||||
|
||||
# 原料消耗表
|
||||
conn.execute('''
|
||||
CREATE TABLE IF NOT EXISTS fabric_consumption (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
style_number TEXT,
|
||||
model TEXT,
|
||||
single_usage REAL,
|
||||
quantity_made INTEGER,
|
||||
loss_rate REAL,
|
||||
consume_quantity REAL,
|
||||
consume_date TEXT,
|
||||
unit TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (style_number) REFERENCES garments(style_number),
|
||||
FOREIGN KEY (model) REFERENCES fabrics(model)
|
||||
)
|
||||
''')
|
||||
|
||||
# 为fabric_consumption表添加索引
|
||||
conn.execute('CREATE INDEX IF NOT EXISTS idx_fabric_consumption_style ON fabric_consumption(style_number)')
|
||||
conn.execute('CREATE INDEX IF NOT EXISTS idx_fabric_consumption_model ON fabric_consumption(model)')
|
||||
conn.execute('CREATE INDEX IF NOT EXISTS idx_fabric_consumption_date ON fabric_consumption(consume_date)')
|
||||
|
||||
# 添加库存计算视图
|
||||
conn.execute('''
|
||||
CREATE VIEW IF NOT EXISTS fabric_stock_view AS
|
||||
SELECT
|
||||
f.model,
|
||||
f.category,
|
||||
f.supplier,
|
||||
f.color,
|
||||
f.unit,
|
||||
COALESCE(stock_in.total_in, 0) as total_stock_in,
|
||||
COALESCE(consumption.total_consumed, 0) as total_consumed,
|
||||
COALESCE(stock_in.total_in, 0) - COALESCE(consumption.total_consumed, 0) as current_stock
|
||||
FROM fabrics f
|
||||
LEFT JOIN (
|
||||
SELECT model, SUM(quantity) as total_in
|
||||
FROM fabric_stock_in
|
||||
GROUP BY model
|
||||
) stock_in ON f.model = stock_in.model
|
||||
LEFT JOIN (
|
||||
SELECT model, SUM(consume_quantity) as total_consumed
|
||||
FROM fabric_consumption
|
||||
GROUP BY model
|
||||
) consumption ON f.model = consumption.model
|
||||
''')
|
||||
|
||||
# 初始化默认密码
|
||||
if not self.get_setting("admin_password"):
|
||||
conn.execute("INSERT INTO admin_settings (key, value) VALUES ('admin_password', ?)", ("123456",))
|
||||
if not self.get_setting("user_password"):
|
||||
conn.execute("INSERT INTO admin_settings (key, value) VALUES ('user_password', ?)", ("123456",))
|
||||
|
||||
conn.commit()
|
||||
except Exception as e:
|
||||
raise Exception(f"无法初始化数据库:{str(e)}")
|
||||
|
||||
def get_setting(self, key):
|
||||
"""获取设置值"""
|
||||
try:
|
||||
with self.get_conn() as conn:
|
||||
cursor = conn.execute("SELECT value FROM admin_settings WHERE key = ?", (key,))
|
||||
row = cursor.fetchone()
|
||||
return row[0] if row else None
|
||||
except:
|
||||
return None
|
||||
|
||||
def set_setting(self, key, value):
|
||||
"""设置配置值"""
|
||||
try:
|
||||
with self.get_conn() as conn:
|
||||
conn.execute("INSERT OR REPLACE INTO admin_settings (key, value) VALUES (?, ?)", (key, value))
|
||||
conn.commit()
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def get_fabric_categories(db_path):
|
||||
"""获取所有面料类目"""
|
||||
try:
|
||||
with get_db_connection(db_path) as conn:
|
||||
cursor = conn.execute("""
|
||||
SELECT DISTINCT
|
||||
CASE
|
||||
WHEN category LIKE '%-%' THEN SUBSTR(category, 1, INSTR(category, '-') - 1)
|
||||
ELSE category
|
||||
END as major_category
|
||||
FROM fabrics
|
||||
WHERE category IS NOT NULL AND category != ''
|
||||
ORDER BY major_category
|
||||
""")
|
||||
categories = set()
|
||||
for row in cursor.fetchall():
|
||||
if row[0] and row[0].strip():
|
||||
categories.add(row[0])
|
||||
|
||||
# 添加默认类目
|
||||
categories.update(["布料", "辅料", "其他"])
|
||||
return sorted(categories)
|
||||
except:
|
||||
return ["布料", "辅料", "其他"]
|
||||
|
||||
|
||||
def get_fabric_types_by_category(db_path, category):
|
||||
"""根据类目获取面料类型"""
|
||||
try:
|
||||
with get_db_connection(db_path) as conn:
|
||||
cursor = conn.execute("""
|
||||
SELECT DISTINCT
|
||||
CASE
|
||||
WHEN category LIKE '%-%' THEN SUBSTR(category, INSTR(category, '-') + 1)
|
||||
ELSE '默认类型'
|
||||
END as fabric_type
|
||||
FROM fabrics
|
||||
WHERE category LIKE ? OR category = ?
|
||||
ORDER BY fabric_type
|
||||
""", (f"{category}-%", category))
|
||||
|
||||
types = []
|
||||
for row in cursor.fetchall():
|
||||
if row[0] and row[0] != '默认类型':
|
||||
types.append(row[0])
|
||||
return types
|
||||
except:
|
||||
return []
|
||||
|
||||
|
||||
def get_fabric_models_by_category_type(db_path, category, fabric_type):
|
||||
"""根据类目和类型获取面料型号"""
|
||||
try:
|
||||
with get_db_connection(db_path) as conn:
|
||||
cursor = conn.execute("""
|
||||
SELECT model, color, unit
|
||||
FROM fabrics
|
||||
WHERE category = ? OR category = ? OR category LIKE ?
|
||||
ORDER BY model
|
||||
""", (category, f"{category}-{fabric_type}", f"{category}-{fabric_type}-%"))
|
||||
|
||||
models = []
|
||||
for row in cursor.fetchall():
|
||||
model, color, unit = row
|
||||
display_text = model
|
||||
if color and color.strip():
|
||||
display_text = f"{model}-{color}"
|
||||
models.append((display_text, model, unit))
|
||||
return models
|
||||
except:
|
||||
return []
|
||||
|
||||
|
||||
def get_password(db_path, password_type):
|
||||
"""获取密码设置"""
|
||||
try:
|
||||
with get_db_connection(db_path) as conn:
|
||||
cursor = conn.execute(
|
||||
"SELECT value FROM admin_settings WHERE key = ?",
|
||||
(f"{password_type}_password",)
|
||||
)
|
||||
row = cursor.fetchone()
|
||||
return row[0] if row else "123456"
|
||||
except:
|
||||
return "123456"
|
||||
|
||||
|
||||
def update_password(db_path, password_type, new_password):
|
||||
"""更新密码"""
|
||||
try:
|
||||
with get_db_connection(db_path) as conn:
|
||||
conn.execute(
|
||||
"UPDATE admin_settings SET value = ?, updated_at = CURRENT_TIMESTAMP WHERE key = ?",
|
||||
(new_password, f"{password_type}_password")
|
||||
)
|
||||
conn.commit()
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
Reference in New Issue
Block a user