提交 9aa9e4a9 authored 作者: 贺阳's avatar 贺阳

扫码理货推送优化

上级 7ed3b3b6
# 导入odoo
import ast
import base64
# 导入日志
import logging
from datetime import timedelta
import pytz
import re
import xlrd
from datetime import timedelta, datetime
from odoo import models, fields, api, _
from odoo.exceptions import UserError
from pygtrans import Translate
# 获取日志
_logger = logging.getLogger(__name__)
......@@ -1068,18 +1064,6 @@ class CcBL(models.Model):
# print(wizard_obj.get_order())
wizard_obj.submit()
def try_callback_track(self, max_retries=3, ship_package_ids=[]):
""" 封装的重试逻辑 """
for i in range(max_retries):
if not ship_package_ids:
is_ok = self.callback_track()
else:
is_ok = self.package_callback_func(ship_package_ids)
if is_ok:
return True
logging.warning(f"Attempt {i + 1}/{max_retries} failed. Retrying...")
return False
# 增加一个清关进度的业务对象,继承自models.Model, 用于管理业务数据.业务数据包括提单号、清关节点(业务对象)、进度日期、进度描述、更新人
class CcProgress(models.Model):
......
# -*- coding: utf-8 -*-
import aiohttp
import asyncio
import certifi
import json
import logging
import math
import random
import re
import ssl
import threading
from datetime import datetime, timedelta
from odoo import http, fields, exceptions, _
from odoo import http, exceptions
# from odoo.addons.queue_job import job
from odoo.http import request
......@@ -170,21 +162,21 @@ class OrderController(http.Controller):
tally_time = package_item.get('tally_time')
if (action_type == 'tally' and package_item.get('tally_state') == 'checked_goods') or (
action_type == 'handover' and package_item.get(
'tally_state') == 'handover_completed'):
'tally_state') == 'handover_completed'):
if package_type == 'ship':
ship_packages.append({
'id': package_obj.id,
'id': [package_obj.id],
'tally_time': tally_time})
else:
for package in package_obj:
ship_packages += [{
'id': ship_package.id,
'tally_time': tally_time} for ship_package in
package.ship_package_ids if
(
action_type == 'tally' and package.tally_state == 'unprocessed_goods') or (
action_type == 'handover' and package.tally_state in (
'unprocessed_goods', 'checked_goods'))] # 小包
if (
action_type == 'tally' and package.tally_state == 'unprocessed_goods') or (
action_type == 'handover' and package.tally_state in (
'unprocessed_goods', 'checked_goods')):
ship_packages.append({
'id': package.ship_package_ids.ids,
'tally_time': tally_time
}) # 小包
package_obj.update_big_package_info(action_type=action_type,
tally_state=package_item.get('tally_state'),
tally_user_id=package_item.get(
......
# -*- coding: utf-8 -*-
# Part of SmartGo. See LICENSE file for full copyright and licensing details.
from datetime import datetime
import logging
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError, Warning
import logging
......
import aiohttp
import asyncio
import base64
import certifi
import logging
import pytz
import ssl
from datetime import datetime
from datetime import timedelta, datetime
from lxml import etree
from odoo import models, fields, api, tools, _
import aiohttp
import certifi
import pytz
from odoo import models, fields, api, _
def get_rfc339_time(utc_time=None):
......@@ -272,12 +270,12 @@ class CcBl(models.Model):
logging.info('package_callback_func ship_packages:%s' % len(ship_packages))
is_ok = True
tt_api_obj = self.env["ao.tt.api"].sudo()
async def perform_requests():
ssl_context = ssl.create_default_context(cafile=certifi.where())
async with aiohttp.ClientSession(connector=aiohttp.TCPConnector(ssl=ssl_context),
timeout=aiohttp.ClientTimeout(total=60)) as session:
tasks = []
logging.info('------123')
for index, package in enumerate(ship_packages):
if not package.is_sync and package.state and package.state.tk_code:
data = package.get_callback_track_data()
......@@ -311,7 +309,7 @@ class CcBl(models.Model):
request_id = response_data['requestID']
self.env['ao.tt.api.log'].sudo().create_api_log(
package_order.tracking_no or '', '', data, 0, request_id, source='推出')
# 如果提单有小包变成了清关开始,提单状态变为清关中;如果提单所有小包的清关节点变成“是完成节点”,则该提单状态变成已完成
# 如果提单有小包变成了清关开始,提单状态变为清关中;如果提单所有小包的清关节点变成"是完成节点",则该提单状态变成已完成
self.change_state_by_ship_package()
return is_ok
......@@ -384,83 +382,120 @@ class CcBl(models.Model):
lambda r: r.bl_no.replace('-', '').replace(' ', '').lower() == processed_bl_no) # 提单
return bl_obj
def try_callback_track(self, max_retries=3, ship_package_ids=[]):
""" 封装的重试逻辑 """
for i in range(max_retries):
if not ship_package_ids:
is_ok = self.callback_track()
else:
is_ok = self.package_callback_func(ship_package_ids)
if is_ok:
return True
logging.warning(f"Attempt {i + 1}/{max_retries} failed. Retrying...")
return False
def mail_auto_push(self, mail_time=False, ship_packages=[], action_type='tally'):
self = self.with_context(dict(self._context, is_mail=True))
for item in self:
try:
if mail_time:
utc_time = datetime.strptime(mail_time, "%Y-%m-%d %H:%M:%S")
before_min = self.env['ir.config_parameter'].sudo().get_param('before_min') or 10
before_utc_time = utc_time - timedelta(minutes=int(before_min))
item.push_clear_customs_start(before_utc_time)
# 尝试调用 callback_track
if self.try_callback_track():
item.push_clear_customs_end(utc_time)
# 再次尝试调用 callback_track
if not self.try_callback_track():
logging.error(f"Failed to push item after {3} attempts.")
else:
logging.error(f"Failed to start process for item after {3} attempts.")
elif ship_packages:
ship_package_ids = [ship_package_dict['id'] for ship_package_dict in ship_packages if
ship_package_dict['id']]
tally_state = 'checked_goods' if action_type == 'tally' else 'handover_completed'
# 后续节点
node_obj = self.env['cc.node'].sudo().search([
('node_type', '=', 'package'),
('tally_state', '=', tally_state) # Check for both states
], order='seq asc') # Order by sequence and creation date ascending
if node_obj:
next_minutes = int(self.env['ir.config_parameter'].sudo().get_param('next_minutes', default=20))
# 前序节点 理货或尾程交接之前没有生成的节点
before_node_obj = self.env['cc.node'].sudo().search([
('node_type', '=', 'package'), ('is_must', '=', True), ('seq', '<', node_obj[0].seq)],
order='seq asc')
# 理货或尾程交接之前没有生成的节点
for beforeidx, before_node in enumerate(before_node_obj):
for ship_package_dict in ship_packages:
ship_package_id = ship_package_dict['id']
ship_package = self.env['cc.ship.package'].browse(ship_package_id) # 小包
tally_time = ship_package_dict['tally_time']
before_minutes = before_node.calculate_total_interval(node_obj[0])
operation_time = (datetime.strptime(tally_time, '%Y-%m-%d %H:%M:%S') - timedelta(
minutes=before_minutes)) if tally_time else fields.Datetime.now() - timedelta(
minutes=before_minutes)
# 检查有没有同步过,没有同步过需要调用同步
sync_log_obj = ship_package.sync_log_ids.filtered(
lambda line: line.process_code == before_node.tk_code)
if not sync_log_obj: # Ensure the current state is valid
ship_package.write({
# try:
if mail_time:
utc_time = datetime.strptime(mail_time, "%Y-%m-%d %H:%M:%S")
before_min = self.env['ir.config_parameter'].sudo().get_param('before_min') or 10
before_utc_time = utc_time - timedelta(minutes=int(before_min))
item.push_clear_customs_start(before_utc_time)
# 尝试调用 callback_track
if self.try_callback_track():
item.push_clear_customs_end(utc_time)
# 再次尝试调用 callback_track
if not self.try_callback_track():
logging.error(f"Failed to push item after {3} attempts.")
else:
logging.error(f"Failed to start process for item after {3} attempts.")
elif ship_packages:
ship_package_ids = [ship_package_dict for sublist in [d['id'] for d in ship_packages] for
ship_package_dict in sublist]
tally_state = 'checked_goods' if action_type == 'tally' else 'handover_completed'
# 后续节点
node_obj = self.env['cc.node'].sudo().search([
('node_type', '=', 'package'),
('tally_state', '=', tally_state) # 检查理货或尾程交接的节点,根据排序进行升序
], order='seq asc')
if node_obj:
all_ship_package_obj = self.env['cc.ship.package'].search(
[('id', 'in', ship_package_ids)]) # 所有小包
# 预先获取所有同步日志 - 批量查询
all_sync_logs = self.env['cc.ship.package.sync.log'].sudo().search([
('package_id', 'in', ship_package_ids)
])
# 构建同步日志字典以加快查找
sync_log_dict = {}
for log in all_sync_logs:
if log.package_id.id not in sync_log_dict:
sync_log_dict[log.package_id.id] = set()
sync_log_dict[log.package_id.id].add(log.process_code)
# 构建ship_packages字典,用于快速查找
ship_packages_dict = {}
for package in ship_packages:
# 如果一个id在多个package中出现,使用最后一个package的tally_time
if package.get('tally_time'):
for single_id in package['id']:
ship_packages_dict[single_id] = package['tally_time']
# 前序节点 理货或尾程交接之前没有生成的节点
before_node_obj = self.env['cc.node'].sudo().search([
('node_type', '=', 'package'), ('is_must', '=', True), ('seq', '<', node_obj[0].seq)],
order='seq asc')
# 理货或尾程交接之前没有生成的节点
for before_node in before_node_obj:
before_minutes = before_node.calculate_total_interval(node_obj[0])
for package in all_ship_package_obj:
package_id = package.id
if package_id not in sync_log_dict or before_node.tk_code not in sync_log_dict.get(
package_id, set()):
tally_time = ship_packages_dict.get(package_id)
if tally_time:
operation_time = (
datetime.strptime(tally_time, '%Y-%m-%d %H:%M:%S') - timedelta(
minutes=before_minutes)) if tally_time else fields.Datetime.now() - timedelta(
minutes=before_minutes)
package.write({
'state': before_node.id,
'process_time': operation_time,
'state_explain': before_node.desc,
'is_sync': True if before_node.is_default else False
})
self.try_callback_track(max_retries=2, ship_package_ids=ship_package_ids)
# 理货或尾程交接的节点
for index, node in enumerate(node_obj):
for ship_package_dict in ship_packages:
ship_package_id = ship_package_dict['id']
ship_package = self.env['cc.ship.package'].browse(ship_package_id) # 小包
tally_time = ship_package_dict['tally_time']
operation_time = (datetime.strptime(tally_time, '%Y-%m-%d %H:%M:%S') + timedelta(
minutes=next_minutes * index)) if tally_time else fields.Datetime.now() + timedelta(
minutes=next_minutes * index) # Increment time by 20 minutes for each node
state_node_obj = self.env['cc.node'].sudo().search(
[('node_type', '=', 'package'), ('name', '=', ship_package.state.name)],
limit=1)
if state_node_obj.seq < node.seq: # Ensure the current state is valid
ship_package.write({
'state': node.id,
'process_time': operation_time,
'state_explain': node.desc,
'is_sync': True if node.is_default else False
})
self.try_callback_track(max_retries=2, ship_package_ids=ship_package_ids)
self.try_callback_track(max_retries=2, ship_package_ids=ship_package_ids)
# 理货或尾程交接的节点
# 预先获取所有状态节点
all_state_nodes = self.env['cc.node'].sudo().search([
('node_type', '=', 'package')
])
state_node_dict = {node.name: node for node in all_state_nodes}
next_minutes = int(self.env['ir.config_parameter'].sudo().get_param('next_minutes', default=20))
for index, node in enumerate(node_obj):
for package in all_ship_package_obj:
if package.state.name in state_node_dict:
current_state_node = state_node_dict[package.state.name]
if current_state_node.seq < node.seq:
tally_time = ship_packages_dict.get(package.id)
if tally_time:
operation_time = (
datetime.strptime(tally_time, '%Y-%m-%d %H:%M:%S') + timedelta(
minutes=next_minutes * index)) if tally_time else fields.Datetime.now() + timedelta(
minutes=next_minutes * index)
package.write({
'state': node.id,
'process_time': operation_time,
'state_explain': node.desc,
'is_sync': True if node.is_default else False
})
self.try_callback_track(max_retries=2, ship_package_ids=ship_package_ids)
return True
except Exception as err:
logging.error('fetch_mail_dlv--error:%s' % str(err))
# except Exception as err:
# logging.error('fetch_mail_dlv--error:%s' % str(err))
def change_state_by_ship_package(self):
"""
......@@ -471,7 +506,7 @@ class CcBl(models.Model):
if self.state == 'draft' and self.ship_package_ids.filtered(
lambda line: line.state.tk_code == 'cb_imcustoms_start'):
self.ccing_func()
# 如果提单所有小包的清关节点变成“是完成节点”,则该提单状态变成已完成
# 如果提单所有小包的清关节点变成"是完成节点",则该提单状态变成已完成
if all(line.state.is_done for line in self.ship_package_ids) and self.unsync_package_count <= 0:
self.done_func()
......
......@@ -40,7 +40,6 @@ class TT(models.Model):
param_json_str = json.dumps(param_json, ensure_ascii=False)
# print(param_json_str)
sign = self.make_sign(app_key, app_secret, version, timestamp, param_json_str)
print(f"sign={sign}") # 输出生成的签名值
return sign
......
......@@ -28,16 +28,19 @@ redis_options = dict(
# )
# product
# db_ip = "172.18.183.214"
# db_port = "9169"
# db_name = "air_order"
# db_user = "admin"
# db_password = "YHB1408ups"
# db_ip = "172.104.182.220"
# db_port = "8269"
# db_name = "ccs"
# db_user = "YJ@yizuo.com"
# db_password = "yizuo123"
#
# redis_options = dict(
# host='172.18.183.214',
# host='some-redis',
# port=32768,
# password='top123',
# # password='top123',
# decode_responses=True,
# db=3
# db=2
# )
pda_db_user = "pda"
pda_db_password = "2025"
# coding=utf-8
import json
import logging
import odoorpc
import redis
import requests
import time
from datetime import datetime
from requests.adapters import HTTPAdapter
import config
......@@ -25,6 +22,9 @@ class Order_dispose(object):
# rpc连接
self.odoo_db = odoorpc.ODOO(config.db_ip, port=config.db_port)
self.odoo_db.login(config.db_name, config.db_user, config.db_password)
# pda用户
self.pda_odoo_db = odoorpc.ODOO(config.db_ip, port=config.db_port)
self.pda_odoo_db.login(config.db_name, config.pda_db_user, config.pda_db_password)
def order_data(self, data):
res_data = []
......@@ -33,7 +33,10 @@ class Order_dispose(object):
logging.info('mail_push_data: %s', data)
ship_packages = eval(data['ship_packages']) if data.get('ship_packages') else [] # 小包
action_type = data.get('action_type') # 类型
utc_time = data.get('utc_time')
bl_obj = self.odoo_db.env['cc.bl']
if action_type and not utc_time:
bl_obj = self.pda_odoo_db.env['cc.bl']
bl_record = bl_obj.browse(data['id'])
# utc_time = datetime.strptime(data['utc_time'], "%Y-%m-%d %H:%M:%S")
utc_time = data.get('utc_time')
......@@ -57,5 +60,4 @@ try:
logging.error(e)
continue
except Exception as e:
logging.error("登录失败")
logging.error(e)
logging.error("登录失败:%s" % e)
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论