Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化
This commit is contained in:
@@ -4,9 +4,9 @@
|
|||||||
<!-- <templates xml:space="preserve"> -->
|
<!-- <templates xml:space="preserve"> -->
|
||||||
|
|
||||||
<t t-name="og.web.ListRenderer" t-inherit="web.ListRenderer" t-inherit-mode="extension">
|
<t t-name="og.web.ListRenderer" t-inherit="web.ListRenderer" t-inherit-mode="extension">
|
||||||
<xpath expr="//table/thead/tr/th[@t-if='hasSelectors']" position="before">
|
<!-- <xpath expr="//table/thead/tr/th[@t-if='hasSelectors']" position="before">
|
||||||
<th class="row_no"><i class="fa fa-list-ol"/></th>
|
<th class="row_no"><i class="fa fa-list-ol"/></th>
|
||||||
</xpath>
|
</xpath> -->
|
||||||
</t>
|
</t>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -791,11 +791,11 @@ class MrpProduction(models.Model):
|
|||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
iot_code = self.env['stock.lot']._get_next_serial(self.company_id, self.product_id) or self.env[
|
iot_code = self.env['stock.lot']._get_next_serial(self.company_id, self.product_id) or self.env[
|
||||||
'ir.sequence'].next_by_code('stock.lot.serial')
|
'ir.sequence'].next_by_code('stock.lot.serial')
|
||||||
iot_code_name = re.sub('[\u4e00-\u9fa5]', "", iot_code)
|
# iot_code_name = re.sub('[\u4e00-\u9fa5]', "", iot_code)
|
||||||
self.lot_producing_id = self.env['stock.lot'].create({
|
self.lot_producing_id = self.env['stock.lot'].create({
|
||||||
'product_id': self.product_id.id,
|
'product_id': self.product_id.id,
|
||||||
'company_id': self.company_id.id,
|
'company_id': self.company_id.id,
|
||||||
'name': iot_code_name,
|
'name': iot_code,
|
||||||
})
|
})
|
||||||
if self.move_finished_ids.filtered(lambda m: m.product_id == self.product_id).move_line_ids:
|
if self.move_finished_ids.filtered(lambda m: m.product_id == self.product_id).move_line_ids:
|
||||||
self.move_finished_ids.filtered(
|
self.move_finished_ids.filtered(
|
||||||
|
|||||||
@@ -103,7 +103,11 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
record.back_button_display = True
|
record.back_button_display = True
|
||||||
else:
|
else:
|
||||||
record.back_button_display = False
|
record.back_button_display = False
|
||||||
if cur_workorder.is_subcontract or cur_workorder.name == '解除装夹':
|
# tag_type
|
||||||
|
if cur_workorder.is_subcontract or cur_workorder.name == '解除装夹' or any(
|
||||||
|
detection_result.processing_panel == cur_workorder.processing_panel and detection_result.routing_type == cur_workorder.routing_type and cur_workorder.tag_type !='重新加工'
|
||||||
|
for detection_result in cur_workorder.production_id.detection_result_ids
|
||||||
|
):
|
||||||
record.back_button_display = False
|
record.back_button_display = False
|
||||||
else:
|
else:
|
||||||
next_workorder = sorted_workorders[position + 1]
|
next_workorder = sorted_workorders[position + 1]
|
||||||
@@ -113,7 +117,10 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
record.back_button_display = True
|
record.back_button_display = True
|
||||||
else:
|
else:
|
||||||
record.back_button_display = False
|
record.back_button_display = False
|
||||||
if cur_workorder.is_subcontract or cur_workorder.name == '解除装夹':
|
if cur_workorder.is_subcontract or cur_workorder.name == '解除装夹' or any(
|
||||||
|
detection_result.processing_panel == cur_workorder.processing_panel and detection_result.routing_type == cur_workorder.routing_type and cur_workorder.tag_type !='重新加工'
|
||||||
|
for detection_result in cur_workorder.production_id.detection_result_ids
|
||||||
|
):
|
||||||
record.back_button_display = False
|
record.back_button_display = False
|
||||||
|
|
||||||
date_planned_start = fields.Datetime(tracking=True)
|
date_planned_start = fields.Datetime(tracking=True)
|
||||||
@@ -1513,7 +1520,8 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
# ('state', '!=', 'done')])
|
# ('state', '!=', 'done')])
|
||||||
# if raw_move:
|
# if raw_move:
|
||||||
# raw_move.write({'state': 'done'})
|
# raw_move.write({'state': 'done'})
|
||||||
record.production_id.button_mark_done1()
|
if record.production_id.state != 'rework':
|
||||||
|
record.production_id.button_mark_done1()
|
||||||
# record.production_id.state = 'done'
|
# record.production_id.state = 'done'
|
||||||
|
|
||||||
# ============工单完成,修改对应[质检单]的值=====================
|
# ============工单完成,修改对应[质检单]的值=====================
|
||||||
|
|||||||
@@ -455,7 +455,8 @@ class ProductionLot(models.Model):
|
|||||||
[('company_id', '=', company.id), ('product_id', '=', product.id), ('name', 'ilike', product.name)],
|
[('company_id', '=', company.id), ('product_id', '=', product.id), ('name', 'ilike', product.name)],
|
||||||
limit=1, order='name desc')
|
limit=1, order='name desc')
|
||||||
move_line_id = self.env['stock.move.line'].sudo().search(
|
move_line_id = self.env['stock.move.line'].sudo().search(
|
||||||
[('product_id', '=', product.id), ('lot_name', 'ilike', product.name)], limit=1, order='lot_name desc')
|
[('company_id', '=', company.id), ('product_id', '=', product.id), ('lot_name', 'ilike', product.name)],
|
||||||
|
limit=1, order='lot_name desc')
|
||||||
if last_serial or move_line_id:
|
if last_serial or move_line_id:
|
||||||
return self.env['stock.lot'].generate_lot_names1(product.name, last_serial.name if (
|
return self.env['stock.lot'].generate_lot_names1(product.name, last_serial.name if (
|
||||||
not move_line_id or
|
not move_line_id or
|
||||||
@@ -645,6 +646,16 @@ class StockPicking(models.Model):
|
|||||||
stock_picking = stock_picking_list.filtered(lambda p: p.state not in ("done", "cancel"))
|
stock_picking = stock_picking_list.filtered(lambda p: p.state not in ("done", "cancel"))
|
||||||
if sale_id and not stock_picking:
|
if sale_id and not stock_picking:
|
||||||
sale_id.write({'state': 'delivered'})
|
sale_id.write({'state': 'delivered'})
|
||||||
|
if self.location_dest_id.name == '成品存货区' and self.state == 'done':
|
||||||
|
for move in self.move_ids:
|
||||||
|
for production in self.sale_order_id.mrp_production_ids:
|
||||||
|
moves = self.env['stock.move'].search([
|
||||||
|
('name', '=', production.name),
|
||||||
|
('state', '!=', 'cancel')
|
||||||
|
])
|
||||||
|
finish_move = next((move for move in moves if move.location_dest_id.name == '制造后'), None)
|
||||||
|
if finish_move.id in move.move_orig_ids.ids and finish_move.state == 'done':
|
||||||
|
production.workorder_ids.write({'back_button_display': False})
|
||||||
return res
|
return res
|
||||||
|
|
||||||
# 创建 外协出库入单
|
# 创建 外协出库入单
|
||||||
@@ -713,20 +724,6 @@ class StockPicking(models.Model):
|
|||||||
'draft', 'sent']:
|
'draft', 'sent']:
|
||||||
picking.state = 'waiting'
|
picking.state = 'waiting'
|
||||||
|
|
||||||
# def write(self, vals):
|
|
||||||
#
|
|
||||||
# old_state = None
|
|
||||||
# if 'state' in vals:
|
|
||||||
# old_state = self.state
|
|
||||||
# res = super(StockPicking, self).write(vals)
|
|
||||||
# if (self.picking_type_id.use_existing_lots is False and self.picking_type_id.use_create_lots is True and
|
|
||||||
# (('move_ids_without_package' in vals and self.state == 'assigned')
|
|
||||||
# or ('state' in vals and vals['state'] == 'assigned' and old_state not in ['assigned', 'done']))):
|
|
||||||
# if self.move_ids_without_package:
|
|
||||||
# for move_id in self.move_ids_without_package:
|
|
||||||
# move_id.action_show_details()
|
|
||||||
# return res
|
|
||||||
|
|
||||||
@api.constrains('state', 'move_ids_without_package')
|
@api.constrains('state', 'move_ids_without_package')
|
||||||
def _check_move_ids_without_package(self):
|
def _check_move_ids_without_package(self):
|
||||||
"""
|
"""
|
||||||
@@ -913,8 +910,8 @@ class ReStockMove(models.Model):
|
|||||||
lot_code = '%s-%s-%s' % ('%s-T-DJWL-%s' % (
|
lot_code = '%s-%s-%s' % ('%s-T-DJWL-%s' % (
|
||||||
product.cutting_tool_model_id.code.split('-')[0], product.cutting_tool_material_id.code),
|
product.cutting_tool_model_id.code.split('-')[0], product.cutting_tool_material_id.code),
|
||||||
datetime.now().strftime("%Y%m%d"), origin)
|
datetime.now().strftime("%Y%m%d"), origin)
|
||||||
move_line_ids = self.env['stock.move.line'].sudo().search([('lot_name', 'like', lot_code)], limit=1,
|
move_line_ids = self.env['stock.move.line'].sudo().search(
|
||||||
order='id desc')
|
[('company_id', '=', company.id), ('lot_name', 'like', lot_code)], limit=1, order='id desc')
|
||||||
if not move_line_ids:
|
if not move_line_ids:
|
||||||
lot_code = '%s-001' % lot_code
|
lot_code = '%s-001' % lot_code
|
||||||
else:
|
else:
|
||||||
@@ -951,7 +948,8 @@ class ReStockMove(models.Model):
|
|||||||
[('company_id', '=', company.id), ('product_id', '=', product.id), ('name', 'ilike', origin)],
|
[('company_id', '=', company.id), ('product_id', '=', product.id), ('name', 'ilike', origin)],
|
||||||
limit=1, order='id DESC')
|
limit=1, order='id DESC')
|
||||||
move_line_id = self.env['stock.move.line'].sudo().search(
|
move_line_id = self.env['stock.move.line'].sudo().search(
|
||||||
[('product_id', '=', product.id), ('lot_name', 'ilike', origin)], limit=1, order='lot_name desc')
|
[('company_id', '=', company.id), ('product_id', '=', product.id), ('lot_name', 'ilike', origin)],
|
||||||
|
limit=1, order='lot_name desc')
|
||||||
split_codes = product.cutting_tool_model_id.code.split('-')
|
split_codes = product.cutting_tool_model_id.code.split('-')
|
||||||
if last_serial or move_line_id:
|
if last_serial or move_line_id:
|
||||||
return "%s-T-%s-%s-%03d" % (
|
return "%s-T-%s-%s-%03d" % (
|
||||||
@@ -1059,6 +1057,8 @@ class ReStockMove(models.Model):
|
|||||||
更新序列号 功能按钮
|
更新序列号 功能按钮
|
||||||
"""
|
"""
|
||||||
self.move_line_nosuggest_ids.unlink()
|
self.move_line_nosuggest_ids.unlink()
|
||||||
|
if self.state != 'assigned':
|
||||||
|
self.state = 'assigned'
|
||||||
return self.action_show_details()
|
return self.action_show_details()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -202,10 +202,11 @@
|
|||||||
attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked')]}"/>
|
attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked')]}"/>
|
||||||
<button name="do_inspect" type="object" string="送检" class="btn-success" confirm="是否确认送检"
|
<button name="do_inspect" type="object" string="送检" class="btn-success" confirm="是否确认送检"
|
||||||
attrs="{'invisible': ['|', '|', ('state', 'not in', ('progress')), ('is_inspect', '=', False), ('routing_type','=','CNC加工')]}"/>
|
attrs="{'invisible': ['|', '|', ('state', 'not in', ('progress')), ('is_inspect', '=', False), ('routing_type','=','CNC加工')]}"/>
|
||||||
|
<button name="do_inspect" type="object" string="送检" class="btn-success" confirm="是否确认送检"
|
||||||
<!-- <button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="停工" -->
|
attrs="{'invisible': ['|', '|', ('state', 'not in', ('progress')), ('is_inspect', '=', False), ('production_line_state','!=','已下产线')]}"/>
|
||||||
<!-- context="{'default_workcenter_id': workcenter_id}" class="btn-danger" -->
|
<!-- <button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="停工" -->
|
||||||
<!-- groups="sf_base.group_sf_mrp_user" -->
|
<!-- context="{'default_workcenter_id': workcenter_id}" class="btn-danger" -->
|
||||||
|
<!-- groups="sf_base.group_sf_mrp_user" -->
|
||||||
<!-- attrs="{'invisible': ['|', ('production_state', '!=', 'pending_processing'), ('state','!=','progress')]}"/> -->
|
<!-- attrs="{'invisible': ['|', ('production_state', '!=', 'pending_processing'), ('state','!=','progress')]}"/> -->
|
||||||
<!-- <button name="button_unblock" type="object" string="Unblock" -->
|
<!-- <button name="button_unblock" type="object" string="Unblock" -->
|
||||||
<!-- context="{'default_workcenter_id': workcenter_id}" class="btn-danger" -->
|
<!-- context="{'default_workcenter_id': workcenter_id}" class="btn-danger" -->
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
import logging
|
import logging
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
from odoo import models, api, fields, _
|
from odoo import models, api, fields, _
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
class ProductionTechnologyWizard(models.TransientModel):
|
class ProductionTechnologyWizard(models.TransientModel):
|
||||||
@@ -88,7 +89,10 @@ class ProductionTechnologyWizard(models.TransientModel):
|
|||||||
for item in productions:
|
for item in productions:
|
||||||
workorder = item.workorder_ids.filtered(lambda wo: wo.state not in ('cancel')).sorted(
|
workorder = item.workorder_ids.filtered(lambda wo: wo.state not in ('cancel')).sorted(
|
||||||
key=lambda a: a.sequence)
|
key=lambda a: a.sequence)
|
||||||
if workorder[0].state in ['pending']:
|
first_element = workorder[0] if workorder else None
|
||||||
if workorder[0].production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程':
|
if not first_element:
|
||||||
workorder[0].state = 'waiting'
|
raise UserError('工艺确认后,工单未生成,请检查配置')
|
||||||
|
if first_element.state in ['pending']:
|
||||||
|
if first_element.production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程':
|
||||||
|
first_element.state = 'waiting'
|
||||||
return productions
|
return productions
|
||||||
|
|||||||
@@ -262,7 +262,7 @@
|
|||||||
<field name="msgtype">markdown</field>
|
<field name="msgtype">markdown</field>
|
||||||
<field name="urgency">normal</field>
|
<field name="urgency">normal</field>
|
||||||
<field name="content">### {{picking_type_name}}待处理提醒:
|
<field name="content">### {{picking_type_name}}待处理提醒:
|
||||||
单号:{{name}}
|
单号:[{{name}}]({{request_url}})
|
||||||
事项:质量检查已完成</field>
|
事项:质量检查已完成</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ class SFMessageStockPicking(models.Model):
|
|||||||
all_ready_or_done = all(picking.state in ['assigned', 'done'] for picking in stock_picking_list)
|
all_ready_or_done = all(picking.state in ['assigned', 'done'] for picking in stock_picking_list)
|
||||||
if all_ready_or_done:
|
if all_ready_or_done:
|
||||||
mrp_production.add_queue('工序外协发料通知')
|
mrp_production.add_queue('工序外协发料通知')
|
||||||
if all(qc.quality_state in ['pass', 'fail'] for qc in record.quality_check_ids):
|
if record.quality_check_ids and all(
|
||||||
|
qc.quality_state in ['pass', 'fail'] for qc in record.quality_check_ids):
|
||||||
record.add_queue('调拨单质检完成提醒')
|
record.add_queue('调拨单质检完成提醒')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.info('add_queue_compute_state error:%s' % e)
|
logging.info('add_queue_compute_state error:%s' % e)
|
||||||
@@ -90,8 +91,14 @@ class SFMessageStockPicking(models.Model):
|
|||||||
contents.append(content)
|
contents.append(content)
|
||||||
elif message_queue_id.message_template_id.name == '调拨单质检完成提醒':
|
elif message_queue_id.message_template_id.name == '调拨单质检完成提醒':
|
||||||
content = message_queue_id.message_template_id.content
|
content = message_queue_id.message_template_id.content
|
||||||
content = content.replace('{{picking_type_name}}', self.picking_type_id.name).replace(
|
stock_picking_line = self.env['stock.picking'].sudo().search(
|
||||||
'{{name}}', self.name)
|
[('id', '=', int(message_queue_id.res_id))])
|
||||||
|
url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
|
||||||
|
action_id = self.env.ref('stock.action_picking_tree_ready').id
|
||||||
|
menu_id = self.env.ref('stock.menu_stock_root').id
|
||||||
|
url_with_id = f"{url}/web#view_type=form&action={action_id}&menu_id={menu_id}&id={stock_picking_line.id}"
|
||||||
|
content = content.replace('{{picking_type_name}}', stock_picking_line.picking_type_id.name).replace(
|
||||||
|
'{{name}}', stock_picking_line.name).replace('{{request_url}}', url_with_id)
|
||||||
contents.append(content)
|
contents.append(content)
|
||||||
return contents, message_queue_ids
|
return contents, message_queue_ids
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,14 @@ class QualityCheck(models.Model):
|
|||||||
operation_id = fields.Many2one('mrp.routing.workcenter', '作业', store=True, compute='_compute_operation_id')
|
operation_id = fields.Many2one('mrp.routing.workcenter', '作业', store=True, compute='_compute_operation_id')
|
||||||
is_inspect = fields.Boolean('需送检', related='point_id.is_inspect')
|
is_inspect = fields.Boolean('需送检', related='point_id.is_inspect')
|
||||||
|
|
||||||
|
lot_name = fields.Char('批次/序列号 名称', compute='_compute_lot_name', store=True)
|
||||||
|
|
||||||
|
@api.depends('move_line_id', 'move_line_id.lot_name')
|
||||||
|
def _compute_lot_name(self):
|
||||||
|
for qc in self:
|
||||||
|
if qc.move_line_id:
|
||||||
|
qc.lot_name = qc.move_line_id.lot_name
|
||||||
|
|
||||||
@api.depends('point_id.operation_id')
|
@api.depends('point_id.operation_id')
|
||||||
def _compute_operation_id(self):
|
def _compute_operation_id(self):
|
||||||
for qc in self:
|
for qc in self:
|
||||||
|
|||||||
@@ -127,6 +127,9 @@
|
|||||||
<xpath expr="//field[@name='order_line']/tree/field[@name='product_uom_qty']" position="replace">
|
<xpath expr="//field[@name='order_line']/tree/field[@name='product_uom_qty']" position="replace">
|
||||||
<field name="product_uom_qty" string="数量" widget="merge_field" optional="show" />
|
<field name="product_uom_qty" string="数量" widget="merge_field" optional="show" />
|
||||||
</xpath>
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='order_line']/tree/field[@name='product_uom'][2]" position="attributes">
|
||||||
|
<attribute name="optional">hide</attribute>
|
||||||
|
</xpath>
|
||||||
<xpath expr="//field[@name='order_line']/tree/field[@name='product_uom']" position="attributes">
|
<xpath expr="//field[@name='order_line']/tree/field[@name='product_uom']" position="attributes">
|
||||||
<attribute name="optional">hide</attribute>
|
<attribute name="optional">hide</attribute>
|
||||||
</xpath>
|
</xpath>
|
||||||
|
|||||||
Reference in New Issue
Block a user