开发sf制造模块权限角色

This commit is contained in:
qihao.gong@jikimo.com
2023-11-21 17:42:36 +08:00
parent 580f95f338
commit e6bb5db0e1
13 changed files with 162 additions and 52 deletions

View File

@@ -1 +1 @@
from. import common from . import common

View File

@@ -8,7 +8,7 @@ class Common(models.Model):
_name = 'sf.sync.common' _name = 'sf.sync.common'
_description = u'公用类' _description = u'公用类'
def get_headers(self,token, secret_key): def get_headers(self, token, secret_key):
''' '''
获取requests中的heardes参数 获取requests中的heardes参数
''' '''
@@ -19,5 +19,3 @@ class Common(models.Model):
'TIMESTAMP': str(timestamp), 'TIMESTAMP': str(timestamp),
'checkstr': check_sf_str} 'checkstr': check_sf_str}
return headers return headers

View File

@@ -1,4 +1,37 @@
<odoo> <odoo>
<data> <data>
<record id="group_sf_mrp_user" model="res.groups">
<field name="name">制造普通用户</field>
<field name="category_id" ref="base.module_category_manufacturing_manufacturing"/>
</record>
<record id="group_sf_mrp_manager" model="res.groups">
<field name="name">制造管理用户</field>
<field name="implied_ids" eval="[(4, ref('group_sf_mrp_user'))]"/>
<field name="category_id" ref="base.module_category_manufacturing_manufacturing"/>
<field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
</record>
<record id="group_sf_equipment_user" model="res.groups">
<field name="name">机床操作岗</field>
<field name="implied_ids" eval="[(4, ref('group_sf_mrp_user'))]"/>
<field name="category_id" ref="base.module_category_manufacturing_manufacturing"/>
</record>
<record id="group_sf_tool_user" model="res.groups">
<field name="name">刀具组装岗</field>
<field name="implied_ids" eval="[(4, ref('group_sf_mrp_user'))]"/>
<field name="category_id" ref="base.module_category_manufacturing_manufacturing"/>
</record>
<record id="group_sf_order_user" model="res.groups">
<field name="name">工件装夹岗</field>
<field name="implied_ids" eval="[(4, ref('group_sf_mrp_user'))]"/>
<field name="category_id" ref="base.module_category_manufacturing_manufacturing"/>
</record>
<record id="group_sf_mrp_manager" model="res.groups">
<field name="name">生产总监</field>
<field name="implied_ids" eval="[(4, ref('group_sf_mrp_manager'))]"/>
<field name="category_id" ref="base.module_category_manufacturing_manufacturing"/>
</record>
</data> </data>
</odoo> </odoo>

View File

@@ -12,7 +12,8 @@ class SfMaintenanceEquipmentCategory(models.Model):
_inherit = 'maintenance.equipment.category' _inherit = 'maintenance.equipment.category'
_description = '设备类别' _description = '设备类别'
equipment_type = fields.Selection([('机床', '机床'), ('机器人', '机器人'), ('AGV小车', 'AGV小车'), ('检测设备', '检测设备')], string='类型', default='机床') equipment_type = fields.Selection([('机床', '机床'), ('机器人', '机器人'), ('AGV小车', 'AGV小车'), ('检测设备', '检测设备')]
, string='类型', default='机床')
class SfMaintenanceEquipment(models.Model): class SfMaintenanceEquipment(models.Model):
@@ -64,7 +65,8 @@ class SfMaintenanceEquipment(models.Model):
MTcode = fields.Char("编码", default=get_no) MTcode = fields.Char("编码", default=get_no)
created_user = fields.Many2one('res.users', string='创建人', default=lambda self: self.env.user) created_user = fields.Many2one('res.users', string='创建人', default=lambda self: self.env.user)
equipment_type = fields.Selection([('机床', '机床'), ('机器人', '机器人'), ('AGV小车', 'AGV小车'), ('检测设备', '检测设备')], compute='_compute_category_id') equipment_type = fields.Selection([('机床', '机床'), ('机器人', '机器人'), ('AGV小车', 'AGV小车'), ('检测设备', '检测设备')]
, compute='_compute_category_id')
@api.depends('category_id') @api.depends('category_id')
def _compute_category_id(self): def _compute_category_id(self):
@@ -278,7 +280,8 @@ class SfMaintenanceEquipment(models.Model):
detect_y_axis = fields.Char('检测Y轴') detect_y_axis = fields.Char('检测Y轴')
detect_z_axis = fields.Char('检测Z轴') detect_z_axis = fields.Char('检测Z轴')
detect_precision = fields.Char('测量精度') detect_precision = fields.Char('测量精度')
detect_measurement_mode = fields.Selection([('光栅尺', '光栅尺'), ('容栅', '容栅'), ('磁栅', '磁栅'), ('激光干涉仪', '激光干涉仪')], string='测量方式') detect_measurement_mode = fields.Selection([('光栅尺', '光栅尺'), ('容栅', '容栅'), ('磁栅', '磁栅'),
('激光干涉仪', '激光干涉仪')], string='测量方式')
detect_resolution = fields.Char('分辨率') detect_resolution = fields.Char('分辨率')
detect_load_weight_max = fields.Char('最大负载重量') detect_load_weight_max = fields.Char('最大负载重量')
detect_weight = fields.Char('本体总重量') detect_weight = fields.Char('本体总重量')
@@ -304,13 +307,15 @@ class SfMaintenanceEquipment(models.Model):
robot_load_weight_max = fields.Char('最大负载重量') robot_load_weight_max = fields.Char('最大负载重量')
robot_weight = fields.Char('本体总重量') robot_weight = fields.Char('本体总重量')
robot_repeatable_positioning_accuracy = fields.Char('重复定位精度') robot_repeatable_positioning_accuracy = fields.Char('重复定位精度')
robot_axis_num = fields.Selection([('2轴', '2轴'), ('3轴', '3轴'), ('4轴', '4轴'), ('5轴', '5轴'), ('6轴', '6轴'), ('7轴', '7轴'), ('8轴', '8轴')], string='轴数') robot_axis_num = fields.Selection([('2轴', '2轴'), ('3轴', '3轴'), ('4轴', '4轴'), ('5轴', '5轴'), ('6轴', '6轴'),
('7轴', '7轴'), ('8轴', '8轴')], string='轴数')
axis_ids = fields.One2many('sf.robot.axis.num', 'equipment_id', string='动作范围') axis_ids = fields.One2many('sf.robot.axis.num', 'equipment_id', string='动作范围')
robot_track_dimensions_L = fields.Char('轨道尺寸(长)') robot_track_dimensions_L = fields.Char('轨道尺寸(长)')
robot_track_dimensions_W = fields.Char('轨道尺寸(宽)') robot_track_dimensions_W = fields.Char('轨道尺寸(宽)')
robot_track_dimensions_H = fields.Char('轨道尺寸(高)') robot_track_dimensions_H = fields.Char('轨道尺寸(高)')
robot_drive_mode = fields.Char('驱动方式') robot_drive_mode = fields.Char('驱动方式')
robot_installation_method = fields.Selection([('置地式', '置地式'), ('壁挂式', '壁挂式'), ('倒挂式', '倒挂式')], string='安装方式') robot_installation_method = fields.Selection([('置地式', '置地式'), ('壁挂式', '壁挂式'), ('倒挂式', '倒挂式')],
string='安装方式')
robot_operating_temperature = fields.Char('机器人环境温度') robot_operating_temperature = fields.Char('机器人环境温度')
robot_operating_humidity = fields.Char('机器人环境湿度') robot_operating_humidity = fields.Char('机器人环境湿度')
@@ -433,7 +438,8 @@ class SfMaintenanceEquipment(models.Model):
if next_maintenance_todo and last_maintenance_done: if next_maintenance_todo and last_maintenance_done:
next_date = next_maintenance_todo.request_date next_date = next_maintenance_todo.request_date
date_gap = next_maintenance_todo.request_date - last_maintenance_done.close_date date_gap = next_maintenance_todo.request_date - last_maintenance_done.close_date
# If the gap between the last_maintenance_done and the next_maintenance_todo one is bigger than 2 times the period and next request is in the future # If the gap between the last_maintenance_done and the next_maintenance_todo one is bigger than
# 2 times the period and next request is in the future
# We use 2 times the period to avoid creation too closed request from a manually one created # We use 2 times the period to avoid creation too closed request from a manually one created
if date_gap > timedelta(0) and date_gap > timedelta( if date_gap > timedelta(0) and date_gap > timedelta(
days=equipment.period) * 2 and next_maintenance_todo.request_date > date_now: days=equipment.period) * 2 and next_maintenance_todo.request_date > date_now:
@@ -445,7 +451,8 @@ class SfMaintenanceEquipment(models.Model):
elif next_maintenance_todo: elif next_maintenance_todo:
next_date = next_maintenance_todo.request_date next_date = next_maintenance_todo.request_date
date_gap = next_maintenance_todo.request_date - date_now date_gap = next_maintenance_todo.request_date - date_now
# If next maintenance to do is in the future, and in more than 2 times the period, we insert an new request # If next maintenance to do is in the future, and in more than 2 times the period, we insert
# an new request
# We use 2 times the period to avoid creation too closed request from a manually one created # We use 2 times the period to avoid creation too closed request from a manually one created
if date_gap > timedelta(0) and date_gap > timedelta(days=equipment.period) * 2: if date_gap > timedelta(0) and date_gap > timedelta(days=equipment.period) * 2:
next_date = date_now + timedelta(days=equipment.period) next_date = date_now + timedelta(days=equipment.period)
@@ -475,7 +482,8 @@ class SfMaintenanceEquipment(models.Model):
if next_maintenance_todo and last_maintenance_done: if next_maintenance_todo and last_maintenance_done:
next_date = next_maintenance_todo.request_date next_date = next_maintenance_todo.request_date
date_gap = next_maintenance_todo.request_date - last_maintenance_done.close_date date_gap = next_maintenance_todo.request_date - last_maintenance_done.close_date
# If the gap between the last_maintenance_done and the next_maintenance_todo one is bigger than 2 times the period and next request is in the future # If the gap between the last_maintenance_done and the next_maintenance_todo one is bigger than 2
# times the period and next request is in the future
# We use 2 times the period to avoid creation too closed request from a manually one created # We use 2 times the period to avoid creation too closed request from a manually one created
if date_gap > timedelta(0) and date_gap > timedelta( if date_gap > timedelta(0) and date_gap > timedelta(
days=equipment.overhaul_period) * 2 and next_maintenance_todo.request_date > date_now: days=equipment.overhaul_period) * 2 and next_maintenance_todo.request_date > date_now:
@@ -487,7 +495,8 @@ class SfMaintenanceEquipment(models.Model):
elif next_maintenance_todo: elif next_maintenance_todo:
next_date = next_maintenance_todo.request_date next_date = next_maintenance_todo.request_date
date_gap = next_maintenance_todo.request_date - date_now date_gap = next_maintenance_todo.request_date - date_now
# If next maintenance to do is in the future, and in more than 2 times the period, we insert an new request # If next maintenance to do is in the future, and in more than 2 times the period, we insert
# an new request
# We use 2 times the period to avoid creation too closed request from a manually one created # We use 2 times the period to avoid creation too closed request from a manually one created
if date_gap > timedelta(0) and date_gap > timedelta(days=equipment.overhaul_period) * 2: if date_gap > timedelta(0) and date_gap > timedelta(days=equipment.overhaul_period) * 2:
next_date = date_now + timedelta(days=equipment.overhaul_period) next_date = date_now + timedelta(days=equipment.overhaul_period)
@@ -577,7 +586,8 @@ class SfMaintenanceEquipment(models.Model):
if not next_requests: if not next_requests:
equipment._create_new_request1(equipment.overhaul_date) equipment._create_new_request1(equipment.overhaul_date)
image_id = fields.Many2many('maintenance.equipment.image', 'equipment_id', string='加工能力', domain="[('type', '=', '加工能力')]") image_id = fields.Many2many('maintenance.equipment.image', 'equipment_id', string='加工能力',
domain="[('type', '=', '加工能力')]")
class SfRobotAxisNum(models.Model): class SfRobotAxisNum(models.Model):

View File

@@ -10,11 +10,12 @@
""", """,
'category': 'sf', 'category': 'sf',
'website': 'https://www.sf.jikimo.com', 'website': 'https://www.sf.jikimo.com',
'depends': ['mrp_workorder', 'sf_base', 'sf_maintenance', 'web_widget_model_viewer', 'stock'], 'depends': ['sf_base', 'sf_maintenance', 'web_widget_model_viewer', 'stock'],
'data': [ 'data': [
'data/stock_data.xml', 'data/stock_data.xml',
'security/group_security.xml', 'security/group_security.xml',
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'views/mrp_views_menus.xml',
'views/mrp_production_addional_change.xml', 'views/mrp_production_addional_change.xml',
# 'views/mrp_maintenance_views.xml', # 'views/mrp_maintenance_views.xml',
'views/mrp_routing_workcenter_view.xml', 'views/mrp_routing_workcenter_view.xml',
@@ -23,7 +24,7 @@
'views/mrp_workorder_view.xml', 'views/mrp_workorder_view.xml',
'views/model_type_view.xml', 'views/model_type_view.xml',
'views/sf_maintenance_equipment.xml', 'views/sf_maintenance_equipment.xml',
# 'views/kanban_change.xml'
], ],
'assets': { 'assets': {

View File

@@ -3,8 +3,8 @@ from odoo import models, fields, api, _
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
from odoo.modules import get_resource_path from odoo.modules import get_resource_path
from odoo.addons.sf_base.commons.common import Common from odoo.addons.sf_base.commons.common import Common
from OCC.Extend.DataExchange import read_step_file #from OCC.Extend.DataExchange import read_step_file
from OCC.Extend.DataExchange import write_stl_file #from OCC.Extend.DataExchange import write_stl_file
import logging import logging
import base64 import base64
import hashlib import hashlib

View File

@@ -97,12 +97,15 @@ class QualityPoint(models.Model):
component_ids = fields.One2many('product.product', compute='_compute_component_ids') component_ids = fields.One2many('product.product', compute='_compute_component_ids')
product_ids = fields.Many2many( product_ids = fields.Many2many(
default=_default_product_ids, default=_default_product_ids,
domain="operation_id and [('id', 'in', bom_product_ids)] or [('type', 'in', ('product', 'consu')), '|', ('company_id', '=', False), ('company_id', '=', company_id)]") domain="operation_id and [('id', 'in', bom_product_ids)] or"
" [('type', 'in', ('product', 'consu')),"
" '|', ('company_id', '=', False), ('company_id', '=', company_id)]")
bom_product_ids = fields.One2many('product.product', compute="_compute_bom_product_ids") bom_product_ids = fields.One2many('product.product', compute="_compute_bom_product_ids")
test_type_id = fields.Many2one( test_type_id = fields.Many2one(
'quality.point.test_type', 'quality.point.test_type',
domain="[('allow_registration', '=', operation_id and is_workorder_step)]") domain="[('allow_registration', '=', operation_id and is_workorder_step)]")
test_report_type = fields.Selection([('pdf', 'PDF'), ('zpl', 'ZPL')], string="Report Type", default="pdf", required=True) test_report_type = fields.Selection([('pdf', 'PDF'), ('zpl', 'ZPL')], string="Report Type",
default="pdf", required=True)
source_document = fields.Selection( source_document = fields.Selection(
selection=[('operation', 'Specific Page of Operation Worksheet'), ('step', 'Custom')], selection=[('operation', 'Specific Page of Operation Worksheet'), ('step', 'Custom')],
string="Step Document", string="Step Document",
@@ -125,20 +128,23 @@ class QualityPoint(models.Model):
points_for_workorder_step = self.filtered(lambda p: p.operation_id and p.bom_id) points_for_workorder_step = self.filtered(lambda p: p.operation_id and p.bom_id)
for point in points_for_workorder_step: for point in points_for_workorder_step:
bom_product_ids = point.bom_id.product_id or point.bom_id.product_tmpl_id.product_variant_ids bom_product_ids = point.bom_id.product_id or point.bom_id.product_tmpl_id.product_variant_ids
point.bom_product_ids = bom_product_ids.filtered(lambda p: not p.company_id or p.company_id == point.company_id._origin) point.bom_product_ids = bom_product_ids.filtered(lambda p: not p.company_id or
p.company_id == point.company_id._origin)
@api.depends('product_ids', 'test_type_id', 'is_workorder_step') @api.depends('product_ids', 'test_type_id', 'is_workorder_step')
def _compute_component_ids(self): def _compute_component_ids(self):
self.component_ids = False self.component_ids = False
for point in self: for point in self:
if not point.is_workorder_step or not self.bom_id or point.test_type not in ('register_consumed_materials', 'register_byproducts'): if not point.is_workorder_step or not self.bom_id or point.test_type not in ('register_consumed_materials',
'register_byproducts'):
point.component_id = None point.component_id = None
continue continue
if point.test_type == 'register_byproducts': if point.test_type == 'register_byproducts':
point.component_ids = point.bom_id.byproduct_ids.product_id point.component_ids = point.bom_id.byproduct_ids.product_id
else: else:
bom_products = point.bom_id.product_id or point.bom_id.product_tmpl_id.product_variant_ids bom_products = point.bom_id.product_id or point.bom_id.product_tmpl_id.product_variant_ids
# If product_ids is set the step will exist only for these product variant then we can filter out for the bom explode # If product_ids is set the step will exist only for these product variant then we can filter
# out for the bom explode
if point.product_ids: if point.product_ids:
bom_products &= point.product_ids._origin bom_products &= point.product_ids._origin
@@ -183,7 +189,8 @@ class QualityCheck(models.Model):
workorder_id = fields.Many2one( workorder_id = fields.Many2one(
'mrp.workorder', 'Operation', check_company=True) 'mrp.workorder', 'Operation', check_company=True)
workcenter_id = fields.Many2one('mrp.workcenter', related='workorder_id.workcenter_id', store=True, readonly=True) # TDE: necessary ? workcenter_id = fields.Many2one('mrp.workcenter', related='workorder_id.workcenter_id', store=True,
readonly=True) # TDE: necessary ?
production_id = fields.Many2one( production_id = fields.Many2one(
'mrp.production', 'Production Order', check_company=True) 'mrp.production', 'Production Order', check_company=True)
@@ -201,12 +208,14 @@ class QualityCheck(models.Model):
component_uom_id = fields.Many2one('uom.uom', related='move_id.product_uom', readonly=True) component_uom_id = fields.Many2one('uom.uom', related='move_id.product_uom', readonly=True)
qty_done = fields.Float('Done', digits='Product Unit of Measure') qty_done = fields.Float('Done', digits='Product Unit of Measure')
finished_lot_id = fields.Many2one('stock.lot', 'Finished Lot/Serial', related='production_id.lot_producing_id', store=True) finished_lot_id = fields.Many2one('stock.lot', 'Finished Lot/Serial', related='production_id.lot_producing_id',
store=True)
additional = fields.Boolean('Register additional product', compute='_compute_additional') additional = fields.Boolean('Register additional product', compute='_compute_additional')
component_tracking = fields.Selection(related='component_id.tracking', string="Is Component Tracked") component_tracking = fields.Selection(related='component_id.tracking', string="Is Component Tracked")
# Workorder specific fields # Workorder specific fields
component_remaining_qty = fields.Float('Remaining Quantity for Component', compute='_compute_component_data', digits='Product Unit of Measure') component_remaining_qty = fields.Float('Remaining Quantity for Component', compute='_compute_component_data',
digits='Product Unit of Measure')
component_qty_to_do = fields.Float(compute='_compute_component_qty_to_do') component_qty_to_do = fields.Float(compute='_compute_component_qty_to_do')
is_user_working = fields.Boolean(related="workorder_id.is_user_working") is_user_working = fields.Boolean(related="workorder_id.is_user_working")
consumption = fields.Selection(related="workorder_id.consumption") consumption = fields.Selection(related="workorder_id.consumption")
@@ -241,7 +250,8 @@ class QualityCheck(models.Model):
super()._compute_title() super()._compute_title()
for check in self: for check in self:
if not check.point_id or check.component_id: if not check.point_id or check.component_id:
check.title = '{} "{}"'.format(check.test_type_id.display_name, check.component_id.name or check.workorder_id.name) check.title = '{} "{}"'.format(check.test_type_id.display_name, check.component_id.name
or check.workorder_id.name)
@api.depends('point_id', 'quality_state', 'component_id', 'component_uom_id', 'lot_id', 'qty_done') @api.depends('point_id', 'quality_state', 'component_id', 'component_uom_id', 'lot_id', 'qty_done')
def _compute_result(self): def _compute_result(self):
@@ -266,7 +276,8 @@ class QualityCheck(models.Model):
def _get_check_result(self): def _get_check_result(self):
if self.test_type in ('register_consumed_materials', 'register_byproducts') and self.lot_id: if self.test_type in ('register_consumed_materials', 'register_byproducts') and self.lot_id:
return '{} - {}, {} {}'.format(self.component_id.name, self.lot_id.name, self.qty_done, self.component_uom_id.name) return '{} - {}, {} {}'.format(self.component_id.name, self.lot_id.name, self.qty_done,
self.component_uom_id.name)
elif self.test_type in ('register_consumed_materials', 'register_byproducts'): elif self.test_type in ('register_consumed_materials', 'register_byproducts'):
return '{}, {} {}'.format(self.component_id.name, self.qty_done, self.component_uom_id.name) return '{}, {} {}'.format(self.component_id.name, self.qty_done, self.component_uom_id.name)
else: else:
@@ -281,12 +292,14 @@ class QualityCheck(models.Model):
for check in self: for check in self:
if check.test_type in ('register_byproducts', 'register_consumed_materials'): if check.test_type in ('register_byproducts', 'register_consumed_materials'):
if check.quality_state == 'none': if check.quality_state == 'none':
completed_lines = check.workorder_id.move_line_ids.filtered(lambda l: l.lot_id) if check.component_id.tracking != 'none' else check.workorder_id.move_line_ids completed_lines = check.workorder_id.move_line_ids.filtered(lambda l: l.lot_id)\
if check.component_id.tracking != 'none' else check.workorder_id.move_line_ids
if check.move_id.additional: if check.move_id.additional:
qty = check.workorder_id.qty_remaining qty = check.workorder_id.qty_remaining
else: else:
qty = check.workorder_id.qty_producing qty = check.workorder_id.qty_producing
check.component_remaining_qty = self._prepare_component_quantity(check.move_id, qty) - sum(completed_lines.mapped('qty_done')) check.component_remaining_qty = self._prepare_component_quantity(check.move_id, qty) -\
sum(completed_lines.mapped('qty_done'))
check.component_uom_id = check.move_id.product_uom check.component_uom_id = check.move_id.product_uom
def action_print(self): def action_print(self):
@@ -369,7 +382,8 @@ class QualityCheck(models.Model):
vals_list = [] vals_list = []
# apply putaway # apply putaway
location_dest_id = self.move_id.location_dest_id._get_putaway_strategy(self.move_id.product_id) location_dest_id = self.move_id.location_dest_id._get_putaway_strategy(self.move_id.product_id)
quants = self.env['stock.quant']._gather(self.product_id, self.move_id.location_id, lot_id=self.lot_id, strict=False) quants = self.env['stock.quant']._gather(self.product_id, self.move_id.location_id, lot_id=self.lot_id,
strict=False)
# Search for a sub-locations where the product is available. # Search for a sub-locations where the product is available.
# Loop on the quants to get the locations. If there is not enough # Loop on the quants to get the locations. If there is not enough
# quantity into stock, we take the move location. Anyway, no # quantity into stock, we take the move location. Anyway, no
@@ -386,7 +400,8 @@ class QualityCheck(models.Model):
for quant in quants: for quant in quants:
vals = shared_vals.copy() vals = shared_vals.copy()
quantity = quant.quantity - quant.reserved_quantity quantity = quant.quantity - quant.reserved_quantity
quantity = self.product_id.uom_id._compute_quantity(quantity, self.product_uom_id, rounding_method='HALF-UP') quantity = self.product_id.uom_id._compute_quantity(quantity, self.product_uom_id,
rounding_method='HALF-UP')
rounding = quant.product_uom_id.rounding rounding = quant.product_uom_id.rounding
if (float_compare(quant.quantity, 0, precision_rounding=rounding) <= 0 or if (float_compare(quant.quantity, 0, precision_rounding=rounding) <= 0 or
float_compare(quantity, 0, precision_rounding=self.product_uom_id.rounding) <= 0): float_compare(quantity, 0, precision_rounding=self.product_uom_id.rounding) <= 0):
@@ -469,7 +484,8 @@ class QualityCheck(models.Model):
def _update_component_quantity(self): def _update_component_quantity(self):
if self.component_tracking == 'serial': if self.component_tracking == 'serial':
self._origin.qty_done = self.component_id.uom_id._compute_quantity(1, self.component_uom_id, rounding_method='HALF-UP') self._origin.qty_done = self.component_id.uom_id._compute_quantity(1, self.component_uom_id,
rounding_method='HALF-UP')
return return
move = self.move_id move = self.move_id
# Compute the new quantity for the current component # Compute the new quantity for the current component

View File

@@ -5,4 +5,4 @@ from odoo import fields, models
class Users(models.Model): class Users(models.Model):
_inherit = 'res.users' _inherit = 'res.users'
workcenter_ids = fields.Many2many("mrp.workcenter", 'users_workcenter') workcenter_ids = fields.Many2many("mrp.workcenter", 'users_workcenter')

View File

@@ -124,7 +124,8 @@ class StockRule(models.Model):
moves_values_by_company[procurement.company_id.id].append(move_values) moves_values_by_company[procurement.company_id.id].append(move_values)
for company_id, moves_values in moves_values_by_company.items(): for company_id, moves_values in moves_values_by_company.items():
# create the move as SUPERUSER because the current user may not have the rights to do it (mto product launched by a sale for example) # create the move as SUPERUSER because the current user may not have the rights to do it (mto product
# launched by a sale for example)
moves = self.env['stock.move'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(moves_values) 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. # Since action_confirm launch following procurement_group we should activate it.
moves._action_confirm() moves._action_confirm()
@@ -147,7 +148,8 @@ class StockRule(models.Model):
raise ProcurementException(errors) raise ProcurementException(errors)
for company_id, productions_values in productions_values_by_company.items(): for company_id, productions_values in productions_values_by_company.items():
# create the MO as SUPERUSER because the current user may not have the rights to do it (mto product launched by a sale for example) # create the MO as SUPERUSER because the current user may not have the rights to do it (mto product
# launched by a sale for example)
'''创建制造订单''' '''创建制造订单'''
productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create( productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(
productions_values) productions_values)
@@ -161,7 +163,8 @@ class StockRule(models.Model):
productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \ productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \
( (
p.move_dest_ids.procure_method != 'make_to_order' and not p.move_raw_ids and not p.workorder_ids)).action_confirm() p.move_dest_ids.procure_method != 'make_to_order' and not
p.move_raw_ids and not p.workorder_ids)).action_confirm()
for production in productions: for production in productions:
''' '''
@@ -187,7 +190,6 @@ class StockRule(models.Model):
values={'self': production, 'origin': origin_production}, values={'self': production, 'origin': origin_production},
subtype_id=self.env.ref('mail.mt_note').id) subtype_id=self.env.ref('mail.mt_note').id)
''' '''
创建生产计划 创建生产计划
''' '''
@@ -404,7 +406,8 @@ class ReStockMove(models.Model):
'fixture_clamp_workpiece_diameter_max': item.product_id.fixture_clamp_workpiece_diameter_max, 'fixture_clamp_workpiece_diameter_max': item.product_id.fixture_clamp_workpiece_diameter_max,
'fixture_maximum_carrying_weight': item.product_id.fixture_maximum_carrying_weight, 'fixture_maximum_carrying_weight': item.product_id.fixture_maximum_carrying_weight,
'fixture_maximum_clamping_force': item.product_id.fixture_maximum_clamping_force, 'fixture_maximum_clamping_force': item.product_id.fixture_maximum_clamping_force,
'fixture_driving_way': '' if not item.product_id.fixture_driving_way else item.product_id.fixture_driving_way, 'fixture_driving_way': '' if not item.product_id.fixture_driving_way
else item.product_id.fixture_driving_way,
'fixture_apply_machine_tool_type_codes': self.env[ 'fixture_apply_machine_tool_type_codes': self.env[
'product.template']._json_apply_machine_tool_type_item_code(item), 'product.template']._json_apply_machine_tool_type_item_code(item),
'fixture_through_hole_size': item.product_id.fixture_through_hole_size, 'fixture_through_hole_size': item.product_id.fixture_through_hole_size,
@@ -463,12 +466,14 @@ class ReStockMove(models.Model):
'blade_tip_taper': item.product_id.cutting_tool_blade_tip_taper, 'blade_tip_taper': item.product_id.cutting_tool_blade_tip_taper,
'blade_helix_angle': item.product_id.cutting_tool_blade_helix_angle, 'blade_helix_angle': item.product_id.cutting_tool_blade_helix_angle,
'blade_type': item.product_id.cutting_tool_blade_type, 'blade_type': item.product_id.cutting_tool_blade_type,
'coarse_medium_fine': '' if item.product_id.cutting_tool_coarse_medium_fine is False else item.product_id.cutting_tool_coarse_medium_fine, 'coarse_medium_fine': '' if item.product_id.cutting_tool_coarse_medium_fine is False
else item.product_id.cutting_tool_coarse_medium_fine,
'run_out_accuracy_max': item.product_id.cutting_tool_run_out_accuracy_max, 'run_out_accuracy_max': item.product_id.cutting_tool_run_out_accuracy_max,
'run_out_accuracy_min': item.product_id.cutting_tool_run_out_accuracy_min, 'run_out_accuracy_min': item.product_id.cutting_tool_run_out_accuracy_min,
'head_diameter': item.product_id.cutting_tool_head_diameter, 'head_diameter': item.product_id.cutting_tool_head_diameter,
'diameter': item.product_id.cutting_tool_diameter, 'diameter': item.product_id.cutting_tool_diameter,
'blade_number': '' if item.product_id.cutting_tool_blade_number is False else item.product_id.cutting_tool_blade_number, 'blade_number': '' if item.product_id.cutting_tool_blade_number is False
else item.product_id.cutting_tool_blade_number,
'front_angle': item.product_id.cutting_tool_front_angle, 'front_angle': item.product_id.cutting_tool_front_angle,
'rear_angle': item.product_id.cutting_tool_rear_angle, 'rear_angle': item.product_id.cutting_tool_rear_angle,
'main_included_angle': item.product_id.cutting_tool_main_included_angle, 'main_included_angle': item.product_id.cutting_tool_main_included_angle,
@@ -512,7 +517,8 @@ class ReStockMove(models.Model):
'inner_diameter': item.product_id.cutting_tool_inner_diameter, 'inner_diameter': item.product_id.cutting_tool_inner_diameter,
'cooling_suit_type_ids': item.product_id.cooling_suit_type_ids, 'cooling_suit_type_ids': item.product_id.cooling_suit_type_ids,
'er_size_model': item.product_id.cutting_tool_er_size_model, 'er_size_model': item.product_id.cutting_tool_er_size_model,
'image': '' if not item.product_id.image_1920 else base64.b64encode(item.product_id.image_1920).decode('utf-8'), 'image': '' if not item.product_id.image_1920 else base64.b64encode(item.product_id.image_1920).decode(
'utf-8'),
} }
try: try:
if item.product_id.industry_code: if item.product_id.industry_code:

View File

@@ -1,11 +1,24 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sf_cnc_processing,sf_cnc_processing,model_sf_cnc_processing,base.group_user,1,1,1,1 access_sf_cnc_processing,sf_cnc_processing,model_sf_cnc_processing,sf_base.group_sf_mrp_user,1,0,0,0
access_sf_model_type,sf_model_type,model_sf_model_type,base.group_user,1,1,1,1 access_sf_cnc_processing_manager,sf_cnc_processing,model_sf_cnc_processing,sf_base.group_sf_mrp_manager,1,1,1,1
access_sf_product_model_type_routing_sort,sf_product_model_type_routing_sort,model_sf_product_model_type_routing_sort,base.group_user,1,1,1,1 access_sf_model_type,sf_model_type,model_sf_model_type,sf_base.group_sf_mrp_user,1,0,0,0
access_sf_embryo_model_type_routing_sort,sf_embryo_model_type_routing_sort,model_sf_embryo_model_type_routing_sort,base.group_user,1,1,1,1 access_sf_model_type_manager,sf_model_type,model_sf_model_type,sf_base.group_sf_mrp_manager,1,1,1,1
access_sf_surface_technics_model_type_routing_sort,sf_surface_technics_model_type_routing_sort,model_sf_surface_technics_model_type_routing_sort,base.group_user,1,1,1,1 access_sf_product_model_type_routing_sort,sf_product_model_type_routing_sort,model_sf_product_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0
access_sf_production_line,sf.production.line,model_sf_production_line,base.group_user,1,1,1,1 access_sf_product_model_type_routing_sort_manager,sf_product_model_type_routing_sort,model_sf_product_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,1
access_maintenance_equipment_tool,maintenance_equipment_tool,model_maintenance_equipment_tool,base.group_user,1,1,1,1 access_sf_embryo_model_type_routing_sort,sf_embryo_model_type_routing_sort,model_sf_embryo_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0
access_sf_embryo_model_type_routing_sort_manager,sf_embryo_model_type_routing_sort,model_sf_embryo_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,1
access_sf_surface_technics_model_type_routing_sort,sf_surface_technics_model_type_routing_sort,model_sf_surface_technics_model_type_routing_sort,sf_base.group_sf_mrp_user,1,0,0,0
access_sf_surface_technics_model_type_routing_sort_manager,sf_surface_technics_model_type_routing_sort,model_sf_surface_technics_model_type_routing_sort,sf_base.group_sf_mrp_manager,1,1,1,1
access_sf_production_line,sf.production.line,model_sf_production_line,sf_base.group_sf_mrp_user,1,0,0,0
access_sf_production_line_manager,sf.production.line,model_sf_production_line,sf_base.group_sf_mrp_manager,1,1,1,1
access_maintenance_equipment_tool,maintenance_equipment_tool,model_maintenance_equipment_tool,sf_base.group_sf_mrp_user,1,0,0,0
access_maintenance_equipment_tool_manager,maintenance_equipment_tool,model_maintenance_equipment_tool,sf_base.group_sf_mrp_manager,1,1,1,1
access_mrp_production,mrp_production,model_mrp_production,sf_base.group_sf_mrp_user,1,1,1,0
access_mrp_production_manager,mrp_production,model_mrp_production,sf_base.group_sf_mrp_manager,1,1,1,0
access_mrp_workorder,mrp_workorder,model_mrp_workorder,sf_base.group_sf_mrp_user,1,1,1,0
access_mrp_workorder_manager,mrp_workorder,model_mrp_workorder,sf_base.group_sf_mrp_manager,1,1,1,0
access_mrp_workcenter,mrp_workcenter,model_mrp_workcenter,sf_base.group_sf_mrp_user,1,1,1,0
access_mrp_workcenter_manager,mrp_workcenter,model_mrp_workcenter,sf_base.group_sf_mrp_manager,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_sf_cnc_processing sf_cnc_processing model_sf_cnc_processing base.group_user sf_base.group_sf_mrp_user 1 1 0 1 0 1 0
3 access_sf_model_type access_sf_cnc_processing_manager sf_model_type sf_cnc_processing model_sf_model_type model_sf_cnc_processing base.group_user sf_base.group_sf_mrp_manager 1 1 1 1
4 access_sf_product_model_type_routing_sort access_sf_model_type sf_product_model_type_routing_sort sf_model_type model_sf_product_model_type_routing_sort model_sf_model_type base.group_user sf_base.group_sf_mrp_user 1 1 0 1 0 1 0
5 access_sf_embryo_model_type_routing_sort access_sf_model_type_manager sf_embryo_model_type_routing_sort sf_model_type model_sf_embryo_model_type_routing_sort model_sf_model_type base.group_user sf_base.group_sf_mrp_manager 1 1 1 1
6 access_sf_surface_technics_model_type_routing_sort access_sf_product_model_type_routing_sort sf_surface_technics_model_type_routing_sort sf_product_model_type_routing_sort model_sf_surface_technics_model_type_routing_sort model_sf_product_model_type_routing_sort base.group_user sf_base.group_sf_mrp_user 1 1 0 1 0 1 0
7 access_sf_production_line access_sf_product_model_type_routing_sort_manager sf.production.line sf_product_model_type_routing_sort model_sf_production_line model_sf_product_model_type_routing_sort base.group_user sf_base.group_sf_mrp_manager 1 1 1 1
8 access_maintenance_equipment_tool access_sf_embryo_model_type_routing_sort maintenance_equipment_tool sf_embryo_model_type_routing_sort model_maintenance_equipment_tool model_sf_embryo_model_type_routing_sort base.group_user sf_base.group_sf_mrp_user 1 1 0 1 0 1 0
9 access_sf_embryo_model_type_routing_sort_manager sf_embryo_model_type_routing_sort model_sf_embryo_model_type_routing_sort sf_base.group_sf_mrp_manager 1 1 1 1
10 access_sf_surface_technics_model_type_routing_sort sf_surface_technics_model_type_routing_sort model_sf_surface_technics_model_type_routing_sort sf_base.group_sf_mrp_user 1 0 0 0
11 access_sf_surface_technics_model_type_routing_sort_manager sf_surface_technics_model_type_routing_sort model_sf_surface_technics_model_type_routing_sort sf_base.group_sf_mrp_manager 1 1 1 1
12 access_sf_production_line sf.production.line model_sf_production_line sf_base.group_sf_mrp_user 1 0 0 0
13 access_sf_production_line_manager sf.production.line model_sf_production_line sf_base.group_sf_mrp_manager 1 1 1 1
14 access_maintenance_equipment_tool maintenance_equipment_tool model_maintenance_equipment_tool sf_base.group_sf_mrp_user 1 0 0 0
15 access_maintenance_equipment_tool_manager maintenance_equipment_tool model_maintenance_equipment_tool sf_base.group_sf_mrp_manager 1 1 1 1
16 access_mrp_production mrp_production model_mrp_production sf_base.group_sf_mrp_user 1 1 1 0
17 access_mrp_production_manager mrp_production model_mrp_production sf_base.group_sf_mrp_manager 1 1 1 0
18 access_mrp_workorder mrp_workorder model_mrp_workorder sf_base.group_sf_mrp_user 1 1 1 0
19 access_mrp_workorder_manager mrp_workorder model_mrp_workorder sf_base.group_sf_mrp_manager 1 1 1 0
20 access_mrp_workcenter mrp_workcenter model_mrp_workcenter sf_base.group_sf_mrp_user 1 1 1 0
21 access_mrp_workcenter_manager mrp_workcenter model_mrp_workcenter sf_base.group_sf_mrp_manager 1 1 1 0
22
23
24

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<menuitem id="mrp.menu_mrp_root"
name="Manufacturing"
groups="mrp.group_mrp_user,mrp.group_mrp_manager,sf_base.group_sf_mrp_user,sf_base.group_sf_mrp_manager"
web_icon="mrp,static/description/icon.svg"
sequence="145">
<menuitem id="mrp.menu_mrp_manufacturing"
name="Operations"
sequence="10"/>
<menuitem id="mrp.mrp_planning_menu_root"
name="Planning"
sequence="15"/>
<menuitem id="mrp.enu_mrp_bom"
name="Products"
sequence="20"/>
<menuitem id="mrp.menu_mrp_reporting"
name="Reporting"
sequence="25"/>
<menuitem id="mrp.menu_mrp_configuration"
name="Configuration"
groups="mrp.group_mrp_manager,sf_base.group_sf_mrp_manager"
sequence="100"/>
</menuitem>
</odoo>

View File

@@ -2,7 +2,7 @@
import logging import logging
from odoo.modules import get_resource_path from odoo.modules import get_resource_path
from odoo import fields, models, api from odoo import fields, models, api
from quatotion import readSql, feature_recognize, auto_quatotion #from quatotion import readSql, feature_recognize, auto_quatotion
__author__ = 'jinling.yang' __author__ = 'jinling.yang'
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)

View File

@@ -1,7 +1,7 @@
from odoo import models, fields, api from odoo import models, fields, api
from odoo.modules import get_resource_path from odoo.modules import get_resource_path
from OCC.Extend.DataExchange import read_step_file #from OCC.Extend.DataExchange import read_step_file
from OCC.Extend.DataExchange import write_stl_file #from OCC.Extend.DataExchange import write_stl_file
from odoo.exceptions import ValidationError, UserError from odoo.exceptions import ValidationError, UserError
from odoo.addons.sf_base.commons.common import Common from odoo.addons.sf_base.commons.common import Common
from datetime import datetime from datetime import datetime