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:
@@ -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]]:
|
||||
"""
|
||||
执行查询语句并返回结果
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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}%",))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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("生产订单号")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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']};"
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user