Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/产品优化

# Conflicts:
#	sf_dlm/models/product_supplierinfo.py
This commit is contained in:
jinling.yang
2023-11-17 09:12:41 +08:00
11 changed files with 310 additions and 145 deletions

View File

@@ -32,8 +32,8 @@
'jikimo_frontend/static/src/scss/rowno_in_tree.scss',
# 'jikimo_frontend/static/src/views/list_nums/list_render.xml',
'jikimo_frontend/static/src/list/list_up_down_button.xml',
'jikimo_frontend/static/src/list/custom_import.js',
'jikimo_frontend/static/src/list/custom_width.js',
# 'jikimo_frontend/static/src/list/custom_import.js',
# 'jikimo_frontend/static/src/list/custom_width.js',
'jikimo_frontend/static/src/views/list_nums/extent_purchase.xml',
],

View File

@@ -205,8 +205,8 @@ div[class="o_content o_component_with_search_panel"] img[name="equipment_image"]
div[class="o_content o_component_with_search_panel"] .o_kanban_card_content button {
position: absolute;
top: -52px;
left: -55px;
//top: -52px;
//left: -55px;
width: 80px;
}
@@ -253,11 +253,11 @@ div[class="o_content o_component_with_search_panel"] .show_state span {
font-size: 12px;
}
div[class="o_content o_component_with_search_panel"] .o_kanban_primary_right > .row {
position: absolute;
top: 55px;
right: 43.5%;
}
//div[class="o_content o_component_with_search_panel"] .o_kanban_primary_right > .row {
// position: absolute;
// top: 55px;
// right: 43.5%;
//}
//------------------------------------------
.test_model > .o_form_label {
@@ -270,10 +270,10 @@ div[class="o_content o_component_with_search_panel"] .o_kanban_primary_right > .
right: 52%;
}
div[class="o_content o_component_with_search_panel"] .o_kanban_card_content button {
left: -95px;
}
//div[class="o_content o_component_with_search_panel"] .o_kanban_card_content button {
//
// left: -95px;
//}
}
@@ -354,3 +354,25 @@ div:has(.o_required_modifier) > label::before {
}
// 2023-11-16 hy 新增
.o_kanban_card_content .btn-group {
position: unset;
}
.o_kanban_card_content .btn-group button{
top: 100px;
left: 168px;
}
.o_kanban_primary_right {
position: absolute;
top: 40px;
left: 168px;
padding: 0;
.row {
>div {
width: unset;
}
}
}

View File

@@ -39,6 +39,7 @@
],
},
'external_dependencies': {'python': ['opcua(使用pip install opcua -i https://pypi.tuna.tsinghua.edu.cn/simple)']},
'installable': True,
'application': True,

View File

@@ -104,5 +104,55 @@
<!-- <filter string="草稿" name="filter_draft" domain="[('state', '=', 'draft')]"/> -->
<!-- </xpath> -->
<!-- 产品模板修改>>>增加“规格”字段specification_id -->
<record id="custom_product_template_kanban_view" model="ir.ui.view">
<field name="name">custom.Product.template.product.kanban</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_kanban_view"/>
<field name="arch" type="xml">
<xpath expr="//kanban" position="replace">
<kanban sample="1" class="o_kanban_product_template">
<field name="id"/>
<field name="product_variant_count"/>
<field name="currency_id"/>
<field name="activity_state"/>
<progressbar field="activity_state" colors='{"planned": "success", "today": "warning", "overdue": "danger"}'/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_card oe_kanban_global_click">
<div class="o_kanban_image me-1">
<img t-att-src="kanban_image('product.template', 'image_128', record.id.raw_value)" alt="Product" class="o_image_64_contain"/>
</div>
<div class="oe_kanban_details">
<div class="o_kanban_record_top mb-0">
<div class="o_kanban_record_headings">
<strong class="o_kanban_record_title">
<field name="name"/>
</strong>
</div>
<field name="priority" widget="priority"/>
</div>
<t t-if="record.default_code.value">[<field name="default_code"/>]</t>
<div t-if="record.product_variant_count.value &gt; 1" groups="product.group_product_variant">
<strong>
<t t-esc="record.product_variant_count.value"/> Variants
</strong>
</div>
<div name="product_lst_price" class="mt-1">
Price: <field name="list_price" widget="monetary" options="{'currency_field': 'currency_id', 'field_digits': True}"></field>
</div>
<div name="product_specification_id" class="mt-1">
规格: <field name="specification_id"></field>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -162,6 +162,86 @@ class sf_production_plan(models.Model):
# delivery_date = fields.Datetime(string='交货日期', related='plan_end_time', readonly=False, store=True)
# 当不设置计划结束时间时,增加计算计划结束时间的方法,根据采购周期加缓冲期两个值来算就可以了
# def do_production_schedule(self):
# """
# 排程方法
# """
# if not self.production_line_id:
# raise ValidationError("未选择生产线")
# else:
# aa = self.env['mrp.production'].sudo().search([('name', '=', self.name)])
# workorder_time = 0
# workorder_id_list = self.production_id.workorder_ids.ids
# print(workorder_id_list)
# print(type(self.production_id.workorder_ids))
# if self.production_id.workorder_ids:
# for item in self.production_id.workorder_ids:
# if item.name == 'CNC加工':
# item.date_planned_start = self.date_planned_start
# item.date_planned_finished = item.date_planned_start + timedelta(
# minutes=self.env['mrp.routing.workcenter'].sudo().search(
# [('name', '=', 'CNC加工')]).time_cycle)
# item.duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
# [('name', '=', 'CNC加工')]).time_cycle
# # print(item.id)
# sequence = workorder_id_list.index(item.id) - 1
# # print('sequence', sequence)
# # print('total', len(workorder_id_list))
# # 计算CNC加工之前工单的开始结束时间
# for i in range(sequence):
# current_workorder_id = (item.id - (i + 1))
# current_workorder_obj = self.env['mrp.workorder'].sudo().search(
# [('id', '=', current_workorder_id)])
# old_workorder_obj = self.env['mrp.workorder'].sudo().search(
# [('id', '=', (current_workorder_id + 1))])
# work_order = self.env['mrp.workorder'].sudo().search(
# [('production_id', '=', self.production_id.id), ('id', '=', current_workorder_id)])
# work_order.date_planned_finished = old_workorder_obj.date_planned_start
# work_order.date_planned_start = old_workorder_obj.date_planned_start - timedelta(
# minutes=self.env['mrp.routing.workcenter'].sudo().search(
# [('name', '=', current_workorder_obj.name)]).time_cycle)
# work_order.duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
# [('name', '=', current_workorder_obj.name)]).time_cycle
# # 计算CNC加工之后工单的开始结束时间
# for j in range(len(workorder_id_list) - sequence - 2):
# current_workorder_id = (item.id + (j + 1))
# current_workorder_obj = self.env['mrp.workorder'].sudo().search(
# [('id', '=', current_workorder_id)])
# old_workorder_obj = self.env['mrp.workorder'].sudo().search(
# [('id', '=', (current_workorder_id - 1))])
# work_order = self.env['mrp.workorder'].sudo().search(
# [('production_id', '=', self.production_id.id), ('id', '=', current_workorder_id)])
# try:
# work_order.date_planned_start = old_workorder_obj.date_planned_finished
# print('work_order.data_start', work_order.date_planned_start)
# work_order.date_planned_finished = old_workorder_obj.date_planned_finished + timedelta(
# minutes=self.env['mrp.routing.workcenter'].sudo().search(
# [('name', '=', current_workorder_obj.name)]).time_cycle)
# work_order.duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
# [('name', '=', current_workorder_obj.name)]).time_cycle
# except ValueError as e:
# print('时间设置失败,请检查是否为工序分配工作中心,%s' % e)
#
# current_workorder = self.env['mrp.workorder'].sudo().search([('id', '=', item.id)])
# workorder_time += current_workorder.duration_expected
# print('workorder_time', workorder_time)
# self.date_planned_finished = self.date_planned_start + timedelta(minutes=workorder_time)
# self.state = 'done'
# self.production_id.schedule_state = '已排'
# # self.production_id.date_planned_start = self.date_planned_start
# # self.production_id.date_planned_finished = self.date_planned_finished
# else:
# raise ValidationError("未找到工单")
# # self.date_planned_finished = self.date_planned_start + timedelta(days=3)
# # self.state = 'done'
# return {
# 'name': '排程甘特图',
# 'type': 'ir.actions.act_window',
# 'res_model': 'sf.production.plan', # 要跳转的模型名称
# 'view_mode': 'gantt,tree,form', # 要显示的视图类型,可以是'form', 'tree', 'kanban', 'graph', 'calendar', 'pivot'等
# 'target': 'current', # 跳转的目标窗口,可以是'current'或'new'
# }
def do_production_schedule(self):
"""
排程方法
@@ -169,60 +249,20 @@ class sf_production_plan(models.Model):
if not self.production_line_id:
raise ValidationError("未选择生产线")
else:
aa = self.env['mrp.production'].sudo().search([('name', '=', self.name)])
workorder_time = 0
workorder_id_list = self.production_id.workorder_ids.ids
print(workorder_id_list)
print(type(self.production_id.workorder_ids))
if self.production_id.workorder_ids:
for item in self.production_id.workorder_ids:
if item.name == 'CNC加工':
item.date_planned_finished = datetime.now() + timedelta(days=100)
item.date_planned_start = self.date_planned_start
item.date_planned_finished = item.date_planned_start + timedelta(
minutes=self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', 'CNC加工')]).time_cycle)
item.duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', 'CNC加工')]).time_cycle
# print(item.id)
sequence = workorder_id_list.index(item.id) - 1
# print('sequence', sequence)
# print('total', len(workorder_id_list))
# 计算CNC加工之前工单的开始结束时间
for i in range(sequence):
current_workorder_id = (item.id - (i + 1))
current_workorder_obj = self.env['mrp.workorder'].sudo().search(
[('id', '=', current_workorder_id)])
old_workorder_obj = self.env['mrp.workorder'].sudo().search(
[('id', '=', (current_workorder_id + 1))])
work_order = self.env['mrp.workorder'].sudo().search(
[('production_id', '=', self.production_id.id), ('id', '=', current_workorder_id)])
work_order.date_planned_finished = old_workorder_obj.date_planned_start
work_order.date_planned_start = old_workorder_obj.date_planned_start - timedelta(
minutes=self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', current_workorder_obj.name)]).time_cycle)
# work_order.duration_expected = self.env['mrp.routing.workcenter'].sudo().search([('name', '=', current_workorder_obj.name)]).time_cycle
# 计算CNC加工之后工单的开始结束时间
for j in range(len(workorder_id_list) - sequence - 2):
current_workorder_id = (item.id + (j + 1))
current_workorder_obj = self.env['mrp.workorder'].sudo().search(
[('id', '=', current_workorder_id)])
old_workorder_obj = self.env['mrp.workorder'].sudo().search(
[('id', '=', (current_workorder_id - 1))])
work_order = self.env['mrp.workorder'].sudo().search(
[('production_id', '=', self.production_id.id), ('id', '=', current_workorder_id)])
try:
work_order.date_planned_start = old_workorder_obj.date_planned_finished
print('work_order.data_start', work_order.date_planned_start)
work_order.date_planned_finished = old_workorder_obj.date_planned_finished + timedelta(
minutes=self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', current_workorder_obj.name)]).time_cycle)
except ValueError as e:
print('时间设置失败,请检查是否为工序分配工作中心,%s' % e)
current_workorder = self.env['mrp.workorder'].sudo().search([('id', '=', item.id)])
workorder_time += current_workorder.duration_expected
print('workorder_time', workorder_time)
self.date_planned_finished = self.date_planned_start + timedelta(minutes=workorder_time)
self.calculate_plan_time_before(item, workorder_id_list)
self.calculate_plan_time_after(item, workorder_id_list)
self.date_planned_start, self.date_planned_finished = item.date_planned_start, item.date_planned_finished
self.state = 'done'
self.production_id.schedule_state = '已排'
# self.production_id.date_planned_start = self.date_planned_start
@@ -238,36 +278,62 @@ class sf_production_plan(models.Model):
'view_mode': 'gantt,tree,form', # 要显示的视图类型,可以是'form', 'tree', 'kanban', 'graph', 'calendar', 'pivot'等
'target': 'current', # 跳转的目标窗口,可以是'current'或'new'
}
# if self.production_line_id:
# if self.plan_start_time and self.plan_end_time:
# return None
# elif self.plan_start_time and not self.plan_end_time:
# # 如果没有给出计划结束时间,则计划结束时间为计划开始时间+采购周期+缓冲期
# # 采购周期
# purchase_cycle = 3
# # 缓冲期
# buffer_period = 1
# # 计划结束时间 = 计划开始时间 + 采购周期 + 缓冲期
# self.plan_end_time = self.plan_start_time + timedelta(days=purchase_cycle) + timedelta(
# days=buffer_period)
# self.state = 'produce'
# return self.plan_end_time
# else:
# return None
# # 后面要补充计划开始时间的计算方法
# # # 坯料预制时间
# # # pl_time = 0.5
# # # 采购周期
# # purchase_cycle = 3
# # # 缓冲期
# # buffer_period = 1
# # # 计划结束时间 = 计划开始时间 + 坯料预制时间 + 采购周期 + 缓冲期
# # # plan_end_time = plan_start_time + pl_time + purchase_cycle + buffer_period
# # # 计划结束时间 = 计划开始时间(是一个datatime) + 采购周期(Float) + 缓冲期(Float)
# # self.plan_end_time = self.plan_start_time + timedelta(days=purchase_cycle) + timedelta(days=buffer_period)
# # return self.plan_end_time
# else:
# raise ValidationError('生产线为空!')
def calculate_plan_time_before(self, item, workorder_id_list):
"""
根据CNC工单的时间去计算之前的其他工单的开始结束时间
"""
sequence = workorder_id_list.index(item.id) - 1
# 计算CNC加工之前工单的开始结束时间
for i in range(sequence):
current_workorder_id = (item.id - (i + 1))
current_workorder_obj = self.env['mrp.workorder'].sudo().search(
[('id', '=', current_workorder_id)])
old_workorder_obj = self.env['mrp.workorder'].sudo().search(
[('id', '=', (current_workorder_id + 1))])
work_order = self.env['mrp.workorder'].sudo().search(
[('production_id', '=', self.production_id.id), ('id', '=', current_workorder_id)])
work_order.date_planned_finished = datetime.now() + timedelta(days=100)
work_order.date_planned_start = old_workorder_obj.date_planned_start - timedelta(
minutes=self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', current_workorder_obj.name)]).time_cycle)
work_order.date_planned_finished = old_workorder_obj.date_planned_start
work_order.duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', current_workorder_obj.name)]).time_cycle
first_workorder = self.env['mrp.workorder'].sudo().search([('id', '=', workorder_id_list[0])])
second_workorder = self.env['mrp.workorder'].sudo().search([('id', '=', workorder_id_list[1])])
if second_workorder.date_planned_start < first_workorder.date_planned_finished:
item.date_planned_start += timedelta(minutes=60)
item.date_planned_finished += timedelta(minutes=60)
item.duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', 'CNC加工')]).time_cycle
self.calculate_plan_time_before(item, workorder_id_list)
def calculate_plan_time_after(self, item, workorder_id_list):
"""
计算CNC加工之后工单的开始结束时间
"""
sequence = workorder_id_list.index(item.id) - 1
# 计算CNC加工之后工单的开始结束时间
for j in range(len(workorder_id_list) - sequence - 2):
current_workorder_id = (item.id + (j + 1))
current_workorder_obj = self.env['mrp.workorder'].sudo().search(
[('id', '=', current_workorder_id)])
old_workorder_obj = self.env['mrp.workorder'].sudo().search(
[('id', '=', (current_workorder_id - 1))])
work_order = self.env['mrp.workorder'].sudo().search(
[('production_id', '=', self.production_id.id), ('id', '=', current_workorder_id)])
try:
work_order.date_planned_finished = datetime.now() + timedelta(days=100)
work_order.date_planned_start = old_workorder_obj.date_planned_finished
print('work_order.data_start', work_order.date_planned_start)
work_order.date_planned_finished = old_workorder_obj.date_planned_finished + timedelta(
minutes=self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', current_workorder_obj.name)]).time_cycle)
work_order.duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', current_workorder_obj.name)]).time_cycle
except ValueError as e:
print('时间设置失败,请检查是否为工序分配工作中心,%s' % e)
def cancel_production_schedule(self):
self.date_planned_finished = False

View File

@@ -10,8 +10,9 @@
<record id="mrp_workorder.menu_mrp_workorder_workcenter" model="ir.ui.menu">
<!-- <field name="name">工单计划</field> -->
<field name="sequence" eval="300"/>
<field name="parent_id" ref="sf_plan.sf_production_plan_menu"/>
<!-- <field name="sequence" eval="300"/> -->
<!-- <field name="parent_id" ref="sf_plan.sf_production_plan_menu"/> -->
<field name="active" eval="False"/>
</record>

View File

@@ -688,45 +688,46 @@ class FunctionalToolAssembly(models.Model):
# 整体式刀具型号
integral_code_id = fields.Many2one('stock.lot', string='整体式刀具序列号', readonly=True)
cutting_tool_integral_model_id = fields.Many2one('sf.cutting.tool.material', string='整体式刀具型号', readonly=True)
integral_name = fields.Char('整体式刀具名称', readonly=True)
cutting_tool_integral_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='整体式刀具型号', readonly=True)
integral_name = fields.Char('整体式刀具名称', readonly=True, compute='_compute_auto_fill')
sf_tool_brand_id_1 = fields.Many2one('sf.machine.brand', string='整体式刀具品牌', readonly=True)
# 刀片型号
blade_code_id = fields.Many2one('stock.lot', '刀片序列号', readonly=True)
cutting_tool_blade_model_id = fields.Many2one('sf.cutting.tool.material', string='刀片型号', readonly=True)
blade_name = fields.Char('刀片名称', readonly=True)
cutting_tool_blade_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀片型号', readonly=True)
blade_name = fields.Char('刀片名称', readonly=True, compute='_compute_auto_fill')
sf_tool_brand_id_2 = fields.Many2one('sf.machine.brand', '刀片品牌', readonly=True)
# 刀杆型号
bar_code_id = fields.Many2one('stock.lot', '刀杆序列号', readonly=True)
cutting_tool_cutterbar_model_id = fields.Many2one('sf.cutting.tool.material', string='刀杆型号', readonly=True)
bar_name = fields.Char('刀杆名称', readonly=True)
cutting_tool_cutterbar_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀杆型号', readonly=True)
bar_name = fields.Char('刀杆名称', readonly=True, compute='_compute_auto_fill')
sf_tool_brand_id_3 = fields.Many2one('sf.machine.brand', '刀杆品牌', readonly=True)
# 刀盘型号
pad_code_id = fields.Many2one('stock.lot', '刀盘序列号', readonly=True)
cutting_tool_cutterpad_model_id = fields.Many2one('sf.cutting.tool.material', string='刀盘型号', readonly=True)
pad_name = fields.Char('刀盘名称', readonly=True)
cutting_tool_cutterpad_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀盘型号', readonly=True)
pad_name = fields.Char('刀盘名称', readonly=True, compute='_compute_auto_fill')
sf_tool_brand_id_4 = fields.Many2one('sf.machine.brand', '刀盘品牌', readonly=True)
# 刀柄型号
handle_code_id = fields.Many2one('stock.lot', '刀柄序列号', readonly=True)
cutting_tool_cutterhandle_model_id = fields.Many2one('sf.cutting.tool.material', string='刀柄型号', readonly=True)
handle_name = fields.Char('刀柄名称', readonly=True)
cutting_tool_cutterhandle_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀柄型号', readonly=True)
handle_name = fields.Char('刀柄名称', readonly=True, compute='_compute_auto_fill')
sf_tool_brand_id_5 = fields.Many2one('sf.machine.brand', '刀柄品牌', readonly=True)
# 夹头型号
chuck_code_id = fields.Many2one('stock.lot', '夹头序列号', readonly=True)
cutting_tool_cutterhead_model_id = fields.Many2one('sf.cutting.tool.material', string='夹头型号', readonly=True)
chuck_name = fields.Char('夹头名称', readonly=True)
cutting_tool_cutterhead_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='夹头型号', readonly=True)
chuck_name = fields.Char('夹头名称', readonly=True, compute='_compute_auto_fill')
sf_tool_brand_id_6 = fields.Many2one('sf.machine.brand', '夹头品牌', readonly=True)
@api.depends('integral_code_id', 'blade_code_id', 'bar_code_id', 'pad_code_id', 'handle_code_id', 'chuck_code_id')
def _compute_auto_fill(self):
for record in self:
if record.integral_code_id:
record.cutting_tool_integral_model_id = record.integral_code_id.product_id.cutting_tool_material_id.id
print(record.integral_code_id.product_id)
record.cutting_tool_integral_model_id = record.integral_code_id.product_id.cutting_tool_model_id.id
record.integral_name = record.integral_code_id.product_id.name
record.sf_tool_brand_id_1 = record.integral_code_id.product_id.brand_id.id
else:
@@ -734,7 +735,7 @@ class FunctionalToolAssembly(models.Model):
record.integral_name = None
record.sf_tool_brand_id_1 = None
if record.blade_code_id:
record.cutting_tool_blade_model_id = record.blade_code_id.product_id.cutting_tool_material_id.id
record.cutting_tool_blade_model_id = record.blade_code_id.product_id.cutting_tool_model_id.id
record.blade_name = record.blade_code_id.product_id.name
record.sf_tool_brand_id_2 = record.blade_code_id.product_id.brand_id.id
else:
@@ -742,7 +743,7 @@ class FunctionalToolAssembly(models.Model):
record.blade_name = None
record.sf_tool_brand_id_2 = None
if record.bar_code_id:
record.cutting_tool_cutterbar_model_id = record.bar_code_id.product_id.cutting_tool_material_id.id
record.cutting_tool_cutterbar_model_id = record.bar_code_id.product_id.cutting_tool_model_id.id
record.bar_name = record.bar_code_id.product_id.name
record.sf_tool_brand_id_3 = record.bar_code_id.product_id.brand_id.id
else:
@@ -750,7 +751,7 @@ class FunctionalToolAssembly(models.Model):
record.bar_name = None
record.sf_tool_brand_id_3 = None
if record.pad_code_id:
record.cutting_tool_cutterpad_model_id = record.pad_code_id.product_id.cutting_tool_material_id.id
record.cutting_tool_cutterpad_model_id = record.pad_code_id.product_id.cutting_tool_model_id.id
record.pad_name = record.pad_code_id.product_id.name
record.sf_tool_brand_id_4 = record.pad_code_id.product_id.brand_id.id
else:
@@ -758,7 +759,7 @@ class FunctionalToolAssembly(models.Model):
record.pad_name = None
record.sf_tool_brand_id_4 = None
if record.handle_code_id:
record.cutting_tool_cutterhandle_model_id = record.handle_code_id.product_id.cutting_tool_material_id.id
record.cutting_tool_cutterhandle_model_id = record.handle_code_id.product_id.cutting_tool_model_id.id
record.handle_name = record.handle_code_id.product_id.name
record.sf_tool_brand_id_5 = record.handle_code_id.product_id.brand_id.id
else:
@@ -766,7 +767,7 @@ class FunctionalToolAssembly(models.Model):
record.handle_name = None
record.sf_tool_brand_id_5 = None
if record.chuck_code_id:
record.cutting_tool_cutterhead_model_id = record.chuck_code_id.product_id.cutting_tool_material_id.id
record.cutting_tool_cutterhead_model_id = record.chuck_code_id.product_id.cutting_tool_model_id.id
record.chuck_name = record.chuck_code_id.product_id.name
record.sf_tool_brand_id_6 = record.chuck_code_id.product_id.brand_id.id
else:

View File

@@ -796,7 +796,7 @@
</group>
<notebook>
<page string="待换功能刀具信息">
<group>
<group attrs="{'invisible': [('sf_functional_tool_assembly_id', '=', False)]}">
<group>
<field name="replacement_tool_name_id"/>
<field name="replacement_tool_type_id"/>

View File

@@ -17,7 +17,8 @@ class ToolChangeRequirementInformation(models.TransientModel):
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=True)
# replacement_tool_code = fields.Char(string='待换功能刀具编码', readonly=True)
replacement_tool_name_id = fields.Many2one('product.product', string='待换功能刀具名称', )
replacement_tool_name_id = fields.Many2one('product.product', string='待换功能刀具名称',
domain=[('name', '=', '功能刀具')])
replacement_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='待换功能刀具类型')
replacement_tool_coarse_middle_thin = fields.Selection([("1", ""), ('2', ''), ('3', '')],
string='粗/中/精')
@@ -139,42 +140,42 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
# 整体式刀具型号
integral_code_id = fields.Many2one('stock.lot', string='整体式刀具序列号',
domain=[('product_id.cutting_tool_material_id.name', '=', '整体式刀具')])
cutting_tool_integral_model_id = fields.Many2one('sf.cutting.tool.material', string='整体式刀具型号', readonly=True)
cutting_tool_integral_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='整体式刀具型号', readonly=True)
integral_name = fields.Char('整体式刀具名称', readonly=True)
sf_tool_brand_id_1 = fields.Many2one('sf.machine.brand', string='整体式刀具品牌', readonly=True)
# 刀片型号
blade_code_id = fields.Many2one('stock.lot', '刀片序列号',
domain=[('product_id.cutting_tool_material_id.name', '=', '刀片')])
cutting_tool_blade_model_id = fields.Many2one('sf.cutting.tool.material', string='刀片型号', readonly=True)
cutting_tool_blade_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀片型号', readonly=True)
blade_name = fields.Char('刀片名称', readonly=True)
sf_tool_brand_id_2 = fields.Many2one('sf.machine.brand', '刀片品牌', readonly=True)
# 刀杆型号
bar_code_id = fields.Many2one('stock.lot', '刀杆序列号',
domain=[('product_id.cutting_tool_material_id.name', '=', '刀杆')])
cutting_tool_cutterbar_model_id = fields.Many2one('sf.cutting.tool.material', string='刀杆型号', readonly=True)
cutting_tool_cutterbar_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀杆型号', readonly=True)
bar_name = fields.Char('刀杆名称', readonly=True)
sf_tool_brand_id_3 = fields.Many2one('sf.machine.brand', '刀杆品牌', readonly=True)
# 刀盘型号
pad_code_id = fields.Many2one('stock.lot', '刀盘序列号',
domain=[('product_id.cutting_tool_material_id.name', '=', '刀盘')])
cutting_tool_cutterpad_model_id = fields.Many2one('sf.cutting.tool.material', string='刀盘型号', readonly=True)
cutting_tool_cutterpad_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀盘型号', readonly=True)
pad_name = fields.Char('刀盘名称', readonly=True)
sf_tool_brand_id_4 = fields.Many2one('sf.machine.brand', '刀盘品牌', readonly=True)
# 刀柄型号
handle_code_id = fields.Many2one('stock.lot', '刀柄序列号',
domain=[('product_id.cutting_tool_material_id.name', '=', '刀柄')])
cutting_tool_cutterhandle_model_id = fields.Many2one('sf.cutting.tool.material', string='刀柄型号', readonly=True)
cutting_tool_cutterhandle_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀柄型号', readonly=True)
handle_name = fields.Char('刀柄名称', readonly=True)
sf_tool_brand_id_5 = fields.Many2one('sf.machine.brand', '刀柄品牌', readonly=True)
# 夹头型号
chuck_code_id = fields.Many2one('stock.lot', '夹头序列号',
domain=[('product_id.cutting_tool_material_id.name', '=', '夹头')])
cutting_tool_cutterhead_model_id = fields.Many2one('sf.cutting.tool.material', string='夹头型号', readonly=True)
cutting_tool_cutterhead_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='夹头型号', readonly=True)
chuck_name = fields.Char('夹头名称', readonly=True, compute='_compute_auto_fill')
sf_tool_brand_id_6 = fields.Many2one('sf.machine.brand', '夹头品牌', readonly=True)
@@ -207,7 +208,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
def _compute_auto_fill(self):
for record in self:
if record.integral_code_id:
record.cutting_tool_integral_model_id = record.integral_code_id.product_id.cutting_tool_material_id.id
record.cutting_tool_integral_model_id = record.integral_code_id.product_id.cutting_tool_model_id.id
record.integral_name = record.integral_code_id.product_id.name
record.sf_tool_brand_id_1 = record.integral_code_id.product_id.brand_id.id
else:
@@ -215,7 +216,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
record.integral_name = None
record.sf_tool_brand_id_1 = None
if record.blade_code_id:
record.cutting_tool_blade_model_id = record.blade_code_id.product_id.cutting_tool_material_id.id
record.cutting_tool_blade_model_id = record.blade_code_id.product_id.cutting_tool_model_id.id
record.blade_name = record.blade_code_id.product_id.name
record.sf_tool_brand_id_2 = record.blade_code_id.product_id.brand_id.id
else:
@@ -223,7 +224,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
record.blade_name = None
record.sf_tool_brand_id_2 = None
if record.bar_code_id:
record.cutting_tool_cutterbar_model_id = record.bar_code_id.product_id.cutting_tool_material_id.id
record.cutting_tool_cutterbar_model_id = record.bar_code_id.product_id.cutting_tool_model_id.id
record.bar_name = record.bar_code_id.product_id.name
record.sf_tool_brand_id_3 = record.bar_code_id.product_id.brand_id.id
else:
@@ -231,7 +232,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
record.bar_name = None
record.sf_tool_brand_id_3 = None
if record.pad_code_id:
record.cutting_tool_cutterpad_model_id = record.pad_code_id.product_id.cutting_tool_material_id.id
record.cutting_tool_cutterpad_model_id = record.pad_code_id.product_id.cutting_tool_model_id.id
record.pad_name = record.pad_code_id.product_id.name
record.sf_tool_brand_id_4 = record.pad_code_id.product_id.brand_id.id
else:
@@ -239,7 +240,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
record.pad_name = None
record.sf_tool_brand_id_4 = None
if record.handle_code_id:
record.cutting_tool_cutterhandle_model_id = record.handle_code_id.product_id.cutting_tool_material_id.id
record.cutting_tool_cutterhandle_model_id = record.handle_code_id.product_id.cutting_tool_model_id.id
record.handle_name = record.handle_code_id.product_id.name
record.sf_tool_brand_id_5 = record.handle_code_id.product_id.brand_id.id
else:
@@ -247,7 +248,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
record.handle_name = None
record.sf_tool_brand_id_5 = None
if record.chuck_code_id:
record.cutting_tool_cutterhead_model_id = record.chuck_code_id.product_id.cutting_tool_material_id.id
record.cutting_tool_cutterhead_model_id = record.chuck_code_id.product_id.cutting_tool_model_id.id
record.chuck_name = record.chuck_code_id.product_id.name
record.sf_tool_brand_id_6 = record.chuck_code_id.product_id.brand_id.id
else:
@@ -302,12 +303,12 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
'barcode_id': stock_lot.id,
'functional_tool_name_id': self.functional_tool_name_id.id,
'mrs_cutting_tool_type_id': self.functional_tool_type_id.id,
'cutting_tool_integral_model_id': self.cutting_tool_integral_model_id.id,
'cutting_tool_blade_model_id': self.cutting_tool_blade_model_id.id,
'cutting_tool_cutterbar_model_id': self.cutting_tool_cutterbar_model_id.id,
'cutting_tool_cutterpad_model_id': self.cutting_tool_cutterpad_model_id.id,
'cutting_tool_cutterhandle_model_id': self.cutting_tool_cutterhandle_model_id.id,
'cutting_tool_cutterhead_model_id': self.cutting_tool_cutterhead_model_id.id,
'cutting_tool_integral_model_id': self.integral_code_id.product_id.id,
'cutting_tool_blade_model_id': self.blade_code_id.product_id.id,
'cutting_tool_cutterbar_model_id': self.bar_code_id.product_id.id,
'cutting_tool_cutterpad_model_id': self.pad_code_id.product_id.id,
'cutting_tool_cutterhandle_model_id': self.handle_code_id.product_id.id,
'cutting_tool_cutterhead_model_id': self.chuck_code_id.product_id.id,
'diameter': self.functional_tool_diameter,
'tool_grade': None,
'machining_accuracy': None,

View File

@@ -4,7 +4,6 @@ from odoo import SUPERUSER_ID, _, api, fields, models
from odoo.osv import expression
class SfLocation(models.Model):
_inherit = 'stock.location'
@@ -201,7 +200,6 @@ class SfLocation(models.Model):
j_str = str(j + 1).zfill(3) # 确保是两位数如果不足两位左侧补0
return area_type_barcode + self.channel + self.direction + '-' + self.barcode + '-' + i_str + '-' + j_str
# def generate_barcode(self, i, j):
# # 这里是你生成barcode的代码
# area_type_barcode = self.location_id.barcode
@@ -217,26 +215,51 @@ class SfProcurementGroup(models.Model):
修改路线多规则条件选取
"""
if warehouse_id:
domain = expression.AND([['|', ('warehouse_id', '=', warehouse_id.id), ('warehouse_id', '=', False)], domain])
domain = expression.AND(
[['|', ('warehouse_id', '=', warehouse_id.id), ('warehouse_id', '=', False)], domain])
Rule = self.env['stock.rule']
res = self.env['stock.rule']
if route_ids:
res = Rule.search(expression.AND([[('route_id', 'in', route_ids.ids)], domain]), order='route_sequence, sequence', limit=1)
res_list = Rule.search(expression.AND([[('route_id', 'in', route_ids.ids)], domain]),
order='route_sequence, sequence')
for res1 in res_list:
if product_id.categ_id in res1.location_dest_id.product_type or product_id.categ_id in res1.location_src_id.product_type:
res = res1
if not res:
res = Rule.search(expression.AND([[('route_id', 'in', route_ids.ids)], domain]),
order='route_sequence, sequence', limit=1)
if not res and packaging_id:
packaging_routes = packaging_id.route_ids
if packaging_routes:
res = Rule.search(expression.AND([[('route_id', 'in', packaging_routes.ids)], domain]), order='route_sequence, sequence', limit=1)
if not res:
product_routes = product_id.route_ids | product_id.categ_id.total_route_ids
if product_routes:
res = Rule.search(expression.AND([[('route_id', 'in', product_routes.ids)], domain]), order='route_sequence, sequence', limit=1)
if not res and warehouse_id:
warehouse_routes = warehouse_id.route_ids
if warehouse_routes:
res_list = Rule.search(expression.AND([[('route_id', 'in', warehouse_routes.ids)], domain]), order='route_sequence, sequence')
res_list = Rule.search(expression.AND([[('route_id', 'in', packaging_routes.ids)], domain]),
order='route_sequence, sequence')
for res1 in res_list:
if product_id.categ_id in res1.location_dest_id.product_type or product_id.categ_id in res1.location_src_id.product_type:
res = res1
if not res:
res = Rule.search(expression.AND([[('route_id', 'in', packaging_routes.ids)], domain]),
order='route_sequence, sequence', limit=1)
if not res:
res = Rule.search(expression.AND([[('route_id', 'in', warehouse_routes.ids)], domain]), order='route_sequence, sequence', limit=1)
return res
product_routes = product_id.route_ids | product_id.categ_id.total_route_ids
if product_routes:
res_list = Rule.search(expression.AND([[('route_id', 'in', product_routes.ids)], domain]),
order='route_sequence, sequence')
for res1 in res_list:
if product_id.categ_id in res1.location_dest_id.product_type or product_id.categ_id in res1.location_src_id.product_type:
res = res1
if not res:
res = Rule.search(expression.AND([[('route_id', 'in', product_routes.ids)], domain]),
order='route_sequence, sequence', limit=1)
if not res and warehouse_id:
warehouse_routes = warehouse_id.route_ids
if warehouse_routes:
res_list = Rule.search(expression.AND([[('route_id', 'in', warehouse_routes.ids)], domain]),
order='route_sequence, sequence')
for res1 in res_list:
if product_id.categ_id in res1.location_dest_id.product_type or product_id.categ_id in res1.location_src_id.product_type:
res = res1
if not res:
res = Rule.search(expression.AND([[('route_id', 'in', warehouse_routes.ids)], domain]),
order='route_sequence, sequence', limit=1)
return res

View File

@@ -77,13 +77,13 @@
<t t-if="widget.state.scale in formats" t-esc="slot.format(formats[widget.state.scale])"/>
<small t-else="">
<t t-if="slot.format('k') == 24">
<div>夜班</div>
<div>夜班(00:00-08:00)</div>
</t>
<t t-if="slot.format('k') == 8">
<div>早班</div>
<div>早班(08:00-16:00)</div>
</t>
<t t-if="slot.format('k') == 16">
<div>晚班</div>
<div>晚班(16:00-00:00)</div>
</t>
<!-- <b t-esc="slot.format('k')"/> -->
<!-- <span class="d-block d-xl-inline-block" t-esc="slot.format('a')"/> -->