提交 e41599c4 authored 作者: 贺阳's avatar 贺阳

增加异常信息和尾程服务商,增加关联托盘向导和添加异常信息向导的初步写法

上级 c93e7482
......@@ -19,10 +19,14 @@
'security/ir.model.access.csv',
'wizard/batch_input_ship_package_statu_wizard.xml',
'wizard/export_bl_big_package_xlsx_wizard.xml',
'wizard/associate_pallet_wizard_views.xml',
'data/data.xml',
'data/sequence.xml',
'views/menu_view.xml',
'views/cc_clearance_file_view.xml',
'views/cc_node_view.xml',
'views/cc_last_mile_provider_views.xml',
'views/cc_exception_info_views.xml',
'views/cc_process_view.xml',
'views/cc_package_good_view.xml',
'views/cc_ship_package_view.xml',
......
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="sequence_cc_exception_info" model="ir.sequence">
<field name="name">异常信息编码规则</field>
<field name="code">cc.exception.info</field>
<field name="padding">2</field>
<field name="number_next_actual">10</field>
<field name="company_id" eval="False"/>
</record>
</data>
</odoo>
\ No newline at end of file
from . import res_partner
from . import cc_node
from . import cc_bill_loading
from . import cc_customs_declaration_order
from . import cc_exception_info
from . import cc_last_mile_provider
from . import cc_node
from . import cc_node_exception_reason
from . import mail_thread
from . import common_common
from . import fetch_mail
from . import mail_thread
from . import order_state_change_rule
from . import res_config_setting
# 导入odoo
import ast
import base64
# 导入日志
import logging
import pytz
import re
from datetime import timedelta, datetime
from pygtrans import Translate
import xlrd
import pytz
from datetime import timedelta, datetime
from odoo import models, fields, api, _
# 导入日志
import logging
from odoo.exceptions import UserError
from pygtrans import Translate
# 获取日志
_logger = logging.getLogger(__name__)
......@@ -43,6 +41,11 @@ class CcBigPackage(models.Model):
# 商品纪录数
goods_qty = fields.Integer(string='Package Qty', compute='_compute_big_package_qty', store=True)
# New fields: pallet_number (char type), pallet_usage_date
# 托盘号(char型),托盘使用日期
pallet_number = fields.Char(string='Pallet Number')
pallet_usage_date = fields.Date(string='Pallet Usage Date')
# 计算包裹数量
@api.depends('ship_package_ids', 'goods_ids', 'ship_package_ids.is_cancel', 'goods_ids.is_cancel')
def _compute_big_package_qty(self):
......@@ -54,8 +57,11 @@ class CcBigPackage(models.Model):
# 增加is_cancel字段, 用于标识大包是否取消, 来自提单的is_cancel字段
is_cancel = fields.Boolean(string='Is Cancel', related='bl_id.is_cancel', store=True)
tally_state = fields.Selection([('unprocessed_goods', 'Unprocessed goods'), ('checked_goods', 'Checked goods')],
default='unprocessed_goods', string='Tally Status', index=True) # 理货状态 未理货/已理货
tally_state = fields.Selection([
('unprocessed_goods', 'Unprocessed goods'),
('checked_goods', 'Checked goods'),
('handover_completed', 'Handover Completed')
], default='unprocessed_goods', string='Tally Status', index=True) # 理货状态 未理货/已理货/尾程交接
tally_user_id = fields.Many2one('res.users', 'Tally User', index=True) # 理货人
tally_time = fields.Datetime('Tally Time') # 理货时间
......@@ -81,6 +87,19 @@ class CcBigPackage(models.Model):
'domain': [('big_package_id', '=', self.id), ('is_cancel', '=', False)],
}
def action_link_pallet(self):
"""
点击关联托盘,弹出向导
"""
return {
'name': _('Link Pallet'),
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'associate.pallet.wizard',
'target': 'new',
'context': {'active_id': self.id}
}
# 创建一个商品的业务对象,用来管理包裹的商品信息.商品信息包括所属包裹、SKU标识ID、商品中文名称、商品英文名称、出口HSCode,进口HSCode,重量、数量,数量单位,申报单价,运费, COD金额, VAT税率, 商品VAT,原产国, 类型:赠品,商品总价,商品链接,商品交税情况(包含:TTSTaxed: 已税
# Sentinel: 未税
......@@ -329,6 +348,9 @@ class CcShipPackage(models.Model):
node_exception_reason_id = fields.Many2one('cc.node.exception.reason', 'Exception Reason')
process_time = fields.Datetime('Process Time')
exception_info_ids = fields.Many2many('cc.exception.info', 'shippackage_exception_info_rel',
string='Exception Information')
# 重载write方法,在进度状态变化时,将is_sync置为False, 同时检查is_sync为false时,不允许修改进度状态
def write(self, vals):
# if not self.is_sync and 'state' in vals:
......@@ -900,8 +922,10 @@ class CcBL(models.Model):
def push_clear_customs_start(self, utc_time):
# 创建向导
push_node_obj = self.env['cc.node'].sudo().search([('node_type', '=', 'package'), ('tk_code', '=', 'cb_imcustoms_start')], limit=1)
node_obj = self.env['cc.node'].sudo().search([('node_type', '=', 'package'), ('seq', '<', push_node_obj.seq)], order='seq desc',
push_node_obj = self.env['cc.node'].sudo().search(
[('node_type', '=', 'package'), ('tk_code', '=', 'cb_imcustoms_start')], limit=1)
node_obj = self.env['cc.node'].sudo().search([('node_type', '=', 'package'), ('seq', '<', push_node_obj.seq)],
order='seq desc',
limit=1)
vals = {
'bl_id': self.id,
......@@ -918,7 +942,8 @@ class CcBL(models.Model):
def push_clear_customs_end(self, utc_time):
# 创建向导
push_node_obj = self.env['cc.node'].sudo().search([('node_type', '=', 'package'), ('tk_code', '=', 'cb_imcustoms_finished')], limit=1)
push_node_obj = self.env['cc.node'].sudo().search(
[('node_type', '=', 'package'), ('tk_code', '=', 'cb_imcustoms_finished')], limit=1)
node_obj = self.env['cc.node'].sudo().search([('node_type', '=', 'package'), ('seq', '<', push_node_obj.seq)],
order='seq desc',
limit=1)
......
import random
from odoo import models, fields, api
class CCExceptionInfo(models.Model):
_name = 'cc.exception.info'
_description = 'Exception Information'
_rec_name = 'reason'
@api.model
def create(self, vals):
if 'exception_code' not in vals or vals['exception_code'] == '/':
vals['exception_code'] = self.env['ir.sequence'].next_by_code('cc.exception.info') or '/'
obj = super(CCExceptionInfo, self).create(vals)
return obj
exception_code = fields.Char(string='Exception Code', default='/', required=True) # 异常编码*
reason = fields.Text(string='Reason', required=True, translate=True) # 异常原因
responsible_email = fields.Text(string='Responsible Email') # 异常接收负责人邮箱(可输入多个)
# 异常编码增加唯一约束
_sql_constraints = [('exception_code_uniq', 'unique(exception_code)', 'The Exception Code must be unique.')]
from odoo import models, fields
class CCLastMileProvider(models.Model):
_name = 'cc.last.mile.provider'
_description = 'Last Mile Provider'
name = fields.Char(string='Courier Name', required=True) # 快递名称
abbreviation = fields.Char(string='Abbreviation', required=True) # 简称
tape_color_value = fields.Char(string='Tape Color Value') # 胶带色值
active = fields.Boolean(default=True) # 有效☑️
matching_value = fields.Float(string='Matching Value') # 尾程快递匹配值
def __str__(self):
return f"LastMileProvider(courier_name={self.courier_name}, abbreviation={self.abbreviation}, tape_color_value={self.tape_color_value}, is_valid={self.is_valid}, matching_value={self.matching_value})"
\ No newline at end of file
# 导入odoo
import base64
import xlrd
from odoo import models, fields, api, _
# 导入日志
import logging
import xlrd
from odoo import models, fields, api, _
from odoo.exceptions import UserError
# 获取日志
......@@ -45,3 +42,9 @@ class CcNode(models.Model):
], string='Node Type', default='bl')
next_code_ids = fields.Many2many('cc.node', 'node_next_node_rel', 'node_id', 'next_node_id', 'Next Node',
domain="[('node_type','=',node_type)]")
tally_state = fields.Selection([
('unprocessed_goods', 'Unprocessed goods'),
('checked_goods', 'Checked goods'),
('handover_completed', 'Handover Completed')
], default='unprocessed_goods', string='Tally Status', index=True) # 理货状态 未理货/已理货/尾程交接
......@@ -9,7 +9,6 @@ import json
import xlrd
import base64
import pdfplumber
import demjson
from io import BytesIO
from datetime import datetime, timedelta
import re
......
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
batch_input_ship_package_status_wizard_group_user,batch_input_ship_package_status_wizard_group_user,ccs_base.model_batch_input_ship_package_status_wizard,base.group_user,1,1,1,1
export_bl_big_package_xlsx_wizard_group_user,export_bl_big_package_xlsx_wizard_group_user,ccs_base.model_export_bl_big_package_xlsx_wizard,base.group_user,1,1,1,1
associate_pallet_wizard_group_user,associate_pallet_wizard_group_user,ccs_base.model_associate_pallet_wizard,base.group_user,1,1,1,1
access_group_user_common_common,access_group_user_common_common,model_common_common,base.group_user,1,1,1,1
......@@ -11,6 +15,12 @@ access_cc_node_exception_reason_base.group_user,cc_node_exception_reason base.gr
access_cc_node_exception_reason_base.group_erp_manager,cc_node_exception_reason base.group_erp_manager,ccs_base.model_cc_node_exception_reason,base.group_erp_manager,1,1,1,1
cc_exception_info_group_user,cc_exception_info_group_user,ccs_base.model_cc_exception_info,base.group_user,1,0,0,0
cc_exception_info_group_erp_manager,cc_exception_info_group_erp_manager,ccs_base.model_cc_exception_info,base.group_erp_manager,1,1,1,1
cc_last_mile_provider_group_user,cc_last_mile_provider_group_user,ccs_base.model_cc_last_mile_provider,base.group_user,1,0,0,0
cc_last_mile_provider_group_erp_manager,cc_last_mile_provider_group_erp_manager,ccs_base.model_cc_last_mile_provider,base.group_erp_manager,1,1,1,1
......
<odoo>
<record id="view_exception_info_form" model="ir.ui.view">
<field name="name">exception.info.form</field>
<field name="model">cc.exception.info</field>
<field name="arch" type="xml">
<form string="Exception Information">
<sheet>
<group>
<field name="exception_code" readonly="1"/> <!-- 异常编码 -->
<field name="reason"/> <!-- 异常原因 -->
<field name="responsible_email"/> <!-- 异常接收负责人邮箱 -->
</group>
</sheet>
</form>
</field>
</record>
<record id="view_exception_info_tree" model="ir.ui.view">
<field name="name">exception.info.tree</field>
<field name="model">cc.exception.info</field>
<field name="arch" type="xml">
<tree string="Exception Information">
<field name="exception_code"/> <!-- 异常编码 -->
<field name="reason"/> <!-- 异常原因 -->
<field name="responsible_email"/> <!-- 异常接收负责人邮箱 -->
</tree>
</field>
</record>
<record model="ir.ui.view" id="view_exception_info_search">
<field name="name">exception.info.search</field>
<field name="model">cc.exception.info</field>
<field name="arch" type="xml">
<search string="Exception Information">
<field name="exception_code"/>
<field name="reason"/>
</search>
</field>
</record>
<record id="action_exception_info" model="ir.actions.act_window">
<field name="name">Exception Information</field>
<field name="res_model">cc.exception.info</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_exception_info" name="Exception Information" parent="menu_ccs_base_main" sequence="98"
action="action_exception_info"/>
</odoo>
\ No newline at end of file
<odoo>
<record id="view_last_mile_provider_form" model="ir.ui.view">
<field name="name">last.mile.provider.form</field>
<field name="model">cc.last.mile.provider</field>
<field name="arch" type="xml">
<form string="Last Mile Provider">
<sheet>
<group>
<group>
<field name="name"/> <!-- 快递名称 -->
<field name="abbreviation"/> <!-- 简称 -->
<field name="tape_color_value"/> <!-- 胶带色值 -->
<field name="matching_value"/> <!-- 尾程快递匹配值 -->
</group>
<group>
<field name="active"/> <!-- 有效☑️ -->
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_last_mile_provider_tree" model="ir.ui.view">
<field name="name">last.mile.provider.tree</field>
<field name="model">cc.last.mile.provider</field>
<field name="arch" type="xml">
<tree string="Last Mile Provider">
<field name="name"/> <!-- 快递名称 -->
<field name="abbreviation"/> <!-- 简称 -->
<field name="tape_color_value"/> <!-- 胶带色值 -->
<field name="matching_value"/> <!-- 尾程快递匹配值 -->
<field name="active"/> <!-- 有效☑️ -->
</tree>
</field>
</record>
<record model="ir.ui.view" id="view_last_mile_provider_search">
<field name="name">last.mile.provider.search</field>
<field name="model">cc.last.mile.provider</field>
<field name="arch" type="xml">
<search string="Last Mile Provider">
<field name="name"/>
<field name="abbreviation"/>
</search>
</field>
</record>
<record id="action_last_mile_provider" model="ir.actions.act_window">
<field name="name">Last Mile Providers</field>
<field name="res_model">cc.last.mile.provider</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_last_mile_provider" name="Last Mile Providers" parent="menu_ccs_base_main" sequence="95"
action="action_last_mile_provider"/>
</odoo>
\ No newline at end of file
......@@ -2,8 +2,5 @@
from . import batch_input_ship_package_statu_wizard
from . import export_bl_big_package_xlsx_wizard
# from . import again_push_wizard
# from . import parcel_exception_wizard
# from . import big_bag_pickup_wizard
# from . import batch_push_tiktok
# from . import big_bag_check_wizard
from . import associate_pallet_wizard
from odoo import models, fields, api
from odoo.exceptions import UserError
class AddExceptionInfoWizard(models.TransientModel):
_name = 'add.exception.info.wizard'
_description = 'Add Exception Information Wizard'
exception_ids = fields.Many2many('exception.info', 'big_package_add_exception_rel', string='Exception Information',
required=True) # 异常信息(多选)
send_email = fields.Boolean(string='Send Email Notification', default=False) # 发送邮件通知
email_language = fields.Selection([
('zh', 'Chinese'),
('en', 'English')
], string='Email Language', default='zh') # 邮件语言
@api.multi
def confirm(self):
for record in self:
# 更新小包的异常信息
exception_objs=record.exception_ids
package_objs = self.env['big.package'].search([('id', 'in', self.env.context.get('active_id'))])
for package in package_objs:
package.exception_info_ids = [(6,0,exception_objs.ids)] # 回写小包的异常信息
# 发送邮件通知
if record.send_email:
self.send_email_notification(package)
def send_email_notification(self, package,exception_objs):
"""
发送对应语言的邮件 '/'.join([exception.reason for exception in exception_objs])
"""
if self.email_language == 'zh':
template_id = self.env.ref('your_module.email_template_exception_notification')
else:
template_id = self.env.ref('your_module.email_template_exception_notification_en') # Assuming you have an English template
if template_id:
template_id.send_mail(package.id, force_send=True,
email_values={
'email_to': '',
'email_from': ''
})
else:
raise UserError("Email template not found.")
<odoo>
<record id="view_add_exception_info_wizard" model="ir.ui.view">
<field name="name">add.exception.info.wizard.form</field>
<field name="model">add.exception.info.wizard</field>
<field name="arch" type="xml">
<form string="Add Exception Information">
<sheet>
<group>
<field name="exception_ids" widget="many2many_tags"/> <!-- 异常信息 -->
<field name="send_email"/> <!-- 实付发送邮件通知 -->
<field name="email_language"/> <!-- 邮件语言 -->
</group>
<footer>
<button string="Confirm" type="object" name="confirm" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</sheet>
</form>
</field>
</record>
</odoo>
\ No newline at end of file
from datetime import date
from odoo import models, fields, api
class AssociatePalletWizard(models.TransientModel):
_name = 'associate.pallet.wizard'
_description = 'Associate Pallet Wizard'
usage_date = fields.Date(string='Usage Date', default=date.today) # 使用日期
pallet_number = fields.Char(string='Pallet Number', required=True) # 托盘号
big_package_numbers = fields.Text(string='Big Package Numbers') # 大包号(可输入多个)
def confirm(self):
for record in self:
# 处理大包号
big_package_ids = record.big_package_numbers.splitlines()
for package_number in big_package_ids:
package = self.env['big.package'].search([('number', '=', package_number)], limit=1)
if package:
# 更新托盘号和使用日期
old_pallet_number = package.pallet_number
old_usage_date = package.usage_date
package.pallet_number = record.pallet_number
package.usage_date = record.usage_date
body = '%s %s更改了托盘号,由%s变更为%s,托盘使用日期%s变更为%s' % (
self.env.user.name, fields.Datetime.now(), old_pallet_number, record.pallet_number,
old_usage_date,
record.usage_date)
package.message_post(body=body)
<odoo>
<record id="view_associate_pallet_wizard" model="ir.ui.view">
<field name="name">associate.pallet.wizard.form</field>
<field name="model">associate.pallet.wizard</field>
<field name="arch" type="xml">
<form string="Associate Pallet">
<sheet>
<group>
<field name="usage_date"/> <!-- 使用日期 -->
<field name="pallet_number"/> <!-- 托盘号 -->
<field name="big_package_numbers"/> <!-- 大包号 -->
</group>
<footer>
<button string="Confirm" type="object" name="confirm" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</sheet>
</form>
</field>
</record>
<record id="action_associate_pallet" model="ir.actions.act_window">
<field name="name">Associate Pallet</field>
<field name="res_model">associate.pallet.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</odoo>
\ No newline at end of file
<odoo>
<record id="email_template_exception_notification" model="mail.template">
<field name="name">Exception Notification</field>
<field name="model_id" ref="model_exception_info"/>
<field name="email_from">${(object.user_id.email or '')|safe}</field>
<field name="subject">大包(或小包)异常</field>
<field name="body_html">
<![CDATA[
<p>Dear all,</p>
<p>包裹:${object.big_package_numbers}(取大包号或小包物流订单号)</p>
<p>出现异常,异常原因:${object.reason}(若有多个,以/进行区分)</p>
<p>请知晓。</p>
<p>Best regards,</p>
<p>Your Team</p>
]]>
</field>
<field name="body_html_en">
<![CDATA[
<p>Dear all,</p>
<p>Package: ${object.big_package_numbers} (取大包号或小包物流订单号)</p>
<p>Please know that there is an exception and the cause of the exception is: ${object.reason} (若有多个,以/进行区分).</p>
<p>Best regards,</p>
<p>Your Team</p>
]]>
</field>
</record>
</odoo>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论