判断外协工序是否连续有多个外协工序为同一个供应商(产品为表面工艺服务的供应商),
This commit is contained in:
@@ -119,6 +119,7 @@ class MrsProductionProcessParameter(models.Model):
|
|||||||
code = fields.Char("编码")
|
code = fields.Char("编码")
|
||||||
name = fields.Char('名称')
|
name = fields.Char('名称')
|
||||||
gain_way = fields.Selection([("自加工", "自加工"), ("外协", "外协")], default="", string="获取方式")
|
gain_way = fields.Selection([("自加工", "自加工"), ("外协", "外协")], default="", string="获取方式")
|
||||||
|
is_check = fields.Boolean(default=True)
|
||||||
# price = fields.Float('单价')
|
# price = fields.Float('单价')
|
||||||
process_id = fields.Many2one('sf.production.process', string='表面工艺')
|
process_id = fields.Many2one('sf.production.process', string='表面工艺')
|
||||||
materials_model_ids = fields.Many2many('sf.materials.model', 'applicable_material', string='适用材料')
|
materials_model_ids = fields.Many2many('sf.materials.model', 'applicable_material', string='适用材料')
|
||||||
@@ -127,7 +128,7 @@ class MrsProductionProcessParameter(models.Model):
|
|||||||
def name_get(self):
|
def name_get(self):
|
||||||
result = []
|
result = []
|
||||||
for parameter in self:
|
for parameter in self:
|
||||||
name = parameter.process_id.name + ',' + parameter.name
|
name = parameter.process_id.name + '-' + parameter.name
|
||||||
result.append((parameter.id, name))
|
result.append((parameter.id, name))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class ResProductTemplate(models.Model):
|
|||||||
# 模型的长,宽,高,体积,精度,材料
|
# 模型的长,宽,高,体积,精度,材料
|
||||||
model_name = fields.Char('模型名称')
|
model_name = fields.Char('模型名称')
|
||||||
categ_type = fields.Selection(
|
categ_type = fields.Selection(
|
||||||
[("成品", "成品"), ("胚料", "胚料"), ("原材料", "原材料"), ("表面工艺", "表面工艺"), ("服务", "服务")],
|
[("成品", "成品"), ("胚料", "胚料"), ("原材料", "原材料"), ("表面工艺", "表面工艺")],
|
||||||
string='产品的类别', related='categ_id.type',
|
string='产品的类别', related='categ_id.type',
|
||||||
store=True)
|
store=True)
|
||||||
model_long = fields.Float('模型长[mm]', digits=(16, 3))
|
model_long = fields.Float('模型长[mm]', digits=(16, 3))
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
attrs="{'invisible': [('categ_type', '=', '表面工艺')]}"/>
|
attrs="{'invisible': [('categ_type', '=', '表面工艺')]}"/>
|
||||||
<field name="server_product_process_parameters_id" string="表面工艺参数"
|
<field name="server_product_process_parameters_id" string="表面工艺参数"
|
||||||
options="{'no_create': True}"
|
options="{'no_create': True}"
|
||||||
attrs="{'invisible': ['|',('categ_type', '!=', '服务'),('categ_type', '=', False)]}"/>
|
attrs="{'invisible': ['|',('categ_type', '!=', '表面工艺'),('categ_type', '=', False)]}"/>
|
||||||
</field>
|
</field>
|
||||||
|
|
||||||
<xpath expr="//label[@for='volume']" position="before">
|
<xpath expr="//label[@for='volume']" position="before">
|
||||||
|
|||||||
@@ -149,6 +149,9 @@ class MrpProduction(models.Model):
|
|||||||
for param in production.product_id.model_process_parameters_ids:
|
for param in production.product_id.model_process_parameters_ids:
|
||||||
process_parameter = self.env['sf.production.process.parameter'].search(
|
process_parameter = self.env['sf.production.process.parameter'].search(
|
||||||
[('process_id.id', '=', pitem.id), ('id', '=', param.id)])
|
[('process_id.id', '=', pitem.id), ('id', '=', param.id)])
|
||||||
|
# 产品为表面工艺服务的供应商
|
||||||
|
product_production_process = self.env['product.template'].search(
|
||||||
|
[('server_product_process_parameters_id', '=', process_parameter.id)])
|
||||||
if process_parameter:
|
if process_parameter:
|
||||||
for ritem in route_workcenter_arr:
|
for ritem in route_workcenter_arr:
|
||||||
route_production_process = self.env['mrp.routing.workcenter'].search(
|
route_production_process = self.env['mrp.routing.workcenter'].search(
|
||||||
@@ -157,7 +160,8 @@ class MrpProduction(models.Model):
|
|||||||
workorders_values.append(
|
workorders_values.append(
|
||||||
self.env['mrp.workorder']._json_workorder_surface_process_str(
|
self.env['mrp.workorder']._json_workorder_surface_process_str(
|
||||||
production, route_production_process,
|
production, route_production_process,
|
||||||
process_parameter))
|
process_parameter,
|
||||||
|
product_production_process.seller_ids[0].id))
|
||||||
elif production.product_id.categ_id.type == '胚料':
|
elif production.product_id.categ_id.type == '胚料':
|
||||||
embryo_routing_workcenter = self.env['sf.embryo.model.type.routing.sort'].search(
|
embryo_routing_workcenter = self.env['sf.embryo.model.type.routing.sort'].search(
|
||||||
[('embryo_model_type_id', '=', production.product_id.embryo_model_type_id.id)],
|
[('embryo_model_type_id', '=', production.product_id.embryo_model_type_id.id)],
|
||||||
@@ -167,8 +171,23 @@ class MrpProduction(models.Model):
|
|||||||
workorders_values.append(
|
workorders_values.append(
|
||||||
self.env['mrp.workorder'].json_workorder_str('', production, route))
|
self.env['mrp.workorder'].json_workorder_str('', production, route))
|
||||||
production.workorder_ids = workorders_values
|
production.workorder_ids = workorders_values
|
||||||
|
process_parameter_workorder = self.env['mrp.workorder'].search(
|
||||||
|
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', 58)])
|
||||||
|
if process_parameter_workorder:
|
||||||
|
|
||||||
|
# for st in process_parameter_workorder:
|
||||||
|
consecutive_workorders = []
|
||||||
|
sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.id)
|
||||||
|
for i in range(len(sorted_workorders) - 1):
|
||||||
|
if sorted_workorders[i].supplier_id == sorted_workorders[i + 1].supplier_id and \
|
||||||
|
sorted_workorders[i].id == sorted_workorders[i + 1].id - 1:
|
||||||
|
consecutive_workorders.append(sorted_workorders[i])
|
||||||
|
consecutive_workorders.append(sorted_workorders[i + 1])
|
||||||
for workorder in production.workorder_ids:
|
for workorder in production.workorder_ids:
|
||||||
workorder.duration_expected = workorder._get_duration_expected()
|
workorder.duration_expected = workorder._get_duration_expected()
|
||||||
|
# 判断外协工序是否连续有多个外协工序为同一个供应商(产品为表面工艺服务的供应商),
|
||||||
|
# 如果有的话,则将连续的多个外协工序(ID),绑定同一张外协出入库单,单独的供应商工序则生成单独的外协出入库单
|
||||||
|
# 如果没有连续的外协工序为同一个供应商,则根据规则生成多张外协出入库单,并绑定不同的工序ID
|
||||||
|
|
||||||
# 在之前的销售单上重新生成制造订单
|
# 在之前的销售单上重新生成制造订单
|
||||||
def create_production1_values(self, production):
|
def create_production1_values(self, production):
|
||||||
|
|||||||
@@ -93,6 +93,9 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
glb_file = fields.Binary("glb模型文件")
|
glb_file = fields.Binary("glb模型文件")
|
||||||
is_subcontract = fields.Boolean(string='是否外协')
|
is_subcontract = fields.Boolean(string='是否外协')
|
||||||
surface_technics_parameters_id = fields.Many2one('sf.production.process.parameter', string="表面工艺可选参数")
|
surface_technics_parameters_id = fields.Many2one('sf.production.process.parameter', string="表面工艺可选参数")
|
||||||
|
stock_picking_in_ids = fields.One2many('stock.picking', 'workorder_in_id',string='库存外协入库单')
|
||||||
|
stock_picking_out_ids = fields.One2many('stock.picking', 'workorder_out_id', string='库存外协出库单')
|
||||||
|
supplier_id = fields.Integer('供应商Id')
|
||||||
|
|
||||||
# 计算配料中心点和与x轴倾斜度方法
|
# 计算配料中心点和与x轴倾斜度方法
|
||||||
def getcenter(self):
|
def getcenter(self):
|
||||||
@@ -160,7 +163,7 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
return workorders_values_str
|
return workorders_values_str
|
||||||
|
|
||||||
# 拼接工单对象属性值(表面工艺)
|
# 拼接工单对象属性值(表面工艺)
|
||||||
def _json_workorder_surface_process_str(self, production, route, process_parameter):
|
def _json_workorder_surface_process_str(self, production, route, process_parameter, supplier_id):
|
||||||
workorders_values_str = [0, '', {
|
workorders_values_str = [0, '', {
|
||||||
'product_uom_id': production.product_uom_id.id,
|
'product_uom_id': production.product_uom_id.id,
|
||||||
'qty_producing': 0,
|
'qty_producing': 0,
|
||||||
@@ -170,6 +173,7 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
'routing_type': '表面工艺',
|
'routing_type': '表面工艺',
|
||||||
'surface_technics_parameters_id': process_parameter.id,
|
'surface_technics_parameters_id': process_parameter.id,
|
||||||
'work_state': '',
|
'work_state': '',
|
||||||
|
'supplier_id': supplier_id,
|
||||||
'is_subcontract': True if process_parameter.gain_way == '外协' else False,
|
'is_subcontract': True if process_parameter.gain_way == '外协' else False,
|
||||||
'workcenter_id': self.env[
|
'workcenter_id': self.env[
|
||||||
'mrp.workcenter'].get_process_outsourcing_workcenter() if process_parameter.gain_way == '外协' else
|
'mrp.workcenter'].get_process_outsourcing_workcenter() if process_parameter.gain_way == '外协' else
|
||||||
@@ -494,7 +498,7 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
subcontract_workorder_count = self.env['mrp.workorder'].search_count(
|
subcontract_workorder_count = self.env['mrp.workorder'].search_count(
|
||||||
[('production_id', '=', workorder.production_id.id), ('is_subcontract', '=', True),
|
[('production_id', '=', workorder.production_id.id), ('is_subcontract', '=', True),
|
||||||
('state', '=', 'done')])
|
('state', '=', 'done')])
|
||||||
if len(finish_workorder_count) == len(subcontract_workorder_count):
|
if finish_workorder_count > 0 and subcontract_workorder_count > 0:
|
||||||
subcontract_workorder = self.env['mrp.workorder'].search(
|
subcontract_workorder = self.env['mrp.workorder'].search(
|
||||||
[('production_id', '=', workorder.production_id.id), ('is_subcontract', '=', True),
|
[('production_id', '=', workorder.production_id.id), ('is_subcontract', '=', True),
|
||||||
('state', '=', 'done')])
|
('state', '=', 'done')])
|
||||||
@@ -504,12 +508,12 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
[('server_product_process_parameters_id', '=', item.surface_technics_parameters_id.id),
|
[('server_product_process_parameters_id', '=', item.surface_technics_parameters_id.id),
|
||||||
('categ_type', '=', '服务'), ('detailed_type', '=', 'service')])
|
('categ_type', '=', '服务'), ('detailed_type', '=', 'service')])
|
||||||
order_line_ids.append((0, 0, {
|
order_line_ids.append((0, 0, {
|
||||||
'product_id': server_product.id,
|
'product_id': server_product.product_variant_id.id,
|
||||||
'product_qty': 1,
|
'product_qty': 1,
|
||||||
'product_uom': server_product.uom_id.id
|
'product_uom': server_product.uom_id.id
|
||||||
}))
|
}))
|
||||||
self.env['purchase.order'].create({
|
self.env['purchase.order'].create({
|
||||||
'partner_id': server_product.seller_ids[0].id,
|
'partner_id': server_product.seller_ids.partner_id.id,
|
||||||
'state': 'draft',
|
'state': 'draft',
|
||||||
'order_line': order_line_ids,
|
'order_line': order_line_ids,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ from collections import defaultdict, namedtuple
|
|||||||
from odoo.addons.stock.models.stock_rule import ProcurementException
|
from odoo.addons.stock.models.stock_rule import ProcurementException
|
||||||
from re import findall as regex_findall
|
from re import findall as regex_findall
|
||||||
from re import split as regex_split
|
from re import split as regex_split
|
||||||
from odoo import SUPERUSER_ID, _, api, models
|
from odoo import SUPERUSER_ID, _, api, fields,models
|
||||||
from odoo.tools import float_compare
|
from odoo.tools import float_compare
|
||||||
|
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
@@ -229,36 +230,29 @@ class ProductionLot(models.Model):
|
|||||||
return "%s-%03d" % (product.name, 1)
|
return "%s-%03d" % (product.name, 1)
|
||||||
|
|
||||||
|
|
||||||
|
class ResStockPicking(models.Model):
|
||||||
|
_inherit = 'stock.picking'
|
||||||
|
|
||||||
|
workorder_in_id = fields.Many2one('mrp.workorder')
|
||||||
|
workorder_out_id = fields.Many2one('mrp.workorder')
|
||||||
|
|
||||||
|
|
||||||
class ResPurchaseOrder(models.Model):
|
class ResPurchaseOrder(models.Model):
|
||||||
_inherit = 'purchase.order'
|
_inherit = 'purchase.order'
|
||||||
|
|
||||||
# def button_approve(self, force=False):
|
# 外协出库、入库单
|
||||||
# result = super().button_approve(force=force)
|
def _prepare_picking_outcontract(self, sequence_code):
|
||||||
# self._create_picking_RES()
|
# if not self.group_id:
|
||||||
# return result
|
# self.group_id = self.group_id.create({
|
||||||
|
# 'name': self.name,
|
||||||
|
# 'partner_id': self.partner_id.id
|
||||||
|
# })
|
||||||
|
# if not self.partner_id.property_stock_supplier.id:
|
||||||
|
# raise UserError(_("You must set a Vendor Location for this partner %s", self.partner_id.name))
|
||||||
|
|
||||||
# @api.depends('order_line.move_ids')
|
picking_type_id_oc = self.env['stock.picking.type'].search([('sequence_code', '=', sequence_code)])
|
||||||
# def _compute_subcontracting_resupply_picking_count(self):
|
|
||||||
# for purchase in self:
|
|
||||||
# purchase.subcontracting_resupply_picking_count = len(purchase._get_subcontracting_resupplies_new())
|
|
||||||
#
|
|
||||||
# def _get_subcontracting_resupplies_new(self):
|
|
||||||
# moves_subcontracted = self.order_line.move_ids.filtered(lambda m: m.is_subcontract)
|
|
||||||
# # subcontracted_productions = moves_subcontracted.move_orig_ids.production_id
|
|
||||||
# return moves_subcontracted.picking_id
|
|
||||||
|
|
||||||
def _prepare_picking_RES(self):
|
|
||||||
if not self.group_id:
|
|
||||||
self.group_id = self.group_id.create({
|
|
||||||
'name': self.name,
|
|
||||||
'partner_id': self.partner_id.id
|
|
||||||
})
|
|
||||||
if not self.partner_id.property_stock_supplier.id:
|
|
||||||
raise UserError(_("You must set a Vendor Location for this partner %s", self.partner_id.name))
|
|
||||||
picking_type_id_res = self.env['stock.picking.type'].search(
|
|
||||||
[('sequence_code', '=', 'RES'), ('barcode', '=', 'WH-RESUPPLY')])
|
|
||||||
return {
|
return {
|
||||||
'picking_type_id': picking_type_id_res.id if picking_type_id_res else self.picking_type_id.id,
|
'picking_type_id': picking_type_id_oc.id if picking_type_id_oc else self.picking_type_id.id,
|
||||||
'partner_id': self.partner_id.id,
|
'partner_id': self.partner_id.id,
|
||||||
'user_id': False,
|
'user_id': False,
|
||||||
'date': self.date_order,
|
'date': self.date_order,
|
||||||
@@ -268,17 +262,14 @@ class ResPurchaseOrder(models.Model):
|
|||||||
'company_id': self.company_id.id,
|
'company_id': self.company_id.id,
|
||||||
}
|
}
|
||||||
|
|
||||||
def _create_picking(self):
|
def _create_picking_outcontract(self):
|
||||||
StockPicking = self.env['stock.picking']
|
StockPicking = self.env['stock.picking']
|
||||||
for order in self.filtered(lambda po: po.state in ('purchase', 'done')):
|
for order in self.filtered(lambda po: po.state in ('purchase', 'done')):
|
||||||
if any(product.type in ['product', 'consu'] for product in order.order_line.product_id):
|
if any(product.type in ['product', 'consu'] for product in order.order_line.product_id):
|
||||||
order = order.with_company(order.company_id)
|
order = order.with_company(order.company_id)
|
||||||
pickings = order.picking_ids.filtered(lambda x: x.state not in ('done', 'cancel'))
|
pickings = order.picking_ids.filtered(lambda x: x.state not in ('done', 'cancel'))
|
||||||
if not pickings:
|
if not pickings:
|
||||||
if order.order_line.product_id.categ_type == '胚料':
|
res = order._prepare_picking_outcontract()
|
||||||
res = order._prepare_picking_RES()
|
|
||||||
else:
|
|
||||||
res = order._prepare_picking()
|
|
||||||
picking = StockPicking.with_user(SUPERUSER_ID).create(res)
|
picking = StockPicking.with_user(SUPERUSER_ID).create(res)
|
||||||
pickings = picking
|
pickings = picking
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
<field name="model">mrp.workorder</field>
|
<field name="model">mrp.workorder</field>
|
||||||
<field name="inherit_id" ref="mrp.mrp_production_workorder_tree_editable_view"/>
|
<field name="inherit_id" ref="mrp.mrp_production_workorder_tree_editable_view"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
|
<field name="name" position="replace">
|
||||||
|
<field name="is_subcontract" invisible="1"/>
|
||||||
|
<field name="name" decoration-success="is_subcontract" decoration-bf="is_subcontract"/>
|
||||||
|
</field>
|
||||||
<field name="name" position="before">
|
<field name="name" position="before">
|
||||||
<field name="sequence"/>
|
<field name="sequence"/>
|
||||||
<field name='user_permissions' invisible="1"/>
|
<field name='user_permissions' invisible="1"/>
|
||||||
@@ -113,8 +117,7 @@
|
|||||||
('is_user_working', '!=', False),('user_permissions','=',False),('name','=','获取CNC加工程序')]}"/>
|
('is_user_working', '!=', False),('user_permissions','=',False),('name','=','获取CNC加工程序')]}"/>
|
||||||
<button name="button_pending" type="object" string="暂停" class="btn-warning"
|
<button name="button_pending" type="object" string="暂停" class="btn-warning"
|
||||||
attrs="{'invisible': ['|', '|','|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False),('name','=','获取CNC加工程序')]}"/>
|
attrs="{'invisible': ['|', '|','|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False),('name','=','获取CNC加工程序')]}"/>
|
||||||
<button name="button_finish" type="object" string="完成" class="btn-success"
|
<button name="button_finish" type="object" string="完成" class="btn-success"/>
|
||||||
attrs="{'invisible': ['|', '|','|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False),('name','=','获取CNC加工程序')]}"/>
|
|
||||||
<button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="停工"
|
<button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="停工"
|
||||||
context="{'default_workcenter_id': workcenter_id}" class="btn-danger"
|
context="{'default_workcenter_id': workcenter_id}" class="btn-danger"
|
||||||
attrs="{'invisible': ['|', '|','|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'),('user_permissions','=',False),('name','=','获取CNC加工程序')]}"/>
|
attrs="{'invisible': ['|', '|','|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'),('user_permissions','=',False),('name','=','获取CNC加工程序')]}"/>
|
||||||
@@ -162,7 +165,7 @@
|
|||||||
<group>
|
<group>
|
||||||
<div class="col-12 col-lg-6 o_setting_box" style="white-space: nowrap">
|
<div class="col-12 col-lg-6 o_setting_box" style="white-space: nowrap">
|
||||||
<button type="object" class="oe_highlight" name="fetchCNC" string="获取CNC程序代码"
|
<button type="object" class="oe_highlight" name="fetchCNC" string="获取CNC程序代码"
|
||||||
attrs='{"invisible": ["|", "|", ("state","!=","progress"),("user_permissions","=",False),("programming_no","!=",False)]}'/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
|
|||||||
12
sf_manufacturing/views/stock_picking_view.xml
Normal file
12
sf_manufacturing/views/stock_picking_view.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<record model="ir.ui.view" id="view_picking_form_inherit_sf">
|
||||||
|
<field name="name">stock.picking.form.inherit.sf</field>
|
||||||
|
<field name="model">stock.picking</field>
|
||||||
|
<field name="inherit_id" ref="stock.view_picking_form"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
Reference in New Issue
Block a user