Merge branch develop into feature/1103_sf_machine_connect

This commit is contained in:
马广威
2022-11-08 15:03:55 +08:00
29 changed files with 1135 additions and 105 deletions

View File

@@ -10,13 +10,16 @@
""",
'category': 'YZ',
'website': 'https://www.sf.jikimo.com',
'depends': ['account', 'base', 'mrp'],
'depends': ['account', 'base', 'mrp', 'sale', 'sf_manufacturing_orders'],
'data': [
'security/group_security.xml',
'security/ir.model.access.csv',
'views/mrs_base_view.xml',
'views/mrs_common_view.xml',
"views/menu_view.xml"
"views/menu_view.xml",
'views/mrp_routing_workcenter_view.xml',
'views/sale_order_view.xml',
'views/product_template_view.xml',
],
'demo': [

View File

@@ -0,0 +1,52 @@
<!--<?xml version="1.0" encoding="UTF-8" ?>-->
<!--<odoo>-->
<!-- <data noupdate="0">-->
<!-- <record id="mrp_routing_workcenter_template_automatic_coding_sf" model="mrp.routing.workcenter">-->
<!-- <field name="name">获取自动编码程序</field>-->
<!-- <field name="code">automatic coding</field>-->
<!-- <field name="time_mode">manual</field>-->
<!-- <field name="time_cycle">60</field>-->
<!-- <field name="active">True</field>-->
<!-- </record>-->
<!-- <record id="mrp_routing_workcenter_template_clamping_sf" model="mrp.routing.workcenter">-->
<!-- <field name="name">装夹</field>-->
<!-- <field name="code">clamping</field>-->
<!-- <field name="time_mode">manual</field>-->
<!-- <field name="time_cycle">60</field>-->
<!-- <field name="active">True</field>-->
<!-- </record>-->
<!-- <record id="mrp_routing_workcenter_template_pre_ternary_sf" model="mrp.routing.workcenter">-->
<!-- <field name="name">前置三元定位检测</field>-->
<!-- <field name="code">pre-ternary</field>-->
<!-- <field name="time_mode">manual</field>-->
<!-- <field name="time_cycle">60</field>-->
<!-- <field name="active">True</field>-->
<!-- </record>-->
<!-- <record id="mrp_routing_workcenter_template_cnc_sf" model="mrp.routing.workcenter">-->
<!-- <field name="name">CNC加工</field>-->
<!-- <field name="code">CNC machining</field>-->
<!-- <field name="time_mode">manual</field>-->
<!-- <field name="time_cycle">60</field>-->
<!-- <field name="active">True</field>-->
<!-- </record>-->
<!-- <record id="mrp_routing_workcenter_template_post_ternary_sf" model="mrp.routing.workcenter">-->
<!-- <field name="name">后置三元质量检测</field>-->
<!-- <field name="code">post ternary</field>-->
<!-- <field name="time_mode">manual</field>-->
<!-- <field name="time_cycle">60</field>-->
<!-- <field name="active">True</field>-->
<!-- </record>-->
<!-- <record id="mrp_routing_workcenter_template_remove_clamping_sf" model="mrp.routing.workcenter">-->
<!-- <field name="name">解除装夹</field>-->
<!-- <field name="code">remove the clamping</field>-->
<!-- <field name="time_mode">manual</field>-->
<!-- <field name="time_cycle">60</field>-->
<!-- <field name="active">True</field>-->
<!-- </record>-->
<!-- </data>-->
<!--</odoo>-->

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
<record id="product_template_sf" model="product.product">
<field name="name">CNC加工产品模板</field>
<field name="categ_id" ref="product.product_category_5"/>
<field name="invoice_policy">delivery</field>
<field name="detailed_type">product</field>
<field name="purchase_ok">false</field>
<field name="uom_id" ref="uom.product_uom_unit"/>
<field name="uom_po_id" ref="uom.product_uom_unit"/>
<field name="company_id" ref="base.main_company"/>
<field name="active">false</field>
</record>
</data>
</odoo>

View File

@@ -1,2 +1,5 @@
from. import sf_base
from. import sf_common
from. import process
from. import product_template
from. import sale_order

71
sf_base/models/process.py Normal file
View File

@@ -0,0 +1,71 @@
from odoo import fields, models, api
class ModelType(models.Model):
_name = 'sf.model.type'
_description = '模型类型'
name = fields.Char('名称')
routing_tmpl_ids = fields.One2many('sf.model.type.routing.sort', 'model_type_id', '工序模板')
class ResMrpRoutingWorkcenter(models.Model):
_inherit = 'mrp.routing.workcenter'
routing_type = fields.Selection([
('获取CNC加工程序', '获取CNC加工程序'),
('装夹', '装夹'),
('前置三元定位检测', '前置三元定位检测'),
('CNC加工', 'CNC加工'),
('后置三元质量检测', '后置三元质量检测'),
('解除装夹', '解除装夹'),
], string="工序类型")
is_repeat = fields.Boolean('重复', default=False)
workcenter_id = fields.Many2one('mrp.workcenter', required=False)
workcenter_ids = fields.Many2many('mrp.workcenter', 'rel_workcenter_route', required=True)
bom_id = fields.Many2one('mrp.bom', required=False)
# 获得当前登陆者公司
def get_company_id(self):
self.company_id = self.env.user.company_id.id
company_id = fields.Many2one('res.company', compute="get_company_id", related=False)
# 工单对应的工作中心,根据工序中的工作中心去匹配,
# 如果只配置了一个工作中心,则默认采用该工作中心;
# 如果有多个工作中心,
# 则根据该工作中心的工单个数进行分配(优先分配给工单个数最少的);
def get_workcenter(self, workcenter_ids):
if workcenter_ids:
if len(workcenter_ids) == 1:
return workcenter_ids[0]
elif len(workcenter_ids) >= 2:
# workcenter_ids_str = ','.join([str(s) for s in workcenter_ids])
self.env.cr.execute("""
SELECT workcenter_id FROM mrp_workorder where workcenter_id
in %s group by workcenter_id
order by count(*),workcenter_id asc limit 1 """, [tuple(workcenter_ids)])
return self.env.cr.dictfetchall()[0].get('workcenter_id')
class ModelTypeRoutingSort(models.Model):
_name = 'sf.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([
('获取CNC加工程序', '获取CNC加工程序'),
('装夹', '装夹'),
('前置三元定位检测', '前置三元定位检测'),
('CNC加工', 'CNC加工'),
('后置三元质量检测', '后置三元质量检测'),
('解除装夹', '解除装夹'),
], string="工序类型", related='route_workcenter_id.routing_type')
workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids')
model_type_id = fields.Many2one('sf.model.type')
_sql_constraints = [
('route_model_type_uniq', 'unique (route_workcenter_id,model_type_id)', '工序不能重复!')
]

View File

@@ -0,0 +1,124 @@
from odoo import models, fields,api
from odoo.exceptions import ValidationError
class ResProductTemplate(models.Model):
_inherit = 'product.template'
# 模型的长,宽,高,体积,精度,材料
model_long = fields.Float('模型长[mm]', digits=(16, 3))
model_width = fields.Float('模型宽[mm]', digits=(16, 3))
model_height = fields.Float('模型高[mm]', digits=(16, 3))
model_volume = fields.Float('模型体积[mm³]', digits=(16, 3))
model_precision = fields.Float('精度要求', digits=(16, 3))
model_materials_id = fields.Many2one('mrs.production.materials', string='模型材料')
model_materials_type_id = fields.Many2one('mrs.materials.model', string='模型材料型号')
model_type_id = fields.Many2one('sf.model.type', string='模型类型')
processing_panel = fields.Char('模型加工面板')
# 胚料的长,宽,高
embryo_long = fields.Float('胚料长[mm]', digits=(16, 3), onchange='count_embryo_size')
embryo_width = fields.Float('胚料宽[mm]', digits=(16, 3), onchange='count_embryo_size')
embryo_height = fields.Float('胚料高[mm]', digits=(16, 3), onchange='count_embryo_size')
embryo_materials_id = fields.Many2one('mrs.production.materials', string='胚料材料')
embryo_materials_type_id = fields.Many2one('mrs.materials.model', string='胚料材料型号')
volume = fields.Float(compute='_compute_volume', store=True)
@api.depends('embryo_long', 'embryo_width', 'embryo_height')
def _compute_volume(self):
self.volume = self.embryo_long * self.embryo_width * self.embryo_height
# 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品
def product_create(self, product_id, item, order_id, order_number, i):
copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy()
copy_product_id.product_tmpl_id.active = True
vals = {
'name': '%s-%s' % (order_id.name, i),
'model_long': item['model_long'],
'model_width': item['model_width'],
'model_height': item['model_height'],
'model_volume': item['model_volume'],
'list_price': item['price'],
'model_materials_id': self.env['mrs.production.materials'].search(
[('materials_no', '=', item['texture_code'])]).id,
'model_materials_type_id': self.env['mrs.materials.model'].search(
[('materials_no', '=', item['texture_type_code'])]).id,
'default_code': '%s-%s' % (order_number, i),
'barcode': item['barcode'],
'active': True
}
copy_product_id.sudo().write(vals)
return copy_product_id
# 在产品上增加模型类型和加工的面例如A、B)
# 并根据模型类型计算出产品的胚料尺寸;
@api.onchange('model_type_id')
def count_embryo_size(self):
if not self.model_type_id:
return
bom = self.env['product.product'].search(
[('categ_id.is_embryo', '=', True), ('product_tmpl_id', '=', self.id)],
limit=1,
order='volume desc'
)
for item in self:
item.embryo_long = bom.embryo_long + 1
item.embryo_width = bom.embryo_width + 1
item.embryo_height = bom.embryo_height + 1
class ResProductCategory(models.Model):
_inherit = "product.category"
is_embryo = fields.Boolean('胚料')
class ResMrpBom(models.Model):
_inherit = 'mrp.bom'
# 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品后再次进行创建bom
def bom_create(self, product):
bom_id = self.env['mrp.bom'].create({
'product_tmpl_id': product.product_tmpl_id.id,
'type': 'normal',
'product_qty': 1,
'product_uom_id': 1
})
return bom_id
# 生成产品BOM匹配胚料胚料的匹配规则
# 一、匹配的胚料类别需要带有胚料的标签;
# 二、胚料的材料型号与生成产品的材料型号一致;
# 三、胚料的长宽高均要大于模型的长宽高;
# 四、如果匹配成功多个胚料,则选取体积最小的胚料;
def bom_create_Line(self, product):
embryo = self.env['product.product'].search(
[('categ_id.is_embryo', '=', True), ('embryo_materials_type_id', '=', product.model_materials_type_id.id),
('embryo_long', '>', product.model_long), ('embryo_width', '>', product.model_width),
('embryo_height', '>', product.model_height)
],
limit=1,
order='volume desc'
)
vals = {
'bom_id': self.id,
'product_id': embryo.id,
'product_tmpl_id': embryo.product_tmpl_id.id,
'product_qty': 1,
'product_uom_id': 1
}
return self.env['mrp.bom.line'].create(vals)

View File

@@ -0,0 +1,34 @@
from odoo import models, fields
from odoo.exceptions import ValidationError
import datetime
class ReSaleOrder(models.Model):
_inherit = 'sale.order'
deadline_of_delivery = fields.Date('交货截止日期')
# 业务平台分配工厂后在智能工厂先创建销售订单
def sale_order_create(self, deadline_of_delivery, company_id):
now_time = datetime.datetime.now()
order_id = self.env['sale.order'].sudo().create({
'company_id': company_id.id,
'date_order': now_time,
'name': self.env['ir.sequence'].next_by_code('sale.order', sequence_date=now_time),
'partner_id': 8,
'state': 'sale',
'user_id': 6,
'deadline_of_delivery': deadline_of_delivery
})
return order_id
# 业务平台分配工厂时在创建完产品后再创建销售明细信息
def sale_order_create_line(self, product, item):
vals = {
'order_id': self.id,
'product_id': product.id,
'name': '%s/%s/%s/%s/%s' % (item['model_long'], item['model_width'], item['model_height'], item['model_volume'], product.model_materials_id.name),
'price_unit': item['price'],
'product_uom_qty': item['number']
}
return self.env['sale.order.line'].create(vals)

View File

@@ -247,3 +247,20 @@ class CuttingToolType(models.Model):
brand_id = fields.Many2one('mrs.machine.brand', string='品牌')
remark = fields.Text('备注')
active = fields.Boolean('有效', default=True)
class CNCprocessing(models.Model):
_name = 'cnc.processing'
_description = "CNC加工"
FNo = fields.Char(string="序号")
FPGName = fields.Char(string="程序名")
FKnifeName = fields.Char(string="刀具名称")
FDNo = fields.Char(string="刀号")
FWorkType = fields.Char(string="加工类型")
FXY = fields.Char(string="余量_X/Y")
FZ = fields.Char(string="余量_Z")
FJGSD = fields.Char(string="加工深度(Z)")
FSCCD = fields.Char(string="刀具伸出长度")
FDJSpec = fields.Char(string="刀柄型号")
FJGDate = fields.Char(string="预计加工时间")
FComment = fields.Char(string="备注")

View File

@@ -72,9 +72,9 @@ class Tray(models.Model):
_name = 'sf.tray'
_description = '托盘'
code = fields.Char('编码')
code = fields.Char('编码',copy=False)
name = fields.Char('名称')
state = fields.Selection(
[("空闲", "空闲"), ("占用", "占用"), ("报损", "报损")],
default=" ", string="状态")
default="空闲", string="状态")
active = fields.Boolean('有效', default=True)

View File

@@ -13,6 +13,9 @@ access_mrs_production_materials,mrs_production_materials,model_mrs_production_ma
access_mrs_materials_model,mrs_materials_model,model_mrs_materials_model,base.group_user,1,1,1,1
access_mrs_processing_technology,mrs_processing_technology,model_mrs_processing_technology,base.group_user,1,1,1,1
access_sf_tray,sf_tray,model_sf_tray,base.group_user,1,1,1,1
access_cnc_processing,cnc_processing,model_cnc_processing,base.group_user,1,1,1,1
access_sf_model_type,sf_model_type,model_sf_model_type,base.group_user,1,1,1,1
access_sf_model_type_routing_sort,sf_model_type_routing_sort,model_sf_model_type_routing_sort,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
13 access_mrs_processing_technology mrs_processing_technology model_mrs_processing_technology base.group_user 1 1 1 1
14 access_sf_tray sf_tray model_sf_tray base.group_user 1 1 1 1
15 access_cnc_processing cnc_processing model_cnc_processing base.group_user 1 1 1 1
16 access_sf_model_type sf_model_type model_sf_model_type base.group_user 1 1 1 1
17 access_sf_model_type_routing_sort sf_model_type_routing_sort model_sf_model_type_routing_sort base.group_user 1 1 1 1
18
19
20
21

View File

@@ -142,13 +142,13 @@
action="action_mrs_machine_control_system"/>
<!-- <menuitem-->
<!-- id="menu_sf_partner_views"-->
<!-- name="工厂token"-->
<!-- parent="menu_mrs_base"-->
<!-- sequence="1"-->
<!-- action="token_factory_view"-->
<!-- />-->
<menuitem
id="menu_sf_model_type"
name="模型类型"
parent="mrp.menu_mrp_configuration"
sequence="10"
action="action_sf_model_type"
/>

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
#-----------------作业-------------------
<record model="ir.ui.view" id="view_mrp_routing_workcenter_form_inherit_sf">
<field name="name">mrp.routing.workcenter.form.inherit.sf</field>
<field name="model">mrp.routing.workcenter</field>
<field name="inherit_id" ref="mrp.mrp_routing_workcenter_form_view"/>
<field name="arch" type="xml">
<field name="workcenter_id" position="replace">
<field name="workcenter_ids" widget="many2many_tags" string="工作中心" required="0"/>
</field>
<field name="bom_product_template_attribute_value_ids" position="after">
<field name="routing_type" required="1"/>
<field name="is_repeat"/>
</field>
</field>
</record>
#-----------------工单-------------------
<record model="ir.ui.view" id="view_mrp_production_workorder_form_inherit_sf">
<field name="name">mrp.production.workorder.form.inherit.sf</field>
<field name="model">mrp.workorder</field>
<field name="inherit_id" ref="mrp.mrp_production_workorder_form_view_inherit"/>
<field name="arch" type="xml">
<field name="production_id" position="after">
<field name="processing_panel" readonly="1"/>
</field>
</field>
</record>
<!-- <record model="ir.ui.view" id="view_mrp_production_workorder_tree_inherit_sf">-->
<!-- <field name="name">mrp.production.workorder.tree.inherit.sf</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- <field name="inherit_id" ref="mrp.mrp_production_workorder_tree_view"/>-->
<!-- <field name="arch" type="xml">-->
<!-- <field name="workcenter_id" position="replace">-->
<!-- <filter name="workcenter_ids" string="工作中心" />-->
<!-- </field>-->
<!-- </field>-->
<!-- </record>-->
<!-- <record model="ir.ui.view" id="view_mrp_production_workorder_filter_inherit_sf">-->
<!-- <field name="name">mrp.production.workorder.filter.inherit.sf</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- <field name="inherit_id" ref="mrp.view_mrp_production_workorder_form_view_filter"/>-->
<!-- <field name="arch" type="xml">-->
<!-- <xpath expr="//filter[@name='work_center']" position="replace">-->
<!-- <filter name="work_center" string="工作中心" context="{'group_by': 'workcenter_ids'}"/>-->
<!-- </xpath>-->
<!-- </field>-->
<!-- </record>-->
#-----------------制造订单里的工单-------------------
<record model="ir.ui.view" id="view_mrp_production_workorder_tree_editable_inherit_sf">
<field name="name">mrp.production.workorder.tree.editable.inherit.sf</field>
<field name="model">mrp.workorder</field>
<field name="inherit_id" ref="mrp.mrp_production_workorder_tree_editable_view"/>
<field name="arch" type="xml">
<field name="name" position="after">
<field name="processing_panel"/>
</field>
</field>
</record>
</data>
</odoo>

View File

@@ -359,11 +359,11 @@
<field name="arch" type="xml">
<form string="机床">
<header>
<button type="object" class="oe_highlight" name ='enroll_machine_tool' string="机床注册" />
<button type="object" class="oe_highlight" name='enroll_machine_tool' string="机床注册"/>
</header>
<group string="基本信息">
<group>
<field name="MTcode" string="编码" />
<field name="MTcode" string="编码"/>
<field name="brand_id"
required="1"
@@ -372,7 +372,8 @@
</group>
<group>
<field name="name" required="1"/>
<field name="type_id" required="1" options="{'no_create': True}" domain="[('brand_id', '=', brand_id)]" attrs="{'invisible': [('brand_id','=',False)]}"/>
<field name="type_id" required="1" options="{'no_create': True}"
domain="[('brand_id', '=', brand_id)]" attrs="{'invisible': [('brand_id','=',False)]}"/>
</group>
<group>
@@ -499,4 +500,61 @@
</p>
</field>
</record>
#------------------模型类型------------------
<record model="ir.ui.view" id="search_sf_model_type_view">
<field name="name">search.sf.model.type</field>
<field name="model">sf.model.type</field>
<field name="arch" type="xml">
<search string="模型类型">
<field name="name" string="模糊搜索"
filter_domain="[('name', 'ilike', self)]"/>
</search>
</field>
</record>
<record model="ir.ui.view" id="tree_sf_model_type_view">
<field name="name">tree.sf.model.type</field>
<field name="model">sf.model.type</field>
<field name="arch" type="xml">
<tree string="模型类型">
<field name="name"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="form_sf_model_type">
<field name="name">form.sf.model.type</field>
<field name="model">sf.model.type</field>
<field name="arch" type="xml">
<form string="模型类型">
<group>
<field name="name" required="1"/>
</group>
<group>
<field name='routing_tmpl_ids'>
<tree editable='bottom'>
<field name="sequence" widget="handle"/>
<field name="route_workcenter_id" string="工序"/>
</tree>
</field>
</group>
</form>
</field>
</record>
<record id="action_sf_model_type" model="ir.actions.act_window">
<field name="name">模型类型</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sf.model.type</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
[模型类型] 还没有哦!点左上角的[创建]按钮,沙发归你了!
</p>
<p>
</p>
</field>
</record>
</odoo>

View File

@@ -277,6 +277,18 @@
</record>
#------------------托盘------------------
<record id="action_sf_tray" model="ir.actions.act_window">
<field name="name">托盘</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sf.tray</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
创建托盘吧
</p>
</field>
</record>
<record id="view_sf_tray_search" model="ir.ui.view">
<field name="name">sf.tray.search</field>
<field name="model">sf.tray</field>
@@ -309,11 +321,13 @@
<field name="name">sf.tray.form</field>
<field name="model">sf.tray</field>
<field name="arch" type="xml">
<header>
<field name='state' widget="radio" options="{'horizontal': True}"/>
</header>
<form string="托盘">
<group string="基本信息">
<group string="基本信息" name="group1">
<group>
<field name="code" required="1"/>
<field name="state" required="1"/>
</group>
<group>
<field name="name" required="1"/>
@@ -323,17 +337,6 @@
</field>
</record>
<record id="action_sf_tray" model="ir.actions.act_window">
<field name="name">托盘</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sf.tray</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
创建托盘吧
</p>
</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
<record model="ir.ui.view" id="view_product_template_form_inherit_sf">
<field name="name">product.template.form.inherit.sf</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_only_form_view"/>
<field name="arch" type="xml">
<xpath expr="//page[last()]" position="after">
<page string="加工参数">
<group>
<group string="模型">
<field name="model_long" string="长[mm]"/>
<field name="model_width" string="宽[mm]"/>
<field name="model_height" string="高[mm]"/>
<field name="model_volume" string="体积[mm]"/>
<field name="model_type_id" string="模板类型"/>
<field name="processing_panel" placeholder="例如A,B" string="加工面板"/>
<field name="model_precision" string="精度要求"/>
<field name="model_materials_id" string="材料"/>
<field name="model_materials_type_id" string="型号"
domain="[('materials_id', '=', model_materials_id)]"/>
</group>
<group string="胚料">
<field name="embryo_long" string="长[mm]"/>
<field name="embryo_width" string="宽[mm]"/>
<field name="embryo_height" string="高[mm]"/>
<field name="volume" string="体积[mm³]"/>
<field name="embryo_materials_id" string="材料"/>
<field name="embryo_materials_type_id" string="型号"
domain="[('materials_id', '=',embryo_materials_id)]"/>
</group>
</group>
</page>
</xpath>
</field>
</record>
<record id="view_product_category_form_inherit_sf" model="ir.ui.view">
<field name="name">product.category.form.inherit.sf</field>
<field name="model">product.category</field>
<field name="inherit_id" ref="product.product_category_form_view"/>
<field name="arch" type="xml">
<field name="parent_id" position="before">
<field name="is_embryo"/>
</field>
</field>
</record>
</data>
</odoo>

View File

@@ -12,9 +12,7 @@
'website': 'https://www.sf.cs.jikimo.com',
'depends': ['sale', 'sf_base'],
'data': [
'data/product_data.xml',
'views/product_template_view.xml',
'views/sale_order_view.xml'
],
'demo': [
],

View File

@@ -1,5 +1,3 @@
from . import sale_order
from . import product_template
from . import http
from . import models

View File

@@ -1,69 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
<record model="ir.ui.view" id="view_product_template_form_inherit_sf">
<field name="name">product.template.form.inherit.sf</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_only_form_view"/>
<field name="arch" type="xml">
<xpath expr="//page[last()]" position="after">
<page string="CNC加工">
<group string="模型">
<group>
<field name="model_long"/>
<field name="model_width"/>
<field name="model_height"/>
<field name="model_volume"/>
</group>
<group>
<field name="model_precision"/>
<field name="model_materials_id"/>
<field name="model_materials_type_id"/>
</group>
</group>
</page>
</xpath>
<xpath expr="//label[@for='volume']" position="before">
<label for="embryo_long" string="尺寸"
attrs="{'invisible':[('product_variant_count', '>', 1), ('is_product_variant', '=', False)]}"/>
<div class="o_address_format"
attrs="{'invisible':[('product_variant_count', '>', 1), ('is_product_variant', '=', False)]}">
<label for="embryo_long" string="长"/>
<field name="embryo_long" class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="embryo_width" string="宽"/>
<field name="embryo_width" class="o_address_zip"/>
<span>&amp;nbsp;</span>
<label for="embryo_height" string="高"/>
<field name="embryo_height" class="o_address_zip"/>
</div>
</xpath>
<xpath expr="//label[@for='produce_delay']" position="before">
<label for="embryo_materials_id"
attrs="{'invisible':[('product_variant_count', '>', 1), ('is_product_variant', '=', False)]}"/>
<div class="o_row"
attrs="{'invisible':[('product_variant_count', '>', 1), ('is_product_variant', '=', False)]}">
<field name="embryo_materials_id"/>
</div>
<label for="embryo_materials_type_id"
attrs="{'invisible':[('product_variant_count', '>', 1), ('is_product_variant', '=', False)]}"/>
<div class="o_row"
attrs="{'invisible':[('product_variant_count', '>', 1), ('is_product_variant', '=', False)]}">
<field name="embryo_materials_type_id" domain="[('materials_id', '=', embryo_materials_id)]"/>
</div>
</xpath>
</field>
</record>
<record id="view_product_category_form_inherit_sf" model="ir.ui.view">
<field name="name">product.category.form.inherit.sf</field>
<field name="model">product.category</field>
<field name="inherit_id" ref="product.product_category_form_view"/>
<field name="arch" type="xml">
<field name="parent_id" position="before">
<field name="is_embryo"/>
</field>
</field>
</record>
</data>
</odoo>

View File

@@ -1 +1,2 @@
from. import sf_production
from . import sf_production
from . import mrp_workorder

View File

@@ -0,0 +1,23 @@
from odoo import api, fields, models, SUPERUSER_ID, _
class ResWorkcenterProductivity(models.Model):
_inherit = 'mrp.workcenter.productivity'
workcenter_id = fields.Many2one('mrp.workcenter', required=False)
class ResMrpWorkOrder(models.Model):
_inherit = 'mrp.workorder'
workcenter_id = fields.Many2one('mrp.workcenter', required=False)
processing_panel = fields.Char('加工面')
routing_type = fields.Selection([
('获取CNC加工程序', '获取CNC加工程序'),
('装夹', '装夹'),
('前置三元定位检测', '前置三元定位检测'),
('CNC加工', 'CNC加工'),
('后置三元质量检测', '后置三元质量检测'),
('解除装夹', '解除装夹'),
], string="工序类型")

View File

@@ -29,10 +29,67 @@ class MrpProduction(models.Model):
_inherit = 'mrp.production'
_description = "制造订单"
# 重载根据工序生成工单的程序如果产品BOM中没有工序时
# 根据产品对应的模板类型中工序,去生成工单;
# CNC加工工序的选取规则
# 如果自动报价有带过来预分配的机床,
# 则根据设备找到工作中心;否则采用前面描述的工作中心分配机制;
# 其他规则限制: 默认只分配给工作中心状态为非故障的工作中心;
def _create_workorder(self):
for production in self:
if not production.bom_id or not production.product_id:
continue
workorders_values = []
product_qty = production.product_uom_id._compute_quantity(production.product_qty,
production.bom_id.product_uom_id)
exploded_boms, dummy = production.bom_id.explode(production.product_id,
product_qty / production.bom_id.product_qty,
picking_type=production.bom_id.picking_type_id)
for bom, bom_data in exploded_boms:
# If the operations of the parent BoM and phantom BoM are the same, don't recreate work orders.
if not (bom.operation_ids and (not bom_data['parent_line'] or bom_data[
'parent_line'].bom_id.operation_ids != bom.operation_ids)):
continue
for operation in bom.operation_ids:
if operation._skip_operation_line(bom_data['product']):
continue
workorders_values += [{
'name': operation.name,
'production_id': production.id,
'workcenter_id': operation.workcenter_id.id,
'product_uom_id': production.product_uom_id.id,
'operation_id': operation.id,
'state': 'pending',
}]
# 根据加工面板的面数及对应的工序模板生成工单
for k in (production.product_id.processing_panel.split(',')):
for route in production.product_id.model_type_id.routing_tmpl_ids:
if route:
workorders_values_str = [0, '', {
'product_uom_id': production.product_uom_id.id,
'qty_producing': 0,
'operation_id': False,
'name': route.route_workcenter_id.name,
'processing_panel': k,
'routing_type': route.routing_type,
'workcenter_id': self.env['mrp.routing.workcenter'].get_workcenter(route.workcenter_ids.ids),
'date_planned_start': False,
'date_planned_finished': False,
'duration_expected': 60,
'duration': 0
}]
workorders_values.append(workorders_values_str)
production.workorder_ids = workorders_values
for workorder in production.workorder_ids:
workorder.duration_expected = workorder._get_duration_expected()
class StockRule(models.Model):
_inherit = 'stock.rule'
@api.model
def _run_pull(self, procurements):
moves_values_by_company = defaultdict(list)
@@ -142,6 +199,7 @@ class StockRule(models.Model):
moves = self.env['stock.move'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(moves_values)
# Since action_confirm launch following procurement_group we should activate it.
moves._action_confirm()
return True
# @api.model
@@ -256,5 +314,3 @@ class StockRule(models.Model):
# mo_lists.append(vals)
#
# return mo_lists

View File

@@ -0,0 +1,3 @@
# -*-coding:utf-8-*-
from . import models
from . import report

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': '机企猫藏智能工厂 工序',
'version': '1.0',
'summary': '智能工厂工作中心工序',
'sequence': 1,
'description': """
在本模块,同步资源库
""",
'category': 'YZ',
'website': 'https://www.sf.cs.jikimo.com',
'depends': ['mrp', 'sf_base','hr_holidays'],
'data': [
'views/sf_tray_view.xml',
'views/sf_workorder.xml',
'report/sf_tray_report.xml'
],
'demo': [
],
'qweb': [
],
'installable': True,
'application': False,
'auto_install': False,
}

View File

@@ -0,0 +1,2 @@
# -*-coding:utf-8-*-
from . import workcenter

View File

@@ -0,0 +1,216 @@
# -*- coding: utf-8 -*-
# Part of SmartGo. See LICENSE file for full copyright and licensing details.
import base64
import logging
import math
from io import BytesIO
from odoo import api, fields, models
from pystrich.code128 import Code128Encoder
_logger = logging.getLogger(__name__)
class CNCprocessing(models.Model):
_inherit = 'cnc.processing'
_description = "CNC加工"
workorder_id = fields.Many2one('mrp.workorder', string="工单")
class Tray(models.Model):
_inherit = 'sf.tray'
_description = '托盘'
qr_image = fields.Binary(string="托盘二维码", compute='compute_qr_image')
production_id = fields.Many2one('mrp.production', string='制造订单',
related='workorder_id.production_id'
)
workorder_id = fields.Many2one('mrp.workorder', string="工单"
)
@api.onchange('production_id')
def updateTrayState(self):
if self.workorder_id != False:
self.state = '占用'
else:
self.state = '空闲'
def unclamp(self):
self.workorder_id = False
self.production_id = False
self.state = '空闲'
@api.depends('code')
def compute_qr_image(self):
for item in self:
if not item.code:
item.qr_image = False
continue
# 根据code动态生成二维码图片
# qr = qrcode.QRCode(
# version=1,
# error_correction=qrcode.constants.ERROR_CORRECT_L,
# box_size=10,
# border=4,
# )
# qr.add_data(item.code)
# qr.make(fit=True)
# img = qr.make_image()
# 生成条形码文件
# bar = barcode.get("ean13", "123456789102", writer=ImageWriter())
# a = bar.get_fullcode()
# b = bar.save('occ')
# 生成条形码图片
partner_encoder = Code128Encoder(item.code)
# 转换bytes流
temp = BytesIO()
partner_encoder.save(temp)
# img.save(temp, format='PNG')
qr_image = base64.b64encode(temp.getvalue())
item.qr_image = qr_image
'''
工单绑定托盘信息
'''
class MrpWorkOrder(models.Model):
_inherit = 'mrp.workorder'
_description = '工单'
cnc_id = fields.Many2many('ir.attachment', 'cnc_attachment', string="cnc程序获取")
tray_ids = fields.One2many('sf.tray', 'workorder_id', string='托盘')
# def get_tray_info(self):
# @api.onchange('X_axis', 'Y_axis', 'Z_axis')
# def get_center_point(self):
# return 'X:%s,Y:%s,Z:%s' % (self.X_axis, self.Y_axis, self.Z_axis)
# 加工面
# surface = fields.Selection([("前面", "前面"), ("后面", "后面"), ("左面", "左面"), ("右面", "右面"),
# ("上面", "上面")], string="加工面1")
material_center_point = fields.Char(string='配料中心点')
X1_axis = fields.Float(string='Lx1', default=0)
Y1_axis = fields.Float(string='Ly1', default=0)
Z1_axis = fields.Float(string='Lz1', default=0)
X2_axis = fields.Float(string='Lx2', default=0)
Y2_axis = fields.Float(string='Ly2', default=0)
Z2_axis = fields.Float(string='Lz2', default=0)
X3_axis = fields.Float(string='Fx3', default=0)
Y3_axis = fields.Float(string='Fy3', default=0)
Z3_axis = fields.Float(string='Fz3', default=0)
X4_axis = fields.Float(string='Fx4', default=0)
Y4_axis = fields.Float(string='Fy4', default=0)
Z4_axis = fields.Float(string='Fz4', default=0)
X5_axis = fields.Float(string='Rx5', default=0)
Y5_axis = fields.Float(string='Ry5', default=0)
Z5_axis = fields.Float(string='Rz5', default=0)
X6_axis = fields.Float(string='Rx6', default=0)
Y6_axis = fields.Float(string='Ry6', default=0)
Z6_axis = fields.Float(string='Rz6', default=0)
X7_axis = fields.Float(string='Bx7', default=0)
Y7_axis = fields.Float(string='By7', default=0)
Z7_axis = fields.Float(string='Bz7', default=0)
X8_axis = fields.Float(string='Bx8', default=0)
Y8_axis = fields.Float(string='By8', default=0)
Z8_axis = fields.Float(string='Bz8', default=0)
X9_axis = fields.Float(string='Uz9', default=0)
Y9_axis = fields.Float(string='Uz9', default=0)
Z9_axis = fields.Float(string='Uz9', default=0)
X10_axis = fields.Float(string='Uz10', default=0)
Y10_axis = fields.Float(string='Uz10', default=0)
Z10_axis = fields.Float(string='Uz10', default=0)
# 扫码绑定托盘方法
def gettray(self):
return ""
#解除托盘绑定
def unbindtray(self):
return ""
# 计算配料中心点和与x轴倾斜度方法
def getcenter(self):
x1 = self.X1_axis
x2 = self.X2_axis
x3 = self.X3_axis
x4 = self.X4_axis
x5 = self.X5_axis
x6 = self.X6_axis
x7 = self.X7_axis
x8 = self.X8_axis
y1 = self.Y1_axis
y2 = self.Y2_axis
y3 = self.Y3_axis
y4 = self.Y4_axis
y5 = self.Y5_axis
y6 = self.Y6_axis
y7 = self.Y7_axis
y8 = self.Y8_axis
z1 = self.Z9_axis
x0 = ((x3 - x4) * (x2 * y1 - x1 * y2) - (x1 - x2) * (x4 * y3 - x3 * y4)) / (
(x3 - x4) * (y1 - y2) - (x1 - x2) * (y3 - y4))
y0 = ((y3 - y4) * (y2 * x1 - y1 * x2) - (y1 - y2) * (y4 * x3 - y3 * x4)) / (
(y3 - y4) * (x1 - x2) - (y1 - y2) * (x3 - x4))
x1 = ((x7 - x8) * (x6 * y5 - x5 * y7) - (x5 - x6) * (x8 * y7 - x7 * y8)) / (
(x7 - x8) * (y5 - y6) - (x5 - x6) * (y7 - y8));
y1 = ((y7 - y8) * (y6 * x5 - y5 * x7) - (y5 - y6) * (y8 * x7 - y7 * x8)) / (
(y7 - y8) * (x5 - x6) - (y5 - y6) * (x7 - x8))
x = (x0 + x1) / 2
y = (y0 + y1) / 2
z = z1 / 2
jd = math.atan2((x7 - x8), (y7 - y8))
jdz = jd * 180 / math.pi
print("(%s,%s)" % (x, y))
self.material_center_point = ("(%s,%s,%s)" % (x, y, z))
self.X_deviation_angle = jdz
X_deviation_angle = fields.Integer(string="X轴偏差度", default=0)
test_results = fields.Selection([("合格", "合格"), ("返工", "返工"), ("报废", "报废")], string="检测结果")
cnc_ids = fields.One2many("cnc.processing", 'workorder_id', string="CNC加工")
# @api.depends('tray_id')
# def updateTrayState(self):
#
# for item in self:
# if item.tray_code == False:
# continue
# trayInfo = self.env['sf.tray'].sudo.search([('code', '=', item.tray_code)])
# if trayInfo:
# trayInfo.update(
# {
# 'production_id': item.production_id,
# 'state': "占用",
# }
# )
def recreateManufacturing(self):
return ""
def recreateWorkerOrder(self):
return ""
'''
制造订单绑定托盘信息
'''
class MrpProduction(models.Model):
_inherit = 'mrp.production'
_description = "制造订单"
tray_ids = fields.One2many('sf.tray', 'production_id', string="托盘")
class Attachment(models.Model):
_inherit = 'ir.attachment'
cnc_model = fields.Binary('cnc文件', attachment=False)
model_name = fields.Char('模型名称')

View File

@@ -0,0 +1,50 @@
<odoo>
<data>
<record id="sf_tray1" model="report.paperformat">
<field name="name">Dymo Label Sheet</field>
<field name="default" eval="True"/>
<field name="format">custom</field>
<field name="page_height">100</field>
<field name="page_width">60</field>
<field name="orientation">Landscape</field>
<field name="margin_top">0</field>
<field name="margin_bottom">0</field>
<field name="margin_left">0</field>
<field name="margin_right">0</field>
<field name="disable_shrinking" eval="True"/>
<field name="dpi">96</field>
</record>
<record id="label_sf_tray_code" model="ir.actions.report">
<field name="name">打印条形码</field>
<field name="model">sf.tray</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">sf_route_workcenter.sf_tray_template</field>
<field name="report_file">sf_route_workcenter.sf_tray_template</field>
<field name="binding_model_id" ref="model_sf_tray"/>
<field name="binding_type">report</field>
<field name="paperformat_id" ref="sf_route_workcenter.sf_tray1"/>
</record>
<template id="sf_tray_template">
<t t-call="web.html_container">
<t t-call="web.external_layout">
<t t-foreach="docs" t-as="o">
<div class="page">
<div t-field="o.code"
t-options="{'widget': 'barcode', 'width': 600, 'height': 100, 'img_style': 'width:350px;height:60px'}"/>
<div t-field="o.code" style="text-align: center"/>
</div>
</t>
</t>
</t>
</template>
</data>
</odoo>

View File

@@ -0,0 +1,30 @@
<odoo>
<data>
<record id="sf_tray_form_inherit" model="ir.ui.view">
<field name="name">托盘条形码生成</field>
<field name="model">sf.tray</field>
<field name="inherit_id" ref="sf_base.sf_tray_form"/>
<field name="arch" type="xml">
<xpath expr="//group[@name='group1']" position="after">
<notebook>
<page string="生成条形码">
<field name='qr_image' widget="image"/>
<group>
<field name='production_id' readonly="1"
attrs='{"invisible": [("production_id","=",False)]}'/>
<field name="workorder_id"/>
</group>
<div class="col
-12 col-lg-6 o_setting_box">
<button type="object" class="oe_highlight" name="unclamp" string="解除装夹"
attrs='{"invisible": [("state","=","空闲")]}'/>
</div>
</page>
</notebook>
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,196 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="sf_install_the_tray_workorder_form_view" model="ir.ui.view">
<field name="name">装夹工序工单</field>
<field name="model">mrp.workorder</field>
<field name="inherit_id" ref="mrp.mrp_production_workorder_form_view_inherit"/>
<field name="arch" type="xml">
<xpath expr="//page[last()]" position="after">
<page string="获取CNC加工程序" attrs='{"invisible": [("routing_type","!=","获取CNC加工程序")]}'>
<group>
<field name="cnc_id" widget="many2many_binary"/>
</group>
</page>
</xpath>
<xpath expr="//page[last()]" position="after" >
<page string="装夹托盘" attrs='{"invisible": [("routing_type","!=","装夹")]}'>
<group >
<field name="routing_type" invisible="1"/>
<field name="processing_panel" readonly = "1" />
<div class="col-12 col-lg-6 o_setting_box">
<button type="object" class="oe_highlight" name="gettray" string="扫描托盘"
attrs='{"invisible": [("production_id","=",False)]}'
/>
</div>
</group>
</page>
</xpath>
<xpath expr="//page[last()]" position="after">
<page string="三元前置检测定位参数" attrs='{"invisible": [("routing_type","!=","前置三元定位检测")]}'>
<group>
<group>
<field name="processing_panel" readonly = "1"/>
</group>
</group>
<group>
<div>左面:</div>
<div></div>
<div class="o_address_city">
<label for="X1_axis" string="Lx1"/>
<field name='X1_axis' class="o_address_city"/>
<label for="Y1_axis" string="Ly1"/>
<field name='Y1_axis' class="o_address_city"/>
<label for="Z1_axis" string="Lz1"/>
<field name='Z1_axis' class="o_address_city"/>
</div>
<div class="o_address_city">
<label for="X2_axis" string="Lx2"/>
<field name='X2_axis' class="o_address_city"/>
<label for="Y2_axis" string="Ly2"/>
<field name='Y2_axis' class="o_address_city"/>
<label for="Z2_axis" string="Lz2"/>
<field name='Z2_axis' class="o_address_city"/>
</div>
<div>前面:</div>
<div></div>
<div class="o_address_city">
<label for="X3_axis" string="Fx1"/>
<field name='X3_axis' class="o_address_city"/>
<label for="Y3_axis" string="Fy1"/>
<field name='Y3_axis' class="o_address_city"/>
<label for="Z3_axis" string="Fz1"/>
<field name='Z3_axis' class="o_address_city"/>
</div>
<div class="o_address_city">
<label for="X4_axis" string="Fx2"/>
<field name='X4_axis' class="o_address_city"/>
<label for="Y4_axis" string="Fy2"/>
<field name='Y4_axis' class="o_address_city"/>
<label for="Z4_axis" string="Fz2"/>
<field name='Z4_axis' class="o_address_city"/>
</div>
<div>右面:</div>
<div></div>
<div class="o_address_city">
<label for="X5_axis" string="Rx1"/>
<field name='X5_axis' class="o_address_city"/>
<label for="Y5_axis" string="Ry1"/>
<field name='Y5_axis' class="o_address_city"/>
<label for="Z5_axis" string="Rz1"/>
<field name='Z5_axis' class="o_address_city"/>
</div>
<div class="o_address_city">
<label for="X6_axis" string="Rx2"/>
<field name='X6_axis' class="o_address_city"/>
<label for="Y6_axis" string="Ry2"/>
<field name='Y6_axis' class="o_address_city"/>
<label for="Z6_axis" string="Rz2"/>
<field name='Z6_axis' class="o_address_city"/>
</div>
<div>下面:</div>
<div></div>
<div class="o_address_city">
<label for="X7_axis" string="Bx1"/>
<field name='X7_axis' class="o_address_city"/>
<label for="Y7_axis" string="By1"/>
<field name='Y7_axis' class="o_address_city"/>
<label for="Z7_axis" string="Bz1"/>
<field name='Z7_axis' class="o_address_city"/>
</div>
<div class="o_address_city">
<label for="X8_axis" string="Bx2"/>
<field name='X8_axis' class="o_address_city"/>
<label for="Y8_axis" string="By2"/>
<field name='Y8_axis' class="o_address_city"/>
<label for="Z8_axis" string="Bz2"/>
<field name='Z8_axis' class="o_address_city"/>
</div>
<div>上面:</div>
<div></div>
<div class="o_address_city">
<label for="X9_axis" string="Ux1"/>
<field name='X9_axis' class="o_address_city"/>
<label for="Y9_axis" string="Uy1"/>
<field name='Y9_axis' class="o_address_city"/>
<label for="Z9_axis" string="Uz1"/>
<field name='Z9_axis' class="o_address_city"/>
</div>
<div class="o_address_city">
<label for="X10_axis" string="Ux2"/>
<field name='X10_axis' class="o_address_city"/>
<label for="Y10_axis" string="Uy2"/>
<field name='Y10_axis' class="o_address_city"/>
<label for="Z10_axis" string="Uz2"/>
<field name='Z10_axis' class="o_address_city"/>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<button type="object" class="oe_highlight" name="getcenter" string="中心定位"
/>
</div>
</group>
<group>
<field name="material_center_point"/>
<field name='X_deviation_angle'/>
</group>
</page>
</xpath>
<xpath expr="//page[last()]" position="after">
<page string="CNC加工" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>
<group>
<field name="cnc_ids" widget="one2many"/>
</group>
</page>
</xpath>
<xpath expr="//page[last()]" position="after">
<page string="后置三元检测" attrs='{"invisible": [("routing_type","!=","后置三元质量检测")]}'>
<group>
<field name="test_results" widget="radio"/>
<div class="col-12 col-lg-6 o_setting_box">
<button type="object" class="oe_highlight" name="recreateWorkerOrder" string="重新生成工单"
attrs='{"invisible": [("test_results","!=","返工")]}'
/>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<button type="object" class="oe_highlight" name="recreateManufacturing" string="重新生成制造订单"
attrs='{"invisible": [("test_results","!=","报废")]}'
/>
</div>
</group>
</page>
</xpath>
<xpath expr="//page[last()]" position="after">
<page string="解除装夹" attrs='{"invisible": [("routing_type","!=","解除装夹")]}' >
<div class="col-12 col-lg-6 o_setting_box">
<button type="object" class="oe_highlight" name="unbindtray" string="解除装夹"
/>
</div>
</page>
</xpath>
</field>
</record>
</data>
</odoo>