backup: 价格bug修复 + 订单批量识别设计文档
This commit is contained in:
+32
-10
@@ -178,18 +178,30 @@ class ProductDatabase:
|
||||
try:
|
||||
row = conn.execute("SELECT avg_price FROM products WHERE barcode=?",
|
||||
(str(barcode).strip(),)).fetchone()
|
||||
return row[0] if row and row[0] else None
|
||||
if not row:
|
||||
return None
|
||||
return row[0] if row[0] is not None else 0.0
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def get_prices(self, barcodes: List[str]) -> Dict[str, float]:
|
||||
def get_prices(self, barcodes: List[str], column: str = 'price') -> Dict[str, float]:
|
||||
"""批量查进货价。
|
||||
|
||||
Args:
|
||||
barcodes: 条码列表
|
||||
column: 价字段,默认 'price'(Excel 导入的进货价,按商家主单位),
|
||||
可选 'avg_price'(OCR 学来的历史均价,调试用)。
|
||||
"""
|
||||
if not barcodes:
|
||||
return {}
|
||||
valid = {'price', 'avg_price', 'min_price', 'max_price'}
|
||||
if column not in valid:
|
||||
raise ValueError(f"column must be one of {valid}")
|
||||
conn = self._connect()
|
||||
try:
|
||||
placeholders = ','.join('?' * len(barcodes))
|
||||
rows = conn.execute(
|
||||
f"SELECT barcode, avg_price FROM products WHERE barcode IN ({placeholders})",
|
||||
f"SELECT barcode, {column} FROM products WHERE barcode IN ({placeholders})",
|
||||
[str(b).strip() for b in barcodes]).fetchall()
|
||||
return {r[0]: r[1] for r in rows if r[1]}
|
||||
finally:
|
||||
@@ -357,13 +369,23 @@ class ProductDatabase:
|
||||
else:
|
||||
# 高可信度源全字段覆盖;低可信度仅填空
|
||||
if source in ('template', 'user_confirmed') or new_conf > 50:
|
||||
conn.execute(
|
||||
"UPDATE products SET name=?, specification=?, unit=?, price=?, "
|
||||
"source=?, confidence=?, usage_count=?, last_seen=?, updated_at=?, "
|
||||
"avg_price=?, min_price=?, max_price=?, price_count=? WHERE barcode=?",
|
||||
(name or old_name, spec or old_spec, unit or old_unit, price,
|
||||
source, new_conf, new_count, now, now,
|
||||
new_avg, new_min, new_max, new_pc, barcode))
|
||||
# OCR 来源不覆盖 price(price 是商品资料 Excel 导入的进货价,应作为基准不被 OCR 学习的"按箱单价"覆盖)
|
||||
if source == 'ocr':
|
||||
conn.execute(
|
||||
"UPDATE products SET name=?, specification=?, unit=?, "
|
||||
"source=?, confidence=?, usage_count=?, last_seen=?, updated_at=?, "
|
||||
"avg_price=?, min_price=?, max_price=?, price_count=? WHERE barcode=?",
|
||||
(name or old_name, spec or old_spec, unit or old_unit,
|
||||
source, new_conf, new_count, now, now,
|
||||
new_avg, new_min, new_max, new_pc, barcode))
|
||||
else:
|
||||
conn.execute(
|
||||
"UPDATE products SET name=?, specification=?, unit=?, price=?, "
|
||||
"source=?, confidence=?, usage_count=?, last_seen=?, updated_at=?, "
|
||||
"avg_price=?, min_price=?, max_price=?, price_count=? WHERE barcode=?",
|
||||
(name or old_name, spec or old_spec, unit or old_unit, price,
|
||||
source, new_conf, new_count, now, now,
|
||||
new_avg, new_min, new_max, new_pc, barcode))
|
||||
else:
|
||||
conn.execute(
|
||||
"UPDATE products SET "
|
||||
|
||||
+13
-23
@@ -352,29 +352,8 @@ class ExcelProcessor:
|
||||
product['package_quantity'] = package_quantity
|
||||
logger.info(f"解析已设置的规格: {product['specification']} -> 包装数量={package_quantity}")
|
||||
|
||||
# 新增逻辑:根据规格推断单位为"件"
|
||||
if not product['unit'] and product.get('barcode') and product.get('specification') and product.get('quantity') and product.get('price') is not None:
|
||||
# 检查规格是否符合容量*数量格式
|
||||
volume_pattern = r'(\d+(?:\.\d+)?)\s*(?:ml|[mL]L|l|L|升|毫升)[*×xX](\d+)'
|
||||
match = re.search(volume_pattern, product['specification'])
|
||||
|
||||
# 判断是否需要推断单位为"件"
|
||||
if match:
|
||||
product['unit'] = '件'
|
||||
logger.info(f"根据规格推断单位: {product['specification']} -> 单位=件")
|
||||
else:
|
||||
# 检查简单的数量*数量格式
|
||||
simple_pattern = r'(\d+)[*×xX](\d+)'
|
||||
match = re.search(simple_pattern, product['specification'])
|
||||
if match:
|
||||
product['unit'] = '件'
|
||||
logger.info(f"根据规格推断单位: {product['specification']} -> 单位=件")
|
||||
|
||||
# 应用单位转换规则
|
||||
product = self.unit_converter.process_unit_conversion(product)
|
||||
|
||||
# 如果数量为0但单价和金额都存在,计算数量 = 金额/单价
|
||||
if (product['quantity'] == 0 or product['quantity'] is None) and product['price'] > 0 and product['amount']:
|
||||
# 如果数量为0但单价和金额都存在,先算数量(必须在 unit 推断之前,否则 unit 推断条件因 quantity=0 被跳过)
|
||||
if (product['quantity'] == 0 or product['quantity'] is None) and product['price'] and product['amount']:
|
||||
try:
|
||||
amount = parse_monetary_string(product['amount'])
|
||||
if amount is not None and amount > 0:
|
||||
@@ -383,6 +362,17 @@ class ExcelProcessor:
|
||||
product['quantity'] = quantity
|
||||
except Exception as e:
|
||||
logger.warning(f"通过金额和单价计算数量失败: {e}")
|
||||
|
||||
# 推断单位为"件":仅依赖规格文本(spec 已经是 "1*N"),不再要求 quantity 非零
|
||||
if not product['unit'] and product.get('specification'):
|
||||
volume_pattern = r'(\d+(?:\.\d+)?)\s*(?:ml|[mL]L|l|L|升|毫升)[*×xX](\d+)'
|
||||
simple_pattern = r'(\d+)[*×xX](\d+)'
|
||||
if re.search(volume_pattern, product['specification']) or re.search(simple_pattern, product['specification']):
|
||||
product['unit'] = '件'
|
||||
logger.info(f"根据规格推断单位: {product['specification']} -> 单位=件")
|
||||
|
||||
# 应用单位转换规则
|
||||
product = self.unit_converter.process_unit_conversion(product)
|
||||
|
||||
# 应用记忆库补全
|
||||
product = self._apply_memory(product)
|
||||
|
||||
Reference in New Issue
Block a user