提交 2d04ffe8 authored 作者: 贺阳's avatar 贺阳

1、PDA扫码记录的操作增加 按托盘理货或按托盘交货

2、按托盘理货接口
上级 9344661e
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
""", """,
'category': 'Clearance of customs', 'category': 'Clearance of customs',
'website': 'https://www.yizuo.ltd', 'website': 'https://www.yizuo.ltd',
'depends': ['base_setup', 'ccs_base'], 'depends': ['base_setup', 'ccs_base', 'ccs_pallet'],
'data': [ 'data': [
'security/security.xml', 'security/security.xml',
'security/ir.model.access.csv', 'security/ir.model.access.csv',
......
...@@ -642,17 +642,17 @@ class OrderController(http.Controller): ...@@ -642,17 +642,17 @@ class OrderController(http.Controller):
logging.info('last_mile_delivery_time_check res:%s' % res) logging.info('last_mile_delivery_time_check res:%s' % res)
return res return res
def _get_last_mile_grouped(self, tally_state, pda_lang): def _get_last_mile_grouped(self, tally_state, pda_lang, is_pallet=False):
lang = 'zh_CN' if pda_lang == 'zh' else 'en_US' # 语言 lang = 'zh_CN' if pda_lang == 'zh' else 'en_US' # 语言
# 1. 查所有清关中提单 # if is_pallet:
bls = request.env['cc.bl'].sudo().search([('state', '=', 'ccing')]) # domain=[('state', '!=', 'done')]# 1. 按托盘理货时,查非已完成状态的提单
# else:
#先都查清关中的,如果以后要查非已完成状态的提单,再修改domain。而且查尾程快递和对应的大包或托盘信息得分两个接口
domain=[('state', '=', 'ccing')]# 1. 按尾程理货时,查所有清关中提单
bls = request.env['cc.bl'].sudo().search(domain)
# 2. 查所有大包 # 2. 查所有大包
big_packages = request.env['cc.big.package'].sudo().search([ big_packages = request.env['cc.big.package'].sudo().search([('bl_id', 'in', bls.ids),('tally_state', '=', tally_state)])
('bl_id', 'in', bls.ids),
('tally_state', '=', tally_state)
])
# 3. 按"下一阶段服务商名称"分组 # 3. 按"下一阶段服务商名称"分组
group_dict = {} group_dict = {}
for pkg in big_packages: for pkg in big_packages:
provider = request.env['cc.last.mile.provider'].sudo().with_context({'lang': lang}).match_provider( provider = request.env['cc.last.mile.provider'].sudo().with_context({'lang': lang}).match_provider(
...@@ -663,13 +663,21 @@ class OrderController(http.Controller): ...@@ -663,13 +663,21 @@ class OrderController(http.Controller):
if key not in group_dict: if key not in group_dict:
group_dict[key] = provider.search_pro_info() # 查询快递信息 group_dict[key] = provider.search_pro_info() # 查询快递信息
group_dict[key]['count'] = 0 group_dict[key]['count'] = 0
group_dict[key]['big_package_arr'] = [] group_dict[key]['big_package_arr'] = []#大包信息
group_dict[key]['ship_package_arr'] = [] group_dict[key]['ship_package_arr'] = []#小包信息
group_dict[key]['pallet_info_arr'] = []#托盘信息
group_dict[key]['count'] += 1 group_dict[key]['count'] += 1
group_dict[key]['big_package_arr'].append(pkg.search_big_package_info(pda_lang=pda_lang, type=tally_state)) group_dict[key]['big_package_arr'].append(pkg.search_big_package_info(pda_lang=pda_lang, type=tally_state))
group_dict[key]['ship_package_arr'].extend( #按托盘理货时返回未使用的托盘信息,按尾程时返回小包信息
[ship_package_item.search_ship_package_info(pda_lang=pda_lang) for ship_package_item in if is_pallet:
pkg.ship_package_ids]) unused_pallets = request.env['cc.pallet'].sudo().search([('usage_state', '=', 'unused'),('express_company_id', '=', key)])
pallet_info_arr=[pallet.search_pallet_info() for pallet in unused_pallets]
group_dict[key]['pallet_info_arr'] = pallet_info_arr
group_dict[key]['pallet_info_arr'].sort(key=lambda x: x.get('name', ''))#根据托盘号升序排序
else:
group_dict[key]['ship_package_arr'].extend(
[ship_package_item.search_ship_package_info(pda_lang=pda_lang) for ship_package_item in
pkg.ship_package_ids])
# 4. 返回 # 4. 返回
provider_info_arr = list(group_dict.values()) provider_info_arr = list(group_dict.values())
# 按服务商名称升序排序 # 按服务商名称升序排序
...@@ -758,3 +766,229 @@ class OrderController(http.Controller): ...@@ -758,3 +766,229 @@ class OrderController(http.Controller):
return latest_time.strftime('%Y-%m-%d %H:%M:%S') return latest_time.strftime('%Y-%m-%d %H:%M:%S')
else: else:
return request.env['common.common'].sudo().get_utc_time(datetime.now()) return request.env['common.common'].sudo().get_utc_time(datetime.now())
@http.route('/api/pallet/tally', type='json', auth='public', csrf=False)
def pallet_tally(self):
"""
按托盘理货接口
返回尾程服务商信息供前端选择
"""
kwargs = json.loads(request.httprequest.data)
pda_lang = kwargs.get('pda_lang') or 'zh'
res = {'state': 201, 'message': ''}
try:
logging.info('pallet_tally kwargs:%s' % kwargs)
return self._get_last_mile_grouped('unprocessed_goods', pda_lang, is_pallet=True)
except Exception as e:
exceptions_msg_dic = {
'en': 'System parsing error, the reason for the error is %s' % e,
'zh': '系统解析错误,错误原因是%s' % e
}
logging.info('pallet_tally error:%s' % e)
res['message'] = exceptions_msg_dic[pda_lang] # _('System parsing error, the reason for the error is %s', e) # 系统解析错误,错误原因是
logging.info('pallet_tally res:%s' % res)
return res
@http.route('/api/pallet/tally/complete', type='json', auth='public', csrf=False)
def pallet_tally_complete(self):
"""
按托盘理货完成接口
处理理货完成后的数据
"""
kwargs = json.loads(request.httprequest.data)
pda_lang = kwargs.get('pda_lang') or 'zh'
res = {'state': 201, 'message': ''}
operation = 'pallet_tally'
tally_user_id = kwargs.get('tally_user_id')
try:
logging.info('pallet_tally_complete kwargs:%s' % kwargs)
pallet_data = kwargs.get('pallet_data', [])
if not pallet_data:
res['message'] = {
'en': 'Pallet data is required',
'zh': '托盘数据必须提供'
}[pda_lang]
return res
for pallet_item in pallet_data:
pallet_id = pallet_item.get('pallet_id')
usage_time = pallet_item.get('usage_time')
big_package_nos = pallet_item.get('big_package_nos', [])
if not pallet_id or not usage_time or not big_package_nos:
continue
# 获取托盘对象
pallet = request.env['cc.pallet'].sudo().browse(pallet_id)
if not pallet.exists():
continue
# 获取大包对象
big_packages = request.env['cc.big.package'].sudo().search([
('big_package_no', 'in', big_package_nos)
])
if big_packages:
# 更新托盘状态为已使用
pallet.usage_state = 'used'
# 关联大包到托盘
pallet.package_ids = [(4, pkg.id) for pkg in big_packages]
# 更新大包的托盘信息
for pkg in big_packages:
pkg.update_pallet_info(
pallet_number=pallet.name,
pallet_usage_date=usage_time,
pallet_id=pallet.id
)
# 更新大包理货状态
pkg.update_big_package_info(
action_type='tally',
tally_state='checked_goods',
tally_user_id=tally_user_id,
tally_time=usage_time
)
# 创建成功的PDA扫码记录
bl_obj = big_packages[0].bl_id if big_packages else None
if bl_obj:
request.env['pda.scan.record'].sudo().create_scan_record(
operation=operation,
record_type='tally',
bill_number=bl_obj.bl_no,
transfer_number=bl_obj.transfer_bl_no,
state='success',
bl_id=bl_obj.id,
operation_time=usage_time,
operator_id=tally_user_id
)
res['state'] = 200
except Exception as e:
error = str(e)
logging.info('pallet_tally_complete error:%s' % error)
exceptions_msg_dic = {
'en': 'System parsing error, the reason for the error is %s' % error,
'zh': '系统解析错误,错误原因是%s' % error
}
res['message'] = exceptions_msg_dic[pda_lang]
# 创建失败的PDA扫码记录
request.env['pda.scan.record'].sudo().create_scan_record(
operation=operation,
record_type='tally',
bill_number='',
transfer_number='',
state='failed',
failure_reason=error,
operator_id=tally_user_id
)
logging.info('pallet_tally_complete res:%s' % res)
return res
@http.route('/api/pallet/handover', type='json', auth='public', csrf=False)
def pallet_handover(self):
"""
按托盘交货接口
返回尾程服务商信息供前端选择
"""
kwargs = json.loads(request.httprequest.data)
pda_lang = kwargs.get('pda_lang') or 'zh'
res = {'state': 201, 'message': ''}
try:
logging.info('pallet_handover kwargs:%s' % kwargs)
res = self._get_last_mile_grouped('checked_goods', pda_lang, is_pallet=True)
except Exception as e:
exceptions_msg_dic = {
'en': 'System parsing error, the reason for the error is %s' % e,
'zh': '系统解析错误,错误原因是%s' % e
}
logging.info('pallet_handover error:%s' % e)
res['message'] = exceptions_msg_dic[pda_lang] # _('System parsing error, the reason for the error is %s', e) # 系统解析错误,错误原因是
logging.info('pallet_handover res:%s' % res)
return res
@http.route('/api/pallet/handover/complete', type='json', auth='public', csrf=False)
def pallet_handover_complete(self):
"""
按托盘交货完成接口
处理交货完成后的数据
"""
kwargs = json.loads(request.httprequest.data)
pda_lang = kwargs.get('pda_lang') or 'zh'
res = {'state': 201, 'message': ''}
operation = 'pallet_handover'
tally_user_id = kwargs.get('tally_user_id')
try:
logging.info('pallet_handover_complete kwargs:%s' % kwargs)
pallet_data = kwargs.get('pallet_data', [])
if not pallet_data:
res['message'] = {
'en': 'Pallet data is required',
'zh': '托盘数据必须提供'
}[pda_lang]
return res
for pallet_item in pallet_data:
pallet_id = pallet_item.get('pallet_id')
handover_time = pallet_item.get('handover_time')
plate_number = pallet_item.get('plate_number', '')
if not pallet_id or not handover_time:
continue
# 获取托盘对象
pallet = request.env['cc.pallet'].sudo().browse(pallet_id)
if not pallet.exists():
continue
# 更新托盘交货时间和车牌号
pallet.delivery_plate_number = plate_number
# 更新托盘关联的大包交货信息
for pkg in pallet.package_ids:
pkg.update_big_package_info(
action_type='handover',
tally_state='handover_completed',
tally_user_id=tally_user_id,
tally_time=handover_time
)
# 创建成功的PDA扫码记录
if pallet.package_ids:
bl_obj = pallet.package_ids[0].bl_id
if bl_obj:
request.env['pda.scan.record'].sudo().create_scan_record(
operation=operation,
record_type='handover',
bill_number=bl_obj.bl_no,
transfer_number=bl_obj.transfer_bl_no,
state='success',
bl_id=bl_obj.id,
operation_time=handover_time,
operator_id=tally_user_id
)
res['state'] = 200
except Exception as e:
error = str(e)
logging.info('pallet_handover_complete error:%s' % error)
exceptions_msg_dic = {
'en': 'System parsing error, the reason for the error is %s' % error,
'zh': '系统解析错误,错误原因是%s' % error
}
res['message'] = exceptions_msg_dic[pda_lang]
# 创建失败的PDA扫码记录
request.env['pda.scan.record'].sudo().create_scan_record(
operation=operation,
record_type='handover',
bill_number='',
transfer_number='',
state='failed',
failure_reason=error,
operator_id=tally_user_id
)
logging.info('pallet_handover_complete res:%s' % res)
return res
\ No newline at end of file
...@@ -10,6 +10,7 @@ from . import ir_attachment ...@@ -10,6 +10,7 @@ from . import ir_attachment
from . import http from . import http
from . import pda_scan_record from . import pda_scan_record
from . import bl_patrol from . import bl_patrol
from . import cc_pallet
# -*- coding: utf-8 -*-
# 导入日志
import logging
from odoo import models, fields, api, _
# 获取日志
_logger = logging.getLogger(__name__)
class CcPallet(models.Model):
# 模型名称
_inherit = 'cc.pallet'
# 模型描述
_description = 'Pallet'
def search_pallet_info(self):
"""搜索托盘信息"""
return {
'id': self.id,#托盘id
'name': self.name,#托盘号
'express_company_id': self.express_company_id.id,#快递公司id
'express_company_name': self.express_company_id.name,#快递公司名称
'usage_state': self.usage_state,#使用状态 unused未使用 used已使用
'print_state': self.print_state,#打印状态 unprinted未打印 printed已打印
'sorting_time': self.sorting_time,#托盘理货时间
'delivery_time': self.delivery_time,#托盘交货时间
'package_count': self.package_count,#大包数量
'partner_id': self.partner_id.id,#使用客户id
'partner_name': self.partner_id.name,#使用客户名称
'delivery_plate_number': self.delivery_plate_number,#托盘交付车牌号
}
\ No newline at end of file
...@@ -24,8 +24,10 @@ class PDAScanRecord(models.Model): ...@@ -24,8 +24,10 @@ class PDAScanRecord(models.Model):
operation = fields.Selection([ operation = fields.Selection([
('bill_tally', _('Bill Tally')), # 按提单理货 ('bill_tally', _('Bill Tally')), # 按提单理货
('tail_tally', _('Tail Tally')), # 按尾程理货 ('tail_tally', _('Tail Tally')), # 按尾程理货
('pallet_tally', _('Pallet Tally')), # 按托盘理货
('bill_handover', _('Bill Handover')), # 按提单交货 ('bill_handover', _('Bill Handover')), # 按提单交货
('tail_handover', _('Tail Handover')) # 按尾程交货 ('tail_handover', _('Tail Handover')), # 按尾程交货
('pallet_handover', _('Pallet Handover')) # 按托盘交货
], string=_('Operation'), required=True) # 操作 ], string=_('Operation'), required=True) # 操作
record_type = fields.Selection([ record_type = fields.Selection([
('tally', _('Tally')), # 理货 ('tally', _('Tally')), # 理货
......
...@@ -124,6 +124,7 @@ class CcPallet(models.Model): ...@@ -124,6 +124,7 @@ class CcPallet(models.Model):
'target': 'new', 'target': 'new',
'context': { 'context': {
'default_pallet_ids': [(6, 0, self.ids)], 'default_pallet_ids': [(6, 0, self.ids)],
'active_ids': self.ids,
}, },
} }
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<odoo> <odoo>
<!-- 托盘标签纸张格式 -->
<record id="paperformat_pallet_label" model="report.paperformat">
<field name="name">托盘标签 (10x15cm)</field>
<field name="default" eval="True"/>
<field name="format">custom</field>
<field name="orientation">Portrait</field>
<field name="margin_top">0</field>
<field name="margin_bottom">0</field>
<field name="margin_left">0</field>
<field name="margin_right">0</field>
<field name="header_line" eval="False"/>
<field name="header_spacing">0</field>
<field name="dpi">90</field>
<field name="page_width">10</field>
<field name="page_height">15</field>
</record>
<!-- 托盘标签打印报告 --> <!-- 托盘标签打印报告 -->
<record id="action_pallet_label_report" model="ir.actions.report"> <record id="action_pallet_label_report" model="ir.actions.report">
<field name="name">托盘标签</field> <field name="name">托盘标签</field>
...@@ -7,6 +24,7 @@ ...@@ -7,6 +24,7 @@
<field name="report_type">qweb-pdf</field> <field name="report_type">qweb-pdf</field>
<field name="report_name">ccs_pallet.pallet_label_report</field> <field name="report_name">ccs_pallet.pallet_label_report</field>
<field name="report_file">ccs_pallet.pallet_label_report</field> <field name="report_file">ccs_pallet.pallet_label_report</field>
<field name="paperformat_id" ref="paperformat_pallet_label"/>
<field name="binding_model_id" ref="model_cc_pallet"/> <field name="binding_model_id" ref="model_cc_pallet"/>
<field name="binding_type">report</field> <field name="binding_type">report</field>
</record> </record>
...@@ -15,22 +33,21 @@ ...@@ -15,22 +33,21 @@
<template id="pallet_label_report"> <template id="pallet_label_report">
<t t-call="web.html_container"> <t t-call="web.html_container">
<t t-foreach="docs" t-as="pallet"> <t t-foreach="docs" t-as="pallet">
<div class="page" style="width: 10cm; height: 15cm; margin: 0; padding: 0.5cm; border: 1px solid #ccc; page-break-after: always;"> <div class="page" style="width: 100%; height: 100%; margin: 0; padding: 0.3cm; page-break-after: always; font-family: 'DejaVu Sans', Arial, sans-serif; box-sizing: border-box; position: relative;">
<!-- 客户名称和快递简称 --> <!-- 客户名称和快递简称 -->
<div style="text-align: center; margin-bottom: 1cm;"> <div style="text-align: center; height: 2cm; display: flex; align-items: center; justify-content: center; margin-bottom: 0.2cm;">
<h2 style="margin: 0; font-size: 24px; font-weight: bold;"> <h2 style="margin: 0; font-size: 18px; font-weight: bold; line-height: 1.2;">
<t t-esc="pallet.customer_id.name or 'TIKTOK'"/> / <t t-esc="pallet.express_company_id.name or 'RM'"/> <t t-esc="pallet.partner_id.name or 'TIKTOK'"/> / <t t-esc="pallet.express_company_id.name or 'RM'"/>
</h2> </h2>
</div> </div>
<!-- 条形码区域 --> <!-- 条形码区域 -->
<div style="text-align: center; margin: 2cm 0; padding: 1cm; border: 2px dashed #999; background-color: #f9f9f9;"> <div style="text-align: center; height: 8cm; border: 2px dashed #999; background-color: #f9f9f9; display: flex; flex-direction: column; justify-content: center; margin-bottom: 0.2cm;">
<div style="font-size: 18px; color: #666; margin-bottom: 0.5cm;"> <div style="font-size: 14px; color: #666; margin-bottom: 0.5cm;">
<!-- 托盘号作为二维码 --> <!-- 托盘号作为条形码 -->
<t t-if="pallet.name"> <t t-if="pallet.name">
<!-- `quiet=0` to remove the left and right margins on the barcode --> <div t-out="pallet.name" style="padding:0; margin-bottom: 0.3cm;" t-options="{'widget': 'barcode', 'quiet': 0, 'symbology': 'auto', 'width': 2, 'height': 60}"/>
<div t-out="pallet.name" style="padding:0" t-options="{'widget': 'barcode', 'quiet': 0, 'symbology': 'auto', 'img_style': barcode_size}"/> <div class="o_label_name" style="height:1.2em;background-color: transparent; font-size: 12px;">
<div class="o_label_name" style="height:1.7em;background-color: transparent;">
<span t-out="pallet.name"/> <span t-out="pallet.name"/>
</div> </div>
</t> </t>
...@@ -38,8 +55,8 @@ ...@@ -38,8 +55,8 @@
</div> </div>
<!-- 托盘号 --> <!-- 托盘号 -->
<div style="text-align: center; margin-top: 1cm;"> <div style="text-align: center; height: 3cm; display: flex; align-items: center; justify-content: center;">
<h1 style="margin: 0; font-size: 28px; font-weight: bold;"> <h1 style="margin: 0; font-size: 22px; font-weight: bold; line-height: 1.2;">
<t t-esc="pallet.name"/> <t t-esc="pallet.name"/>
</h1> </h1>
</div> </div>
......
...@@ -31,13 +31,4 @@ class PalletPrintWizard(models.TransientModel): ...@@ -31,13 +31,4 @@ class PalletPrintWizard(models.TransientModel):
def _generate_print_report(self): def _generate_print_report(self):
"""生成打印报告""" """生成打印报告"""
return { return self.env.ref('ccs_pallet.action_pallet_label_report').report_action(self.pallet_ids)
'type': 'ir.actions.report',
'report_name': 'ccs_pallet.pallet_label_report',
'report_type': 'qweb-pdf',
'data': {
'ids': self.pallet_ids.ids,
'model': 'cc.pallet',
},
'context': self.env.context,
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论