mirror of
https://github.com/rnvm9wjdtj-bot/myaps_api.git
synced 2026-06-02 05:54:40 +00:00
211 lines
7.8 KiB
Python
211 lines
7.8 KiB
Python
"""
|
|
淮安超越橡塑项目文件
|
|
需要 ERP 推送的数据:
|
|
- 各种主数据
|
|
- 销售订单SO
|
|
- 审批好的新 PO 及后续执行情况
|
|
- 报工数据
|
|
|
|
其他:
|
|
- 物料主数据
|
|
- free1 是否倒冲料,Y 表示倒冲料,N 表示普通物料
|
|
|
|
# - 销售订单SO
|
|
# - free1 客户订单号
|
|
# - free2 客户产品号
|
|
# - free3 包装要求
|
|
"""
|
|
from core.settings import MYAPS_DB_SET, MYAPS_MAIN_DB, THIS_BASE_URL, SCHEDULER_HOUR, SCHEDULER_MINUTE
|
|
from .._base import (
|
|
get_scheduler_minute, cron_task, CLIENT_LOGGER, CLIENT_SESSION, PROJECT_JSON_FILE,
|
|
ApsHelpers, get_session
|
|
)
|
|
|
|
|
|
from apps.data_opt.components.yonyou_tplus import TplusConnection, RsPushModel, MoPushModel, model_validator
|
|
from typing import Dict, Any
|
|
|
|
#################################################################################
|
|
# ⬇️ 项目对象及参数
|
|
#################################################################################
|
|
REMAIN_NATIVE_SUPPLYNO = True # 本项目需要推送 MO 前后关系,所以必须保留原生供应号,否则会导致关系断开
|
|
|
|
# 延迟初始化TplusConnection,避免在模块导入时立即连接
|
|
_tplus_conn = None
|
|
|
|
def get_tplus_conn():
|
|
"""获取TplusConnection实例(延迟初始化)"""
|
|
global _tplus_conn
|
|
if _tplus_conn is None:
|
|
_tplus_conn = TplusConnection()
|
|
return _tplus_conn
|
|
|
|
#################################################################################
|
|
# ⬇️ 项目可复用逻辑
|
|
#################################################################################
|
|
|
|
def refresh_stock(dbs: str=MYAPS_DB_SET):
|
|
"""刷新库存数据"""
|
|
try:
|
|
tplus_conn = get_tplus_conn()
|
|
stock_data = tplus_conn.pull_stock()
|
|
if stock_data:
|
|
ApsHelpers.refresh_supply(stock_data, dbs=dbs)
|
|
except Exception as e:
|
|
CLIENT_LOGGER.fail("刷新库存数据", "", str(e))
|
|
raise
|
|
|
|
|
|
#################################################################################
|
|
# ⬇️ 定时任务
|
|
#################################################################################
|
|
@cron_task(hour=SCHEDULER_HOUR, minute=get_scheduler_minute(), description="刷新库存数据")
|
|
def task_refresh_stock():
|
|
"""定时任务:刷新库存数据"""
|
|
try:
|
|
refresh_stock()
|
|
CLIENT_LOGGER.success("定时任务执行", "刷新库存数据", "任务完成")
|
|
except Exception as e:
|
|
CLIENT_LOGGER.fail("定时任务执行", "刷新库存数据", f"任务失败: {str(e)}")
|
|
# 不抛出异常,避免影响其他任务
|
|
|
|
|
|
@cron_task(hour=SCHEDULER_HOUR, minute=get_scheduler_minute(1), description="确认报工")
|
|
def task_confirm_workreport():
|
|
"""定时任务:确认报工"""
|
|
try:
|
|
ApsHelpers.confirm_workreport()
|
|
CLIENT_LOGGER.success("定时任务执行", "确认报工", "任务完成")
|
|
except Exception as e:
|
|
CLIENT_LOGGER.fail("定时任务执行", "确认报工", f"任务失败: {str(e)}")
|
|
# 不抛出异常,避免影响其他任务
|
|
|
|
#################################################################################
|
|
# ⬇️ 数据库事件
|
|
#################################################################################
|
|
class CustomMoPushModel(MoPushModel):
|
|
|
|
class Config:
|
|
extra = 'allow'
|
|
|
|
@model_validator(mode="before")
|
|
@classmethod
|
|
def model_valid(cls, values: Dict[str, Any]):
|
|
cleaned_values = MoPushModel.model_valid(values)
|
|
|
|
workcenter = None
|
|
try:
|
|
first_orderwc = values["orderwc"][0]
|
|
workcenter = first_orderwc.get("workcenter", "")
|
|
except:
|
|
workcenter = ""
|
|
cleaned_values['Department'] = {'Code': workcenter}
|
|
|
|
mo_details = cleaned_values['ManufactureOrderDetails'][0]
|
|
mo_material_details: list[dict] = mo_details['ManufactureOrderMaterialDetails']
|
|
|
|
# 批量查询所有物料的 free1 字段
|
|
materialnos = [md['Inventory']['Code'] for md in mo_material_details]
|
|
materials = ApsHelpers.query_material(materialnos)
|
|
materials = {item['materialno']: item for item in materials}
|
|
|
|
for md in mo_material_details:
|
|
materialno = md['Inventory']['Code']
|
|
free1 = materials.get(materialno, {}).get('free1')
|
|
if free1 == 'Y': # 该物料为倒冲料
|
|
md['Warehouse'] = {'Code': '5'} # 倒冲料仓库
|
|
md.pop('IsMaterialRequest')
|
|
|
|
mo_details['DynamicPropertyKeys'] = []
|
|
mo_details['DynamicPropertyValues'] = []
|
|
# 构建后续工单关系
|
|
next_mos: list[dict] = values.get('next_mo')
|
|
if next_mos:
|
|
next_mo_sn = ','.join([_['supplyno'] for _ in next_mos])
|
|
if next_mo_sn:
|
|
mo_details['DynamicPropertyKeys'].append('priuserdefnvc1') # 存入自定义字段
|
|
mo_details['DynamicPropertyValues'].append(next_mo_sn)
|
|
|
|
# 源销售订单号
|
|
so = values.get('so')
|
|
if so:
|
|
mo_details['DynamicPropertyKeys'].append('priuserdefnvc4') # 存入自定义字段
|
|
mo_details['DynamicPropertyValues'].append(so.get('demandno', ""))
|
|
return cleaned_values
|
|
|
|
|
|
class CustomRsPushModel(RsPushModel):
|
|
|
|
class Config:
|
|
extra = 'allow'
|
|
|
|
@model_validator(mode="before")
|
|
@classmethod
|
|
def model_valid(cls, values: Dict[str, Any]):
|
|
cleaned_values = RsPushModel.model_valid(values)
|
|
|
|
mr_details:list[dict] = cleaned_values['MaterialRequestDetails']
|
|
materialnos = [md['Inventory']['Code'] for md in mr_details]
|
|
materials = ApsHelpers.query_material(materialnos)
|
|
# materialnos = ','.join([md['Inventory']['Code'] for md in mr_details])
|
|
# materials = CLIENT_SESSION.get(f"{THIS_BASE_URL}/api/t_material/{materialnos}")
|
|
# materials = materials.json()['data']
|
|
materials = {item['materialno']: item for item in materials}
|
|
|
|
mr_details2 = []
|
|
for md in mr_details:
|
|
materialno = md['Inventory']['Code']
|
|
free1 = materials.get(materialno, {}).get('free1')
|
|
if free1 != 'Y': # 该物料 不为 倒冲料
|
|
mr_details2.append(md)
|
|
|
|
cleaned_values['MaterialRequestDetails'] = mr_details2
|
|
return cleaned_values
|
|
|
|
|
|
|
|
def handle_pl_status_a2e(supplyno_or_data: str | dict):
|
|
"""处理PL状态变更:从A到E"""
|
|
try:
|
|
if isinstance(supplyno_or_data, str):
|
|
supplyno = supplyno_or_data
|
|
elif isinstance(supplyno_or_data, dict):
|
|
supplyno = supplyno_or_data['supplyno']
|
|
tplus_conn = get_tplus_conn()
|
|
tplus_conn.create_mo(supplyno=supplyno, remain_native_supplyno=REMAIN_NATIVE_SUPPLYNO, pydantic_model=CustomMoPushModel)
|
|
except Exception as e:
|
|
CLIENT_LOGGER.fail("处理PL状态变更", str(supplyno_or_data), str(e))
|
|
raise
|
|
|
|
|
|
def handle_pl_typeto_mo(supplyno_or_data: str | dict):
|
|
"""处理PL类型变更:转为MO"""
|
|
try:
|
|
if isinstance(supplyno_or_data, str):
|
|
supplyno = supplyno_or_data
|
|
elif isinstance(supplyno_or_data, dict):
|
|
supplyno = supplyno_or_data['supplyno']
|
|
tplus_conn = get_tplus_conn()
|
|
mo_data = tplus_conn.query_mo(index_value=supplyno, filter_field='voucherCode')
|
|
if mo_data:
|
|
tplus_conn.push_rs(mdlist_or_supplyno=supplyno, tplus_mo_data_or_id=mo_data, pydantic_model=CustomRsPushModel)
|
|
except Exception as e:
|
|
CLIENT_LOGGER.fail("处理PL类型变更", str(supplyno_or_data), str(e))
|
|
raise
|
|
|
|
|
|
def batch_handle_pr_created(pr_data_list: list[dict]):
|
|
"""批量处理PR创建"""
|
|
try:
|
|
tplus_conn = get_tplus_conn()
|
|
tplus_conn.push_pr(pr_data_list)
|
|
except Exception as e:
|
|
CLIENT_LOGGER.fail("批量处理PR创建", "", str(e))
|
|
raise
|
|
|
|
|
|
if __name__ == '__main__':
|
|
from .._base import HapConnection
|
|
|
|
hap_conn = HapConnection()
|