提交 71cce641 authored 作者: 伍姿英's avatar 伍姿英

Merge branch 'release/3.2.0'

...@@ -41,12 +41,12 @@ class CCLastMileProvider(models.Model): ...@@ -41,12 +41,12 @@ class CCLastMileProvider(models.Model):
matching_value = fields.Text(string='Matching Value') # 尾程服务商匹配值 matching_value = fields.Text(string='Matching Value') # 尾程服务商匹配值
placement_area = fields.Char('Placement Area') # 摆放区域,英文 placement_area = fields.Char('Placement Area') # 摆放区域,英文
def match_provider(self, provider_name): def match_provider(self, provider_name,record_obj=None):
"""Check if the provider name exists in matching values and return the record.""" """Check if the provider name exists in matching values and return the record."""
# 将输入的 provider_name 转换为小写 # 将输入的 provider_name 转换为小写
provider_name_lower = provider_name.lower() provider_name_lower = provider_name.lower()
# 查询所有匹配的记录 # 查询所有匹配的记录
matching_records = self.sudo().search([]) matching_records = self.sudo().search([]) if not record_obj else record_obj
# 检查是否有记录的 matching_value 包含 provider_name(不区分大小写) # 检查是否有记录的 matching_value 包含 provider_name(不区分大小写)
for record in matching_records: for record in matching_records:
if record.matching_value: if record.matching_value:
......
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink 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 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 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 associate_pallet_wizard_group_user,associate_pallet_wizard_group_user,model_associate_pallet_wizard,base.group_user,1,1,1,1
add_exception_info_wizard_group_user,add_exception_info_wizard_group_user,ccs_base.model_add_exception_info_wizard,base.group_user,1,1,1,1 add_exception_info_wizard_group_user,add_exception_info_wizard_group_user,ccs_base.model_add_exception_info_wizard,base.group_user,1,1,1,1
update_bl_status_wizard_group_user,update_bl_status_wizard_group_user,ccs_base.model_update_bl_status_wizard,base.group_user,1,1,1,1 update_bl_status_wizard_group_user,update_bl_status_wizard_group_user,ccs_base.model_update_bl_status_wizard,base.group_user,1,1,1,1
batch_update_transfer_bl_no_wizard_group_user,batch_update_transfer_bl_no_wizard_group_user,ccs_base.model_batch_update_transfer_bl_no_wizard,base.group_user,1,1,1,1 batch_update_transfer_bl_no_wizard_group_user,batch_update_transfer_bl_no_wizard_group_user,ccs_base.model_batch_update_transfer_bl_no_wizard,base.group_user,1,1,1,1
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
<field name="ship_package_qty" string="Packages Qty"/> <field name="ship_package_qty" string="Packages Qty"/>
<field name="goods_qty" string="Goods Qty"/> <field name="goods_qty" string="Goods Qty"/>
<field name="is_cancel" string="Cancelled"/> <field name="is_cancel" string="Cancelled"/>
<field name="next_provider_name"/>
<field name="pallet_number"/> <field name="pallet_number"/>
<field name="pallet_usage_date"/> <field name="pallet_usage_date"/>
<field name="tally_state" optional="show"/> <field name="tally_state" optional="show"/>
...@@ -164,9 +165,6 @@ ...@@ -164,9 +165,6 @@
</field> </field>
</record> </record>
<menuitem parent="" sequence="13" name="Big Package" id="menu_cc_big_package" action="action_cc_big_package"/>
<record id="big_package_add_exception_info_server_action" model="ir.actions.server"> <record id="big_package_add_exception_info_server_action" model="ir.actions.server">
<field name="name">Batch Add Package Exception Information</field> <field name="name">Batch Add Package Exception Information</field>
<field name="model_id" ref="model_cc_big_package"/> <field name="model_id" ref="model_cc_big_package"/>
...@@ -179,16 +177,4 @@ ...@@ -179,16 +177,4 @@
action = records.action_package_exception_info() action = records.action_package_exception_info()
</field> </field>
</record> </record>
<!-- <record id="action_cc_big_package_server" model="ir.actions.server">-->
<!-- <field name="name">全部航班</field>-->
<!-- <field name="model_id" ref="model_cc_big_package"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">-->
<!-- action = model.action_cc_big_package()-->
<!-- </field>-->
<!-- </record>-->
<!-- <menuitem id="menu_cc_big_package" name="Big Package" action="action_cc_big_package_server" sequence="13"/>-->
</odoo> </odoo>
\ No newline at end of file
...@@ -320,8 +320,6 @@ ...@@ -320,8 +320,6 @@
</field> </field>
</record> </record>
<menuitem parent="" sequence="10" name="Bill of Loading" id="menu_cc_bl" action="action_cc_bl"/>
<!--&lt;!&ndash; <record model="ir.ui.view" id="search_cc_bl_view">&ndash;&gt;--> <!--&lt;!&ndash; <record model="ir.ui.view" id="search_cc_bl_view">&ndash;&gt;-->
<!--&lt;!&ndash; <field name="name">search.cc.bl</field>&ndash;&gt;--> <!--&lt;!&ndash; <field name="name">search.cc.bl</field>&ndash;&gt;-->
......
...@@ -84,8 +84,4 @@ ...@@ -84,8 +84,4 @@
</p> </p>
</field> </field>
</record> </record>
<!-- <menuitem parent="" sequence="99" name="Clearance File" id="menu_cc_clearance_file" action="action_cc_clearance_file"/>-->
</odoo> </odoo>
\ No newline at end of file
...@@ -146,13 +146,15 @@ ...@@ -146,13 +146,15 @@
<field name="context">{}</field> <field name="context">{}</field>
<field name="help" type="html"> <field name="help" type="html">
<p class="o_view_nocontent_smiling_face"> <p class="o_view_nocontent_smiling_face">
[Customers Declaration Order] Not yet! Click the Create button in the top left corner and the sofa is yours! [Customers Declaration Order] Not yet! Click the Create button in the top left corner and the sofa is
yours!
</p> </p>
<p> <p>
</p> </p>
</field> </field>
</record> </record>
<!--没用到-->
<menuitem sequence="20" name="CC Order" id="menu_cc_customers_declaration_order" <menuitem sequence="20" name="CC Order" id="menu_cc_customers_declaration_order"
action="action_cc_customers_declaration_order" web_icon="ccs_base,static/description/icon1.png"/> action="action_cc_customers_declaration_order" web_icon="ccs_base,static/description/icon1.png"/>
......
...@@ -45,7 +45,4 @@ ...@@ -45,7 +45,4 @@
<field name="res_model">cc.exception.info</field> <field name="res_model">cc.exception.info</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
</record> </record>
<menuitem id="menu_exception_info" name="Package Exception Information" parent="menu_ccs_base_main" sequence="98"
action="action_exception_info"/>
</odoo> </odoo>
\ No newline at end of file
...@@ -157,32 +157,4 @@ ...@@ -157,32 +157,4 @@
</p> </p>
</field> </field>
</record> </record>
<!-- <record id="big_package_add_exception_info_server_action" model="ir.actions.server">-->
<!-- <field name="name">Batch Add Package Exception Information</field>-->
<!-- <field name="model_id" ref="model_cc_big_package"/>-->
<!-- <field name="binding_model_id" ref="model_cc_big_package"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="binding_view_types">list</field>-->
<!-- <field name="groups_id" eval="[(4, ref('ccs_base.group_clearance_of_customs_manager'))]"/>-->
<!-- <field name="code">-->
<!-- if records:-->
<!-- action = records.action_package_exception_info()-->
<!-- </field>-->
<!-- </record>-->
<!-- <record id="action_cc_big_package_server" model="ir.actions.server">-->
<!-- <field name="name">全部航班</field>-->
<!-- <field name="model_id" ref="model_cc_big_package"/>-->
<!-- <field name="state">code</field>-->
<!-- <field name="code">-->
<!-- action = model.action_cc_big_package()-->
<!-- </field>-->
<!-- </record>-->
<!-- <menuitem id="menu_cc_big_package" name="Big Package" action="action_cc_big_package_server" sequence="13"/>-->
</odoo> </odoo>
\ No newline at end of file
...@@ -57,7 +57,4 @@ ...@@ -57,7 +57,4 @@
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
</record> </record>
<menuitem id="menu_last_mile_provider" name="Last Mile Providers" parent="menu_ccs_base_main" sequence="95"
action="action_last_mile_provider"/>
</odoo> </odoo>
\ No newline at end of file
...@@ -41,9 +41,4 @@ ...@@ -41,9 +41,4 @@
<field name="domain">[]</field> <field name="domain">[]</field>
<field name="context">{}</field> <field name="context">{}</field>
</record> </record>
<menuitem parent="menu_ccs_base_main" sequence="100" name="CC Node Exception Reason"
id="menu_cc_node_exception_reason"
action="action_cc_node_exception_reason"/>
</odoo> </odoo>
\ No newline at end of file
...@@ -54,7 +54,4 @@ ...@@ -54,7 +54,4 @@
</p> </p>
</field> </field>
</record> </record>
<menuitem parent="menu_ccs_base_main" sequence="99" name="CC Node" id="menu_cc_node" action="action_cc_node"/>
</odoo> </odoo>
\ No newline at end of file
...@@ -184,6 +184,4 @@ ...@@ -184,6 +184,4 @@
</field> </field>
</record> </record>
<menuitem parent="" sequence="16" name="Package Goods" id="menu_cc_package_good" action="action_cc_package_good"/>
</odoo> </odoo>
\ No newline at end of file
...@@ -335,8 +335,6 @@ ...@@ -335,8 +335,6 @@
</field> </field>
</record> </record>
<menuitem parent="" sequence="15" name="Ship Package" id="menu_cc_ship_package" action="action_cc_ship_package"/>
<record id="ship_package_add_exception_info_server_action" model="ir.actions.server"> <record id="ship_package_add_exception_info_server_action" model="ir.actions.server">
<field name="name">Batch Add Package Exception Information</field> <field name="name">Batch Add Package Exception Information</field>
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
<record id="menu_ccs_base_main" model="ir.ui.menu"> <record id="menu_ccs_base_main" model="ir.ui.menu">
<field name="name">Master Data</field> <field name="name">Master Data</field>
<field name="sequence" eval="20"/> <field name="sequence" eval="20"/>
<field name="groups_id" eval="[(4, ref('ccs_base.group_clearance_of_customs_manager'))]"/>
<field name="web_icon">ccs_base,static/description/icon5.png</field> <field name="web_icon">ccs_base,static/description/icon5.png</field>
</record> </record>
...@@ -31,6 +32,20 @@ ...@@ -31,6 +32,20 @@
<menuitem sequence="10" name="Customers" id="menu_cc_partner" action="action_cc_partner" <menuitem sequence="10" name="Customers" id="menu_cc_partner" action="action_cc_partner"
parent="menu_ccs_base_main"/> parent="menu_ccs_base_main"/>
<menuitem id="menu_exception_info" name="Package Exception Information" parent="menu_ccs_base_main"
sequence="98"
action="action_exception_info"/>
<menuitem id="menu_last_mile_provider" name="Last Mile Providers" parent="menu_ccs_base_main" sequence="95"
action="action_last_mile_provider"/>
<menuitem parent="menu_ccs_base_main" sequence="100" name="CC Node Exception Reason"
id="menu_cc_node_exception_reason"
action="action_cc_node_exception_reason"/>
<menuitem parent="menu_ccs_base_main" sequence="99" name="CC Node" id="menu_cc_node" action="action_cc_node"/>
<!-- # 增加一个"供应商"action, 仅显示为供应商的partner,显示模式为树,表单--> <!-- # 增加一个"供应商"action, 仅显示为供应商的partner,显示模式为树,表单-->
<record model="ir.actions.act_window" id="action_cc_is_clearance_company"> <record model="ir.actions.act_window" id="action_cc_is_clearance_company">
<field name="name">Clearance Company</field> <field name="name">Clearance Company</field>
...@@ -53,15 +68,34 @@ ...@@ -53,15 +68,34 @@
parent="menu_ccs_base_main"/> parent="menu_ccs_base_main"/>
<menuitem sequence="25" name="History Data" id="menu_cc_history_data" <menuitem sequence="25" name="History Data" id="menu_cc_history_data"
/> groups="ccs_base.group_clearance_of_customs_user,ccs_base.group_clearance_of_customs_manager"
/>
<menuitem parent="menu_cc_history_data" sequence="1" name="History Big Package" id="menu_cc_history_big_package"
action="action_cc_history_big_package"/>
<menuitem parent="menu_cc_history_data" sequence="5" name="History Package Goods"
id="menu_cc_history_package_good" action="action_cc_history_package_good"/>
<menuitem parent="menu_cc_history_data" sequence="3" name="History Ship Package"
id="menu_cc_history_ship_package" action="action_cc_history_ship_package"/>
<menuitem parent="menu_cc_history_data" id="menu_history_flight_tt_api_log" name="TIKTOK推送日志" sequence="7"
action="action_history_tt_api_log"
groups="ccs_base.group_clearance_of_customs_user,ccs_base.group_clearance_of_customs_manager"/>
<menuitem parent="" sequence="10" name="Bill of Loading" id="menu_cc_bl" action="action_cc_bl"
groups="ccs_base.group_clearance_of_customs_user,ccs_base.group_clearance_of_customs_manager"/>
<menuitem parent="menu_cc_history_data" sequence="1" name="History Big Package" id="menu_cc_history_big_package" action="action_cc_history_big_package"/> <menuitem parent="" sequence="13" name="Big Package" id="menu_cc_big_package" action="action_cc_big_package"
groups="ccs_base.group_clearance_of_customs_user,ccs_base.group_clearance_of_customs_manager"/>
<menuitem parent="menu_cc_history_data" sequence="5" name="History Package Goods" id="menu_cc_history_package_good" action="action_cc_history_package_good"/> <menuitem parent="" sequence="16" name="Package Goods" id="menu_cc_package_good" action="action_cc_package_good"
groups="ccs_base.group_clearance_of_customs_user,ccs_base.group_clearance_of_customs_manager"/>
<menuitem parent="menu_cc_history_data" sequence="3" name="History Ship Package" id="menu_cc_history_ship_package" action="action_cc_history_ship_package"/> <menuitem parent="" sequence="15" name="Ship Package" id="menu_cc_ship_package" action="action_cc_ship_package"
groups="ccs_base.group_clearance_of_customs_user,ccs_base.group_clearance_of_customs_manager"/>
<menuitem parent="menu_cc_history_data" id="menu_history_flight_tt_api_log" name="TIKTOK推送日志" sequence="7" action="action_history_tt_api_log"/>
</data> </data>
</odoo> </odoo>
\ No newline at end of file
...@@ -64,14 +64,14 @@ class AssociatePalletWizard(models.TransientModel): ...@@ -64,14 +64,14 @@ class AssociatePalletWizard(models.TransientModel):
new_pallet_number = record.pallet_number # 修改的托盘号 new_pallet_number = record.pallet_number # 修改的托盘号
old_usage_date = package.pallet_usage_date old_usage_date = package.pallet_usage_date
# 同一提单,同一托盘号,使用日期必须一致 # 同一提单,同一托盘号,使用日期必须一致
related_packages = package.bl_id.big_package_ids.filtered( # related_packages = package.bl_id.big_package_ids.filtered(
lambda p: p.pallet_number == new_pallet_number) # 查找对应提单下相同托盘号的所有大包 # lambda p: p.pallet_number == new_pallet_number) # 查找对应提单下相同托盘号的所有大包
warning_package_arr = [related_package.big_package_no for related_package in related_packages if # warning_package_arr = [related_package.big_package_no for related_package in related_packages if
related_package.pallet_usage_date != record.usage_date] # related_package.pallet_usage_date != record.usage_date]
if warning_package_arr: # if warning_package_arr:
raise ValidationError( # raise ValidationError(
_('Big Package No :%s ,The same bill of lading, same pallet number, and usage date must be consistent!') % ( # _('Big Package No :%s ,The same bill of lading, same pallet number, and usage date must be consistent!') % (
'\n'.join(warning_package_arr))) # 大包号关联的同一提单,同一托盘号,使用日期必须一致 # '\n'.join(warning_package_arr))) # 大包号关联的同一提单,同一托盘号,使用日期必须一致
package.update_pallet_info(new_pallet_number, record.usage_date) package.update_pallet_info(new_pallet_number, record.usage_date)
if old_pallet_number: if old_pallet_number:
# %s %s更改了托盘号,由%s变更为%s,托盘使用日期%s变更为%s # %s %s更改了托盘号,由%s变更为%s,托盘使用日期%s变更为%s
......
...@@ -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',
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
'views/cc_bl_view.xml', 'views/cc_bl_view.xml',
'views/pda_scan_record_views.xml', 'views/pda_scan_record_views.xml',
'views/bl_patrol_views.xml', 'views/bl_patrol_views.xml',
'views/menu_view.xml',
], ],
'demo': [ 'demo': [
......
...@@ -361,12 +361,13 @@ class OrderController(http.Controller): ...@@ -361,12 +361,13 @@ class OrderController(http.Controller):
res = {'state': 201, 'message': ''} res = {'state': 201, 'message': ''}
action_type = kwargs.get('action_type') or 'tally' # tally / handover action_type = kwargs.get('action_type') or 'tally' # tally / handover
operation = 'tail_tally' if action_type == 'tally' else 'tail_handover' operation = 'tail_tally' if action_type == 'tally' else 'tail_handover'
tally_user_id = False # 理货人ID tally_user_id = False # 理货人ID
ship_packages = [] ship_packages = []
try: try:
logging.info('update_pro_big_package_tally_detail kw:%s' % kwargs) logging.info('update_pro_big_package_tally_detail kw:%s' % kwargs)
if action_type and (kwargs.get('big_package_arr') or kwargs.get('ship_package_arr')): if action_type and (kwargs.get('big_package_arr') or kwargs.get('ship_package_arr')):
tally_user_id=kwargs['big_package_arr'][0].get('tally_user_id') if kwargs.get('big_package_arr') else ( tally_user_id = kwargs['big_package_arr'][0].get('tally_user_id') if kwargs.get(
'big_package_arr') else (
kwargs['ship_package_arr'][0].get('tally_user_id') if kwargs.get('ship_package_arr') else False) kwargs['ship_package_arr'][0].get('tally_user_id') if kwargs.get('ship_package_arr') else False)
big_package_exception_arr = {} big_package_exception_arr = {}
ship_package_exception_arr = {} ship_package_exception_arr = {}
...@@ -583,7 +584,8 @@ class OrderController(http.Controller): ...@@ -583,7 +584,8 @@ class OrderController(http.Controller):
'zh': '系统解析错误,错误原因是%s' % e 'zh': '系统解析错误,错误原因是%s' % e
} }
logging.info('last_mile_tally error:%s' % e) logging.info('last_mile_tally error:%s' % e)
res['message'] = exceptions_msg_dic[pda_lang] # _('System parsing error, the reason for the error is %s', e) # 系统解析错误,错误原因是 res['message'] = exceptions_msg_dic[
pda_lang] # _('System parsing error, the reason for the error is %s', e) # 系统解析错误,错误原因是
logging.info('last_mile_tally res:%s' % res) logging.info('last_mile_tally res:%s' % res)
return res return res
...@@ -614,7 +616,7 @@ class OrderController(http.Controller): ...@@ -614,7 +616,7 @@ class OrderController(http.Controller):
@http.route('/api/last_mile/delivery/time_check', type='json', auth='public', csrf=False) @http.route('/api/last_mile/delivery/time_check', type='json', auth='public', csrf=False)
def last_mile_delivery_time_check(self): def last_mile_delivery_time_check(self):
""" """
按尾程快递交货接口,查询系统所有清关中的提单,且大包状态为已理货的数量,按下一阶段服务商名称分组,下一个阶段服务商名称匹配尾程快递传给PDA。传输字段与理货的一致。 尾程快递交货检查时间是否正常
""" """
kwargs = json.loads(request.httprequest.data) kwargs = json.loads(request.httprequest.data)
pda_lang = kwargs.get('pda_lang') or 'zh' pda_lang = kwargs.get('pda_lang') or 'zh'
...@@ -642,17 +644,18 @@ class OrderController(http.Controller): ...@@ -642,17 +644,18 @@ 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. 按托盘理货时,查非已完成状态的提单
# 2. 查所有大包 # else:
big_packages = request.env['cc.big.package'].sudo().search([ # 先都查清关中的,如果以后要查非已完成状态的提单,再修改domain。而且查尾程快递和对应的大包或托盘信息得分两个接口
('bl_id', 'in', bls.ids), domain = [('bl_id.state', '=', 'ccing')] # 1. 按尾程理货时,查所有清关中提单
('tally_state', '=', tally_state) # 2. 查所有大包 如果是托盘的交货,不需要过滤理货状态
]) if not is_pallet or (is_pallet and tally_state == 'unprocessed_goods'):
domain += [('tally_state', '=', tally_state)]
big_packages = request.env['cc.big.package'].sudo().search(domain)
# 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 +666,28 @@ class OrderController(http.Controller): ...@@ -663,13 +666,28 @@ 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)) if tally_state == 'unprocessed_goods' or (tally_state == 'checked_goods' and not is_pallet):
group_dict[key]['ship_package_arr'].extend( group_dict[key]['big_package_arr'].append(
[ship_package_item.search_ship_package_info(pda_lang=pda_lang) for ship_package_item in pkg.search_big_package_info(pda_lang=pda_lang, type=tally_state))
pkg.ship_package_ids]) # 按托盘理货时返回未使用的托盘信息,按尾程时返回小包信息
if is_pallet:
# 如果是未理货,查未使用托盘;如果是已理货,查已使用托盘
if tally_state == 'unprocessed_goods':
domain = [('usage_state', '=', 'unused')]
else:
domain = [('usage_state', '=', 'used')]
unused_pallets = request.env['cc.pallet'].sudo().search([('express_company_id', '=', key)] + domain)
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())
# 按服务商名称升序排序 # 按服务商名称升序排序
...@@ -677,17 +695,16 @@ class OrderController(http.Controller): ...@@ -677,17 +695,16 @@ class OrderController(http.Controller):
return {'provider_info_arr': provider_info_arr, 'state': 200, return {'provider_info_arr': provider_info_arr, 'state': 200,
'bl_ids': list(set(list(map(lambda x: x.bl_id.id, big_packages))))} 'bl_ids': list(set(list(map(lambda x: x.bl_id.id, big_packages))))}
def _check_delivery_time_risk(self, bl_obj, pda_lang='zh'): def _check_delivery_time_risk(self, bl_obj, pda_lang='zh', pallet_name=None):
""" """
检查提单交货时间倒序风险 检查提单交货时间倒序风险
:param bl_obj: 提单对象 :param bl_obj: 提单对象
:param pda_lang: 语言设置 :param pda_lang: 语言设置
:param pallet_name: 托盘号
:return: 检查结果字典 :return: 检查结果字典
""" """
# 获取配置的交货操作晚于提货操作的时间参数(分钟) # 获取配置的交货操作晚于提货操作的时间参数(分钟)
config_param = request.env['ir.config_parameter'].sudo().get_param( config_param = request.env['ir.config_parameter'].sudo().get_param('delivery_time', '80')
'delivery_time', '80' # 使用现有的delivery_time参数,默认80分钟
)
allowed_minutes = int(config_param) allowed_minutes = int(config_param)
# 查找该提单的PDA扫码记录,类型为理货的 # 查找该提单的PDA扫码记录,类型为理货的
pda_records = request.env['pda.scan.record'].sudo().search([ pda_records = request.env['pda.scan.record'].sudo().search([
...@@ -705,10 +722,16 @@ class OrderController(http.Controller): ...@@ -705,10 +722,16 @@ class OrderController(http.Controller):
logging.info(f"current_time: {current_time}, operation_time: {operation_time},time_diff: {time_diff}") logging.info(f"current_time: {current_time}, operation_time: {operation_time},time_diff: {time_diff}")
# 如果时间差小于等于配置的参数,则存在风险 # 如果时间差小于等于配置的参数,则存在风险
if time_diff <= allowed_minutes: if time_diff <= allowed_minutes:
if pda_lang == 'en': if pallet_name:
message = f"The bill of lading has not reached the delivery time, and there is a risk of flashback. Please scan the code after {allowed_minutes} minutes." if pda_lang == 'en':
message = f"The pallet {pallet_name} has not reached the delivery time, and there is a risk of flashback. Please scan the code after {allowed_minutes} minutes."
else:
message = f"该托盘号{pallet_name}装载的提单未到交货时间,有风险产生倒叙,请间隔{allowed_minutes}分钟后再扫码;"
else: else:
message = f"该提单未到交货时间,有风险产生倒叙,请间隔{allowed_minutes}分钟后再扫码;" if pda_lang == 'en':
message = f"The bill of lading has not reached the delivery time, and there is a risk of flashback. Please scan the code after {allowed_minutes} minutes."
else:
message = f"该提单%s未到交货时间,有风险产生倒叙,请间隔{allowed_minutes}分钟后再扫码;" % bl_obj.bl_no
return { return {
'has_risk': True, 'has_risk': True,
...@@ -758,3 +781,370 @@ class OrderController(http.Controller): ...@@ -758,3 +781,370 @@ 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/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/update/pallet/big/package/tally/detail', type='json', auth='public', methods=['GET', 'POST'],
csrf=False)
def update_pallet_big_package_tally_detail(self):
"""
修改尾程快递按托盘号的理货信息
:return:
"""
kwargs = json.loads(request.httprequest.data)
pda_lang = kwargs.get('pda_lang') or 'zh'
res = {'state': 201, 'message': ''}
action_type = 'tally'
operation = 'pallet_tally' # 按托盘理货
tally_user_id = False # 理货人ID
ship_packages = []
try:
logging.info('update_pallet_big_package_tally_detail kw:%s' % kwargs)
if kwargs.get('pallet_arr'):
# 判断托盘数组里面的托盘号在托盘表里面是否存在
pallet_nos = [pallet_item.get('pallet_number') for pallet_item in kwargs.get('pallet_arr')]
pallet_obj = request.env['cc.pallet'].sudo().search([('name', 'in', pallet_nos)])
if not pallet_obj:
res['message'] = {
'en': 'Pallet number [%s] does not exist' % ','.join(pallet_nos),
'zh': '托盘号[%s]不存在' % ','.join(pallet_nos)
}[pda_lang]
return res
# 将托盘状态更新为已使用
all_big_package_arr = []
for pallet_item in kwargs.get('pallet_arr'):
pallet_number = pallet_item.get('pallet_number') # 托盘号
pallet_use_date = pallet_item.get('pallet_use_date') # 托盘使用日期
big_package_arr = pallet_item.get('big_package_arr', []) # 大包号数组
all_big_package_arr.extend(big_package_arr)
# 找到对应的托盘对象
pallet = pallet_obj.filtered(lambda p: p.name == pallet_number)
if pallet and big_package_arr:
# 获取大包对象
big_package_objs = request.env['cc.big.package'].sudo().search([
('big_package_no', 'in', [pkg.get('big_package_no') for pkg in big_package_arr])
])
if big_package_objs:
# 调用托盘的update_usage_state方法
pallet.update_usage_state(big_package_objs, pallet_use_date)
tally_user_id = kwargs['pallet_arr'][0]['big_package_arr'][0].get('tally_user_id') if kwargs.get(
'pallet_arr') and kwargs['pallet_arr'][0]['big_package_arr'] else False
big_package_exception_arr = {}
# 处理包裹信息
def process_packages(package_arr, ship_packages):
error_no_set = set() # 使用集合来存储错误信息
for package_item in package_arr:
package_no = package_item.get('big_package_no') # 包裹号
exception_cause_ids = package_item.get('exception_cause_ids') # 异常原因id数组
package_obj = request.env[f'cc.big.package'].sudo().search(
[('big_package_no', '=', package_no)]) # 大包 1个
if package_obj:
if exception_cause_ids:
for excep_item in exception_cause_ids:
if excep_item not in big_package_exception_arr:
big_package_exception_arr[excep_item] = [
]
big_package_exception_arr[excep_item] += package_obj.ids
package_obj.update_exception_info(
exception_cause_ids) # 修改异常信息
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'):
for package in package_obj:
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,
'bl_id': package.bl_id.id,
'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(
'tally_user_id'),
tally_time=tally_time) # 修改理货信息
else:
error_no_set.add(package_no)
return error_no_set
# 处理大包
if all_big_package_arr:
error_no_arr = process_packages(all_big_package_arr, ship_packages)
if error_no_arr:
res['message'] = {
'en': 'Big package number [%s] does not exist' % ','.join(error_no_arr),
'zh': '大包号[%s]不存在' % ','.join(error_no_arr)
}[pda_lang]
return res
# 修改异常原因,发送异常邮件
lang = 'zh_CN' if pda_lang == 'zh' else 'en_US' # 语言
for exception_id, big_package in big_package_exception_arr.items():
if big_package:
big_wizard_obj = request.env[
'add.exception.info.wizard'].sudo().with_context({'active_id': big_package,
'active_name': 'cc.big.package',
'not_update_ex': True}).create_add_exception_wizard(
'big package', [exception_id], big_package_ids=big_package, send_email=True,
email_language=lang)
big_wizard_obj.confirm() # 发送邮件
res['state'] = 200
logging.info('update_pallet_big_package_tally_detail ship_packages:%s' % len(ship_packages))
# 有小包 就更新小包状态和同步
if ship_packages:
# 获取最晚的操作时间
latest_operation_time = self._get_latest_operation_time(ship_packages)
# 在这里创建成功的pda扫码记录
bl_obj = request.env['cc.bl'].sudo().search(
[('id', 'in', [ship_package.get('bl_id') for ship_package in ship_packages])])
logging.info(f"bl_obj: {bl_obj}")
for bl in bl_obj:
request.env['pda.scan.record'].sudo().create_scan_record(
operation=operation,
record_type=action_type,
bill_number=bl.bl_no,
transfer_number=bl.transfer_bl_no,
state='success',
bl_id=bl.id,
operation_time=latest_operation_time,
operator_id=tally_user_id)
redis_conn = request.env['common.common'].sudo().get_redis()
if redis_conn and redis_conn != 'no':
bl_ids = [ship_package.get('bl_id') for ship_package in ship_packages]
logging.info('bl_ids:%s' % bl_ids)
redis_conn.lpush('mail_push_package_list', json.dumps(
{'ids': list(set(bl_ids)), 'ship_packages': str(ship_packages),
'action_type': action_type}))
else:
null_msg_dic = {
'en': 'The pallet data must be provided.',
'zh': '托盘数据必须提供。'
}
res['message'] = null_msg_dic[pda_lang]
except Exception as e:
error = str(e)
logging.info('update_pro_big_package_tally_detail 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扫码记录
if ship_packages:
bl_obj = request.env['cc.bl'].sudo().search(
[('id', 'in', [ship_package.get('bl_id') for ship_package in ship_packages])], limit=1)
if bl_obj:
for bl in bl_obj:
request.env['pda.scan.record'].sudo().create_scan_record(
operation=operation,
record_type=action_type,
bill_number=bl.bl_no,
transfer_number=bl.transfer_bl_no,
state='failed',
bl_id=bl.id,
failure_reason=error,
operator_id=tally_user_id)
else:
request.env['pda.scan.record'].sudo().create_scan_record(
operation=operation,
record_type=action_type,
bill_number='',
transfer_number='',
state='failed',
failure_reason=error,
operator_id=tally_user_id)
logging.info('update_pallet_big_package_tally_detail 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'
handover_user_id = kwargs.get('handover_user_id')
ship_packages = []
try:
logging.info('pallet_handover_complete kwargs:%s' % kwargs)
pallet_arr = kwargs.get('pallet_arr', [])
if not pallet_arr:
res['message'] = {
'en': 'Pallet data is required',
'zh': '托盘数据必须提供'
}[pda_lang]
return res
# 获取交货人
if not handover_user_id:
handover_user_id = kwargs.get('pallet_arr')[0].get('handover_user_id') # 交货人
# 处理托盘以及大包信息
def process_packages(pallet_data, ship_packages):
error_no_set = set() # 使用集合来存储错误信息
for pallet_item in pallet_data:
pallet_number = pallet_item.get('pallet_number') # 托盘号
pallet_obj = request.env['cc.pallet'].sudo().search([('name', '=', pallet_number)])
if not pallet_obj:
error_no_set.add(pallet_number)
continue
plate_number = pallet_item.get('plate_number', '') # 车牌号
handover_time = pallet_item.get('handover_time') # 交货时间
pallet_obj.update_pallet_info(delivery_plate_number=plate_number) # 更新托盘车牌号
package_obj = pallet_obj.package_ids # 获取托盘下的大包
if package_obj:
for package in package_obj:
# 添加小包信息
ship_packages.append({
'id': package.ship_package_ids.ids,
'bl_id': package.bl_id.id,
'tally_time': handover_time
}) # 小包
# 更新大包交货信息
package_obj.update_big_package_info(action_type='handover',
tally_state='handover_completed',
tally_user_id=handover_user_id,
tally_time=handover_time) # 修改交货信息
return error_no_set
# 处理大包
error_no_arr = process_packages(pallet_arr, ship_packages)
if error_no_arr:
res['message'] = {
'en': 'Big package number [%s] does not exist' % ','.join(error_no_arr),
'zh': '大包号[%s]不存在' % ','.join(error_no_arr)
}[pda_lang]
return res
res['state'] = 200
# 有小包 就更新小包状态和同步
if ship_packages:
# 获取最晚的操作时间
latest_operation_time = self._get_latest_operation_time(ship_packages)
# 在这里创建成功的pda扫码记录
bl_obj = request.env['cc.bl'].sudo().search(
[('id', 'in', [ship_package.get('bl_id') for ship_package in ship_packages])])
logging.info(f"bl_obj: {bl_obj}")
for bl in bl_obj:
request.env['pda.scan.record'].sudo().create_scan_record(
operation=operation,
record_type='handover',
bill_number=bl.bl_no,
transfer_number=bl.transfer_bl_no,
state='success',
bl_id=bl.id,
operation_time=latest_operation_time,
operator_id=handover_user_id)
redis_conn = request.env['common.common'].sudo().get_redis()
if redis_conn and redis_conn != 'no':
bl_ids = [ship_package.get('bl_id') for ship_package in ship_packages]
logging.info('bl_ids:%s' % bl_ids)
redis_conn.lpush('mail_push_package_list', json.dumps(
{'ids': list(set(bl_ids)), 'ship_packages': str(ship_packages),
'action_type': 'handover'}))
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=handover_user_id
)
logging.info('pallet_handover_complete res:%s' % res)
return res
@http.route('/api/pallet/delivery/time_check', type='json', auth='public', csrf=False)
def pallet_delivery_time_check(self):
"""
托盘交货检查时间是否正常
"""
kwargs = json.loads(request.httprequest.data)
pda_lang = kwargs.get('pda_lang') or 'zh'
res = {'state': 201, 'message': ''}
try:
logging.info('pallet_delivery_time_check kwargs:%s' % kwargs)
all_pallet_ids_in_request = kwargs['pallet_ids']
if all_pallet_ids_in_request:
pallet_objs = request.env['cc.pallet'].sudo().search([('id', 'in', all_pallet_ids_in_request)])
for pallet_obj in pallet_objs:
bl_objs = pallet_obj.package_ids.mapped('bl_id')
for bl_obj in bl_objs:
time_check_result = self._check_delivery_time_risk(bl_obj, pda_lang, pallet_obj.name)
if time_check_result['has_risk']:
res['state'] = 400
res['message'] = time_check_result['message']
return res
res['state'] = 200
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_delivery_time_check error:%s' % e)
res['message'] = exceptions_msg_dic[pda_lang]
logging.info('pallet_delivery_time_check res:%s' % res)
return res
...@@ -6,11 +6,11 @@ msgid "" ...@@ -6,11 +6,11 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Odoo Server 16.0\n" "Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-08-05 06:34+0000\n" "POT-Creation-Date: 2025-09-15 08:45+0000\n"
"PO-Revision-Date: 2025-08-05 14:38+0800\n" "PO-Revision-Date: 2025-09-15 16:46+0800\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
"Language: zh_CN\n" "Language: zh\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
...@@ -179,6 +179,7 @@ msgstr "创建第一条PDA扫码记录" ...@@ -179,6 +179,7 @@ msgstr "创建第一条PDA扫码记录"
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api__create_uid #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api__create_uid
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__create_uid #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__create_uid
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__create_uid
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_bl_sync_log__create_uid #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_bl_sync_log__create_uid
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_ship_package_sync_log__create_uid #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_ship_package_sync_log__create_uid
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record__create_uid #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record__create_uid
...@@ -188,6 +189,7 @@ msgstr "创建人" ...@@ -188,6 +189,7 @@ msgstr "创建人"
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api__create_date #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api__create_date
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__create_date #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__create_date
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__create_date
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_bl_sync_log__create_date #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_bl_sync_log__create_date
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_ship_package_sync_log__create_date #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_ship_package_sync_log__create_date
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record__create_date #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record__create_date
...@@ -209,6 +211,7 @@ msgstr "前置节点之间的默认间隔时间(分钟)。" ...@@ -209,6 +211,7 @@ msgstr "前置节点之间的默认间隔时间(分钟)。"
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api__display_name #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api__display_name
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__display_name #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__display_name
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__display_name
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_bl_sync_log__display_name #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_bl_sync_log__display_name
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_ship_package_sync_log__display_name #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_ship_package_sync_log__display_name
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record__display_name #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record__display_name
...@@ -259,6 +262,7 @@ msgstr "已更新节点" ...@@ -259,6 +262,7 @@ msgstr "已更新节点"
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api__id #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api__id
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__id #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__id
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__id
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_bl_sync_log__id #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_bl_sync_log__id
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_ship_package_sync_log__id #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_ship_package_sync_log__id
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record__id #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record__id
...@@ -279,6 +283,7 @@ msgstr "是否同步" ...@@ -279,6 +283,7 @@ msgstr "是否同步"
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api____last_update #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api____last_update
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log____last_update #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log____last_update
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol____last_update
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_bl_sync_log____last_update #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_bl_sync_log____last_update
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_ship_package_sync_log____last_update #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_ship_package_sync_log____last_update
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record____last_update #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record____last_update
...@@ -288,6 +293,7 @@ msgstr "" ...@@ -288,6 +293,7 @@ msgstr ""
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api__write_uid #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api__write_uid
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__write_uid #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__write_uid
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__write_uid
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_bl_sync_log__write_uid #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_bl_sync_log__write_uid
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_ship_package_sync_log__write_uid #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_ship_package_sync_log__write_uid
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record__write_uid #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record__write_uid
...@@ -297,6 +303,7 @@ msgstr "" ...@@ -297,6 +303,7 @@ msgstr ""
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api__write_date #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api__write_date
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__write_date #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__write_date
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__write_date
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_bl_sync_log__write_date #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_bl_sync_log__write_date
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_ship_package_sync_log__write_date #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_ship_package_sync_log__write_date
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record__write_date #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record__write_date
...@@ -368,6 +375,27 @@ msgstr "操作" ...@@ -368,6 +375,27 @@ msgstr "操作"
msgid "PDA Scan Record" msgid "PDA Scan Record"
msgstr "PDA扫码记录" msgstr "PDA扫码记录"
#. module: ccs_connect_tiktok
#: model:ir.model,name:ccs_connect_tiktok.model_cc_pallet
msgid "Pallet"
msgstr "托盘"
#. module: ccs_connect_tiktok
#. odoo-python
#: code:addons/ccs_connect_tiktok/models/pda_scan_record.py:0
#: model:ir.model.fields.selection,name:ccs_connect_tiktok.selection__pda_scan_record__operation__pallet_handover
#, python-format
msgid "Pallet Handover"
msgstr "托盘交货"
#. module: ccs_connect_tiktok
#. odoo-python
#: code:addons/ccs_connect_tiktok/models/pda_scan_record.py:0
#: model:ir.model.fields.selection,name:ccs_connect_tiktok.selection__pda_scan_record__operation__pallet_tally
#, python-format
msgid "Pallet Tally"
msgstr "托盘理货"
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_node__interval_minutes #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_cc_node__interval_minutes
msgid "Predecessor Node Interval (Minutes)" msgid "Predecessor Node Interval (Minutes)"
...@@ -478,7 +506,7 @@ msgstr "" ...@@ -478,7 +506,7 @@ msgstr ""
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model:ir.actions.act_window,name:ccs_connect_tiktok.action_ao_tt_api_log #: model:ir.actions.act_window,name:ccs_connect_tiktok.action_ao_tt_api_log
#: model:ir.ui.menu,name:ccs_connect_tiktok.menu_ao_flight_tt_api_log #: model:ir.ui.menu,name:ccs_connect_tiktok.menu_tt_api_log
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.form_ao_tt_api_log_view #: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.form_ao_tt_api_log_view
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view #: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.tree_ao_tt_api_log_view #: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.tree_ao_tt_api_log_view
...@@ -668,11 +696,39 @@ msgstr "" ...@@ -668,11 +696,39 @@ msgstr ""
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view #: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.view_bl_patrol_search
msgid "分组" msgid "分组"
msgstr "" msgstr ""
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model_terms:ir.actions.act_window,help:ccs_connect_tiktok.action_bl_patrol
msgid "创建第一个巡查记录"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,help:ccs_connect_tiktok.field_res_config_settings__patrol_start_hour
msgid "北京时间,24小时制"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__issue_count
msgid "发现问题数量"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_res_config_settings__patrol_sender_email
msgid "发送邮箱地址"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,help:ccs_connect_tiktok.field_res_config_settings__patrol_receiver_emails
msgid "多个邮箱地址,用逗号分隔"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields.selection,name:ccs_connect_tiktok.selection__bl_patrol__state__failed
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view #: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.view_bl_patrol_search
msgid "失败" msgid "失败"
msgstr "" msgstr ""
...@@ -681,6 +737,12 @@ msgstr "" ...@@ -681,6 +737,12 @@ msgstr ""
msgid "失败原因" msgid "失败原因"
msgstr "" msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields.selection,name:ccs_connect_tiktok.selection__bl_patrol__state__done
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.view_bl_patrol_search
msgid "完成"
msgstr ""
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model:ir.actions.server,name:ccs_connect_tiktok.cron_delete_log_ir_actions_server #: model:ir.actions.server,name:ccs_connect_tiktok.cron_delete_log_ir_actions_server
#: model:ir.cron,cron_name:ccs_connect_tiktok.cron_delete_log #: model:ir.cron,cron_name:ccs_connect_tiktok.cron_delete_log
...@@ -692,11 +754,49 @@ msgstr "" ...@@ -692,11 +754,49 @@ msgstr ""
msgid "客户" msgid "客户"
msgstr "" msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__package_issues
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.view_bl_patrol_form
msgid "小包轨迹问题"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__name
msgid "巡查名称"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_res_config_settings__patrol_check_days
msgid "巡查天数"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_res_config_settings__patrol_start_hour
msgid "巡查开始时间(小时)"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__check_date
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.view_bl_patrol_search
msgid "巡查日期"
msgstr ""
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view #: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view
msgid "成功" msgid "成功"
msgstr "" msgstr ""
#. module: ccs_connect_tiktok
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.view_bl_patrol_form
msgid "手动执行巡查"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields.selection,name:ccs_connect_tiktok.selection__bl_patrol__state__running
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.view_bl_patrol_search
msgid "执行中"
msgstr ""
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model:ir.actions.server,name:ccs_connect_tiktok.action_batch_update_package_status #: model:ir.actions.server,name:ccs_connect_tiktok.action_batch_update_package_status
msgid "批量手动处理小包异常数据" msgid "批量手动处理小包异常数据"
...@@ -712,6 +812,11 @@ msgstr "" ...@@ -712,6 +812,11 @@ msgstr ""
msgid "接口版本" msgid "接口版本"
msgstr "" msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_res_config_settings__patrol_receiver_emails
msgid "接收邮件地址"
msgstr ""
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model:ir.model.fields.selection,name:ccs_connect_tiktok.selection__ao_tt_api_log__source__推入 #: model:ir.model.fields.selection,name:ccs_connect_tiktok.selection__ao_tt_api_log__source__推入
msgid "推入" msgid "推入"
...@@ -722,11 +827,34 @@ msgstr "" ...@@ -722,11 +827,34 @@ msgstr ""
msgid "推出" msgid "推出"
msgstr "" msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__bl_issues
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.view_bl_patrol_form
msgid "提单关务节点问题"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.actions.act_window,name:ccs_connect_tiktok.action_bl_patrol
#: model:ir.actions.server,name:ccs_connect_tiktok.cron_bl_patrol_ir_actions_server
#: model:ir.cron,cron_name:ccs_connect_tiktok.cron_bl_patrol
#: model:ir.model,name:ccs_connect_tiktok.model_bl_patrol
#: model:ir.ui.menu,name:ccs_connect_tiktok.menu_bl_patrol
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.view_bl_patrol_form
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.view_bl_patrol_search
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.view_bl_patrol_tree
msgid "提单巡查"
msgstr ""
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record__operator_id #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record__operator_id
msgid "操作人" msgid "操作人"
msgstr "" msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_pda_scan_record__operation_time
msgid "操作时间"
msgstr ""
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view #: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view
msgid "昨日日志" msgid "昨日日志"
...@@ -738,17 +866,49 @@ msgstr "" ...@@ -738,17 +866,49 @@ msgstr ""
msgid "是否成功" msgid "是否成功"
msgstr "" msgstr ""
#. module: ccs_connect_tiktok
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.view_bl_patrol_search
msgid "有问题"
msgstr ""
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view #: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view
msgid "本周日志" msgid "本周日志"
msgstr "" msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__bl_count
msgid "检查提单数量"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,help:ccs_connect_tiktok.field_res_config_settings__patrol_check_days
msgid "检查近几天的提单"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__state
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.view_bl_patrol_search
msgid "状态"
msgstr ""
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__source #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__source
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view #: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view
msgid "类型" msgid "类型"
msgstr "" msgstr ""
#. module: ccs_connect_tiktok
#: model_terms:ir.actions.act_window,help:ccs_connect_tiktok.action_bl_patrol
msgid "系统将自动巡查提单的轨迹问题,包括小包轨迹倒挂和提单关务节点倒挂。"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields.selection,name:ccs_connect_tiktok.selection__bl_patrol__state__draft
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.view_bl_patrol_search
msgid "草稿"
msgstr ""
#. module: ccs_connect_tiktok #. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__request_id #: model:ir.model.fields,field_description:ccs_connect_tiktok.field_ao_tt_api_log__request_id
msgid "请求id" msgid "请求id"
...@@ -763,3 +923,13 @@ msgstr "" ...@@ -763,3 +923,13 @@ msgstr ""
#: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view #: model_terms:ir.ui.view,arch_db:ccs_connect_tiktok.search_ao_tt_api_log_view
msgid "近7日日志" msgid "近7日日志"
msgstr "" msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__email_sent_time
msgid "邮件发送时间"
msgstr ""
#. module: ccs_connect_tiktok
#: model:ir.model.fields,field_description:ccs_connect_tiktok.field_bl_patrol__email_sent
msgid "邮件已发送"
msgstr ""
...@@ -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
# 获取日志
_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已使用
'usage_date': str(self.usage_date) if self.usage_date else '', # 使用日期
'print_state': self.print_state, # 打印状态 unprinted未打印 printed已打印
'sorting_time': str(self.sorting_time) if self.sorting_time else '', # 托盘理货时间
'delivery_time': str(self.delivery_time) if self.delivery_time else '', # 托盘交货时间
'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 or '', # 托盘交付车牌号
}
...@@ -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')), # 理货
......
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_group_user_ao_tt_api,access_group_user_ao_tt_api,ccs_connect_tiktok.model_ao_tt_api,base.group_user,1,0,0,0 access_group_user_ao_tt_api,access_group_user_ao_tt_api,ccs_connect_tiktok.model_ao_tt_api,base.group_user,1,0,0,0
access_ao_tt_api_log,ao_tt_api_log,model_ao_tt_api_log,base.group_system,1,1,1,1
access_cc_ship_package_sync_log_base.group_user,cc_ship_package_sync_log base.group_user,ccs_connect_tiktok.model_cc_ship_package_sync_log,base.group_user,1,0,0,0 access_cc_ship_package_sync_log_base.group_user,cc_ship_package_sync_log base.group_user,ccs_connect_tiktok.model_cc_ship_package_sync_log,base.group_user,1,0,0,0
access_cc_ship_package_sync_log_base.group_erp_manager,cc_ship_package_sync_log base.group_erp_manager,ccs_connect_tiktok.model_cc_ship_package_sync_log,base.group_erp_manager,1,1,1,1 access_cc_ship_package_sync_log_base.group_erp_manager,cc_ship_package_sync_log base.group_erp_manager,ccs_connect_tiktok.model_cc_ship_package_sync_log,base.group_erp_manager,1,1,1,1
...@@ -10,7 +9,12 @@ access_cc_ship_package_sync_log_ccs_base.group_clearance_of_customs_user,cc_ship ...@@ -10,7 +9,12 @@ access_cc_ship_package_sync_log_ccs_base.group_clearance_of_customs_user,cc_ship
access_cc_bl_sync_log_base.group_user,cc_bl_sync_log base.group_user,ccs_connect_tiktok.model_cc_bl_sync_log,base.group_user,1,0,0,0 access_cc_bl_sync_log_base.group_user,cc_bl_sync_log base.group_user,ccs_connect_tiktok.model_cc_bl_sync_log,base.group_user,1,0,0,0
access_cc_bl_sync_log_base.group_erp_manager,cc_bl_sync_log base.group_erp_manager,ccs_connect_tiktok.model_cc_bl_sync_log,base.group_erp_manager,1,1,1,1 access_cc_bl_sync_log_base.group_erp_manager,cc_bl_sync_log base.group_erp_manager,ccs_connect_tiktok.model_cc_bl_sync_log,base.group_erp_manager,1,1,1,1
access_cc_bl_sync_log_ccs_base.group_clearance_of_customs_manager,cc_bl_sync_log ccs_base.group_clearance_of_customs_manager,ccs_connect_tiktok.model_cc_bl_sync_log,ccs_base.group_clearance_of_customs_manager,1,0,0,0 access_cc_bl_sync_log_ccs_base.group_clearance_of_customs_manager,cc_bl_sync_log ccs_base.group_clearance_of_customs_manager,ccs_connect_tiktok.model_cc_bl_sync_log,ccs_base.group_clearance_of_customs_manager,1,0,0,0
access_cc_bl_sync_log_ccs_base.group_clearance_of_customs_user,cc_bl_sync_log ccs_base.group_clearance_of_customs_user,ccs_connect_tiktok.model_cc_bl_sync_log,ccs_base.group_clearance_of_customs_user,1,0,0,0 access_cc_bl_sync_log_ccs_base.group_clearance_of_customs_user,cc_bl_sync_log ccs_base.group_clearance_of_customs_user,model_cc_bl_sync_log,ccs_base.group_clearance_of_customs_user,1,0,0,0
access_ao_tt_api_log_user,access_ao_tt_api_log_user,model_ao_tt_api_log,base.group_user,1,0,0,0
access_ao_tt_api_log,ao_tt_api_log,model_ao_tt_api_log,base.group_system,1,1,1,1
access_pda_scan_record_user,pda.scan.record.user,model_pda_scan_record,base.group_user,1,1,1,0 access_pda_scan_record_user,pda.scan.record.user,model_pda_scan_record,base.group_user,1,1,1,0
access_pda_scan_record_manager,pda.scan.record.manager,model_pda_scan_record,base.group_system,1,1,1,1 access_pda_scan_record_manager,pda.scan.record.manager,model_pda_scan_record,base.group_system,1,1,1,1
......
...@@ -97,11 +97,5 @@ ...@@ -97,11 +97,5 @@
<field name="domain">[]</field> <field name="domain">[]</field>
<field name="context">{'search_default_last_30d':1}</field> <field name="context">{'search_default_last_30d':1}</field>
</record> </record>
<menuitem
id="menu_ao_flight_tt_api_log"
name="TIKTOK推送日志"
sequence="21" action="action_ao_tt_api_log"/>
</data> </data>
</odoo> </odoo>
\ No newline at end of file
...@@ -97,10 +97,5 @@ ...@@ -97,10 +97,5 @@
</field> </field>
</record> </record>
<!-- 菜单项 -->
<menuitem id="menu_bl_patrol"
name="提单巡查"
action="action_bl_patrol"
sequence="22"/>
</data> </data>
</odoo> </odoo>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<menuitem
id="menu_tt_api_log"
name="TIKTOK推送日志" parent=""
groups="ccs_base.group_clearance_of_customs_user,ccs_base.group_clearance_of_customs_manager"
sequence="21" action="action_ao_tt_api_log"/>
<!-- 菜单项 -->
<menuitem id="menu_bl_patrol"
name="提单巡查"
action="action_bl_patrol"
sequence="22"
groups="ccs_base.group_clearance_of_customs_user,ccs_base.group_clearance_of_customs_manager"/>
<!-- 菜单项 -->
<menuitem id="menu_pda_scan_record"
name="PDA Scan Record"
action="action_pda_scan_record"
sequence="21"
groups="ccs_base.group_clearance_of_customs_user,ccs_base.group_clearance_of_customs_manager"/>
</data>
</odoo>
\ No newline at end of file
...@@ -80,10 +80,4 @@ ...@@ -80,10 +80,4 @@
</p> </p>
</field> </field>
</record> </record>
<!-- 菜单项 -->
<menuitem id="menu_pda_scan_record"
name="PDA Scan Record"
action="action_pda_scan_record"
sequence="21"/>
</odoo> </odoo>
\ No newline at end of file
from . import models
from . import wizard
from . import reports
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': '清关托盘模块',
'version': '1.2',
'summary': '清关托盘模块',
'sequence': 10,
'description': """
清关托盘模块
1) 创建托盘和打印
""",
'category': 'Pallet Management',
'website': 'https://www.yizuo.ltd',
'depends': ['base', 'mail', 'web', 'ccs_base'],
'data': [
'security/pallet_security.xml',
'security/ir.model.access.csv',
'wizard/pallet_batch_wizard_view.xml',
'wizard/pallet_print_wizard_view.xml',
'wizard/associate_pallet_wizard_views.xml',
"reports/report_pallet_labe.xml",
'reports/pallet_label_report_templates.xml',
'views/cc_pallet_view.xml',
'views/menu_view.xml',
],
'installable': True,
'application': True,
'assets': {
'web.assets_backend': [
'ccs_pallet/static/src/mixins/batch_create_pallet.js',
'ccs_pallet/static/src/views/bl_list_pallet_controller.js',
'ccs_pallet/static/src/views/list.xml',
],
},
'license': 'AGPL-3',
}
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * ccs_pallet
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-09-17 02:50+0000\n"
"PO-Revision-Date: 2025-09-17 10:51+0800\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: zh_CN\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Generator: Poedit 3.5\n"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/wizard/associate_pallet_wizard.py:0
#, python-format
msgid "%s The package does not exist, please check the input information!"
msgstr "%s 不存在该大包,请检查输入信息!"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#, python-format
msgid "%s at %s associated %d packages to pallet %s"
msgstr "%s 在 %s 将 %d 个大包关联到托盘 %s"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#, python-format
msgid "%s at %s associated tray %s, with a tray usage date of %s"
msgstr "%s %s关联了托盘%s,托盘使用日期为%s"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#, python-format
msgid ""
"%s at %s changed the pallet number from %s to %s, and the pallet usage date "
"from %s to %s"
msgstr "%s %s更改了托盘号,由%s变更为%s,托盘使用日期%s变更为%s"
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__message_needaction
msgid "Action Needed"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__activity_ids
msgid "Activities"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__activity_exception_decoration
msgid "Activity Exception Decoration"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__activity_state
msgid "Activity State"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__activity_type_icon
msgid "Activity Type Icon"
msgstr ""
#. module: ccs_pallet
#: model:ir.model,name:ccs_pallet.model_associate_pallet_wizard
msgid "Associate Pallet Wizard"
msgstr "关联托盘向导"
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__message_attachment_count
msgid "Attachment Count"
msgstr ""
#. module: ccs_pallet
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_form
msgid "Basic Information"
msgstr "基本信息"
#. module: ccs_pallet
#. odoo-javascript
#: code:addons/ccs_pallet/static/src/views/list.xml:0
#, python-format
msgid "Batch Create Pallet"
msgstr "批量创建托盘"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/wizard/pallet_batch_wizard.py:0
#, python-format
msgid "Batch Create Pallet Result"
msgstr "批量创建托盘结果"
#. module: ccs_pallet
#: model:ir.model,name:ccs_pallet.model_pallet_batch_wizard
msgid "Batch Create Pallet Wizard"
msgstr "批量创建托盘向导"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: model:ir.actions.act_window,name:ccs_pallet.action_cc_pallet_batch_create
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_pallet_batch_wizard_form
#, python-format
msgid "Batch Create Pallets"
msgstr "批量创建托盘"
#. module: ccs_pallet
#: model:ir.model,name:ccs_pallet.model_cc_big_package
msgid "Big Package"
msgstr "大包"
#. module: ccs_pallet
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_pallet_batch_wizard_form
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_pallet_print_wizard_form
msgid "Cancel"
msgstr "取消"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/wizard/pallet_batch_wizard.py:0
#, python-format
msgid "Cannot create more than 1000 pallets at once"
msgstr "无法同时创建超过 1000 个托盘"
#. module: ccs_pallet
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_pallet_batch_wizard_form
msgid "Confirm"
msgstr "确认"
#. module: ccs_pallet
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_pallet_print_wizard_form
msgid "Confirm Print"
msgstr "确认打印"
#. module: ccs_pallet
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_pallet_batch_wizard_form
msgid "Confirm and Print"
msgstr "确认并打印"
#. module: ccs_pallet
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_form
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_list
msgid "Create By"
msgstr "创建人"
#. module: ccs_pallet
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_form
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_list
msgid "Create Date"
msgstr "创建时间"
#. module: ccs_pallet
#: model_terms:ir.actions.act_window,help:ccs_pallet.action_cc_pallet
msgid "Create Pallet"
msgstr "创建托盘"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/wizard/pallet_batch_wizard.py:0
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_batch_wizard__quantity
#, python-format
msgid "Create Quantity"
msgstr "创建数量"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/wizard/pallet_batch_wizard.py:0
#, python-format
msgid "Create quantity must be greater than 0"
msgstr "创建数量必须大于0"
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__create_uid
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_batch_wizard__create_uid
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_print_wizard__create_uid
msgid "Created by"
msgstr "创建人"
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__create_date
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_batch_wizard__create_date
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_print_wizard__create_date
msgid "Created on"
msgstr "创建时间"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: code:addons/ccs_pallet/wizard/pallet_batch_wizard.py:0
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__partner_id
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_batch_wizard__partner_id
#, python-format
msgid "Customer"
msgstr "客户"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__delivery_plate_number
#, python-format
msgid "Delivery Plate Number"
msgstr "托盘交付车牌号"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__delivery_time
#, python-format
msgid "Delivery Time"
msgstr "托盘交货时间"
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__display_name
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_batch_wizard__display_name
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_print_wizard__display_name
msgid "Display Name"
msgstr ""
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: code:addons/ccs_pallet/wizard/pallet_batch_wizard.py:0
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__express_company_id
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_batch_wizard__express_company_id
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_search
#, python-format
msgid "Express Company"
msgstr "托盘归属快递"
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__message_follower_ids
msgid "Followers"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__message_partner_ids
msgid "Followers (Partners)"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,help:ccs_pallet.field_cc_pallet__activity_type_icon
msgid "Font awesome icon e.g. fa-tasks"
msgstr ""
#. module: ccs_pallet
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_search
msgid "Group By"
msgstr "分组"
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__has_message
msgid "Has Message"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__id
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_batch_wizard__id
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_print_wizard__id
msgid "ID"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__activity_exception_icon
msgid "Icon"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,help:ccs_pallet.field_cc_pallet__activity_exception_icon
msgid "Icon to indicate an exception activity."
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,help:ccs_pallet.field_cc_pallet__message_needaction
msgid "If checked, new messages require your attention."
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,help:ccs_pallet.field_cc_pallet__message_has_error
msgid "If checked, some messages have a delivery error."
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__message_is_follower
msgid "Is Follower"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet____last_update
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_batch_wizard____last_update
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_print_wizard____last_update
msgid "Last Modified on"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__write_uid
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_batch_wizard__write_uid
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_print_wizard__write_uid
msgid "Last Updated by"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__write_date
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_batch_wizard__write_date
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_print_wizard__write_date
msgid "Last Updated on"
msgstr ""
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_big_package.py:0
#, python-format
msgid "Link Pallet"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__message_main_attachment_id
msgid "Main Attachment"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__message_has_error
msgid "Message Delivery error"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__message_ids
msgid "Messages"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__my_activity_date_deadline
msgid "My Activity Deadline"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__activity_date_deadline
msgid "Next Activity Deadline"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__activity_summary
msgid "Next Activity Summary"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__activity_type_id
msgid "Next Activity Type"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__message_needaction_counter
msgid "Number of Actions"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__message_has_error_counter
msgid "Number of errors"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,help:ccs_pallet.field_cc_pallet__message_needaction_counter
msgid "Number of messages requiring action"
msgstr ""
#. module: ccs_pallet
#: model:ir.model.fields,help:ccs_pallet.field_cc_pallet__message_has_error_counter
msgid "Number of messages with delivery error"
msgstr ""
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__package_count
#, python-format
msgid "Package Count"
msgstr "托盘装载大包数"
#. module: ccs_pallet
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_form
msgid "Package Information"
msgstr "大包信息"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__package_ids
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_form
#, python-format
msgid "Packages"
msgstr "托盘装载大包"
#. module: ccs_pallet
#: model:ir.model,name:ccs_pallet.model_cc_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_associate_pallet_wizard__pallet_id
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_big_package__pallet_id
#: model:ir.ui.menu,name:ccs_pallet.menu_cc_pallet
msgid "Pallet"
msgstr "托盘"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#, python-format
msgid "Pallet %s has been used, cannot be deleted!"
msgstr "托盘 %s 已使用,无法删除!"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/wizard/pallet_print_wizard.py:0
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_print_wizard__pallet_count
#, python-format
msgid "Pallet Count"
msgstr "托盘数量"
#. module: ccs_pallet
#: model:ir.module.category,description:ccs_pallet.module_category_pallet
#: model:ir.module.category,name:ccs_pallet.module_category_pallet
msgid "Pallet Information"
msgstr "托盘信息"
#. module: ccs_pallet
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_pallet_print_wizard_form
msgid "Pallet Label Print"
msgstr "托盘标签打印"
#. module: ccs_pallet
#: model:ir.actions.act_window,name:ccs_pallet.action_cc_pallet
#: model:ir.ui.menu,name:ccs_pallet.menu_cc_pallet_root
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_form
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_list
msgid "Pallet Management"
msgstr "托盘管理"
#. module: ccs_pallet
#: model:res.groups,name:ccs_pallet.group_pallet_manager
msgid "Pallet Manager"
msgstr "托盘管理"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__name
#, python-format
msgid "Pallet Number"
msgstr "托盘号"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#, python-format
msgid "Pallet Packages"
msgstr "托盘关联的大包"
#. module: ccs_pallet
#: model:ir.actions.act_window,name:ccs_pallet.action_pallet_print_wizard
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_pallet_print_wizard_form
msgid "Pallet Print"
msgstr "托盘打印"
#. module: ccs_pallet
#: model:ir.model,name:ccs_pallet.model_pallet_print_wizard
msgid "Pallet Print Wizard"
msgstr "托盘打印向导"
#. module: ccs_pallet
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_search
msgid "Pallet Search"
msgstr "搜索"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/wizard/pallet_batch_wizard.py:0
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_batch_wizard__start_number
#, python-format
msgid "Pallet Start Number"
msgstr "托盘创建开始编号"
#. module: ccs_pallet
#: model_terms:ir.actions.act_window,help:ccs_pallet.action_cc_pallet
msgid ""
"Pallet management system for managing pallets in the warehouse, including "
"pallet number generation,\n"
" status tracking and label printing."
msgstr ""
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/wizard/pallet_batch_wizard.py:0
#, python-format
msgid "Pallet number %s already exists, please check system data"
msgstr "托盘号 %s 已存在,请检查系统数据"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: model:ir.model.fields,help:ccs_pallet.field_cc_pallet__name
#, python-format
msgid "Pallet number format: YYYYMM + 4 digits"
msgstr "托盘号格式:年月+4位数"
#. module: ccs_pallet
#: model:ir.model,name:ccs_pallet.model_report_ccs_pallet_report_palletlabel
msgid "Pallet report"
msgstr "托盘报表"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/wizard/pallet_print_wizard.py:0
#: model:ir.model.fields,field_description:ccs_pallet.field_pallet_print_wizard__pallet_ids
#, python-format
msgid "Pallets"
msgstr "托盘"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/wizard/associate_pallet_wizard.py:0
#, python-format
msgid "Please select a pallet!"
msgstr "请选择托盘!"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/wizard/pallet_print_wizard.py:0
#, python-format
msgid "Please select pallets to print"
msgstr "请选择托盘进行打印"
#. module: ccs_pallet
#: model:ir.actions.server,name:ccs_pallet.action_print_labels_pallet_server
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_form
msgid "Print Labels"
msgstr "打印标签"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#, python-format
msgid "Print Pallet Labels"
msgstr "打印标签"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__print_state
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_search
#, python-format
msgid "Print State"
msgstr "打印状态"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: model:ir.model.fields.selection,name:ccs_pallet.selection__cc_pallet__print_state__printed
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_search
#, python-format
msgid "Printed"
msgstr "已打印"
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__activity_user_id
msgid "Responsible User"
msgstr ""
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__sorting_time
#, python-format
msgid "Sorting Time"
msgstr "托盘理货时间"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/wizard/pallet_batch_wizard.py:0
#, python-format
msgid "Start number has been occupied, please close the window and recreate"
msgstr "开始编码已被占用,关闭窗口,重新创建"
#. module: ccs_pallet
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_form
msgid "Status Information"
msgstr "状态信息"
#. module: ccs_pallet
#: model:ir.model.fields,help:ccs_pallet.field_cc_pallet__activity_state
msgid ""
"Status based on activities\n"
"Overdue: Due date is already passed\n"
"Today: Activity date is today\n"
"Planned: Future activities."
msgstr ""
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/wizard/associate_pallet_wizard.py:0
#, python-format
msgid ""
"The last mile carrier of package 【%s】 does not match the last mile "
"carrier of the pallet. Please check and retry!"
msgstr "大包号【%s】的尾程快递与托盘归属的尾程快递不一致!"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/wizard/associate_pallet_wizard.py:0
#, python-format
msgid "The usage date cannot be later than the current date!"
msgstr "使用日期不能大于当前日期!"
#. module: ccs_pallet
#: model:ir.model.fields,help:ccs_pallet.field_cc_pallet__activity_exception_decoration
msgid "Type of the exception activity on record."
msgstr ""
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: model:ir.model.fields.selection,name:ccs_pallet.selection__cc_pallet__print_state__unprinted
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_search
#, python-format
msgid "Unprinted"
msgstr "未打印"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: model:ir.model.fields.selection,name:ccs_pallet.selection__cc_pallet__usage_state__unused
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_search
#, python-format
msgid "Unused"
msgstr "未使用"
#. module: ccs_pallet
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__usage_date
msgid "Usage Date"
msgstr "托盘使用日期"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: model:ir.model.fields,field_description:ccs_pallet.field_cc_pallet__usage_state
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_search
#, python-format
msgid "Usage State"
msgstr "使用状态"
#. module: ccs_pallet
#. odoo-python
#: code:addons/ccs_pallet/models/cc_pallet.py:0
#: model:ir.model.fields.selection,name:ccs_pallet.selection__cc_pallet__usage_state__used
#: model_terms:ir.ui.view,arch_db:ccs_pallet.view_cc_pallet_search
#, python-format
msgid "Used"
msgstr "已使用"
#. module: ccs_pallet
#: model:ir.actions.report,name:ccs_pallet.action_pallet_label_report
msgid "托盘标签"
msgstr ""
from . import cc_pallet
from . import cc_big_package
# -*- coding: utf-8 -*-
# 导入日志
import logging
from odoo import models, fields, api, _
# 获取日志
_logger = logging.getLogger(__name__)
class CCBigPackage(models.Model):
# 模型名称
_inherit = 'cc.big.package'
# 模型描述
_description = 'Big Package'
pallet_id = fields.Many2one('cc.pallet', string='Pallet',index=True)
def action_link_pallet(self):
return {
'name': _('Link Pallet'),
'type': 'ir.actions.act_window',
'views': [[False, "form"]],
'res_model': 'associate.pallet.wizard',
'target': 'new',
'context': {},
}
def update_pallet_info(self, pallet_number, pallet_usage_date, pallet_id):
"""
修改托盘信息
:param pallet_number:
:param pallet_usage_date:
:param pallet_id:
:return:
"""
self.pallet_usage_date = pallet_usage_date
self.pallet_number = pallet_number
self.pallet_id = pallet_id
\ No newline at end of file
# -*- coding: utf-8 -*-
# 导入日志
import logging
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
# 获取日志
_logger = logging.getLogger(__name__)
class CcPallet(models.Model):
# 模型名称
_name = 'cc.pallet'
_inherit = ['mail.thread', 'mail.activity.mixin']
# 模型描述
_description = 'Pallet'
_order = 'create_date desc'
@api.model
def create(self, vals):
# 托盘号(年月+4位数,不能重复生成)
if not vals.get('name'):
vals['name'] = self.get_start_number()
return super(CcPallet, self).create(vals)
def get_start_number(self):
"""
获取当前年月+4位数,不能重复生成
"""
now = fields.Datetime.now()
year_month = now.strftime('%Y%m')
last_pallet = self.search([('name', 'like', year_month + '%')], order='name desc', limit=1)
if last_pallet and last_pallet.name:
last_number = int(last_pallet.name[-4:])
new_number = last_number + 1
else:
new_number = 1
return f"{year_month}{new_number:04d}"
@api.model
def get_partner_id(self):
"""
默认给值,随机选一个未存档的客户
"""
return self.env['res.partner'].search([('is_customer', '=', True), ('active', '=', True)], limit=1).id
# 计算字段:大包数量
@api.depends('package_ids')
def _compute_package_count(self):
for record in self:
record.package_count = len(record.package_ids)
# 计算字段:托盘理货时间和交货时间
@api.depends('package_ids', 'package_ids.tally_time', 'package_ids.delivery_time')
def _compute_pallet_times(self):
for pallet in self:
if pallet.package_ids:
# 获取所有关联大包的理货时间,取最晚的时间
sorting_times = pallet.package_ids.filtered('tally_time').mapped('tally_time')
if sorting_times:
pallet.sorting_time = max(sorting_times)
else:
pallet.sorting_time = False
# 获取所有关联大包的尾程交货时间,取最晚的时间
delivery_times = pallet.package_ids.filtered('delivery_time').mapped('delivery_time')
if delivery_times:
pallet.delivery_time = max(delivery_times)
else:
pallet.delivery_time = False
else:
pallet.sorting_time = False
pallet.delivery_time = False
# 托盘号(年月+4位数,不能重复生成)
name = fields.Char(string=_('Pallet Number'), copy=False, help=_('Pallet number format: YYYYMM + 4 digits'))
# 托盘归属快递
express_company_id = fields.Many2one('cc.last.mile.provider', string=_('Express Company'), index=True)
# 使用状态
usage_state = fields.Selection([('unused', _('Unused')), ('used', _('Used'))], string=_('Usage State'),
default='unused', index=True, tracking=True)
usage_date = fields.Date(string='Usage Date', index=True)
# 打印状态
print_state = fields.Selection([('unprinted', _('Unprinted')), ('printed', _('Printed'))], string=_('Print State'),
default='unprinted', index=True, tracking=True)
# 托盘理货时间(计算字段)
sorting_time = fields.Datetime(string=_('Sorting Time'), compute='_compute_pallet_times', store=True)
# 托盘交货时间(计算字段)
delivery_time = fields.Datetime(string=_('Delivery Time'), compute='_compute_pallet_times', store=True)
# 托盘装载大包
package_ids = fields.Many2many('cc.big.package', 'pallet_package_rel', string=_('Packages'))
# 大包数量
package_count = fields.Integer(string=_('Package Count'), compute='_compute_package_count', store=True)
# 使用客户
partner_id = fields.Many2one('res.partner', string=_('Customer'), default=get_partner_id,
domain=[('is_customer', '=', True)])
# 托盘交付车牌号
delivery_plate_number = fields.Char(string=_('Delivery Plate Number'))
def update_pallet_info(self, **kwargs):
"""更新托盘信息"""
if kwargs.get('delivery_plate_number', ''):
self.delivery_plate_number = kwargs['delivery_plate_number']
# 当大包关联到托盘时,自动更新使用状态
def update_usage_state(self, success_package, usage_date):
"""更新托盘使用状态"""
for pallet in self:
pallet.usage_state = 'used'
pallet.usage_date = usage_date
# 要把这个大包关联的托盘取消关联
for package in success_package:
package.pallet_id.package_ids = [(3, package.id, 0)] # 移除这个大包
# 关联大包到托盘
pallet.package_ids = [(4, package_id.id, 0) for package_id in success_package]
# 更新大包的托盘信息
for package in success_package:
old_pallet_number = package.pallet_number
new_pallet_number = pallet.name # 使用托盘的编号
old_usage_date = package.pallet_usage_date
# 同一提单,同一托盘号,使用日期必须一致
# related_packages = package.bl_id.big_package_ids.filtered(
# lambda p: p.pallet_number == new_pallet_number) # 查找对应提单下相同托盘号的所有大包
# warning_package_arr = [related_package.big_package_no for related_package in related_packages if
# str(related_package.pallet_usage_date) != usage_date]
# if warning_package_arr:
# raise ValidationError(
# _('Big Package No :%s ,The same bill of lading, same pallet number, and usage date must be consistent!') % (
# '\n'.join(warning_package_arr))) # 大包号关联的同一提单,同一托盘号,使用日期必须一致
# 更新大包的托盘信息
package.update_pallet_info(new_pallet_number, usage_date, pallet.id)
if old_pallet_number:
# %s %s更改了托盘号,由%s变更为%s,托盘使用日期%s变更为%s
body = _(
'%s at %s changed the pallet number from %s to %s, and the pallet usage date from %s to %s') % (
self.env.user.name, fields.Datetime.now(), old_pallet_number, new_pallet_number,
old_usage_date,
usage_date)
else:
# 某人某时关联了托盘xxx,托盘使用日期xxxx
body = _('%s at %s associated tray %s, with a tray usage date of %s') % (
self.env.user.name, fields.Datetime.now(), new_pallet_number, usage_date)
package.message_post(body=body)
# 记录托盘关联日志
body = _('%s at %s associated %d packages to pallet %s') % (
self.env.user.name, fields.Datetime.now(), len(success_package), pallet.name)
pallet.message_post(body=body)
def action_print_labels(self):
"""打印标签动作"""
return {
'type': 'ir.actions.act_window',
'name': _('Print Pallet Labels'),
'res_model': 'pallet.print.wizard',
'view_mode': 'form',
'target': 'new',
'context': {
'default_pallet_ids': [(6, 0, self.ids)],
'active_ids': self.ids,
},
}
def action_view_packages(self):
"""查看大包动作"""
return {
'type': 'ir.actions.act_window',
'name': _('Pallet Packages'),
'res_model': 'cc.big.package',
'view_mode': 'list,form',
'domain': [('pallet_id', '=', self.id)],
'context': {'default_pallet_id': self.id},
}
def action_batch_create(self):
"""批量创建托盘动作"""
return {
'name': _('Batch Create Pallets'),
'type': 'ir.actions.act_window',
'views': [[False, "form"]],
'res_model': 'pallet.batch.wizard',
'target': 'new',
'context': {},
}
def print_labels_success(self):
for pallet in self:
pallet.print_state = 'printed'
def unlink(self):
"""
已使用的托盘需要控制不能删除
"""
for pallet in self:
if pallet.usage_state == 'used':
raise ValidationError(_('Pallet %s has been used, cannot be deleted!') % pallet.name)
return super(CcPallet, self).unlink()
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import report_pallet
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="report_palletlabel">
<t t-call="web.html_container">
<t t-set="barcode_size" t-value="'width:80mm;height:30mm'"/>
<!-- 纵向的 -->
<!-- <t t-set="table_style" t-value="'width:100mm;height:150mm;'"/> -->
<!-- 横向的 -->
<t t-set="table_style" t-value="'width:150mm;height:70mm;'"/>
<t t-set="padding_page" t-value="'padding: 5mm'"/>
<t t-set="pallets" t-value="pallets"/>
<t t-foreach="pallets" t-as="pallet">
<t t-call="ccs_pallet.report_simple_pallet_barcode"/>
</t>
</t>
</template>
<!-- 托盘标签模板 -->
<template id="report_simple_pallet_barcode">
<div class="o_label_sheet o_label_dymo" t-att-style="padding_page">
<div class="o_label_full" t-att-style="table_style" style="display: flex; flex-direction: column; justify-content: space-between; align-items: center; text-align: center;">
<!-- 顶部标题 -->
<div style="flex: 0 0 auto; margin-bottom: 10mm; text-align: center;">
<div style="font-size: 24px; font-weight: bold; line-height: 1.2; font-family: Arial, sans-serif;">
<t t-esc="pallet.partner_id.name or 'TIKTOK'"/> / <t t-esc="pallet.express_company_id.abbreviation"/>
</div>
</div>
<!-- 中间条形码区域 -->
<div style="flex: 1; display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center;">
<t t-if="pallet.name">
<div t-out="pallet.name" style="padding:0; margin: 0 auto;" t-options="{'widget': 'barcode', 'quiet': 0, 'symbology': 'auto', 'img_style': barcode_size}"/>
</t>
</div>
<!-- 底部托盘号 -->
<div style="flex: 0 0 auto; margin-top: 10mm; text-align: center;">
<div style="font-size: 32px; font-weight: bold; line-height: 1.2; font-family: Arial, sans-serif;">
<span t-field="pallet.name"/>
</div>
</div>
</div>
</div>
<!-- <div class="o_label_sheet o_label_dymo" t-att-style="padding_page">
<div class="o_label_full" t-att-style="table_style" style="position: relative; box-sizing: border-box;">
<table style="width: 100%; height: 100%; border-collapse: collapse;">
<tr>
<td style="height: 20mm; text-align: center; vertical-align: middle; padding: 0; margin: 0;">
<div style="font-size: 24px; font-weight: bold; line-height: 1.2; font-family: Arial, sans-serif;">
<t t-esc="pallet.partner_id.name or 'TIKTOK'"/> / <t t-esc="pallet.express_company_id.abbreviation"/>
</div>
</td>
</tr>
<tr>
<td style="height: 60mm; text-align: center; vertical-align: middle; padding: 5mm; background-color: #f0f0f0; border: 1px solid #ddd;">
<t t-if="pallet.name">
<div style="text-align: center; font-size: 12px; color: #666;">
<div t-out="pallet.name"
t-options="{'widget': 'barcode', 'symbology': 'auto', 'img_style': barcode_size}"
style="margin: 10px 0;"/>
</div>
</t>
</td>
</tr>
<tr>
<td style="height: 30mm; text-align: center; vertical-align: middle; padding: 0; margin: 0;">
<div style="font-size: 32px; font-weight: bold; line-height: 1.2; font-family: Arial, sans-serif;">
<span t-field="pallet.name"/>
</div>
</td>
</tr>
</table>
</div>
</div> -->
</template>
</odoo>
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, models, _
from odoo.exceptions import UserError
class ReportPallet(models.AbstractModel):
_name = 'report.ccs_pallet.report_palletlabel'
_description = 'Pallet report'
@api.model
def _get_report_values(self, docids, data=None):
# Overriding data values here since used also in _get_routes.
pallets = self.env['cc.pallet'].browse(docids)
return {
'pallets': pallets,
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- 托盘标签纸张格式 纵向的 10x15cm-->
<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">5</field>
<field name="margin_bottom">0</field>
<field name="margin_left">5</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">100</field>
<field name="page_height">140</field>
</record>
<!-- 托盘标签纸张格式 横向的 10x15cm-->
<record id="paperformat_pallet_label_landscape" model="report.paperformat">
<field name="name">托盘标签 (10x15cm) 横向</field>
<field name="default" eval="True"/>
<field name="format">custom</field>
<field name="orientation">Landscape</field>
<field name="margin_top">10</field>
<field name="margin_bottom">0</field>
<field name="margin_left">7</field>
<field name="margin_right">8</field>
<field name="header_line" eval="False"/>
<field name="header_spacing">0</field>
<field name="dpi">90</field>
<field name="page_width">80</field>
<field name="page_height">140</field>
</record>
<!-- 托盘标签打印报告 -->
<record id="action_pallet_label_report" model="ir.actions.report">
<field name="name">托盘标签</field>
<field name="model">cc.pallet</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">ccs_pallet.report_palletlabel</field>
<field name="report_file">ccs_pallet.report_palletlabel</field>
<field name="paperformat_id" ref="paperformat_pallet_label_landscape"/>
<!-- <field name="binding_model_id" ref="model_cc_pallet"/> -->
<field name="binding_model_id" eval="False"/>
<field name="binding_type">report</field>
</record>
</odoo>
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
pallet_batch_wizard_group_user,pallet_batch_wizard_group_user,model_pallet_batch_wizard,base.group_user,1,1,1,1
pallet_print_wizard_group_user,pallet_print_wizard_group_user,model_pallet_print_wizard,base.group_user,1,1,1,1
cc_pallet_group_user,cc_pallet_group_user,model_cc_pallet,base.group_user,1,1,1,0
cc_pallet_group_system,cc_pallet_group_system,model_cc_pallet,base.group_system,1,1,1,1
cc_pallet_group_pallet_manager,cc_pallet_group_pallet_manager,model_cc_pallet,ccs_pallet.group_pallet_manager,1,1,1,1
cc_big_package_group_pallet_manager,cc_big_package_group_pallet_manager,model_cc_big_package,ccs_pallet.group_pallet_manager,1,1,0,0
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="0">
<record model="ir.module.category" id="ccs_pallet.module_category_pallet">
<field name="name">Pallet Information</field>
<field name="description">Pallet Information</field>
<field name="sequence">7</field>
</record>
<record id="group_pallet_manager" model="res.groups">
<field name="name">Pallet Manager</field>
<field name="category_id" ref="ccs_pallet.module_category_pallet"/>
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
</record>
</data>
</odoo>
/** @odoo-module */
import {useService} from '@web/core/utils/hooks';
const {useRef, useEffect, useState} = owl;
export const BatchCreatePallet = {
setup() {
this._super();
this.actionService = useService('action');
this.notification = useService('notification');
this.orm = useService('orm');
this.http = useService('http');
this.fileInput = useRef('fileInput');
this.root = useRef("root");
},
async onBatchCreatePalletClick() {
// 点击按钮弹出批量创建托盘的向导
const records = this.model.root.selection;
const recordIds = records.map((a) => a.resId);
const action = await this.orm.call('cc.pallet', 'action_batch_create', [recordIds]);
this.actionService.doAction(action);
},
};
/** @odoo-module */
import {BatchCreatePallet} from '../mixins/batch_create_pallet';
import {registry} from '@web/core/registry';
import {patch} from '@web/core/utils/patch';
import {useService} from '@web/core/utils/hooks';
import {listView} from "@web/views/list/list_view";
import {ListController} from "@web/views/list/list_controller";
const {onWillStart} = owl;
export class BlListPalletController extends ListController {
setup() {
super.setup();
console.log('----------引用成功')
this.orm = useService('orm');
this.actionService = useService('action');
this.rpc = useService("rpc");
this.user = useService("user");
this.isPallet = this.model.rootParams.resModel === "cc.pallet";
console.log('ccs isPallet:' + this.isPallet)
onWillStart(async () => {
this.can_batch_create_pallet = await this.user.hasGroup("ccs_pallet.group_pallet_manager");
console.log('ccs can_batch_create_pallet:' + this.can_batch_create_pallet)
});
}
displayLink() {
// 提单页面永远不显示“关联托盘”按钮
return false;
}
displayBatchCreatePallet() {
console.log('ccs flag:' + this.isPallet && this.can_batch_create_pallet)
// 是提单的对象以及有清关用户的权限才显示按钮
return this.isPallet && this.can_batch_create_pallet;
}
}
patch(BlListPalletController.prototype, 'batch_create_pallet', BatchCreatePallet);
registry.category('views').add('cc_pallet_tree', {
...listView,
buttonTemplate: 'ccs_pallet.ListButtons',
Controller: BlListPalletController
});
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="ccs_pallet.ListButtons" t-inherit="web.ListView.Buttons" t-inherit-mode="primary" owl="1">
<xpath expr="//button[hasclass('o_list_button_add')]" position="after">
<button t-if="displayBatchCreatePallet()" type="button" class="d-none d-md-inline o_button_batch_create_pallet btn btn-primary mx-1" t-on-click.prevent="onBatchCreatePalletClick">
Batch Create Pallet
</button>
</xpath>
</t>
</templates>
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record model="ir.ui.view" id="tree_cc_big_package_view">
<field name="name">tree.cc.big.package</field>
<field name="model">cc.big.package</field>
<field name="inherit_id" ref="ccs_base.tree_cc_big_package_view"/>
<field name="arch" type="xml">
<tree position="attributes">
<attribute name="js_class">cc_big_package_tree</attribute>
</tree>
</field>
</record>
</odoo>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- 托盘管理表单视图 -->
<record id="view_cc_pallet_form" model="ir.ui.view">
<field name="name">cc.pallet.form</field>
<field name="model">cc.pallet</field>
<field name="arch" type="xml">
<form string="Pallet Management">
<header>
<button name="action_print_labels" string="Print Labels" type="object" class="btn-primary"
icon="fa-print"/>
<field name="usage_state" widget="statusbar"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="action_view_packages" type="object" class="oe_stat_button" icon="fa-cubes">
<field name="package_count" widget="statinfo" string="Packages"/>
</button>
</div>
<div class="oe_title">
<h1>
<field name="name" readonly="1"/>
</h1>
</div>
<group>
<group string="Basic Information">
<field name="express_company_id" required="1" options="{'no_create': True, 'no_quick_create': True}"/>
<field name="partner_id" options="{'no_create': True, 'no_quick_create': True}"/>
<field name="delivery_plate_number"/>
<field name="create_uid" readonly="1" string="Create By"/>
<field name="create_date" readonly="1" string="Create Date"/>
</group>
<group string="Status Information">
<field name="print_state" readonly="1"/>
<field name="usage_date" readonly="1"/>
<field name="sorting_time" readonly="1"/>
<field name="delivery_time" readonly="1"/>
</group>
</group>
<notebook>
<page string="Package Information" name="packages">
<field name="package_ids" readonly="1"/>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- 托盘管理列表视图 -->
<record id="view_cc_pallet_list" model="ir.ui.view">
<field name="name">cc.pallet.list</field>
<field name="model">cc.pallet</field>
<field name="arch" type="xml">
<tree string="Pallet Management" js_class="cc_pallet_tree">
<field name="name"/>
<field name="express_company_id"/>
<field name="usage_state" decoration-success="usage_state == 'unused'"
decoration-warning="usage_state == 'used'"/>
<field name="print_state" decoration-info="print_state == 'unprinted'"
decoration-success="print_state == 'printed'"/>
<field name="sorting_time"/>
<field name="delivery_time"/>
<field name="package_count"/>
<field name="usage_date"/>
<field name="delivery_plate_number"/>
<field name="create_uid" string="Create By"/>
<field name="create_date" string="Create Date"/>
</tree>
</field>
</record>
<!-- 托盘管理搜索视图 -->
<record id="view_cc_pallet_search" model="ir.ui.view">
<field name="name">cc.pallet.search</field>
<field name="model">cc.pallet</field>
<field name="arch" type="xml">
<search string="Pallet Search">
<field name="name" filter_domain="[('name', 'ilike', self)]"/>
<field name="express_company_id"/>
<field name="partner_id"/>
<field name="delivery_plate_number"/>
<separator/>
<filter name="filter_unused" string="Unused" domain="[('usage_state', '=', 'unused')]"/>
<filter name="filter_used" string="Used" domain="[('usage_state', '=', 'used')]"/>
<filter name="filter_unprinted" string="Unprinted" domain="[('print_state', '=', 'unprinted')]"/>
<filter name="filter_printed" string="Printed" domain="[('print_state', '=', 'printed')]"/>
<separator/>
<group expand="0" string="Group By">
<filter name="group_by_express" string="Express Company"
context="{'group_by': 'express_company_id'}"/>
<filter name="group_by_print_state" string="Print State" context="{'group_by': 'print_state'}"/>
<filter name="group_by_usage_state" string="Usage State" context="{'group_by': 'usage_state'}"/>
</group>
</search>
</field>
</record>
<!-- 托盘管理动作 -->
<record id="action_cc_pallet" model="ir.actions.act_window">
<field name="name">Pallet Management</field>
<field name="res_model">cc.pallet</field>
<field name="view_mode">tree,form</field>
<field name="context">{}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create Pallet
</p>
<p>
Pallet management system for managing pallets in the warehouse, including pallet number generation,
status tracking and label printing.
</p>
</field>
</record>
<!-- 增加server action,批量打印标签 -->
<record id="action_print_labels_pallet_server" model="ir.actions.server">
<field name="name">Print Labels</field>
<field name="groups_id" eval="[(4, ref('ccs_pallet.group_pallet_manager'))]"/>
<field name="model_id" ref="model_cc_pallet"/>
<field name="binding_model_id" ref="model_cc_pallet"/>
<field name="binding_view_types">list</field>
<field name="state">code</field>
<field name="code">
if records:
action = records.action_print_labels()
</field>
</record>
</odoo>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<!-- 菜单项 -->
<menuitem id="menu_cc_pallet_root" name="Pallet Management" sequence="18"
groups="ccs_pallet.group_pallet_manager,ccs_base.group_clearance_of_customs_user,ccs_base.group_clearance_of_customs_manager"/>
<menuitem id="menu_cc_pallet"
name="Pallet"
parent="menu_cc_pallet_root"
action="action_cc_pallet"
sequence="10"/>
</data>
</odoo>
\ No newline at end of file
# -*- coding: utf-8 -*-
from . import pallet_batch_wizard
from . import pallet_print_wizard
from . import associate_pallet_wizard
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import models, fields, _
from odoo.exceptions import ValidationError
class AssociatePalletWizard(models.TransientModel):
_inherit = 'associate.pallet.wizard'
_description = 'Associate Pallet Wizard'
# 字段定义
pallet_id = fields.Many2one('cc.pallet', string='Pallet', index=True)
def confirm(self):
for record in self:
if not record.pallet_id:
raise ValidationError(_('Please select a pallet!')) # 请选择托盘!
if record.usage_date > fields.Date.today():
raise ValidationError(_('The usage date cannot be later than the current date!')) # 使用日期不能大于当前日期!
# 处理大包号
big_package_ids = record.big_package_numbers.splitlines()
success_package = []
fail_package = []
for package_number in big_package_ids:
package = self.env['cc.big.package'].search([('big_package_no', '=', package_number)], limit=1)
if package:
success_package.append(package)
else:
fail_package.append(package_number)
if fail_package:
raise ValidationError(_('%s The package does not exist, please check the input information!') % (
'\n'.join(fail_package))) # 不存在该大包,请检查输入信息
if success_package:
#所有的大包的下一级服务商必须和托盘的下一级服务商一致
error_package = []
for package in success_package:
provider = self.env['cc.last.mile.provider'].sudo().with_context({'lang': self.env.user.lang}).match_provider(
package.next_provider_name,record_obj=record.pallet_id.express_company_id)
if not provider:
error_package.append(package.big_package_no)
if error_package:
raise ValidationError(_('The last mile carrier of package 【%s】 does not match the last mile carrier of the pallet. Please check and retry!') % (
'、'.join(error_package)))#大包号XXXXXX的尾程快递与托盘归属的尾程快递不一致
# 更新托盘的使用状态(理货时间和交货时间会自动通过计算字段更新)
record.pallet_id.update_usage_state(success_package, record.usage_date)
<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="inherit_id" ref="ccs_base.view_associate_pallet_wizard"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='pallet_number']" position="after">
<field name="pallet_id" required="1" options="{'no_create': True, 'no_quick_create': True}"/>
</xpath>
<field name="pallet_number" position="attributes">
<attribute name="invisible">1</attribute>
</field>
</field>
</record>
</odoo>
\ No newline at end of file
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from odoo.exceptions import UserError, ValidationError
class PalletBatchWizard(models.TransientModel):
_name = 'pallet.batch.wizard'
_description = 'Batch Create Pallet Wizard'
# 创建数量必须大于0,且不能超过1000
@api.constrains('quantity')
def _check_quantity(self):
"""Validate create quantity"""
if self.quantity <= 0:
raise ValidationError(_('Create quantity must be greater than 0'))
if self.quantity > 1000:
raise ValidationError(_('Cannot create more than 1000 pallets at once'))
# 托盘归属快递
express_company_id = fields.Many2one('cc.last.mile.provider', string=_('Express Company'), index=True)
# 创建数量
quantity = fields.Integer(string=_('Create Quantity'), default=1)
# 起始托盘号
start_number = fields.Char(string=_('Pallet Start Number'),
default=lambda self: self.env['cc.pallet'].get_start_number())
# 使用客户
partner_id = fields.Many2one('res.partner', string=_('Customer'), domain=[('is_customer', '=', True)],
default=lambda self: self.env['cc.pallet'].get_partner_id())
# 确认创建托盘
def action_confirm(self):
"""确认创建托盘"""
# 检查起始托盘号是否被占用
if self.start_number:
existing_pallet = self.env['cc.pallet'].search([('name', '=', self.start_number)])
if existing_pallet:
raise UserError(_('Start number has been occupied, please close the window and recreate'))
# 创建托盘记录
pallets = []
now = fields.Datetime.now()
year_month = now.strftime('%Y%m')
# 获取起始托盘号
if self.start_number:
start_num = int(self.start_number[-4:])
else:
start_num = 1
for i in range(self.quantity):
pallet_name = f"{year_month}{start_num + i:04d}"
# 检查每个托盘号是否已存在
existing_pallet = self.env['cc.pallet'].search([('name', '=', pallet_name)])
if existing_pallet:
raise UserError(_('Pallet number %s already exists, please check system data') % pallet_name)
pallet_vals = {
'name': pallet_name,
'express_company_id': self.express_company_id.id,
'partner_id': self.partner_id.id if self.partner_id else False,
}
pallet = self.env['cc.pallet'].create(pallet_vals)
pallets.append(pallet)
# 返回创建结果
return {
'type': 'ir.actions.act_window',
'name': _('Batch Create Pallet Result'),
'res_model': 'cc.pallet',
'view_mode': 'list,form',
'domain': [('id', 'in', [p.id for p in pallets])],
'context': {'create': False},
}
# 确认创建托盘并打印
def action_confirm_and_print(self):
"""Confirm create pallets and print"""
# 先创建托盘
result = self.action_confirm()
# 获取创建的托盘
pallets = self.env['cc.pallet'].search([
('id', 'in', result['domain'][0][2])
])
# 修改为已打印
pallets.print_labels_success()
return self._generate_print_report(pallets) # 直接返回打印 不关闭向导
# 获取系统参数中的本地域名
web_base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url', 'http://localhost:8069')
# 生成打印URL
report_url = f"{web_base_url}/report/pdf/ccs_pallet.action_pallet_label_report/{','.join(map(str, pallets.ids))}"
# 使用客户端动作处理打印和关闭向导 关闭后托盘列表空白
# return {
# 'type': 'ir.actions.client',
# 'tag': 'print_and_close',
# 'params': {
# 'report_url': report_url
# }
# }
# 在新窗口中打开打印 服务器不支持
import webbrowser
webbrowser.open_new_tab(report_url)
return {'type': 'ir.actions.act_window_close'}
# 生成打印报告
def _generate_print_report(self, pallets):
"""Generate print report"""
return self.env.ref('ccs_pallet.action_pallet_label_report').report_action(pallets)
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- 批量创建托盘向导表单视图 -->
<record id="view_pallet_batch_wizard_form" model="ir.ui.view">
<field name="name">pallet.batch.wizard.form</field>
<field name="model">pallet.batch.wizard</field>
<field name="arch" type="xml">
<form string="Batch Create Pallets">
<sheet>
<group>
<group>
<field name="express_company_id" required="1"/>
<field name="start_number" readonly="1"/>
<field name="quantity" required="1"/>
<field name="partner_id"/>
</group>
<group></group>
</group>
</sheet>
<footer>
<button name="action_confirm" string="Confirm" type="object" class="btn-primary"/>
<button name="action_confirm_and_print" string="Confirm and Print" type="object" class="btn-success"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<!-- 批量创建托盘动作 -->
<record id="action_cc_pallet_batch_create" model="ir.actions.act_window">
<field name="name">Batch Create Pallets</field>
<field name="res_model">pallet.batch.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="context">{}</field>
</record>
</odoo>
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from odoo.exceptions import UserError
class PalletPrintWizard(models.TransientModel):
_name = 'pallet.print.wizard'
_description = 'Pallet Print Wizard'
@api.depends('pallet_ids')
def _compute_pallet_count(self):
"""计算托盘数量"""
for record in self:
record.pallet_count = len(record.pallet_ids)
pallet_ids = fields.Many2many('cc.pallet',string=_('Pallets'))
pallet_count = fields.Integer(string=_('Pallet Count'),compute='_compute_pallet_count',store=True)
def action_print(self):
"""执行打印"""
if not self.pallet_ids:
raise UserError(_('Please select pallets to print'))
# 更新打印状态为已打印
self.pallet_ids.print_labels_success()
# 生成打印报告
return self._generate_print_report()
def _generate_print_report(self):
"""生成打印报告"""
return self.env.ref('ccs_pallet.action_pallet_label_report').report_action(self.pallet_ids)
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- 托盘打印向导表单视图 -->
<record id="view_pallet_print_wizard_form" model="ir.ui.view">
<field name="name">pallet.print.wizard.form</field>
<field name="model">pallet.print.wizard</field>
<field name="arch" type="xml">
<form string="Pallet Print">
<sheet>
<div class="oe_title">
<h1>Pallet Label Print</h1>
</div>
<group>
<field name="pallet_count" readonly="1"/>
</group>
<field name="pallet_ids" widget="many2many_tags" readonly="1"/>
</sheet>
<footer>
<button name="action_print" string="Confirm Print" type="object" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
<!-- 托盘打印向导动作 -->
<record id="action_pallet_print_wizard" model="ir.actions.act_window">
<field name="name">Pallet Print</field>
<field name="res_model">pallet.print.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
<field name="context">{}</field>
</record>
</odoo>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论