Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/新增工艺退回调整
# Conflicts: # sf_manufacturing/models/mrp_production.py # sf_manufacturing/views/mrp_production_addional_change.xml
This commit is contained in:
@@ -8,17 +8,20 @@ class ModelType(models.Model):
|
||||
name = fields.Char('名称')
|
||||
embryo_tolerance = fields.Integer('坯料容余')
|
||||
product_routing_tmpl_ids = fields.One2many('sf.product.model.type.routing.sort', 'product_model_type_id',
|
||||
'成品工序模板')
|
||||
'成品工序模板(自动化产线加工')
|
||||
embryo_routing_tmpl_ids = fields.One2many('sf.embryo.model.type.routing.sort', 'embryo_model_type_id',
|
||||
'坯料工序模板')
|
||||
'坯料工序模板(人工线下加工)')
|
||||
surface_technics_routing_tmpl_ids = fields.One2many('sf.surface_technics.model.type.routing.sort',
|
||||
'surface_technics_model_type_id',
|
||||
'表面工艺工序模板')
|
||||
manual_product_routing_tmpl_ids = fields.One2many('sf.manual.product.model.type.routing.sort',
|
||||
'manual_product_model_type_id',
|
||||
'成品工序模板(人工线下加工)')
|
||||
|
||||
|
||||
class ProductModelTypeRoutingSort(models.Model):
|
||||
_name = 'sf.product.model.type.routing.sort'
|
||||
_description = '成品工序排序'
|
||||
_description = '成品工序排序(自动化产线加工)'
|
||||
|
||||
sequence = fields.Integer('Sequence')
|
||||
route_workcenter_id = fields.Many2one('mrp.routing.workcenter',
|
||||
@@ -65,3 +68,18 @@ class SurfaceTechnicsModelTypeRoutingSort(models.Model):
|
||||
'route_model_type_uniq', 'unique (route_workcenter_id,surface_technics_model_type_id)',
|
||||
'表面工艺工序不能重复!')
|
||||
]
|
||||
|
||||
class ManualProductModelTypeRoutingSort(models.Model):
|
||||
_name = 'sf.manual.product.model.type.routing.sort'
|
||||
_description = '成品工序排序(人工线下加工)'
|
||||
|
||||
sequence = fields.Integer('Sequence')
|
||||
route_workcenter_id = fields.Many2one('mrp.routing.workcenter')
|
||||
is_repeat = fields.Boolean('重复', related='route_workcenter_id.is_repeat')
|
||||
routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type')
|
||||
workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids')
|
||||
manual_product_model_type_id = fields.Many2one('sf.model.type')
|
||||
|
||||
_sql_constraints = [
|
||||
('route_model_type_uniq', 'unique (route_workcenter_id,manual_product_model_type_id)', '成品工序不能重复!')
|
||||
]
|
||||
@@ -34,6 +34,95 @@ class MrpProduction(models.Model):
|
||||
tool_state_remark = fields.Text(string='功能刀具状态备注(缺刀)', compute='_compute_tool_state_remark', store=True)
|
||||
tool_state_remark2 = fields.Text(string='功能刀具状态备注(无效刀)', readonly=True)
|
||||
|
||||
def _compute_default_delivery_status(self):
|
||||
try:
|
||||
if self.state == 'cancel':
|
||||
return False
|
||||
if not self.deadline_of_delivery:
|
||||
return False
|
||||
hours = self.get_hours_diff()
|
||||
if hours >= 48:
|
||||
return '正常'
|
||||
elif hours > 0 and hours < 48 and self.state != 'done':
|
||||
return '预警'
|
||||
elif hours > 0 and hours < 48 and self.state == 'done':
|
||||
return '正常'
|
||||
else:
|
||||
return '已逾期'
|
||||
except Exception as e:
|
||||
logging.error("Error processing production ID {}: {}".format(self.id, e))
|
||||
raise e
|
||||
|
||||
@api.depends('state', 'deadline_of_delivery')
|
||||
def _compute_delivery_status(self):
|
||||
for production in self:
|
||||
delivery_status = production._compute_default_delivery_status()
|
||||
if delivery_status and production.delivery_status != delivery_status:
|
||||
production.delivery_status = delivery_status
|
||||
|
||||
delivery_status = fields.Selection([('正常', '正常'), ('预警', '预警'), ('已逾期', '已逾期')], string='交期状态',
|
||||
store=True,
|
||||
compute='_compute_delivery_status',
|
||||
default=lambda self: self._compute_default_delivery_status())
|
||||
|
||||
def get_page_all_records(self, model_name, func, domain, page_size=100):
|
||||
# 获取模型对象
|
||||
model = self.env[model_name].sudo()
|
||||
|
||||
# 初始化分页参数
|
||||
page_number = 1
|
||||
while True:
|
||||
# 计算偏移量
|
||||
offset = (page_number - 1) * page_size
|
||||
|
||||
# 获取当前页的数据
|
||||
records = model.search(domain, limit=page_size, offset=offset)
|
||||
|
||||
# 如果没有更多记录,退出循环
|
||||
if not records:
|
||||
break
|
||||
|
||||
# 将当前页的数据添加到结果列表
|
||||
func(records)
|
||||
# 增加页码
|
||||
page_number += 1
|
||||
|
||||
def run_compute_delivery_status(self, records):
|
||||
records._compute_delivery_status()
|
||||
|
||||
def _corn_update_delivery_status(self):
|
||||
need_list = [
|
||||
'draft',
|
||||
'technology_to_confirmed',
|
||||
'confirmed',
|
||||
'pending_cam',
|
||||
'progress',
|
||||
'rework',
|
||||
'scrap',
|
||||
'to_close',
|
||||
]
|
||||
# previous_workorder = self.env['mrp.production'].search([('state', 'in', need_list)])
|
||||
self.get_page_all_records('mrp.production', self.run_compute_delivery_status,
|
||||
[('state', 'in', need_list)], 100)
|
||||
|
||||
def get_hours_diff(self):
|
||||
# 获取当前日期和时间
|
||||
current_datetime = fields.Datetime.now()
|
||||
|
||||
# 将 date_field 转换为 datetime 对象
|
||||
if self.deadline_of_delivery:
|
||||
date_obj = fields.Date.from_string(self.deadline_of_delivery)
|
||||
# 将 date 对象转换为 datetime 对象,设置时间为 00:00:00
|
||||
date_obj = datetime.datetime.combine(date_obj, datetime.time.min)
|
||||
|
||||
# 计算两个日期之间的差值
|
||||
delta = date_obj - current_datetime
|
||||
|
||||
# 返回差值的小时数
|
||||
return int(delta.total_seconds() / 3600)
|
||||
else:
|
||||
return 0.0
|
||||
|
||||
@api.depends('procurement_group_id.mrp_production_ids.move_dest_ids.group_id.sale_id')
|
||||
def _compute_deadline_of_delivery(self):
|
||||
for production in self:
|
||||
@@ -612,20 +701,6 @@ class MrpProduction(models.Model):
|
||||
for workorder in production.workorder_ids:
|
||||
workorder.duration_expected = workorder._get_duration_expected()
|
||||
|
||||
# 生成采购单
|
||||
def get_subcontract_purchase(self):
|
||||
production_all = self.sorted(lambda x: x.id)
|
||||
for production in production_all:
|
||||
for special in production.technology_design_ids:
|
||||
if special.process_parameters_id.gain_way == '外协':
|
||||
product_id_to_production_names = {}
|
||||
grouped_product_ids = {k: list(g) for k, g in
|
||||
groupby(production_all, key=lambda x: x.product_id.id)}
|
||||
for product_id, pd in grouped_product_ids.items():
|
||||
product_id_to_production_names[product_id] = [p.name for p in pd]
|
||||
self.env['purchase.order'].get_purchase_order(special.process_parameters_id,
|
||||
special.production_id,
|
||||
product_id_to_production_names)
|
||||
|
||||
# 外协出入库单处理
|
||||
def get_subcontract_pick_purchase(self):
|
||||
@@ -800,6 +875,7 @@ class MrpProduction(models.Model):
|
||||
if td_ids:
|
||||
work.sequence = td_ids[0].sequence
|
||||
|
||||
|
||||
def _reset_work_order_sequence_1(self):
|
||||
"""
|
||||
工单工序排序方法(旧)
|
||||
|
||||
@@ -144,6 +144,88 @@ class ResMrpWorkOrder(models.Model):
|
||||
|
||||
tag_type = fields.Selection([("重新加工", "重新加工")], string="标签", tracking=True)
|
||||
|
||||
def _compute_default_construction_period_status(self):
|
||||
need_list=['pending', 'waiting', 'ready', 'progress', 'to be detected','done']
|
||||
try:
|
||||
if self.state not in need_list:
|
||||
return False
|
||||
if not self.date_planned_finished:
|
||||
return False
|
||||
hours = self.get_hours_diff()
|
||||
if hours >= 12:
|
||||
return '正常'
|
||||
elif hours > 0 and hours < 12 and self.state!='done':
|
||||
return '预警'
|
||||
elif hours > 0 and hours < 12 and self.state=='done':
|
||||
return '正常'
|
||||
else:
|
||||
return '已逾期'
|
||||
except Exception as e:
|
||||
logging.error("Error processing production ID {}: {}".format(self.id, e))
|
||||
raise e
|
||||
|
||||
@api.depends('state', 'date_planned_finished')
|
||||
def _compute_construction_period_status(self):
|
||||
for worker in self:
|
||||
construction_period_status = worker._compute_default_construction_period_status()
|
||||
if construction_period_status and worker.construction_period_status!=construction_period_status:
|
||||
worker.construction_period_status = construction_period_status
|
||||
|
||||
construction_period_status = fields.Selection([('正常', '正常'), ('预警', '预警'), ('已逾期', '已逾期')],
|
||||
string='工期状态',
|
||||
store=True,
|
||||
compute='_compute_construction_period_status',
|
||||
default=lambda
|
||||
self: self._compute_default_construction_period_status())
|
||||
|
||||
def get_page_all_records(self, model_name, func, domain, page_size=100):
|
||||
# 获取模型对象
|
||||
model = self.env[model_name].sudo()
|
||||
|
||||
# 初始化分页参数
|
||||
page_number = 1
|
||||
while True:
|
||||
# 计算偏移量
|
||||
offset = (page_number - 1) * page_size
|
||||
|
||||
# 获取当前页的数据
|
||||
records = model.search(domain, limit=page_size, offset=offset)
|
||||
|
||||
# 如果没有更多记录,退出循环
|
||||
if not records:
|
||||
break
|
||||
|
||||
# 将当前页的数据添加到结果列表
|
||||
func(records)
|
||||
# 增加页码
|
||||
page_number += 1
|
||||
def run_compute_construction_period_status(self,records):
|
||||
records._compute_construction_period_status()
|
||||
def _corn_update_construction_period_status(self):
|
||||
need_list=['pending', 'waiting', 'ready', 'progress', 'to be detected']
|
||||
# need_list = [
|
||||
# 'progress',
|
||||
# 'to be detected']
|
||||
self.get_page_all_records('mrp.workorder',self.run_compute_construction_period_status,[('state', 'in', need_list)],100)
|
||||
|
||||
def get_hours_diff(self):
|
||||
# 获取当前日期和时间
|
||||
current_datetime = fields.Datetime.now()
|
||||
|
||||
# 将 date_field 转换为 datetime 对象
|
||||
if self.date_planned_finished:
|
||||
date_obj = fields.Datetime.from_string(self.date_planned_finished)
|
||||
# 将 date 对象转换为 datetime 对象,设置时间为 00:00:00
|
||||
# date_obj = datetime.datetime.combine(date_obj, datetime.time.min)
|
||||
|
||||
# 计算两个日期之间的差值
|
||||
delta = date_obj - current_datetime
|
||||
|
||||
# 返回差值的小时数
|
||||
return int(delta.total_seconds() / 3600)
|
||||
else:
|
||||
return 0.0
|
||||
|
||||
@api.depends('name', 'production_id.name')
|
||||
def _compute_surface_technics_picking_ids(self):
|
||||
for workorder in self:
|
||||
|
||||
@@ -859,7 +859,7 @@ class ResProductMo(models.Model):
|
||||
item['model_width'] + model_type.embryo_tolerance) * (
|
||||
item['model_height'] + model_type.embryo_tolerance),
|
||||
'product_model_type_id': model_type.id,
|
||||
# 'model_processing_panel': 'R',
|
||||
'model_processing_panel': item['processing_panel_detail'],
|
||||
'model_machining_precision': item['model_machining_precision'],
|
||||
'model_code': item['barcode'],
|
||||
'length': item['model_long'],
|
||||
@@ -934,6 +934,7 @@ class ResProductMo(models.Model):
|
||||
# if surface_technology:
|
||||
# no_bom_copy_product_id.route_ids |= surface_technology
|
||||
no_bom_copy_product_id.product_tmpl_id.active = True
|
||||
logging.info('no_bom_copy_product_id[is_manual_processing]:%s' % no_bom_copy_product_id.is_manual_processing)
|
||||
materials_id = self.env['sf.production.materials'].search(
|
||||
[('materials_no', '=', item['texture_code'])])
|
||||
materials_type_id = self.env['sf.materials.model'].search(
|
||||
@@ -959,7 +960,7 @@ class ResProductMo(models.Model):
|
||||
'materials_type_id': materials_type_id.id,
|
||||
'single_manufacturing': product_id.single_manufacturing,
|
||||
'is_bfm': True,
|
||||
'active': True
|
||||
'active': True,
|
||||
}
|
||||
# 外协和采购生成的坯料需要根据材料型号绑定供应商
|
||||
if route_type == 'subcontract' or route_type == 'purchase':
|
||||
|
||||
@@ -294,10 +294,10 @@ class StockRule(models.Model):
|
||||
# 为同一个product_id创建一个生产订单名称列表
|
||||
product_id_to_production_names[product_id] = [production.name for production in all_production]
|
||||
for production_item in productions:
|
||||
production_programming = self.env['mrp.production'].search(
|
||||
[('product_id.id', '=', production_item.product_id.id),
|
||||
('origin', '=', production_item.origin)],
|
||||
limit=1, order='id asc')
|
||||
# production_programming = self.env['mrp.production'].search(
|
||||
# [('product_id.id', '=', production_item.product_id.id),
|
||||
# ('origin', '=', production_item.origin)],
|
||||
# limit=1, order='id asc')
|
||||
if production_item.product_id.id in product_id_to_production_names:
|
||||
# 同一个产品多个制造订单对应一个编程单和模型库
|
||||
# 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递
|
||||
@@ -455,6 +455,12 @@ class ProductionLot(models.Model):
|
||||
if product.categ_id.name == '刀具':
|
||||
return self.env['stock.lot'].get_tool_generate_lot_names1(company, product)
|
||||
else:
|
||||
# 对last_serial的name进行检测,如果不是以产品名称+数字的形式的就重新搜索
|
||||
if product.name.split('[')[0] not in last_serial.name:
|
||||
last_serial = self.env['stock.lot'].search(
|
||||
[('company_id', '=', company.id), ('product_id', '=', product.id),
|
||||
('name', 'ilike', product.name.split('[')[0])],
|
||||
limit=1, order='name desc')
|
||||
return self.env['stock.lot'].generate_lot_names1(product.name, last_serial.name, 2)[1]
|
||||
now = datetime.now().strftime("%Y%m%d")
|
||||
if product.cutting_tool_model_id:
|
||||
@@ -775,10 +781,11 @@ class ReStockMove(models.Model):
|
||||
self.next_serial = self._get_tool_next_serial(self.company_id, self.product_id, self.origin)
|
||||
else:
|
||||
self.next_serial = self.env['stock.lot']._get_next_serial(self.company_id, self.product_id)
|
||||
if self.picking_type_id.sequence_code == 'DL' and not self.move_line_nosuggest_ids:
|
||||
self.action_assign_serial_show_details()
|
||||
elif self.product_id.tracking == "lot":
|
||||
self._put_tool_lot(self.company_id, self.product_id, self.origin)
|
||||
if not self.move_line_nosuggest_ids:
|
||||
self._generate_serial_numbers()
|
||||
|
||||
|
||||
return {
|
||||
'name': _('Detailed Operations'),
|
||||
|
||||
Reference in New Issue
Block a user