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

扫码理货推送优化

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