Merge branch 'refs/heads/develop' into feature/tax_sync
This commit is contained in:
@@ -477,7 +477,7 @@ class Manufacturing_Connect(http.Controller):
|
||||
logging.info('LocationChange error:%s' % e)
|
||||
return json.JSONEncoder().encode(res)
|
||||
|
||||
@http.route('/AutoDeviceApi/AGVToProduct', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
|
||||
@http.route('/AutoDeviceApi/AGVToProduct', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
|
||||
cors="*")
|
||||
def AGVToProduct(self, **kw):
|
||||
"""
|
||||
@@ -549,7 +549,7 @@ class Manufacturing_Connect(http.Controller):
|
||||
logging.info('AGVToProduct error:%s' % e)
|
||||
return json.JSONEncoder().encode(res)
|
||||
|
||||
@http.route('/AutoDeviceApi/AGVDownProduct', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
|
||||
@http.route('/AutoDeviceApi/AGVDownProduct', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
|
||||
cors="*")
|
||||
def AGVDownProduct(self, **kw):
|
||||
"""
|
||||
@@ -668,7 +668,7 @@ class Manufacturing_Connect(http.Controller):
|
||||
logging.info('AGVDownProduct error:%s' % e)
|
||||
return json.JSONEncoder().encode(res)
|
||||
|
||||
@http.route('/AutoDeviceApi/AgvStationState', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
|
||||
@http.route('/AutoDeviceApi/AgvStationState', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
|
||||
cors="*")
|
||||
def AGVStationState(self, **kw):
|
||||
"""
|
||||
|
||||
@@ -664,7 +664,7 @@ class MrpProduction(models.Model):
|
||||
# 表面工艺工序
|
||||
# 模型类型的表面工艺工序模版
|
||||
surface_tmpl_ids = model_type_id.surface_technics_routing_tmpl_ids
|
||||
# 产品选择的表面工艺
|
||||
# 产品选择的表面工艺参数
|
||||
model_process_parameters_ids = rec.product_id.model_process_parameters_ids
|
||||
process_dict = {}
|
||||
if model_process_parameters_ids:
|
||||
@@ -673,7 +673,7 @@ class MrpProduction(models.Model):
|
||||
for surface_tmpl_id in surface_tmpl_ids:
|
||||
if process_id == surface_tmpl_id.route_workcenter_id.surface_technics_id:
|
||||
surface_tmpl_name = surface_tmpl_id.route_workcenter_id.name
|
||||
process_dict.update({int(process_id.category_id.code): '%s-%s' % (
|
||||
process_dict.update({int(process_id.sequence): '%s-%s' % (
|
||||
surface_tmpl_name, process_parameters_id.name)})
|
||||
process_list = sorted(process_dict.keys())
|
||||
for process_num in process_list:
|
||||
@@ -690,14 +690,16 @@ class MrpProduction(models.Model):
|
||||
raise ValidationError('该产品【加工面板】为空!')
|
||||
else:
|
||||
raise ValidationError('该产品没有选择【模版类型】!')
|
||||
|
||||
logging.info('sequence_list: %s' % sequence_list)
|
||||
for work in rec.workorder_ids:
|
||||
if sequence_list.get(work.name):
|
||||
work.sequence = sequence_list[work.name]
|
||||
work_name = work.name
|
||||
logging.info(work_name)
|
||||
if sequence_list.get(work_name):
|
||||
work.sequence = sequence_list[work_name]
|
||||
elif sequence_list.get(work.processing_panel):
|
||||
processing_panel = sequence_list.get(work.processing_panel)
|
||||
if processing_panel.get(work.name):
|
||||
work.sequence = processing_panel[work.name]
|
||||
if processing_panel.get(work_name):
|
||||
work.sequence = processing_panel[work_name]
|
||||
else:
|
||||
raise ValidationError('工序【%s】在产品选择的模版类型中不存在!' % work.name)
|
||||
else:
|
||||
@@ -723,8 +725,9 @@ class MrpProduction(models.Model):
|
||||
sequence_max += 1
|
||||
panel_sequence_list.update({tmpl_id.route_workcenter_id.name: sequence_max})
|
||||
for work_id in work_ids:
|
||||
if panel_sequence_list.get(work_id.name):
|
||||
work_id.sequence = panel_sequence_list[work_id.name]
|
||||
work_name = work_id.name
|
||||
if panel_sequence_list.get(work_name):
|
||||
work_id.sequence = panel_sequence_list[work_name]
|
||||
|
||||
# 创建工单并进行排序
|
||||
def _create_workorder(self, item):
|
||||
@@ -1031,8 +1034,8 @@ class MrpProduction(models.Model):
|
||||
[('origin', '=', sale_order.name), ('name', 'ilike', 'WH/OUT/')])
|
||||
move = out_picking.move_ids.filtered(lambda pd: pd.product_id == self.product_id)
|
||||
move_values = {'product_description_variants': '',
|
||||
'date_planned': datetime.now(),
|
||||
'date_deadline': datetime.now(),
|
||||
'date_planned': fields.Datetime.now(),
|
||||
'date_deadline': fields.Datetime.now(),
|
||||
'move_dest_ids': move,
|
||||
'group_id': move.group_id,
|
||||
'route_ids': [],
|
||||
@@ -1101,67 +1104,19 @@ class MrpProduction(models.Model):
|
||||
('is_subcontract', '=', True)])
|
||||
if scarp_process_parameter_workorder:
|
||||
production_programming = self.env['mrp.production'].search(
|
||||
[('programming_no', '=', self.programming_no)], order='name asc')
|
||||
[('programming_no', '=', self.programming_no), ('id', '!=', productions.id)], order='name asc')
|
||||
production_list = [production.name for production in production_programming]
|
||||
purchase_orders = self.env['purchase.order'].search([('origin', '=', ','.join(production_list))])
|
||||
purchase_orders = self.env['purchase.order'].search([('origin', 'ilike', ','.join(production_list))])
|
||||
for purchase_item in purchase_orders.order_line:
|
||||
for process_item in scarp_process_parameter_workorder:
|
||||
if purchase_item.product_id.categ_type == '表面工艺':
|
||||
if purchase_item.product_id.server_product_process_parameters_id == process_item.surface_technics_parameters_id:
|
||||
print(purchase_orders.find(productions.name))
|
||||
if purchase_orders.find(productions.name) == -1:
|
||||
purchase_orders.origin += productions.name
|
||||
print(purchase_orders.origin.find(productions.name))
|
||||
if purchase_orders.origin.find(productions.name) == -1:
|
||||
purchase_orders.origin += ',' + productions.name
|
||||
if item['is_reprogramming'] is False:
|
||||
productions._create_workorder(item)
|
||||
productions.programming_state = '已编程'
|
||||
for production_item in productions:
|
||||
process_parameter_workorder = self.env['mrp.workorder'].search(
|
||||
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', production_item.id),
|
||||
('is_subcontract', '=', True)])
|
||||
if process_parameter_workorder:
|
||||
is_pick = False
|
||||
consecutive_workorders = []
|
||||
m = 0
|
||||
sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.id)
|
||||
for i in range(len(sorted_workorders) - 1):
|
||||
if m == 0:
|
||||
is_pick = False
|
||||
if sorted_workorders[i].supplier_id.id == sorted_workorders[i + 1].supplier_id.id and \
|
||||
sorted_workorders[i].is_subcontract == sorted_workorders[i + 1].is_subcontract and \
|
||||
sorted_workorders[i].id == sorted_workorders[i + 1].id - 1:
|
||||
if sorted_workorders[i] not in consecutive_workorders:
|
||||
consecutive_workorders.append(sorted_workorders[i])
|
||||
consecutive_workorders.append(sorted_workorders[i + 1])
|
||||
m += 1
|
||||
continue
|
||||
else:
|
||||
if m == len(consecutive_workorders) - 1 and m != 0:
|
||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
|
||||
production_item)
|
||||
if sorted_workorders[i] in consecutive_workorders:
|
||||
is_pick = True
|
||||
consecutive_workorders = []
|
||||
m = 0
|
||||
# 当前面的连续工序生成对应的外协出入库单再生成当前工序的外协出入库单
|
||||
if is_pick is False:
|
||||
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i],
|
||||
production_item)
|
||||
if m == len(consecutive_workorders) - 1 and m != 0:
|
||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
|
||||
production_item)
|
||||
if sorted_workorders[i] in consecutive_workorders:
|
||||
is_pick = True
|
||||
consecutive_workorders = []
|
||||
m = 0
|
||||
if m == len(consecutive_workorders) - 1 and m != 0:
|
||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
|
||||
production_item)
|
||||
if is_pick is False and m == 0:
|
||||
if len(sorted_workorders) == 1:
|
||||
self.env['stock.picking'].create_outcontract_picking(sorted_workorders, production_item)
|
||||
else:
|
||||
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i],
|
||||
production_item)
|
||||
else:
|
||||
productions.programming_state = '编程中'
|
||||
return productions
|
||||
|
||||
@@ -58,6 +58,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
('cancel', '取消')], string='Status',
|
||||
compute='_compute_state', store=True,
|
||||
default='pending', copy=False, readonly=True, recursive=True, index=True, tracking=True)
|
||||
|
||||
# state = fields.Selection(selection_add=[('to be detected', "待检测"), ('rework', '返工')], tracking=True)
|
||||
|
||||
@api.depends('production_id.manual_quotation')
|
||||
@@ -183,17 +184,12 @@ class ResMrpWorkOrder(models.Model):
|
||||
if order.routing_type == '表面工艺':
|
||||
production_programming = self.env['mrp.production'].search(
|
||||
[('programming_no', '=', order.production_id.programming_no)], order='name asc')
|
||||
production_no_remanufacture = production_programming.filtered(lambda a: a.is_remanufacture is False)
|
||||
production_list = [production.name for production in production_programming]
|
||||
purchase = self.env['purchase.order'].search([('origin', '=', ','.join(production_list))])
|
||||
for line in purchase.order_line:
|
||||
if line.product_id.server_product_process_parameters_id == order.surface_technics_parameters_id and line.product_qty == len(
|
||||
production_programming):
|
||||
# server_product = self.env['product.template'].search(
|
||||
# [('server_product_process_parameters_id', '=', pp.id),
|
||||
# ('detailed_type', '=', 'service')])
|
||||
# purchase_order_line = self.env['purchase.order.line'].search(
|
||||
# [('product_id', '=', server_product.id), ('product_qty', '=', len(production_programming))])
|
||||
# if purchase_order_line:
|
||||
production_no_remanufacture):
|
||||
order.surface_technics_purchase_count = len(purchase)
|
||||
else:
|
||||
order.surface_technics_purchase_count = 0
|
||||
@@ -243,6 +239,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
store=True, compute='_compute_tool_state')
|
||||
tool_state_remark = fields.Text(string='功能刀具状态备注(缺刀)', compute='_compute_tool_state_remark', store=True)
|
||||
reserved_duration = fields.Float('预留时长', default=30, tracking=True)
|
||||
|
||||
@api.depends('cnc_ids.tool_state')
|
||||
def _compute_tool_state_remark(self):
|
||||
for item in self:
|
||||
@@ -651,7 +648,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
# 拼接工单对象属性值
|
||||
def json_workorder_str(self, k, production, route, item):
|
||||
# 计算预计时长duration_expected
|
||||
routing_types = ['切割', '装夹预调', 'CNC加工','解除装夹']
|
||||
routing_types = ['切割', '装夹预调', 'CNC加工', '解除装夹']
|
||||
if route.routing_type in routing_types:
|
||||
routing_workcenter = self.env['mrp.routing.workcenter'].sudo().search(
|
||||
[('name', '=', route.routing_type)])
|
||||
@@ -704,7 +701,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
item),
|
||||
# 'workpiece_delivery_ids': False if not route.routing_type == '装夹预调' else self._json_workpiece_delivery_list(
|
||||
# production)
|
||||
'reserved_duration': reserved_duration,
|
||||
'reserved_duration': reserved_duration,
|
||||
}]
|
||||
return workorders_values_str
|
||||
|
||||
@@ -969,12 +966,14 @@ class ResMrpWorkOrder(models.Model):
|
||||
else:
|
||||
production_programming = self.env['mrp.production'].search(
|
||||
[('programming_no', '=', self.production_id.programming_no)], order='name asc')
|
||||
production_no_remanufacture = production_programming.filtered(
|
||||
lambda a: a.is_remanufacture is False)
|
||||
production_list = [production.name for production in production_programming]
|
||||
purchase_orders = self.env['purchase.order'].search(
|
||||
[('origin', '=', ','.join(production_list))])
|
||||
[('origin', 'ilike', ','.join(production_list))])
|
||||
for line in purchase_orders.order_line:
|
||||
if line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id and line.product_qty == len(
|
||||
production_programming):
|
||||
production_no_remanufacture):
|
||||
if purchase_orders.state == 'purchase':
|
||||
workorder.state = 'ready'
|
||||
else:
|
||||
@@ -1169,8 +1168,9 @@ class ResMrpWorkOrder(models.Model):
|
||||
if record.routing_type == '装夹预调':
|
||||
if not record.rfid_code and record.is_rework is False:
|
||||
raise UserError("请扫RFID码进行绑定")
|
||||
if not record.material_center_point or record.X_deviation_angle <= 0:
|
||||
raise UserError("请对前置三元检测定位参数进行计算定位")
|
||||
if record.is_rework is False:
|
||||
if not record.material_center_point and record.X_deviation_angle > 0:
|
||||
raise UserError("坯料中心点为空或X偏差角度小于等于0")
|
||||
record.process_state = '待加工'
|
||||
# record.write({'process_state': '待加工'})
|
||||
record.production_id.process_state = '待加工'
|
||||
|
||||
@@ -288,28 +288,46 @@ 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')
|
||||
if production_item.product_id.id in product_id_to_production_names:
|
||||
if production_item.product_id.model_process_parameters_ids:
|
||||
is_purchase = False
|
||||
sorted_process_parameters = sorted(production_item.product_id.model_process_parameters_ids,
|
||||
key=lambda w: w.id)
|
||||
if not production_programming.programming_no:
|
||||
if production_item.product_id.model_process_parameters_ids:
|
||||
is_purchase = False
|
||||
sorted_process_parameters = sorted(production_item.product_id.model_process_parameters_ids,
|
||||
key=lambda w: w.id)
|
||||
|
||||
consecutive_process_parameters = []
|
||||
m = 0
|
||||
for i in range(len(sorted_process_parameters) - 1):
|
||||
if m == 0:
|
||||
is_purchase = False
|
||||
if self.env['product.template']._get_process_parameters_product(
|
||||
sorted_process_parameters[i]).partner_id == self.env[
|
||||
'product.template']._get_process_parameters_product(sorted_process_parameters[
|
||||
i + 1]).partner_id and \
|
||||
sorted_process_parameters[i].gain_way == '外协':
|
||||
if sorted_process_parameters[i] not in consecutive_process_parameters:
|
||||
consecutive_process_parameters.append(sorted_process_parameters[i])
|
||||
consecutive_process_parameters.append(sorted_process_parameters[i + 1])
|
||||
m += 1
|
||||
continue
|
||||
else:
|
||||
consecutive_process_parameters = []
|
||||
m = 0
|
||||
for i in range(len(sorted_process_parameters) - 1):
|
||||
if m == 0:
|
||||
is_purchase = False
|
||||
if self.env['product.template']._get_process_parameters_product(
|
||||
sorted_process_parameters[i]).partner_id == self.env[
|
||||
'product.template']._get_process_parameters_product(sorted_process_parameters[
|
||||
i + 1]).partner_id and \
|
||||
sorted_process_parameters[i].gain_way == '外协':
|
||||
if sorted_process_parameters[i] not in consecutive_process_parameters:
|
||||
consecutive_process_parameters.append(sorted_process_parameters[i])
|
||||
consecutive_process_parameters.append(sorted_process_parameters[i + 1])
|
||||
m += 1
|
||||
continue
|
||||
else:
|
||||
if m == len(consecutive_process_parameters) - 1 and m != 0:
|
||||
self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
|
||||
production_item,
|
||||
product_id_to_production_names)
|
||||
if sorted_process_parameters[i] in consecutive_process_parameters:
|
||||
is_purchase = True
|
||||
consecutive_process_parameters = []
|
||||
m = 0
|
||||
# 当前面的连续外协采购单生成再生成当前外协采购单
|
||||
if is_purchase is False:
|
||||
self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
|
||||
production_item,
|
||||
product_id_to_production_names)
|
||||
if m == len(consecutive_process_parameters) - 1 and m != 0:
|
||||
self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
|
||||
production_item,
|
||||
@@ -318,39 +336,22 @@ class StockRule(models.Model):
|
||||
is_purchase = True
|
||||
consecutive_process_parameters = []
|
||||
m = 0
|
||||
# 当前面的连续外协采购单生成再生成当前外协采购单
|
||||
if is_purchase is False:
|
||||
self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
|
||||
production_item,
|
||||
product_id_to_production_names)
|
||||
if m == len(consecutive_process_parameters) - 1 and m != 0:
|
||||
self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
|
||||
production_item,
|
||||
product_id_to_production_names)
|
||||
if sorted_process_parameters[i] in consecutive_process_parameters:
|
||||
is_purchase = True
|
||||
consecutive_process_parameters = []
|
||||
m = 0
|
||||
if m == len(consecutive_process_parameters) - 1 and m != 0:
|
||||
self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
|
||||
production_item,
|
||||
product_id_to_production_names)
|
||||
if is_purchase is False and m == 0:
|
||||
if len(sorted_process_parameters) == 1:
|
||||
self.env['purchase.order'].get_purchase_order(sorted_process_parameters,
|
||||
production_item,
|
||||
product_id_to_production_names)
|
||||
else:
|
||||
self.env['purchase.order'].get_purchase_order(sorted_process_parameters[i],
|
||||
if m == len(consecutive_process_parameters) - 1 and m != 0:
|
||||
self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
|
||||
production_item,
|
||||
product_id_to_production_names)
|
||||
if is_purchase is False and m == 0:
|
||||
if len(sorted_process_parameters) == 1:
|
||||
self.env['purchase.order'].get_purchase_order(sorted_process_parameters,
|
||||
production_item,
|
||||
product_id_to_production_names)
|
||||
else:
|
||||
self.env['purchase.order'].get_purchase_order(sorted_process_parameters[i],
|
||||
production_item,
|
||||
product_id_to_production_names)
|
||||
# # 同一个产品多个制造订单对应一个编程单和模型库
|
||||
# # 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递
|
||||
if not production_item.programming_no:
|
||||
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 not production_programming.programming_no:
|
||||
production_item.fetchCNC(
|
||||
', '.join(product_id_to_production_names[production_item.product_id.id]))
|
||||
@@ -440,7 +441,7 @@ class ProductionLot(models.Model):
|
||||
if product.tracking == "serial":
|
||||
last_serial = self.env['stock.lot'].search(
|
||||
[('company_id', '=', company.id), ('product_id', '=', product.id)],
|
||||
limit=1, order='id DESC')
|
||||
limit=1, order='name desc')
|
||||
if last_serial:
|
||||
if product.categ_id.name == '刀具':
|
||||
return self.env['stock.lot'].get_tool_generate_lot_names1(company, product)
|
||||
@@ -544,7 +545,7 @@ class StockPicking(models.Model):
|
||||
|
||||
# 设置外协出入单的名称
|
||||
def _get_name_Res(self, rescode):
|
||||
last_picking = self.sudo().search([('name', 'like', rescode)], order='create_date desc,id desc', limit=1)
|
||||
last_picking = self.sudo().search([('name', 'ilike', rescode)], order='create_date desc,id desc', limit=1)
|
||||
if not last_picking:
|
||||
num = "%04d" % 1
|
||||
else:
|
||||
|
||||
@@ -437,6 +437,12 @@
|
||||
<xpath expr="//header//button[@name='action_cancel']" position="replace">
|
||||
<button name="action_cancel" type="object" string="取消" groups="sf_base.group_sf_mrp_user"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='state']" position="replace">
|
||||
<field name="state" decoration-success="state in ('done', 'to_close')"
|
||||
decoration-warning="state == 'progress'" decoration-info="state == 'confirmed'"
|
||||
decoration-danger="state in ('cancel','rework','scrap')" decoration-muted="state == 'draft'"
|
||||
optional="show" widget="badge" class="text-dark"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='state']" position="after">
|
||||
<field name="tool_state" invisible="1"/>
|
||||
</xpath>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<field name="name" decoration-success="is_subcontract" decoration-bf="is_subcontract"/>
|
||||
</field>
|
||||
<field name="name" position="before">
|
||||
<field name="sequence"/>
|
||||
<field name="sequence" string="序号"/>
|
||||
<field name='user_permissions' invisible="1"/>
|
||||
</field>
|
||||
<field name="name" position="after">
|
||||
|
||||
Reference in New Issue
Block a user