style: format all Python files with Black

Apply Black formatter to the entire codebase for consistent code style.

Co-Authored-By: Claude (glm-5) <noreply@anthropic.com>
This commit is contained in:
Misaka
2026-02-26 22:44:03 +08:00
parent 1b16842a2c
commit 3b7c00377f
46 changed files with 1488 additions and 974 deletions

View File

@@ -37,7 +37,9 @@ class BaseDatabaseConnection(ABC):
pass
@abstractmethod
def execute_query(self, sql: str, params: Optional[tuple] = None) -> List[Dict[str, Any]]:
def execute_query(
self, sql: str, params: Optional[tuple] = None
) -> List[Dict[str, Any]]:
"""
执行查询语句并返回结果

View File

@@ -19,6 +19,7 @@ class BaseDAO:
self.db: Optional[BaseDatabaseConnection] = None
# 从配置文件加载数据库类型
from config.loader import ConfigLoader
app_config = ConfigLoader.load()
self._db_type = app_config.database.db_type
@@ -50,7 +51,7 @@ class BaseDAO:
"""
if self._db_type == DatabaseType.MYSQL:
# SQL Server → MySQL
return TableNameConverter.convert_sql(sql, 'mysql')
return TableNameConverter.convert_sql(sql, "mysql")
return sql
def _get_placeholder(self) -> str:

View File

@@ -1,6 +1,7 @@
"""
BIPUsers DAO - Data access object for user authentication and management
"""
from typing import Optional, Dict, Any, List
from db.base_dao import BaseDAO
from db.connection import get_connection
@@ -22,7 +23,7 @@ class BIPUsersDAO(BaseDAO):
Dict with user info if authentication successful, None otherwise
Returns: {id, username, user_type}
"""
table_name = self._convert_sql('[dbo].[BIPUsers]')
table_name = self._convert_sql("[dbo].[BIPUsers]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -43,13 +44,15 @@ class BIPUsersDAO(BaseDAO):
results = db.execute_query(sql, (username, password))
if results:
return {
'id': results[0]['ID'],
'username': results[0]['UserName'],
'user_type': results[0]['UserType']
"id": results[0]["ID"],
"username": results[0]["UserName"],
"user_type": results[0]["UserType"],
}
return None
def authenticate_by_computer_name(self, computer_name: str) -> Optional[Dict[str, Any]]:
def authenticate_by_computer_name(
self, computer_name: str
) -> Optional[Dict[str, Any]]:
"""
Authenticate a user using computer name (silent login)
@@ -60,7 +63,7 @@ class BIPUsersDAO(BaseDAO):
Dict with user info if authentication successful, None otherwise
Returns: {id, username, user_type}
"""
table_name = self._convert_sql('[dbo].[BIPUsers]')
table_name = self._convert_sql("[dbo].[BIPUsers]")
placeholder = self._get_placeholder()
# Note: Column name is 'ComputerNmae' (typo in database schema)
@@ -81,9 +84,9 @@ class BIPUsersDAO(BaseDAO):
results = db.execute_query(sql, (computer_name,))
if results:
return {
'id': results[0]['ID'],
'username': results[0]['UserName'],
'user_type': results[0]['UserType']
"id": results[0]["ID"],
"username": results[0]["UserName"],
"user_type": results[0]["UserType"],
}
return None
@@ -94,7 +97,7 @@ class BIPUsersDAO(BaseDAO):
Returns:
List of user dictionaries: [{id, username, user_type, create_time}]
"""
table_name = self._convert_sql('[dbo].[BIPUsers]')
table_name = self._convert_sql("[dbo].[BIPUsers]")
# 根据数据库类型选择列名格式
if self._db_type == DatabaseType.MYSQL:
@@ -114,15 +117,17 @@ class BIPUsersDAO(BaseDAO):
results = db.execute_query(sql)
return [
{
'id': row['ID'],
'username': row['UserName'],
'user_type': row['UserType'],
'create_time': row['CreateTime']
"id": row["ID"],
"username": row["UserName"],
"user_type": row["UserType"],
"create_time": row["CreateTime"],
}
for row in results
]
def create_user(self, username: str, password: str, user_type: str, computer_name: str = '') -> bool:
def create_user(
self, username: str, password: str, user_type: str, computer_name: str = ""
) -> bool:
"""
Create a new user with optional computer name for silent login
@@ -135,7 +140,7 @@ class BIPUsersDAO(BaseDAO):
Returns:
True if successful, False otherwise
"""
table_name = self._convert_sql('[dbo].[BIPUsers]')
table_name = self._convert_sql("[dbo].[BIPUsers]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -185,7 +190,7 @@ class BIPUsersDAO(BaseDAO):
Returns:
True if successful, False otherwise
"""
table_name = self._convert_sql('[dbo].[BIPUsers]')
table_name = self._convert_sql("[dbo].[BIPUsers]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -221,7 +226,7 @@ class BIPUsersDAO(BaseDAO):
Returns:
True if successful, False otherwise
"""
table_name = self._convert_sql('[dbo].[BIPUsers]')
table_name = self._convert_sql("[dbo].[BIPUsers]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -256,7 +261,7 @@ class BIPUsersDAO(BaseDAO):
Returns:
True if successful, False otherwise
"""
table_name = self._convert_sql('[dbo].[BIPUsers]')
table_name = self._convert_sql("[dbo].[BIPUsers]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -289,7 +294,7 @@ class BIPUsersDAO(BaseDAO):
Returns:
True if username exists, False otherwise
"""
table_name = self._convert_sql('[dbo].[BIPUsers]')
table_name = self._convert_sql("[dbo].[BIPUsers]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -306,4 +311,4 @@ class BIPUsersDAO(BaseDAO):
with get_connection() as db:
results = db.execute_query(sql, (username,))
return results[0]['count'] > 0 if results else False
return results[0]["count"] > 0 if results else False

View File

@@ -34,6 +34,7 @@ def get_connection(config=None) -> BaseDatabaseConnection:
else:
# 从用户配置文件加载
from config.loader import ConfigLoader
app_config = ConfigLoader.load()
database_config = app_config.database

View File

@@ -16,8 +16,7 @@ class ConnectionFactory:
@staticmethod
def create_connection(
db_type: DatabaseType,
config: Optional[Dict[str, Any]] = None
db_type: DatabaseType, config: Optional[Dict[str, Any]] = None
) -> BaseDatabaseConnection:
"""
根据数据库类型创建对应的连接实例
@@ -58,14 +57,14 @@ class ConnectionFactory:
if db_type == DatabaseType.SQLSERVER:
# 构建 SQL Server 配置字典
config = {
'server': database_config.server,
'database': database_config.database,
'username': database_config.username,
'password': database_config.password,
"server": database_config.server,
"database": database_config.database,
"username": database_config.username,
"password": database_config.password,
}
if database_config.sqlserver:
config['driver'] = database_config.sqlserver.driver
config['trust_server_certificate'] = (
config["driver"] = database_config.sqlserver.driver
config["trust_server_certificate"] = (
database_config.sqlserver.trust_server_certificate
)
return SQLServerConnection(config)
@@ -73,17 +72,17 @@ class ConnectionFactory:
elif db_type == DatabaseType.MYSQL:
# 构建 MySQL 配置字典
config = {
'database': database_config.database,
'username': database_config.username,
'password': database_config.password,
"database": database_config.database,
"username": database_config.username,
"password": database_config.password,
}
if database_config.mysql:
config['host'] = database_config.mysql.host
config['port'] = database_config.mysql.port
config['charset'] = database_config.mysql.charset
config["host"] = database_config.mysql.host
config["port"] = database_config.mysql.port
config["charset"] = database_config.mysql.charset
else:
# 回退到 server 字段(兼容旧配置)
config['host'] = database_config.server
config["host"] = database_config.server
return MySQLConnection(config)
else:

View File

@@ -37,19 +37,21 @@ class DiscreteMaterialPlanDAO(BaseDAO):
... print(f"Deleted: {stats['deleted']}, Inserted: {stats['inserted']}")
"""
if df.empty:
return {'deleted': 0, 'inserted': 0}
return {"deleted": 0, "inserted": 0}
# Remove duplicates based on PlanNumber and SequenceNumber
original_count = len(df)
df = df.drop_duplicates(subset=['备料计划单号', '序号'], keep='first')
df = df.drop_duplicates(subset=["备料计划单号", "序号"], keep="first")
duplicates_removed = original_count - len(df)
if duplicates_removed > 0:
print(f"[INFO] 检测到 {duplicates_removed} 条重复记录(相同计划单号和序号),已自动去重")
print(
f"[INFO] 检测到 {duplicates_removed} 条重复记录(相同计划单号和序号),已自动去重"
)
with get_connection() as db:
# Get unique plan numbers
plan_numbers = df['备料计划单号'].unique().tolist()
plan_numbers = df["备料计划单号"].unique().tolist()
# Delete existing records
deleted = self._delete_by_plan_numbers(db, plan_numbers)
@@ -57,7 +59,7 @@ class DiscreteMaterialPlanDAO(BaseDAO):
# Insert new records in batches
inserted = self._batch_insert(db, df)
return {'deleted': deleted, 'inserted': inserted}
return {"deleted": deleted, "inserted": inserted}
def _delete_by_plan_numbers(self, db, plan_numbers: List[str]) -> int:
"""
@@ -79,12 +81,12 @@ class DiscreteMaterialPlanDAO(BaseDAO):
total_deleted = 0
for i in range(0, len(plan_numbers), batch_size):
batch = plan_numbers[i:i + batch_size]
batch = plan_numbers[i : i + batch_size]
placeholder = self._get_placeholder()
placeholders = ','.join([placeholder for _ in batch])
placeholders = ",".join([placeholder for _ in batch])
# 根据数据库类型选择表名
table_name = self._convert_sql('[dbo].[DiscreteMaterialPlanData]')
table_name = self._convert_sql("[dbo].[DiscreteMaterialPlanData]")
sql = f"DELETE FROM {table_name} WHERE PlanNumber IN ({placeholders})"
deleted = db.execute_update(sql, tuple(batch))
@@ -108,7 +110,7 @@ class DiscreteMaterialPlanDAO(BaseDAO):
Total number of records inserted
"""
# 根据数据库类型选择表名
table_name = self._convert_sql('[dbo].[DiscreteMaterialPlanData]')
table_name = self._convert_sql("[dbo].[DiscreteMaterialPlanData]")
placeholder = self._get_placeholder()
sql = f"""
@@ -126,7 +128,7 @@ class DiscreteMaterialPlanDAO(BaseDAO):
records = self._convert_df_to_records(df)
for i in range(0, len(records), batch_size):
batch = records[i:i + batch_size]
batch = records[i : i + batch_size]
for record in batch:
db.execute_update(sql, record)
total_inserted += 1
@@ -150,20 +152,44 @@ class DiscreteMaterialPlanDAO(BaseDAO):
"""
# Column order must match INSERT statement
column_order = [
'工厂', '备料状态', '备料计划单号', '来源单号', '备料类型', '产品编码',
'产品名称', '产品单位', '产品计划数量', '用料部门', '备注', '制单人',
'制单日期', '审批人', '审批日期', '序号', '材料编码', '材料名称',
'规格', '型号', '图号', '物料材质', '计划数量', '单位', '需用日期',
'发料仓库', '单位用量', '累计出库数量', 'BOM版本'
"工厂",
"备料状态",
"备料计划单号",
"来源单号",
"备料类型",
"产品编码",
"产品名称",
"产品单位",
"产品计划数量",
"用料部门",
"备注",
"制单人",
"制单日期",
"审批人",
"审批日期",
"序号",
"材料编码",
"材料名称",
"规格",
"型号",
"图号",
"物料材质",
"计划数量",
"单位",
"需用日期",
"发料仓库",
"单位用量",
"累计出库数量",
"BOM版本",
]
# Numeric columns with their default values and data types
numeric_columns = {
'产品计划数量': (0, int),
'序号': (0, int),
'计划数量': (0, int),
'单位用量': (0.0, float),
'累计出库数量': (0, int),
"产品计划数量": (0, int),
"序号": (0, int),
"计划数量": (0, int),
"单位用量": (0.0, float),
"累计出库数量": (0, int),
}
records = []
@@ -172,7 +198,11 @@ class DiscreteMaterialPlanDAO(BaseDAO):
for col in column_order:
value = row.get(col)
# Handle NaN, None, or empty string values
if pd.isna(value) or value is None or (isinstance(value, str) and value.strip() == ''):
if (
pd.isna(value)
or value is None
or (isinstance(value, str) and value.strip() == "")
):
if col in numeric_columns:
# Use default value for numeric columns
record.append(numeric_columns[col][0])
@@ -209,7 +239,7 @@ class DiscreteMaterialPlanDAO(BaseDAO):
List of dictionaries representing records
"""
with get_connection() as db:
table_name = self._convert_sql('[dbo].[DiscreteMaterialPlanData]')
table_name = self._convert_sql("[dbo].[DiscreteMaterialPlanData]")
placeholder = self._get_placeholder()
sql = f"SELECT * FROM {table_name} WHERE PlanNumber = {placeholder}"
return db.execute_query(sql, (plan_number,))
@@ -227,8 +257,8 @@ class DiscreteMaterialPlanDAO(BaseDAO):
if not plan_numbers:
return []
placeholder = self._get_placeholder()
placeholders = ','.join([placeholder for _ in plan_numbers])
table_name = self._convert_sql('[dbo].[DiscreteMaterialPlanData]')
placeholders = ",".join([placeholder for _ in plan_numbers])
table_name = self._convert_sql("[dbo].[DiscreteMaterialPlanData]")
sql = f"SELECT * FROM {table_name} WHERE PlanNumber IN ({placeholders})"
with get_connection() as db:
return db.execute_query(sql, tuple(plan_numbers))
@@ -244,7 +274,7 @@ class DiscreteMaterialPlanDAO(BaseDAO):
List of dictionaries representing records
"""
with get_connection() as db:
table_name = self._convert_sql('[dbo].[DiscreteMaterialPlanData]')
table_name = self._convert_sql("[dbo].[DiscreteMaterialPlanData]")
placeholder = self._get_placeholder()
sql = f"SELECT * FROM {table_name} WHERE SourceNumber = {placeholder}"
return db.execute_query(sql, (order_id,))
@@ -260,11 +290,11 @@ class DiscreteMaterialPlanDAO(BaseDAO):
Number of records
"""
with get_connection() as db:
table_name = self._convert_sql('[dbo].[DiscreteMaterialPlanData]')
table_name = self._convert_sql("[dbo].[DiscreteMaterialPlanData]")
placeholder = self._get_placeholder()
sql = f"SELECT COUNT(*) as count FROM {table_name} WHERE PlanNumber = {placeholder}"
result = db.execute_query(sql, (plan_number,))
return result[0]['count'] if result else 0
return result[0]["count"] if result else 0
def count_all(self) -> int:
"""
@@ -274,10 +304,10 @@ class DiscreteMaterialPlanDAO(BaseDAO):
Total number of records
"""
with get_connection() as db:
table_name = self._convert_sql('[dbo].[DiscreteMaterialPlanData]')
table_name = self._convert_sql("[dbo].[DiscreteMaterialPlanData]")
sql = f"SELECT COUNT(*) as count FROM {table_name}"
result = db.execute_query(sql)
return result[0]['count'] if result else 0
return result[0]["count"] if result else 0
def delete_by_plan_numbers(self, plan_numbers: List[str]) -> int:
"""
@@ -301,7 +331,7 @@ class DiscreteMaterialPlanDAO(BaseDAO):
unique plans, unique orders, and date range
"""
with get_connection() as db:
table_name = self._convert_sql('[dbo].[DiscreteMaterialPlanData]')
table_name = self._convert_sql("[dbo].[DiscreteMaterialPlanData]")
sql = f"""
SELECT
COUNT(*) as total_records,
@@ -324,7 +354,7 @@ class DiscreteMaterialPlanDAO(BaseDAO):
List of dictionaries representing all records
"""
with get_connection() as db:
table_name = self._convert_sql('[dbo].[DiscreteMaterialPlanData]')
table_name = self._convert_sql("[dbo].[DiscreteMaterialPlanData]")
sql = f"SELECT * FROM {table_name}"
return db.execute_query(sql)
@@ -346,10 +376,10 @@ class DiscreteMaterialPlanDAO(BaseDAO):
all_results = []
for i in range(0, len(source_numbers), batch_size):
batch = source_numbers[i:i + batch_size]
batch = source_numbers[i : i + batch_size]
placeholder = self._get_placeholder()
placeholders = ','.join([placeholder for _ in batch])
table_name = self._convert_sql('[dbo].[DiscreteMaterialPlanData]')
placeholders = ",".join([placeholder for _ in batch])
table_name = self._convert_sql("[dbo].[DiscreteMaterialPlanData]")
sql = f"SELECT * FROM {table_name} WHERE SourceNumber IN ({placeholders})"
with get_connection() as db:
results = db.execute_query(sql, tuple(batch))
@@ -368,7 +398,7 @@ class DiscreteMaterialPlanDAO(BaseDAO):
List of dictionaries representing deduplicated records
"""
with get_connection() as db:
table_name = self._convert_sql('[dbo].[DiscreteMaterialPlanData]')
table_name = self._convert_sql("[dbo].[DiscreteMaterialPlanData]")
sql = f"""
WITH RankedRecords AS (
@@ -414,10 +444,10 @@ class DiscreteMaterialPlanDAO(BaseDAO):
all_results = []
for i in range(0, len(source_numbers), batch_size):
batch = source_numbers[i:i + batch_size]
batch = source_numbers[i : i + batch_size]
placeholder = self._get_placeholder()
placeholders = ','.join([placeholder for _ in batch])
table_name = self._convert_sql('[dbo].[DiscreteMaterialPlanData]')
placeholders = ",".join([placeholder for _ in batch])
table_name = self._convert_sql("[dbo].[DiscreteMaterialPlanData]")
sql = f"""
WITH RankedRecords AS (
@@ -458,23 +488,23 @@ class DiscreteMaterialPlanDAO(BaseDAO):
Returns:
List of unique material names
"""
table_name = self._convert_sql('[dbo].[DiscreteMaterialPlanData]')
table_name = self._convert_sql("[dbo].[DiscreteMaterialPlanData]")
if source_numbers is None or not source_numbers:
# No filter - get all unique material names
sql = f"SELECT DISTINCT MaterialName FROM {table_name} WHERE MaterialName IS NOT NULL"
with get_connection() as db:
results = db.execute_query(sql)
return [r['MaterialName'] for r in results if r.get('MaterialName')]
return [r["MaterialName"] for r in results if r.get("MaterialName")]
else:
# Filter by SourceNumber list
batch_size = 2000
all_material_names = set()
for i in range(0, len(source_numbers), batch_size):
batch = source_numbers[i:i + batch_size]
batch = source_numbers[i : i + batch_size]
placeholder = self._get_placeholder()
placeholders = ','.join([placeholder for _ in batch])
placeholders = ",".join([placeholder for _ in batch])
sql = f"""
SELECT DISTINCT MaterialName
FROM {table_name}
@@ -483,7 +513,9 @@ class DiscreteMaterialPlanDAO(BaseDAO):
"""
with get_connection() as db:
results = db.execute_query(sql, tuple(batch))
batch_materials = [r['MaterialName'] for r in results if r.get('MaterialName')]
batch_materials = [
r["MaterialName"] for r in results if r.get("MaterialName")
]
all_material_names.update(batch_materials)
return list(all_material_names)

View File

@@ -16,9 +16,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
# ==================== CREATE ====================
def insert_material(
self, material_name: str, manager_name: str
) -> bool:
def insert_material(self, material_name: str, manager_name: str) -> bool:
"""
Insert a single material record.
@@ -29,7 +27,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
Returns:
True if successful, False otherwise
"""
table_name = self._convert_sql('[dbo].[MaterialsTypeToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsTypeToBeDeleted]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -65,7 +63,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
if not materials:
return 0
table_name = self._convert_sql('[dbo].[MaterialsTypeToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsTypeToBeDeleted]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -100,7 +98,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
Returns:
List of all materials with MaterialName and ManagerName
"""
table_name = self._convert_sql('[dbo].[MaterialsTypeToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsTypeToBeDeleted]")
# 根据数据库类型选择列名格式
if self._db_type == DatabaseType.MYSQL:
@@ -131,7 +129,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
Returns:
List of materials for the specified manager
"""
table_name = self._convert_sql('[dbo].[MaterialsTypeToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsTypeToBeDeleted]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -160,7 +158,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
Returns:
List of unique manager names
"""
table_name = self._convert_sql('[dbo].[MaterialsTypeToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsTypeToBeDeleted]")
# 根据数据库类型选择列名格式
if self._db_type == DatabaseType.MYSQL:
@@ -180,7 +178,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
with get_connection() as db:
results = db.execute_query(sql)
return [r['ManagerName'] for r in results if r.get('ManagerName')]
return [r["ManagerName"] for r in results if r.get("ManagerName")]
def get_material_names_by_manager(self, manager_name: str) -> List[str]:
"""
@@ -193,15 +191,12 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
List of material names for the specified manager
"""
results = self.get_materials_by_manager(manager_name)
return [r['MaterialName'] for r in results if r.get('MaterialName')]
return [r["MaterialName"] for r in results if r.get("MaterialName")]
# ==================== UPDATE ====================
def update_manager(
self,
material_name: str,
old_manager: str,
new_manager: str
self, material_name: str, old_manager: str, new_manager: str
) -> bool:
"""
Update manager for a specific material.
@@ -214,7 +209,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
Returns:
True if successful, False otherwise
"""
table_name = self._convert_sql('[dbo].[MaterialsTypeToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsTypeToBeDeleted]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -233,7 +228,9 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
try:
with get_connection() as db:
affected = db.execute_update(sql, (new_manager, material_name, old_manager))
affected = db.execute_update(
sql, (new_manager, material_name, old_manager)
)
return affected > 0
except Exception as e:
print(f"Error updating manager: {e}")
@@ -241,11 +238,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
# ==================== DELETE ====================
def delete_material(
self,
material_name: str,
manager_name: str
) -> bool:
def delete_material(self, material_name: str, manager_name: str) -> bool:
"""
Delete a specific material record.
@@ -256,7 +249,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
Returns:
True if successful, False otherwise
"""
table_name = self._convert_sql('[dbo].[MaterialsTypeToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsTypeToBeDeleted]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -289,7 +282,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
Returns:
Number of records deleted
"""
table_name = self._convert_sql('[dbo].[MaterialsTypeToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsTypeToBeDeleted]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -318,7 +311,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
Returns:
Number of records deleted
"""
table_name = self._convert_sql('[dbo].[MaterialsTypeToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsTypeToBeDeleted]")
sql = f"DELETE FROM {table_name}"
try:
@@ -340,7 +333,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
Returns:
True if material exists, False otherwise
"""
table_name = self._convert_sql('[dbo].[MaterialsTypeToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsTypeToBeDeleted]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -359,7 +352,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
with get_connection() as db:
result = db.execute_query(sql, (material_name,))
return result[0]['count'] > 0 if result else False
return result[0]["count"] > 0 if result else False
def count_by_manager(self, manager_name: str) -> int:
"""
@@ -371,7 +364,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
Returns:
Number of materials for the manager
"""
table_name = self._convert_sql('[dbo].[MaterialsTypeToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsTypeToBeDeleted]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -390,7 +383,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
with get_connection() as db:
result = db.execute_query(sql, (manager_name,))
return result[0]['count'] if result else 0
return result[0]["count"] if result else 0
def get_statistics(self) -> Dict[str, Any]:
"""
@@ -400,7 +393,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
Dictionary with statistics including total materials,
unique managers, and materials per manager
"""
table_name = self._convert_sql('[dbo].[MaterialsTypeToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsTypeToBeDeleted]")
# 根据数据库类型选择列名格式
if self._db_type == DatabaseType.MYSQL:
@@ -442,8 +435,8 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
# Get materials per manager
manager_results = db.execute_query(manager_sql)
stats['materials_per_manager'] = [
{r['ManagerName']: r['count']} for r in manager_results
stats["materials_per_manager"] = [
{r["ManagerName"]: r["count"]} for r in manager_results
]
return stats
@@ -458,7 +451,7 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
Returns:
List of matching materials
"""
table_name = self._convert_sql('[dbo].[MaterialsTypeToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsTypeToBeDeleted]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -478,4 +471,4 @@ class MaterialsTypeToBeDeletedDAO(BaseDAO):
"""
with get_connection() as db:
return db.execute_query(sql, (f'%{keyword}%',))
return db.execute_query(sql, (f"%{keyword}%",))

View File

@@ -40,7 +40,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
with get_connection() as db:
if self._db_type == DatabaseType.MYSQL:
# MySQL 使用 INSERT ... ON DUPLICATE KEY UPDATE
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsToBeDeleted]")
placeholder = self._get_placeholder()
if self._db_type == DatabaseType.MYSQL:
@@ -57,7 +57,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
"""
else:
# SQL Server 使用 MERGE
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsToBeDeleted]")
sql = f"""
MERGE {table_name} AS target
USING (SELECT {self._get_placeholder()} AS MaterialCode, {self._get_placeholder()} AS ManagerName) AS source
@@ -69,7 +69,13 @@ class MaterialsToBeDeletedDAO(BaseDAO):
VALUES (source.MaterialCode, source.ManagerName);
"""
db.execute_update(sql, (material_code.strip(), manager_name.strip() if manager_name else None))
db.execute_update(
sql,
(
material_code.strip(),
manager_name.strip() if manager_name else None,
),
)
return True
except Exception as e:
print(f"Error upserting material: {e}")
@@ -86,24 +92,26 @@ class MaterialsToBeDeletedDAO(BaseDAO):
Dictionary with statistics: {'total': int, 'success': int, 'failed': int}
"""
if not materials:
return {'total': 0, 'success': 0, 'failed': 0}
return {"total": 0, "success": 0, "failed": 0}
stats = {'total': len(materials), 'success': 0, 'failed': 0}
stats = {"total": len(materials), "success": 0, "failed": 0}
try:
with get_connection() as db:
for material in materials:
material_code = material.get('material_code', '').strip()
manager_name = material.get('manager_name', '')
material_code = material.get("material_code", "").strip()
manager_name = material.get("manager_name", "")
if not material_code:
stats['failed'] += 1
stats["failed"] += 1
continue
try:
if self._db_type == DatabaseType.MYSQL:
# MySQL 使用 INSERT ... ON DUPLICATE KEY UPDATE
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql(
"[dbo].[MaterialsToBeDeleted]"
)
placeholder = self._get_placeholder()
if self._db_type == DatabaseType.MYSQL:
@@ -120,7 +128,9 @@ class MaterialsToBeDeletedDAO(BaseDAO):
"""
else:
# SQL Server 使用 MERGE
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql(
"[dbo].[MaterialsToBeDeleted]"
)
sql = f"""
MERGE {table_name} AS target
USING (SELECT {self._get_placeholder()} AS MaterialCode, {self._get_placeholder()} AS ManagerName) AS source
@@ -132,15 +142,21 @@ class MaterialsToBeDeletedDAO(BaseDAO):
VALUES (source.MaterialCode, source.ManagerName);
"""
db.execute_update(sql, (material_code, manager_name.strip() if manager_name else None))
stats['success'] += 1
db.execute_update(
sql,
(
material_code,
manager_name.strip() if manager_name else None,
),
)
stats["success"] += 1
except Exception as e:
print(f"Error upserting material {material_code}: {e}")
stats['failed'] += 1
stats["failed"] += 1
except Exception as e:
print(f"Error in batch upsert: {e}")
stats['failed'] = stats['total'] - stats['success']
stats["failed"] = stats["total"] - stats["success"]
return stats
@@ -153,7 +169,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
Returns:
Set of material codes
"""
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsToBeDeleted]")
# 根据数据库类型选择列名格式
if self._db_type == DatabaseType.MYSQL:
@@ -172,7 +188,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
try:
with get_connection() as db:
results = db.execute_query(sql)
return {r['MaterialCode'] for r in results if r.get('MaterialCode')}
return {r["MaterialCode"] for r in results if r.get("MaterialCode")}
except Exception as e:
print(f"Error getting material codes: {e}")
return set()
@@ -184,7 +200,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
Returns:
List of all material records with all fields
"""
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsToBeDeleted]")
# 根据数据库类型选择列名格式
if self._db_type == DatabaseType.MYSQL:
@@ -215,7 +231,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
Returns:
List of materials for the specified manager
"""
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsToBeDeleted]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -244,7 +260,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
Returns:
List of unique manager names
"""
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsToBeDeleted]")
# 根据数据库类型选择列名格式
if self._db_type == DatabaseType.MYSQL:
@@ -264,7 +280,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
with get_connection() as db:
results = db.execute_query(sql)
return [r['ManagerName'] for r in results if r.get('ManagerName')]
return [r["ManagerName"] for r in results if r.get("ManagerName")]
def get_records_by_manager(self, manager_name: str) -> List[Dict[str, Any]]:
"""
@@ -280,7 +296,9 @@ class MaterialsToBeDeletedDAO(BaseDAO):
"""
return self.get_materials_by_manager(manager_name)
def get_record_by_material_code(self, material_code: str) -> Optional[Dict[str, Any]]:
def get_record_by_material_code(
self, material_code: str
) -> Optional[Dict[str, Any]]:
"""
Get a specific record by material code.
@@ -290,7 +308,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
Returns:
Dictionary representing the record, or None if not found
"""
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsToBeDeleted]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -323,7 +341,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
Returns:
True if successful, False otherwise
"""
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsToBeDeleted]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -356,7 +374,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
Returns:
Number of records deleted
"""
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsToBeDeleted]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -385,7 +403,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
Returns:
Number of records deleted
"""
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsToBeDeleted]")
sql = f"DELETE FROM {table_name}"
try:
@@ -412,16 +430,18 @@ class MaterialsToBeDeletedDAO(BaseDAO):
total_deleted = 0
for i in range(0, len(material_codes), batch_size):
batch = material_codes[i:i + batch_size]
batch = material_codes[i : i + batch_size]
placeholder = self._get_placeholder()
placeholders = ','.join([placeholder for _ in batch])
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
placeholders = ",".join([placeholder for _ in batch])
table_name = self._convert_sql("[dbo].[MaterialsToBeDeleted]")
# 根据数据库类型选择列名格式
if self._db_type == DatabaseType.MYSQL:
sql = f"DELETE FROM {table_name} WHERE MaterialCode IN ({placeholders})"
else:
sql = f"DELETE FROM {table_name} WHERE [MaterialCode] IN ({placeholders})"
sql = (
f"DELETE FROM {table_name} WHERE [MaterialCode] IN ({placeholders})"
)
try:
with get_connection() as db:
@@ -444,7 +464,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
Returns:
True if material exists, False otherwise
"""
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsToBeDeleted]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -463,7 +483,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
with get_connection() as db:
result = db.execute_query(sql, (material_code.strip(),))
return result[0]['count'] > 0 if result else False
return result[0]["count"] > 0 if result else False
def count_all(self) -> int:
"""
@@ -472,12 +492,12 @@ class MaterialsToBeDeletedDAO(BaseDAO):
Returns:
Total number of records
"""
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsToBeDeleted]")
sql = f"SELECT COUNT(*) as count FROM {table_name}"
with get_connection() as db:
result = db.execute_query(sql)
return result[0]['count'] if result else 0
return result[0]["count"] if result else 0
def count_by_manager(self, manager_name: str) -> int:
"""
@@ -489,7 +509,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
Returns:
Number of materials for the manager
"""
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsToBeDeleted]")
placeholder = self._get_placeholder()
# 根据数据库类型选择列名格式
@@ -508,7 +528,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
with get_connection() as db:
result = db.execute_query(sql, (manager_name,))
return result[0]['count'] if result else 0
return result[0]["count"] if result else 0
def get_statistics(self) -> Dict[str, Any]:
"""
@@ -518,7 +538,7 @@ class MaterialsToBeDeletedDAO(BaseDAO):
Dictionary with statistics including total materials,
unique managers, and materials per manager
"""
table_name = self._convert_sql('[dbo].[MaterialsToBeDeleted]')
table_name = self._convert_sql("[dbo].[MaterialsToBeDeleted]")
# 根据数据库类型选择列名格式
if self._db_type == DatabaseType.MYSQL:
@@ -560,8 +580,8 @@ class MaterialsToBeDeletedDAO(BaseDAO):
# Get materials per manager
manager_results = db.execute_query(manager_sql)
stats['materials_per_manager'] = [
{r['ManagerName']: r['count']} for r in manager_results
stats["materials_per_manager"] = [
{r["ManagerName"]: r["count"]} for r in manager_results
]
return stats

View File

@@ -72,7 +72,9 @@ def get_materials_to_delete_by_managers(
"""
with get_connection() as conn:
results = conn.execute_query(query)
material_codes = [row["MaterialCode"] for row in results if row["MaterialCode"]]
material_codes = [
row["MaterialCode"] for row in results if row["MaterialCode"]
]
return material_codes
else:
# 使用 IN 子句查询多个负责人
@@ -85,7 +87,9 @@ def get_materials_to_delete_by_managers(
"""
with get_connection() as conn:
results = conn.execute_query(query, tuple(manager_names))
material_codes = [row["MaterialCode"] for row in results if row["MaterialCode"]]
material_codes = [
row["MaterialCode"] for row in results if row["MaterialCode"]
]
return material_codes

View File

@@ -40,13 +40,13 @@ class MySQLConnection(BaseDatabaseConnection):
try:
self.connection = mysql.connector.connect(
host=self.config.get('host', 'localhost'),
port=self.config.get('port', 3306),
database=self.config['database'],
user=self.config['username'],
password=self.config['password'],
charset=self.config.get('charset', 'utf8mb4'),
autocommit=False
host=self.config.get("host", "localhost"),
port=self.config.get("port", 3306),
database=self.config["database"],
user=self.config["username"],
password=self.config["password"],
charset=self.config.get("charset", "utf8mb4"),
autocommit=False,
)
print(
f"成功连接到 MySQL 数据库: {self.config.get('host', 'localhost')}"
@@ -153,7 +153,7 @@ class MySQLConnection(BaseDatabaseConnection):
Returns:
str: SQL query with MySQL-compatible placeholders
"""
return sql.replace('?', '%s')
return sql.replace("?", "%s")
def _convert_table_names(self, sql: str) -> str:
"""
@@ -171,10 +171,10 @@ class MySQLConnection(BaseDatabaseConnection):
import re
# Convert [dbo].[TableName] to dbo_TableName
sql = re.sub(r'\[dbo\]\.\[([^\]]+)\]', r'dbo_\1', sql)
sql = re.sub(r"\[dbo\]\.\[([^\]]+)\]", r"dbo_\1", sql)
# Remove square brackets from column names (e.g., [Column] -> Column)
sql = re.sub(r'\[([^\]]+)\]', r'\1', sql)
sql = re.sub(r"\[([^\]]+)\]", r"\1", sql)
return sql

View File

@@ -32,12 +32,14 @@ class ProductionContractDataDAO(BaseDAO):
all_results = []
for i in range(0, len(总排号_list), batch_size):
batch = 总排号_list[i:i + batch_size]
batch = 总排号_list[i : i + batch_size]
placeholder = self._get_placeholder()
placeholders = ','.join([placeholder for _ in batch])
placeholders = ",".join([placeholder for _ in batch])
# 根据数据库类型选择表名
table_name = self._convert_sql('[productionContractData].[26年压力表合同数据]')
table_name = self._convert_sql(
"[productionContractData].[26年压力表合同数据]"
)
# 根据数据库类型选择列名格式
if self._db_type == DatabaseType.MYSQL:
@@ -73,9 +75,9 @@ class ProductionContractDataDAO(BaseDAO):
"""
results = self.query_by_总排号(总排号_list)
# Extract unique 生产订单号 values, excluding None/null values
source_numbers = list(set(
[r['生产订单号'] for r in results if r.get('生产订单号')]
))
source_numbers = list(
set([r["生产订单号"] for r in results if r.get("生产订单号")])
)
return source_numbers
def get_生产订单号_map(self, 总排号_list: List[str]) -> Dict[str, str]:
@@ -90,7 +92,7 @@ class ProductionContractDataDAO(BaseDAO):
"""
results = self.query_by_总排号(总排号_list)
return {
r['总排号']: r['生产订单号']
r["总排号"]: r["生产订单号"]
for r in results
if r.get('总排号') and r.get('生产订单号')
if r.get("总排号") and r.get("生产订单号")
}

View File

@@ -95,7 +95,9 @@ def _query_order_numbers_from_db(production_ids, db_type):
results = conn.execute_query(query, tuple(batch))
# 提取生产订单号并去除空值
batch_numbers = [row["生产订单号"] for row in results if row.get("生产订单号")]
batch_numbers = [
row["生产订单号"] for row in results if row.get("生产订单号")
]
all_results.extend(batch_numbers)
return all_results
@@ -118,7 +120,7 @@ def query_production_order_numbers(inputs):
return []
production_ids = [] # 需要查询数据库的
order_numbers = [] # 直接使用的
order_numbers = [] # 直接使用的
for item in inputs:
input_type = identify_input_type(item)

View File

@@ -38,7 +38,7 @@ class SQLServerConnection(BaseDatabaseConnection):
return self.connection
# 构建连接字符串
driver = self.config.get('driver', 'ODBC Driver 18 for SQL Server')
driver = self.config.get("driver", "ODBC Driver 18 for SQL Server")
conn_str = (
f"DRIVER={{{driver}}};"
f"SERVER={self.config['server']};"

View File

@@ -12,7 +12,7 @@ class TableNameConverter:
"""表名转换工具类"""
# 匹配 SQL Server 表名格式:[schema].[tablename] 或 [schema].[table name]
SQLSERVER_PATTERN = re.compile(r'\[([^\]]+)\]\.\[([^\]]+)\]')
SQLSERVER_PATTERN = re.compile(r"\[([^\]]+)\]\.\[([^\]]+)\]")
@staticmethod
def to_mysql(table_name: str) -> str:
@@ -66,7 +66,7 @@ class TableNameConverter:
'[productionContractData].[26年压力表合同数据]'
"""
# 分割第一个下划线
parts = table_name.split('_', 1)
parts = table_name.split("_", 1)
if len(parts) == 2:
schema = parts[0]
table = parts[1]
@@ -92,21 +92,24 @@ class TableNameConverter:
>>> TableNameConverter.convert_sql(sql, 'mysql')
'SELECT * FROM dbo_BIPUsers WHERE ID = ?'
"""
if db_type == 'mysql':
if db_type == "mysql":
# SQL Server → MySQL
def replace_to_mysql(match):
schema = match.group(1)
table = match.group(2)
return f"{schema}_{table}"
result = TableNameConverter.SQLSERVER_PATTERN.sub(replace_to_mysql, sql)
return result
elif db_type == 'sqlserver':
elif db_type == "sqlserver":
# MySQL → SQL Server
# 首先查找可能的 MySQL 格式表名schema_table 格式)
# 这是一个简化版本,可能无法处理所有边缘情况
result = sql
# 查找单词字符_单词字符 的模式(可能是表名)
mysql_pattern = re.compile(r'\b([a-zA-Z_][a-zA-Z0-9_]*)_([a-zA-Z0-9_\u4e00-\u9fff]+)\b')
mysql_pattern = re.compile(
r"\b([a-zA-Z_][a-zA-Z0-9_]*)_([a-zA-Z0-9_\u4e00-\u9fff]+)\b"
)
matches = mysql_pattern.findall(result)
for schema, table in set(matches):
mysql_name = f"{schema}_{table}"
@@ -133,7 +136,7 @@ class TableNameConverter:
tables.append(f"{schema}_{table}")
# 查找可能的 MySQL 格式
mysql_pattern = re.compile(r'\b[a-zA-Z_][a-zA-Z0-9_]*_[a-zA-Z0-9_]+\b')
mysql_pattern = re.compile(r"\b[a-zA-Z_][a-zA-Z0-9_]*_[a-zA-Z0-9_]+\b")
mysql_matches = mysql_pattern.findall(sql)
tables.extend(mysql_matches)