Compare commits
5 Commits
35050407e9
...
26397a83dd
| Author | SHA1 | Date | |
|---|---|---|---|
| 26397a83dd | |||
| d33216f9b9 | |||
| 5cf27c8cfe | |||
| 803127062e | |||
| 83609aaa20 |
@@ -42,7 +42,8 @@ class DatabaseManager:
|
||||
unit TEXT DEFAULT '米',
|
||||
timestamp TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
is_deleted INTEGER DEFAULT 0
|
||||
)
|
||||
''')
|
||||
|
||||
@@ -194,6 +195,7 @@ class DatabaseManager:
|
||||
note TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
is_deleted INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (model) REFERENCES fabrics(model)
|
||||
)
|
||||
''')
|
||||
@@ -216,6 +218,7 @@ class DatabaseManager:
|
||||
unit TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
is_deleted INTEGER DEFAULT 0,
|
||||
FOREIGN KEY (style_number) REFERENCES garments(style_number),
|
||||
FOREIGN KEY (model) REFERENCES fabrics(model)
|
||||
)
|
||||
|
||||
@@ -142,17 +142,24 @@ class GarmentLibraryDialog(QDialog):
|
||||
self.garment_table.setRowHeight(i, 140)
|
||||
|
||||
for row_idx, (style_number, image_path) in enumerate(rows):
|
||||
self.garment_table.setItem(row_idx, 0, QTableWidgetItem(style_number))
|
||||
# 款号列 - 设置为只读
|
||||
style_item = QTableWidgetItem(style_number)
|
||||
style_item.setFlags(style_item.flags() & ~Qt.ItemIsEditable)
|
||||
self.garment_table.setItem(row_idx, 0, style_item)
|
||||
|
||||
# 查询材料数量
|
||||
with self.get_conn() as conn:
|
||||
cursor2 = conn.execute("SELECT COUNT(*) FROM garment_materials WHERE style_number = ?", (style_number,))
|
||||
count = cursor2.fetchone()[0]
|
||||
self.garment_table.setItem(row_idx, 1, QTableWidgetItem(str(count)))
|
||||
# 类目数量列 - 设置为只读
|
||||
count_item = QTableWidgetItem(str(count))
|
||||
count_item.setFlags(count_item.flags() & ~Qt.ItemIsEditable)
|
||||
self.garment_table.setItem(row_idx, 1, count_item)
|
||||
|
||||
# 显示图片预览
|
||||
image_item = QTableWidgetItem()
|
||||
image_item.setTextAlignment(Qt.AlignCenter)
|
||||
image_item.setFlags(image_item.flags() & ~Qt.ItemIsEditable)
|
||||
|
||||
if image_path and os.path.exists(image_path):
|
||||
try:
|
||||
|
||||
69
main.py
69
main.py
@@ -234,7 +234,7 @@ class FabricManager(QMainWindow):
|
||||
return
|
||||
quantity = self.quantity_input.value()
|
||||
loss_rate = self.loss_input.value() / 100
|
||||
|
||||
|
||||
try:
|
||||
with self.get_conn() as conn:
|
||||
cursor = conn.execute('''
|
||||
@@ -243,21 +243,24 @@ class FabricManager(QMainWindow):
|
||||
WHERE style_number = ?
|
||||
''', (style_number,))
|
||||
rows = cursor.fetchall()
|
||||
inserted = 0
|
||||
|
||||
|
||||
# 第一步:检查所有原料库存是否充足
|
||||
insufficient_materials = []
|
||||
materials_to_record = []
|
||||
|
||||
for category, fabric_type, usage_per_piece, unit in rows:
|
||||
if usage_per_piece == 0:
|
||||
continue
|
||||
|
||||
|
||||
# 获取该原料在入库时使用的单位
|
||||
stock_cursor = conn.execute('''
|
||||
SELECT unit FROM fabric_stock_in
|
||||
WHERE model = ?
|
||||
ORDER BY purchase_date DESC
|
||||
SELECT unit FROM fabric_stock_in
|
||||
WHERE model = ?
|
||||
ORDER BY purchase_date DESC
|
||||
LIMIT 1
|
||||
''', (category,))
|
||||
stock_unit_row = stock_cursor.fetchone()
|
||||
|
||||
|
||||
# 如果有入库记录,使用入库单位;否则使用原来的单位
|
||||
if stock_unit_row:
|
||||
stock_unit = stock_unit_row[0]
|
||||
@@ -272,17 +275,59 @@ class FabricManager(QMainWindow):
|
||||
# 没有入库记录,使用原单位
|
||||
consume_qty = usage_per_piece * quantity * (1 + loss_rate)
|
||||
final_unit = unit
|
||||
|
||||
|
||||
# 检查当前库存
|
||||
stock_info = conn.execute('''
|
||||
SELECT
|
||||
COALESCE(SUM(CASE WHEN si.is_deleted = 0 THEN si.quantity ELSE 0 END), 0) AS total_in,
|
||||
COALESCE(SUM(CASE WHEN c.is_deleted = 0 THEN c.consume_quantity ELSE 0 END), 0) AS total_out
|
||||
FROM fabrics f
|
||||
LEFT JOIN fabric_stock_in si ON f.model = si.model
|
||||
LEFT JOIN fabric_consumption c ON f.model = c.model
|
||||
WHERE f.model = ?
|
||||
GROUP BY f.model
|
||||
''', (category,)).fetchone()
|
||||
|
||||
if stock_info:
|
||||
total_in, total_out = stock_info
|
||||
current_stock = total_in - total_out
|
||||
else:
|
||||
current_stock = 0
|
||||
|
||||
# 如果库存不足,记录下来
|
||||
if current_stock < consume_qty:
|
||||
material_name = category or "未命名材料"
|
||||
insufficient_materials.append(
|
||||
f"{material_name}: 需要 {consume_qty:.3f} {final_unit},库存仅剩 {current_stock:.3f} {final_unit}"
|
||||
)
|
||||
else:
|
||||
# 库存充足,加入待记录列表
|
||||
materials_to_record.append((
|
||||
style_number, category, usage_per_piece, quantity,
|
||||
loss_rate, consume_qty, final_unit
|
||||
))
|
||||
|
||||
# 如果有库存不足的材料,提示用户并中止操作
|
||||
if insufficient_materials:
|
||||
message = "以下原料库存不足,无法记录消耗:\n\n" + "\n".join(insufficient_materials)
|
||||
QMessageBox.warning(self, "库存不足", message)
|
||||
return
|
||||
|
||||
# 第二步:所有库存都充足,执行记录
|
||||
inserted = 0
|
||||
for material_data in materials_to_record:
|
||||
style_num, model, single_usage, qty, loss, consume_qty, final_unit = material_data
|
||||
conn.execute('''
|
||||
INSERT INTO fabric_consumption
|
||||
(style_number, model, single_usage, quantity_made, loss_rate, consume_quantity, consume_date, unit)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
''', (style_number, category, usage_per_piece, quantity, loss_rate, consume_qty, datetime.now().strftime('%Y-%m-%d'), final_unit))
|
||||
''', (style_num, model, single_usage, qty, loss, consume_qty, datetime.now().strftime('%Y-%m-%d'), final_unit))
|
||||
inserted += 1
|
||||
|
||||
conn.commit()
|
||||
|
||||
|
||||
if inserted > 0:
|
||||
QMessageBox.information(self, "成功", "本次生产消耗已记录到库存!")
|
||||
QMessageBox.information(self, "成功", f"本次生产消耗已记录到库存!共记录 {inserted} 种原料。")
|
||||
else:
|
||||
QMessageBox.information(self, "提示", "本次没有可记录的原料消耗")
|
||||
except Exception as e:
|
||||
|
||||
@@ -111,11 +111,8 @@ class RawMaterialEditDialog(QDialog):
|
||||
"""加载类目和供应商列表"""
|
||||
try:
|
||||
with self.get_conn() as conn:
|
||||
# 加载类目
|
||||
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.update({"布料", "辅料", "其他"})
|
||||
self.edit_major_category.addItems(sorted(majors))
|
||||
# 加载类目 - 设置默认选项为:面料、辅料、其他
|
||||
self.edit_major_category.addItems(["面料", "辅料", "其他"])
|
||||
|
||||
# 加载供应商
|
||||
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")
|
||||
@@ -172,6 +169,26 @@ class RawMaterialEditDialog(QDialog):
|
||||
major = self.edit_major_category.currentText().strip()
|
||||
sub = self.edit_sub_category.text().strip()
|
||||
|
||||
# 验证必填字段:类目
|
||||
if not major:
|
||||
QMessageBox.warning(self, "错误", "请选择类目")
|
||||
return
|
||||
|
||||
# 验证必填字段:类型
|
||||
if not sub:
|
||||
QMessageBox.warning(self, "错误", "请输入类型")
|
||||
return
|
||||
|
||||
# 验证必填字段:幅宽
|
||||
if self.edit_width.value() <= 0:
|
||||
QMessageBox.warning(self, "错误", "请输入幅宽")
|
||||
return
|
||||
|
||||
# 验证必填字段:克重
|
||||
if self.edit_gsm.value() <= 0:
|
||||
QMessageBox.warning(self, "错误", "请输入克重")
|
||||
return
|
||||
|
||||
# 特殊处理胸杯类型
|
||||
if "胸杯" in sub:
|
||||
major = "辅料"
|
||||
@@ -453,17 +470,17 @@ class RawMaterialLibraryDialog(QDialog):
|
||||
self.load_table()
|
||||
|
||||
def load_major_categories(self):
|
||||
"""加载主类目"""
|
||||
"""加载主类目 - 只显示数据库中实际存在的类目"""
|
||||
try:
|
||||
with self.get_conn() as conn:
|
||||
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.update({"布料", "辅料", "其他"})
|
||||
|
||||
self.major_combo.blockSignals(True)
|
||||
self.major_combo.clear()
|
||||
self.major_combo.addItem("全部类目")
|
||||
self.major_combo.addItems(sorted(majors))
|
||||
if majors:
|
||||
self.major_combo.addItems(sorted(majors))
|
||||
self.major_combo.blockSignals(False)
|
||||
except:
|
||||
pass
|
||||
@@ -471,26 +488,12 @@ class RawMaterialLibraryDialog(QDialog):
|
||||
|
||||
def load_add_major_categories(self):
|
||||
"""加载添加界面的主类目"""
|
||||
try:
|
||||
with self.get_conn() as conn:
|
||||
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.update({"布料", "辅料", "其他"})
|
||||
|
||||
self.add_major_category.blockSignals(True)
|
||||
current_text = self.add_major_category.currentText()
|
||||
self.add_major_category.clear()
|
||||
self.add_major_category.addItems(sorted(majors))
|
||||
|
||||
if current_text in majors:
|
||||
self.add_major_category.setCurrentText(current_text)
|
||||
else:
|
||||
self.add_major_category.setCurrentText("布料")
|
||||
self.add_major_category.blockSignals(False)
|
||||
except:
|
||||
self.add_major_category.clear()
|
||||
self.add_major_category.addItems(["布料", "辅料", "其他"])
|
||||
self.add_major_category.setCurrentText("布料")
|
||||
# 设置默认类目选项为:面料、辅料、其他
|
||||
self.add_major_category.blockSignals(True)
|
||||
self.add_major_category.clear()
|
||||
self.add_major_category.addItems(["面料", "辅料", "其他"])
|
||||
self.add_major_category.setCurrentText("面料")
|
||||
self.add_major_category.blockSignals(False)
|
||||
|
||||
def load_sub_categories(self):
|
||||
"""加载子类型"""
|
||||
@@ -521,16 +524,19 @@ class RawMaterialLibraryDialog(QDialog):
|
||||
with self.get_conn() as conn:
|
||||
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()]
|
||||
|
||||
|
||||
self.supplier_combo.blockSignals(True)
|
||||
self.supplier_combo.clear()
|
||||
self.supplier_combo.addItem("全部供应商")
|
||||
self.supplier_combo.addItems(suppliers)
|
||||
self.supplier_combo.blockSignals(False)
|
||||
|
||||
# 新增原料界面的供应商下拉框,添加空选项作为默认值
|
||||
self.add_supplier.blockSignals(True)
|
||||
self.add_supplier.clear()
|
||||
self.add_supplier.addItem("") # 添加空选项
|
||||
self.add_supplier.addItems(suppliers)
|
||||
self.add_supplier.setCurrentIndex(0) # 默认选中空选项
|
||||
self.add_supplier.blockSignals(False)
|
||||
except:
|
||||
pass
|
||||
@@ -647,7 +653,7 @@ class RawMaterialLibraryDialog(QDialog):
|
||||
|
||||
def delete_raw(self, model):
|
||||
"""逻辑删除原料"""
|
||||
reply = QMessageBox.question(self, "确认", f"确定要删除 '{model}' 吗?\n\n此操作将标记删除该原料,不会影响历史数据。")
|
||||
reply = QMessageBox.question(self, "确认", f"确定要删除 '{model}' 吗?")
|
||||
if reply == QMessageBox.Yes:
|
||||
try:
|
||||
with self.get_conn() as conn:
|
||||
@@ -668,6 +674,27 @@ class RawMaterialLibraryDialog(QDialog):
|
||||
|
||||
major = self.add_major_category.currentText().strip()
|
||||
sub = self.add_sub_category.text().strip()
|
||||
|
||||
# 验证必填字段:类目
|
||||
if not major:
|
||||
QMessageBox.warning(self, "错误", "请选择类目")
|
||||
return
|
||||
|
||||
# 验证必填字段:类型
|
||||
if not sub:
|
||||
QMessageBox.warning(self, "错误", "请输入类型")
|
||||
return
|
||||
|
||||
# 验证必填字段:幅宽
|
||||
if self.add_width.value() <= 0:
|
||||
QMessageBox.warning(self, "错误", "请输入幅宽")
|
||||
return
|
||||
|
||||
# 验证必填字段:克重
|
||||
if self.add_gsm.value() <= 0:
|
||||
QMessageBox.warning(self, "错误", "请输入克重")
|
||||
return
|
||||
|
||||
if "胸杯" in sub:
|
||||
major = "辅料"
|
||||
|
||||
@@ -680,23 +707,42 @@ class RawMaterialLibraryDialog(QDialog):
|
||||
|
||||
try:
|
||||
with self.get_conn() as conn:
|
||||
# 检查是否已存在
|
||||
cursor = conn.execute("SELECT model FROM fabrics WHERE model = ?", (model,))
|
||||
if cursor.fetchone():
|
||||
QMessageBox.warning(self, "错误", f"型号 '{model}' 已存在,请使用编辑功能修改")
|
||||
return
|
||||
# 检查是否已存在该型号
|
||||
cursor = conn.execute("SELECT model, is_deleted FROM fabrics WHERE model = ?", (model,))
|
||||
existing = cursor.fetchone()
|
||||
|
||||
conn.execute('''
|
||||
INSERT INTO fabrics
|
||||
(model, category, fabric_type, supplier, color, width, gsm, retail_price, bulk_price, unit, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
''', (model, category, fabric_type, supplier, color,
|
||||
self.add_width.value() or None, self.add_gsm.value() or None,
|
||||
self.add_retail.value() or None, self.add_bulk.value() or None,
|
||||
unit, datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
|
||||
conn.commit()
|
||||
if existing:
|
||||
_, is_deleted = existing
|
||||
|
||||
QMessageBox.information(self, "成功", f"已保存 '{model}'")
|
||||
# 如果型号存在且未被删除,提示使用编辑功能
|
||||
if not is_deleted or is_deleted == 0:
|
||||
QMessageBox.warning(self, "错误", f"型号 '{model}' 已存在,请使用编辑功能修改")
|
||||
return
|
||||
|
||||
# 如果型号已被删除,直接恢复并更新
|
||||
conn.execute('''
|
||||
UPDATE fabrics
|
||||
SET category=?, fabric_type=?, supplier=?, color=?, width=?, gsm=?,
|
||||
retail_price=?, bulk_price=?, unit=?, timestamp=?, is_deleted=0, updated_at=CURRENT_TIMESTAMP
|
||||
WHERE model=?
|
||||
''', (category, fabric_type, supplier, color,
|
||||
self.add_width.value() or None, self.add_gsm.value() or None,
|
||||
self.add_retail.value() or None, self.add_bulk.value() or None,
|
||||
unit, datetime.now().strftime('%Y-%m-%d %H:%M:%S'), model))
|
||||
conn.commit()
|
||||
QMessageBox.information(self, "成功", f"已保存 '{model}'")
|
||||
else:
|
||||
# 型号不存在,创建新记录
|
||||
conn.execute('''
|
||||
INSERT INTO fabrics
|
||||
(model, category, fabric_type, supplier, color, width, gsm, retail_price, bulk_price, unit, timestamp)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
''', (model, category, fabric_type, supplier, color,
|
||||
self.add_width.value() or None, self.add_gsm.value() or None,
|
||||
self.add_retail.value() or None, self.add_bulk.value() or None,
|
||||
unit, datetime.now().strftime('%Y-%m-%d %H:%M:%S')))
|
||||
conn.commit()
|
||||
QMessageBox.information(self, "成功", f"已保存 '{model}'")
|
||||
|
||||
# 清空表单
|
||||
self.add_model.clear()
|
||||
|
||||
Reference in New Issue
Block a user