1.客户信息修改,将硬编码改为动态取值
2.新增项目批量停用、材料批量修改功能
This commit is contained in:
@@ -0,0 +1,281 @@
|
||||
"""
|
||||
项目材料相关后台任务模块
|
||||
|
||||
本模块包含项目材料相关的后台任务,包括:
|
||||
- 项目信息批量停用
|
||||
- 材料信息批量修改
|
||||
|
||||
这些任务在后台线程中执行,不会阻塞主请求。
|
||||
"""
|
||||
import logging
|
||||
import traceback
|
||||
import requests
|
||||
import time
|
||||
from typing import Dict, Any, List, Optional
|
||||
from datetime import datetime
|
||||
from tqdm import tqdm
|
||||
from app.tasks.common import update_jiandaoyun, approve_workflow, get_operate_org_id, get_card_list, \
|
||||
execute_failure_handler
|
||||
import pandas as pd
|
||||
import os
|
||||
|
||||
logger = logging.getLogger('app')
|
||||
|
||||
|
||||
def batch_disable_projects(data: Dict[str, Any], cookies: Dict[str, str], df: pd.DataFrame, save_path: str,
|
||||
option) -> None:
|
||||
"""
|
||||
项目批量停用后台任务
|
||||
|
||||
在后台线程中批量停用项目,从 Excel 文件中读取项目编码。
|
||||
执行完成后会更新简道云表单并自动提交工作流。
|
||||
|
||||
Args:
|
||||
data: 包含表单ID(api_key)、表单ID(entry_id)、数据ID(data_id)的字典
|
||||
cookies: 用户登录 F6 系统的 cookies 信息
|
||||
df: Excel 文件读取的内容,DataFrame 格式,第一列为项目编码
|
||||
save_path: Excel 文件保存的地址,执行完成后会删除此文件
|
||||
option: 批量启用、批量停用
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
注意:
|
||||
- 无效的项目(None、空字符串)会被跳过
|
||||
- 执行完成后会自动删除上传的文件
|
||||
- 执行结果会更新到简道云表单
|
||||
"""
|
||||
if option == "批量启用":
|
||||
type_ = 0 # 1 停用,0启用
|
||||
else:
|
||||
type_ = 1
|
||||
df = df.where(pd.notnull(df), None)
|
||||
|
||||
# 获取门店id
|
||||
org_id = get_operate_org_id(data)
|
||||
# 获取项目信息
|
||||
json_data = {
|
||||
'param': '',
|
||||
'name': '',
|
||||
'customCode': '',
|
||||
'currentPage': 1,
|
||||
'pageSize': 100,
|
||||
'isDel': -type_,
|
||||
'customInvoiceCategory': 0,
|
||||
'idOwnOrg': org_id,
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
'https://ids-goods.f6car.cn/f6-ids-goods/service/getServiceList',
|
||||
cookies=cookies,
|
||||
json=json_data,
|
||||
)
|
||||
all_project_list = []
|
||||
total_pages = response.json().get("data", {}).get("totalPages", "")
|
||||
for page in tqdm(range(1, total_pages + 1)):
|
||||
json_data['currentPage'] = str(page)
|
||||
response = requests.post(
|
||||
'https://ids-goods.f6car.cn/f6-ids-goods/service/getServiceList',
|
||||
cookies=cookies,
|
||||
json=json_data,
|
||||
)
|
||||
project_list = response.json().get("data", {}).get("records", [])
|
||||
all_project_list.extend(project_list)
|
||||
|
||||
# 遍历获取到的项目信息停用文件中的项目
|
||||
code_list = df.iloc[:, 0].dropna().astype(str).tolist()
|
||||
res_data_list = []
|
||||
results = []
|
||||
for item in tqdm(all_project_list):
|
||||
custom_code = item.get("customCode")
|
||||
if not custom_code or str(custom_code) not in code_list or not code_list:
|
||||
continue
|
||||
info_id = item.get("infoId")
|
||||
pk_id = item.get("pkId")
|
||||
json_data = {
|
||||
"orgIdList": [
|
||||
org_id,
|
||||
],
|
||||
"isDel": type_, # 1 停用 0启用
|
||||
"infoId": info_id,
|
||||
"pkId": pk_id,
|
||||
"type": 1,
|
||||
"idOwnOrg": org_id
|
||||
}
|
||||
try:
|
||||
response = requests.post(
|
||||
'https://ids-goods.f6car.cn/f6-ids-goods/service/editAttributeByType',
|
||||
cookies=cookies,
|
||||
json=json_data,
|
||||
)
|
||||
res_data_list.append(response.json())
|
||||
response.raise_for_status() # 抛出HTTP错误
|
||||
results.append({'材料编码': custom_code, '状态': '停用/启用成功'})
|
||||
except requests.exceptions.RequestException as e:
|
||||
results.append({'材料编码': custom_code, '状态': f'停用/启用失败: {str(e)}'})
|
||||
pass
|
||||
|
||||
print({'msg': '已执行', 'msg_details': f'{results}'})
|
||||
logger.info(f"停用/启用结果: {results}")
|
||||
os.remove(save_path)
|
||||
print(f'{save_path}已删除')
|
||||
# 调用api回写改掉 执行明细与执行状态
|
||||
msg = update_jiandaoyun(data, f'{results}')
|
||||
|
||||
if msg.get('msg'):
|
||||
approve_workflow(data)
|
||||
print('表单已自动提交至下一步')
|
||||
|
||||
|
||||
def batch_modify_materials(data: Dict[str, Any], cookies: Dict[str, str], df: pd.DataFrame, save_path: str,
|
||||
) -> None:
|
||||
"""
|
||||
材料批量修改后台任务
|
||||
|
||||
在后台线程中批量修改材料,从 Excel 文件中读取材料编码。
|
||||
执行完成后会更新简道云表单并自动提交工作流。
|
||||
|
||||
Args:
|
||||
data: 包含表单ID(api_key)、表单ID(entry_id)、数据ID(data_id)的字典
|
||||
cookies: 用户登录 F6 系统的 cookies 信息
|
||||
df: Excel 文件读取的内容,DataFrame 格式,第一列为材料编码
|
||||
save_path: Excel 文件保存的地址,执行完成后会删除此文件
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
注意:
|
||||
- 无效的材料编码(None、空字符串)会被跳过
|
||||
- 执行完成后会自动删除上传的文件
|
||||
- 执行结果会更新到简道云表单
|
||||
"""
|
||||
|
||||
# 获取门店id
|
||||
org_id = get_operate_org_id(data)
|
||||
# 获取材料信息
|
||||
json_data = {
|
||||
'keyWord': '',
|
||||
'idOwnOrg': org_id,
|
||||
'currentPage': 1,
|
||||
'pageSize': 100,
|
||||
'name': '',
|
||||
'brand': '',
|
||||
'supplierCode': '',
|
||||
'customCode': '',
|
||||
'categoryName': '',
|
||||
'categoryId': '',
|
||||
'labelId': '',
|
||||
'labelName': '',
|
||||
'spec': '',
|
||||
'applyModel': '',
|
||||
'sellPurchaseStatuses': [
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
],
|
||||
'customInvoiceCategory': 0,
|
||||
'getThirdPlatformCode': 0,
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
'https://ids-goods.f6car.com/f6-ids-goods/part/getExactPartStockInfo',
|
||||
cookies=cookies,
|
||||
json=json_data,
|
||||
)
|
||||
all_materials_list = []
|
||||
total_pages = response.json().get("data", {}).get("totalPages", "")
|
||||
for page in tqdm(range(1, total_pages + 1)):
|
||||
json_data['currentPage'] = str(page)
|
||||
response = requests.post(
|
||||
'https://ids-goods.f6car.com/f6-ids-goods/part/getExactPartStockInfo',
|
||||
cookies=cookies,
|
||||
json=json_data,
|
||||
)
|
||||
materials_list = response.json().get("data", {}).get("records", [])
|
||||
all_materials_list.extend(materials_list)
|
||||
|
||||
# 构建更新映射:{原customCode: {new_customCode, brand, name, spec}}
|
||||
update_map = {}
|
||||
for _, row in df.iterrows():
|
||||
orig_code = str(row.iloc[0]).strip() if pd.notna(row.iloc[0]) else None
|
||||
if not orig_code:
|
||||
continue
|
||||
update_map[orig_code] = {
|
||||
"customCode": str(row.iloc[1]).strip() if pd.notna(row.iloc[1]) else "",
|
||||
"brand": str(row.iloc[2]).strip() if pd.notna(row.iloc[2]) else "",
|
||||
"name": str(row.iloc[3]).strip() if pd.notna(row.iloc[3]) else "",
|
||||
"spec": str(row.iloc[4]).strip() if pd.notna(row.iloc[4]) else "",
|
||||
}
|
||||
|
||||
# 遍历获取到的材料信息修改材料属性
|
||||
code_list = df.iloc[:, 0].dropna().astype(str).tolist()
|
||||
res_data_list = []
|
||||
results = []
|
||||
for item in tqdm(all_materials_list):
|
||||
custom_code = item.get("customCode")
|
||||
# 判断当前材料编码是否在文件中
|
||||
if not custom_code or str(custom_code) not in update_map:
|
||||
continue
|
||||
part_id = item.get("partId")
|
||||
try:
|
||||
# 获取材料明细
|
||||
params = {
|
||||
'partId': part_id,
|
||||
'customInvoiceCategory': '0',
|
||||
'getThirdPlatformCode': '0',
|
||||
}
|
||||
|
||||
materials_response = requests.get(
|
||||
'https://ids-goods.f6car.com/f6-ids-goods/part/getPartInfo',
|
||||
params=params,
|
||||
cookies=cookies,
|
||||
)
|
||||
if materials_response.status_code != 200:
|
||||
results.append({'材料编码': custom_code, '状态': '获取明细失败'})
|
||||
continue
|
||||
|
||||
detail = materials_response.json().get("data")
|
||||
if not detail:
|
||||
results.append({'材料编码': custom_code, '状态': '明细为空'})
|
||||
continue
|
||||
|
||||
updates = update_map[custom_code]
|
||||
# === 关键:强制覆盖,空值也写入 ===
|
||||
detail["customCode"] = updates["customCode"] # 可能是 ""
|
||||
detail["brand"] = updates["brand"] # 可能是 ""
|
||||
detail["name"] = updates["name"] # 可能是 ""
|
||||
detail["showName"] = updates["name"] # 同步 showName(重要!)
|
||||
detail["spec"] = updates["spec"] # 可能是 ""
|
||||
|
||||
# 修复价格和数组(必须!)
|
||||
for f in ["purchasePrice", "sellPrice"]:
|
||||
if isinstance(detail.get(f), (int, float)):
|
||||
detail[f] = f"{detail[f]:.2f}"
|
||||
if detail.get("partBarCodeVos") is None:
|
||||
detail["partBarCodeVos"] = []
|
||||
|
||||
update_resp = requests.post(
|
||||
'https://ids-goods.f6car.com/f6-ids-goods/part/updateAreaPartBasicInfo',
|
||||
cookies=cookies,
|
||||
json=detail
|
||||
)
|
||||
if update_resp.status_code == 200 and update_resp.json().get("code") == 200:
|
||||
results.append({'材料编码': custom_code, '状态': '修改成功'})
|
||||
else:
|
||||
msg = update_resp.json().get("message", "未知错误")
|
||||
results.append({'材料编码': custom_code, '状态': f'修改失败: {msg}'})
|
||||
except requests.exceptions.RequestException as e:
|
||||
results.append({'材料编码': custom_code, '状态': f'修改属性失败: {str(e)}'})
|
||||
pass
|
||||
|
||||
print({'msg': '已执行', 'msg_details': f'{results}'})
|
||||
logger.info(f"批量修改结果: {results}")
|
||||
os.remove(save_path)
|
||||
print(f'{save_path}已删除')
|
||||
# 调用api回写改掉 执行明细与执行状态
|
||||
msg = update_jiandaoyun(data, f'{results}')
|
||||
|
||||
if msg.get('msg'):
|
||||
approve_workflow(data)
|
||||
print('表单已自动提交至下一步')
|
||||
Reference in New Issue
Block a user