实现原料逻辑删除功能
- 为fabrics表添加is_deleted字段用于标记删除状态 - 修改delete_raw方法实现逻辑删除而非物理删除 - 更新所有查询语句过滤已删除的原料数据 - 更新库存视图过滤已删除的原料和相关记录 - 保留历史数据,支持数据恢复 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
26
database.py
26
database.py
@@ -145,6 +145,10 @@ class DatabaseManager:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
# 添加逻辑删除字段
|
# 添加逻辑删除字段
|
||||||
|
try:
|
||||||
|
conn.execute("ALTER TABLE fabrics ADD COLUMN is_deleted INTEGER DEFAULT 0")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
try:
|
try:
|
||||||
conn.execute("ALTER TABLE fabric_stock_in ADD COLUMN is_deleted INTEGER DEFAULT 0")
|
conn.execute("ALTER TABLE fabric_stock_in ADD COLUMN is_deleted INTEGER DEFAULT 0")
|
||||||
except:
|
except:
|
||||||
@@ -223,9 +227,10 @@ class DatabaseManager:
|
|||||||
conn.execute('CREATE INDEX IF NOT EXISTS idx_fabric_consumption_date ON fabric_consumption(consume_date)')
|
conn.execute('CREATE INDEX IF NOT EXISTS idx_fabric_consumption_date ON fabric_consumption(consume_date)')
|
||||||
|
|
||||||
# 添加库存计算视图
|
# 添加库存计算视图
|
||||||
|
conn.execute('DROP VIEW IF EXISTS fabric_stock_view')
|
||||||
conn.execute('''
|
conn.execute('''
|
||||||
CREATE VIEW IF NOT EXISTS fabric_stock_view AS
|
CREATE VIEW fabric_stock_view AS
|
||||||
SELECT
|
SELECT
|
||||||
f.model,
|
f.model,
|
||||||
f.category,
|
f.category,
|
||||||
f.supplier,
|
f.supplier,
|
||||||
@@ -238,13 +243,16 @@ class DatabaseManager:
|
|||||||
LEFT JOIN (
|
LEFT JOIN (
|
||||||
SELECT model, SUM(quantity) as total_in
|
SELECT model, SUM(quantity) as total_in
|
||||||
FROM fabric_stock_in
|
FROM fabric_stock_in
|
||||||
|
WHERE is_deleted IS NULL OR is_deleted = 0
|
||||||
GROUP BY model
|
GROUP BY model
|
||||||
) stock_in ON f.model = stock_in.model
|
) stock_in ON f.model = stock_in.model
|
||||||
LEFT JOIN (
|
LEFT JOIN (
|
||||||
SELECT model, SUM(consume_quantity) as total_consumed
|
SELECT model, SUM(consume_quantity) as total_consumed
|
||||||
FROM fabric_consumption
|
FROM fabric_consumption
|
||||||
|
WHERE is_deleted IS NULL OR is_deleted = 0
|
||||||
GROUP BY model
|
GROUP BY model
|
||||||
) consumption ON f.model = consumption.model
|
) consumption ON f.model = consumption.model
|
||||||
|
WHERE f.is_deleted IS NULL OR f.is_deleted = 0
|
||||||
''')
|
''')
|
||||||
|
|
||||||
# 初始化默认密码
|
# 初始化默认密码
|
||||||
@@ -284,8 +292,8 @@ def get_fabric_categories(db_path):
|
|||||||
with get_db_connection(db_path) as conn:
|
with get_db_connection(db_path) as conn:
|
||||||
cursor = conn.execute("""
|
cursor = conn.execute("""
|
||||||
SELECT DISTINCT category
|
SELECT DISTINCT category
|
||||||
FROM fabrics
|
FROM fabrics
|
||||||
WHERE category IS NOT NULL AND category != ''
|
WHERE category IS NOT NULL AND category != '' AND (is_deleted IS NULL OR is_deleted = 0)
|
||||||
ORDER BY category
|
ORDER BY category
|
||||||
""")
|
""")
|
||||||
categories = set()
|
categories = set()
|
||||||
@@ -306,8 +314,8 @@ def get_fabric_types_by_category(db_path, category):
|
|||||||
with get_db_connection(db_path) as conn:
|
with get_db_connection(db_path) as conn:
|
||||||
cursor = conn.execute("""
|
cursor = conn.execute("""
|
||||||
SELECT DISTINCT fabric_type
|
SELECT DISTINCT fabric_type
|
||||||
FROM fabrics
|
FROM fabrics
|
||||||
WHERE category = ? AND fabric_type IS NOT NULL AND fabric_type != ''
|
WHERE category = ? AND fabric_type IS NOT NULL AND fabric_type != '' AND (is_deleted IS NULL OR is_deleted = 0)
|
||||||
ORDER BY fabric_type
|
ORDER BY fabric_type
|
||||||
""", (category,))
|
""", (category,))
|
||||||
|
|
||||||
@@ -325,9 +333,9 @@ def get_fabric_models_by_category_type(db_path, category, fabric_type):
|
|||||||
try:
|
try:
|
||||||
with get_db_connection(db_path) as conn:
|
with get_db_connection(db_path) as conn:
|
||||||
cursor = conn.execute("""
|
cursor = conn.execute("""
|
||||||
SELECT model, color, unit
|
SELECT model, color, unit
|
||||||
FROM fabrics
|
FROM fabrics
|
||||||
WHERE category = ? OR category = ? OR category LIKE ?
|
WHERE (category = ? OR category = ? OR category LIKE ?) AND (is_deleted IS NULL OR is_deleted = 0)
|
||||||
ORDER BY model
|
ORDER BY model
|
||||||
""", (category, f"{category}-{fabric_type}", f"{category}-{fabric_type}-%"))
|
""", (category, f"{category}-{fabric_type}", f"{category}-{fabric_type}-%"))
|
||||||
|
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ class FabricManager(QMainWindow):
|
|||||||
if fabric_model:
|
if fabric_model:
|
||||||
try:
|
try:
|
||||||
with self.get_conn() as conn:
|
with self.get_conn() as conn:
|
||||||
cursor = conn.execute("SELECT width, gsm FROM fabrics WHERE model = ?", (fabric_model,))
|
cursor = conn.execute("SELECT width, gsm FROM fabrics WHERE model = ? AND (is_deleted IS NULL OR is_deleted = 0)", (fabric_model,))
|
||||||
fabric_info = cursor.fetchone()
|
fabric_info = cursor.fetchone()
|
||||||
if fabric_info and fabric_info[0] and fabric_info[1]:
|
if fabric_info and fabric_info[0] and fabric_info[1]:
|
||||||
width, gsm = fabric_info
|
width, gsm = fabric_info
|
||||||
|
|||||||
@@ -659,7 +659,7 @@ class GarmentEditDialog(QDialog):
|
|||||||
try:
|
try:
|
||||||
with self.get_conn() as conn:
|
with self.get_conn() as conn:
|
||||||
cursor = conn.execute(
|
cursor = conn.execute(
|
||||||
"SELECT category, fabric_type, unit FROM fabrics WHERE model = ?",
|
"SELECT category, fabric_type, unit FROM fabrics WHERE model = ? AND (is_deleted IS NULL OR is_deleted = 0)",
|
||||||
(base_model,)
|
(base_model,)
|
||||||
)
|
)
|
||||||
row_db = cursor.fetchone()
|
row_db = cursor.fetchone()
|
||||||
|
|||||||
2
main.py
2
main.py
@@ -412,7 +412,7 @@ class FabricManager(QMainWindow):
|
|||||||
if fabric_model:
|
if fabric_model:
|
||||||
try:
|
try:
|
||||||
with self.get_conn() as conn:
|
with self.get_conn() as conn:
|
||||||
cursor = conn.execute("SELECT width, gsm FROM fabrics WHERE model = ?", (fabric_model,))
|
cursor = conn.execute("SELECT width, gsm FROM fabrics WHERE model = ? AND (is_deleted IS NULL OR is_deleted = 0)", (fabric_model,))
|
||||||
fabric_info = cursor.fetchone()
|
fabric_info = cursor.fetchone()
|
||||||
if fabric_info and fabric_info[0] and fabric_info[1]:
|
if fabric_info and fabric_info[0] and fabric_info[1]:
|
||||||
width, gsm = fabric_info
|
width, gsm = fabric_info
|
||||||
|
|||||||
@@ -112,13 +112,13 @@ class RawMaterialEditDialog(QDialog):
|
|||||||
try:
|
try:
|
||||||
with self.get_conn() as conn:
|
with self.get_conn() as conn:
|
||||||
# 加载类目
|
# 加载类目
|
||||||
cursor = conn.execute("SELECT DISTINCT category FROM fabrics WHERE category IS NOT NULL AND category != ''")
|
cursor = conn.execute("SELECT DISTINCT category FROM fabrics WHERE category IS NOT NULL AND category != '' AND (is_deleted IS NULL OR is_deleted = 0)")
|
||||||
majors = set(row[0] for row in cursor.fetchall() if row[0])
|
majors = set(row[0] for row in cursor.fetchall() if row[0])
|
||||||
majors.update({"布料", "辅料", "其他"})
|
majors.update({"布料", "辅料", "其他"})
|
||||||
self.edit_major_category.addItems(sorted(majors))
|
self.edit_major_category.addItems(sorted(majors))
|
||||||
|
|
||||||
# 加载供应商
|
# 加载供应商
|
||||||
cursor = conn.execute("SELECT DISTINCT supplier FROM fabrics WHERE supplier IS NOT NULL AND supplier != '' ORDER BY supplier")
|
cursor = conn.execute("SELECT DISTINCT supplier FROM fabrics WHERE supplier IS NOT NULL AND supplier != '' AND (is_deleted IS NULL OR is_deleted = 0) ORDER BY supplier")
|
||||||
suppliers = [row[0] for row in cursor.fetchall()]
|
suppliers = [row[0] for row in cursor.fetchall()]
|
||||||
self.edit_supplier.addItems(suppliers)
|
self.edit_supplier.addItems(suppliers)
|
||||||
except:
|
except:
|
||||||
@@ -129,7 +129,7 @@ class RawMaterialEditDialog(QDialog):
|
|||||||
try:
|
try:
|
||||||
with self.get_conn() as conn:
|
with self.get_conn() as conn:
|
||||||
cursor = conn.execute(
|
cursor = conn.execute(
|
||||||
"SELECT category, fabric_type, supplier, color, width, gsm, unit, retail_price, bulk_price FROM fabrics WHERE model = ?",
|
"SELECT category, fabric_type, supplier, color, width, gsm, unit, retail_price, bulk_price FROM fabrics WHERE model = ? AND (is_deleted IS NULL OR is_deleted = 0)",
|
||||||
(self.model,)
|
(self.model,)
|
||||||
)
|
)
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
@@ -456,10 +456,10 @@ class RawMaterialLibraryDialog(QDialog):
|
|||||||
"""加载主类目"""
|
"""加载主类目"""
|
||||||
try:
|
try:
|
||||||
with self.get_conn() as conn:
|
with self.get_conn() as conn:
|
||||||
cursor = conn.execute("SELECT DISTINCT category FROM fabrics WHERE category IS NOT NULL AND category != ''")
|
cursor = conn.execute("SELECT DISTINCT category FROM fabrics WHERE category IS NOT NULL AND category != '' AND (is_deleted IS NULL OR is_deleted = 0)")
|
||||||
majors = set(row[0] for row in cursor.fetchall() if row[0])
|
majors = set(row[0] for row in cursor.fetchall() if row[0])
|
||||||
majors.update({"布料", "辅料", "其他"})
|
majors.update({"布料", "辅料", "其他"})
|
||||||
|
|
||||||
self.major_combo.blockSignals(True)
|
self.major_combo.blockSignals(True)
|
||||||
self.major_combo.clear()
|
self.major_combo.clear()
|
||||||
self.major_combo.addItem("全部类目")
|
self.major_combo.addItem("全部类目")
|
||||||
@@ -473,15 +473,15 @@ class RawMaterialLibraryDialog(QDialog):
|
|||||||
"""加载添加界面的主类目"""
|
"""加载添加界面的主类目"""
|
||||||
try:
|
try:
|
||||||
with self.get_conn() as conn:
|
with self.get_conn() as conn:
|
||||||
cursor = conn.execute("SELECT DISTINCT category FROM fabrics WHERE category IS NOT NULL AND category != ''")
|
cursor = conn.execute("SELECT DISTINCT category FROM fabrics WHERE category IS NOT NULL AND category != '' AND (is_deleted IS NULL OR is_deleted = 0)")
|
||||||
majors = set(row[0] for row in cursor.fetchall() if row[0])
|
majors = set(row[0] for row in cursor.fetchall() if row[0])
|
||||||
majors.update({"布料", "辅料", "其他"})
|
majors.update({"布料", "辅料", "其他"})
|
||||||
|
|
||||||
self.add_major_category.blockSignals(True)
|
self.add_major_category.blockSignals(True)
|
||||||
current_text = self.add_major_category.currentText()
|
current_text = self.add_major_category.currentText()
|
||||||
self.add_major_category.clear()
|
self.add_major_category.clear()
|
||||||
self.add_major_category.addItems(sorted(majors))
|
self.add_major_category.addItems(sorted(majors))
|
||||||
|
|
||||||
if current_text in majors:
|
if current_text in majors:
|
||||||
self.add_major_category.setCurrentText(current_text)
|
self.add_major_category.setCurrentText(current_text)
|
||||||
else:
|
else:
|
||||||
@@ -498,20 +498,20 @@ class RawMaterialLibraryDialog(QDialog):
|
|||||||
self.sub_combo.blockSignals(True)
|
self.sub_combo.blockSignals(True)
|
||||||
self.sub_combo.clear()
|
self.sub_combo.clear()
|
||||||
self.sub_combo.addItem("全部类型")
|
self.sub_combo.addItem("全部类型")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with self.get_conn() as conn:
|
with self.get_conn() as conn:
|
||||||
if major in ("全部类目", ""):
|
if major in ("全部类目", ""):
|
||||||
cursor = conn.execute("SELECT DISTINCT fabric_type FROM fabrics WHERE fabric_type IS NOT NULL AND fabric_type != ''")
|
cursor = conn.execute("SELECT DISTINCT fabric_type FROM fabrics WHERE fabric_type IS NOT NULL AND fabric_type != '' AND (is_deleted IS NULL OR is_deleted = 0)")
|
||||||
subs = [row[0] for row in cursor.fetchall() if row[0]]
|
subs = [row[0] for row in cursor.fetchall() if row[0]]
|
||||||
self.sub_combo.addItems(sorted(subs))
|
self.sub_combo.addItems(sorted(subs))
|
||||||
else:
|
else:
|
||||||
cursor = conn.execute("SELECT DISTINCT fabric_type FROM fabrics WHERE category = ? AND fabric_type IS NOT NULL AND fabric_type != ''", (major,))
|
cursor = conn.execute("SELECT DISTINCT fabric_type FROM fabrics WHERE category = ? AND fabric_type IS NOT NULL AND fabric_type != '' AND (is_deleted IS NULL OR is_deleted = 0)", (major,))
|
||||||
subs = [row[0] for row in cursor.fetchall() if row[0]]
|
subs = [row[0] for row in cursor.fetchall() if row[0]]
|
||||||
self.sub_combo.addItems(sorted(subs))
|
self.sub_combo.addItems(sorted(subs))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
self.sub_combo.blockSignals(False)
|
self.sub_combo.blockSignals(False)
|
||||||
self.load_table()
|
self.load_table()
|
||||||
|
|
||||||
@@ -519,7 +519,7 @@ class RawMaterialLibraryDialog(QDialog):
|
|||||||
"""加载供应商列表"""
|
"""加载供应商列表"""
|
||||||
try:
|
try:
|
||||||
with self.get_conn() as conn:
|
with self.get_conn() as conn:
|
||||||
cursor = conn.execute("SELECT DISTINCT supplier FROM fabrics WHERE supplier IS NOT NULL AND supplier != '' ORDER BY supplier")
|
cursor = conn.execute("SELECT DISTINCT supplier FROM fabrics WHERE supplier IS NOT NULL AND supplier != '' AND (is_deleted IS NULL OR is_deleted = 0) ORDER BY supplier")
|
||||||
suppliers = [row[0] for row in cursor.fetchall()]
|
suppliers = [row[0] for row in cursor.fetchall()]
|
||||||
|
|
||||||
self.supplier_combo.blockSignals(True)
|
self.supplier_combo.blockSignals(True)
|
||||||
@@ -543,6 +543,9 @@ class RawMaterialLibraryDialog(QDialog):
|
|||||||
params = []
|
params = []
|
||||||
conditions = []
|
conditions = []
|
||||||
|
|
||||||
|
# 过滤已删除的原料
|
||||||
|
conditions.append("(is_deleted IS NULL OR is_deleted = 0)")
|
||||||
|
|
||||||
# 类目过滤
|
# 类目过滤
|
||||||
major = self.major_combo.currentText()
|
major = self.major_combo.currentText()
|
||||||
sub = self.sub_combo.currentText()
|
sub = self.sub_combo.currentText()
|
||||||
@@ -643,12 +646,13 @@ class RawMaterialLibraryDialog(QDialog):
|
|||||||
self.refresh_filters_and_table()
|
self.refresh_filters_and_table()
|
||||||
|
|
||||||
def delete_raw(self, model):
|
def delete_raw(self, model):
|
||||||
"""删除原料"""
|
"""逻辑删除原料"""
|
||||||
reply = QMessageBox.question(self, "确认", f"删除 '{model}'?")
|
reply = QMessageBox.question(self, "确认", f"确定要删除 '{model}' 吗?\n\n此操作将标记删除该原料,不会影响历史数据。")
|
||||||
if reply == QMessageBox.Yes:
|
if reply == QMessageBox.Yes:
|
||||||
try:
|
try:
|
||||||
with self.get_conn() as conn:
|
with self.get_conn() as conn:
|
||||||
conn.execute("DELETE FROM fabrics WHERE model=?", (model,))
|
# 逻辑删除:设置is_deleted=1
|
||||||
|
conn.execute("UPDATE fabrics SET is_deleted=1, updated_at=CURRENT_TIMESTAMP WHERE model=?", (model,))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
self.load_table()
|
self.load_table()
|
||||||
QMessageBox.information(self, "成功", "删除完成")
|
QMessageBox.information(self, "成功", "删除完成")
|
||||||
|
|||||||
@@ -58,10 +58,10 @@ class StockInDialog(QDialog):
|
|||||||
try:
|
try:
|
||||||
with self.get_conn() as conn:
|
with self.get_conn() as conn:
|
||||||
# 查询面料基础信息
|
# 查询面料基础信息
|
||||||
query = "SELECT model, color, supplier, unit FROM fabrics"
|
query = "SELECT model, color, supplier, unit FROM fabrics WHERE (is_deleted IS NULL OR is_deleted = 0)"
|
||||||
params = []
|
params = []
|
||||||
if keyword:
|
if keyword:
|
||||||
query += " WHERE model LIKE ? OR color LIKE ?"
|
query += " AND (model LIKE ? OR color LIKE ?)"
|
||||||
params = ["%" + keyword + "%", "%" + keyword + "%"]
|
params = ["%" + keyword + "%", "%" + keyword + "%"]
|
||||||
query += " ORDER BY timestamp DESC"
|
query += " ORDER BY timestamp DESC"
|
||||||
cursor = conn.execute(query, params)
|
cursor = conn.execute(query, params)
|
||||||
|
|||||||
Reference in New Issue
Block a user