Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造代码优化

# Conflicts:
#	sf_manufacturing/models/stock.py
This commit is contained in:
mgw
2023-11-23 22:23:21 +08:00
57 changed files with 588 additions and 520 deletions

View File

@@ -10,7 +10,7 @@
""", """,
'category': 'sf', 'category': 'sf',
'website': 'https://www.sf.jikimo.com', 'website': 'https://www.sf.jikimo.com',
'depends': ['account', 'base', 'mrp_workorder', 'sale', 'purchase'], 'depends': ['account', 'base', 'mrp_workorder', 'sale', 'purchase', 'sales_team'],
'data': [ 'data': [
'security/group_security.xml', 'security/group_security.xml',
'security/ir.model.access.csv', 'security/ir.model.access.csv',

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

@@ -4,9 +4,3 @@ from . import tool_base_new
from . import fixture from . import fixture
from . import functional_fixture from . import functional_fixture
from . import tool_other_features from . import tool_other_features

View File

@@ -17,29 +17,7 @@ class MrsProductionMaterials(models.Model):
remark = fields.Text("备注") remark = fields.Text("备注")
active = fields.Boolean('有效', default=True) active = fields.Boolean('有效', default=True)
# def open_url_action(self):
# base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
# # url = 'http://192.168.50.202:8080/api'
# url = 'https://bfw.jikimo.com/'
# # data = {
# # 'key' : 'value'
# # }
#
# response = requests.get(url)
# response.raise_for_status()
# return {
# 'type': 'ir.actions.act_url',
# 'url': response.url,
# 'target': 'new'
# }
def open_url_action(self): def open_url_action(self):
# sf_sync_config = self.env['res.config.settings'].get_values()
# token = sf_sync_config['token']
# sf_secret_key = sf_sync_config['sf_secret_key']
# headers = Common.get_headers(self, token, sf_secret_key)
url = 'http://192.168.50.127:8081' url = 'http://192.168.50.127:8081'
params = { params = {
'user_id': self._uid 'user_id': self._uid
@@ -82,7 +60,6 @@ class MrsMaterialModel(models.Model):
active = fields.Boolean('有效', default=True) active = fields.Boolean('有效', default=True)
class MrsProductionProcessCategory(models.Model): class MrsProductionProcessCategory(models.Model):
_name = 'sf.production.process.category' _name = 'sf.production.process.category'
_description = '表面工艺类别' _description = '表面工艺类别'
@@ -131,6 +108,7 @@ class MrsProcessingOrder(models.Model):
index=True, string='加工工艺') index=True, string='加工工艺')
production_process_id = fields.Many2one('sf.production.process', string="表面工艺") production_process_id = fields.Many2one('sf.production.process', string="表面工艺")
class SupplierSort(models.Model): class SupplierSort(models.Model):
_name = 'sf.supplier.sort' _name = 'sf.supplier.sort'
_description = '供应商排序' _description = '供应商排序'

View File

@@ -1,5 +1,5 @@
import requests
import json import json
import requests
from odoo import models, fields, api from odoo import models, fields, api
from odoo.addons.sf_base.commons.common import Common from odoo.addons.sf_base.commons.common import Common
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError

View File

@@ -1,21 +1,58 @@
<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"/>
<field name="implied_ids" eval="[(4, ref('mrp.group_mrp_user'))]"/>
</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'))]"/>-->
<!-- </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"/>-->
<!-- </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_user'))]"/>
<field name="category_id" ref="base.module_category_manufacturing_manufacturing"/>
</record>
<record model="ir.module.category" id="module_category_plan"> <record model="ir.module.category" id="module_category_plan">
<field name="name">计划</field> <field name="name">计划</field>
<field name="sequence">20</field> <field name="sequence">20</field>
</record> </record>
<record id="sales_team.group_sale_manager" model="res.groups"> <record id="group_sale_salemanager" model="res.groups">
<field name="name">销售经理</field> <field name="name">销售经理</field>
<field name="category_id" ref="base.module_category_sales_sales"/> <field name="category_id" ref="base.module_category_sales_sales"/>
<!-- <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>-->
</record> </record>
<!-- <record id="group_sale_director" model="res.groups">--> <record id="group_sale_director" model="res.groups">
<!-- <field name="name">销售总监</field>--> <field name="name">销售总监</field>
<!-- <field name="category_id" ref="base.module_category_sales_sales"/>--> <field name="category_id" ref="base.module_category_sales_sales"/>
<!-- <field name="implied_ids" eval="[(4, ref('sf_base.group_sale_manager'))]"/>--> <field name="implied_ids" eval="[(4, ref('sf_base.group_sale_salemanager'))]"/>
<!-- </record>--> </record>
<record id="group_plan_dispatch" model="res.groups"> <record id="group_plan_dispatch" model="res.groups">
<field name="name">计划调度岗</field> <field name="name">计划调度岗</field>

View File

@@ -40,3 +40,5 @@ access_maintenance_equipment_image,maintenance_equipment_image,model_maintenance
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
40
41
42
43
44

View File

@@ -1,3 +1 @@
from .import controllers from . import controllers

View File

@@ -2,4 +2,3 @@ from . import http
from . import models from . import models
from . import process_status from . import process_status
from . import jd_eclp from . import jd_eclp

View File

@@ -4,7 +4,6 @@ import uuid
import string import string
import random import random
from odoo import fields, models from odoo import fields, models
__author__ = 'jinling.yang' __author__ = 'jinling.yang'
@@ -25,4 +24,4 @@ class ResPartner(models.Model):
return ran_str return ran_str
sf_token = fields.Char(u'Token', default=get_token) sf_token = fields.Char(u'Token', default=get_token)
sf_secret_key = fields.Char(u'密钥', default=get_secret) sf_secret_key = fields.Char(u'密钥', default=get_secret)

View File

@@ -1,2 +1 @@
from . import models from . import models

View File

@@ -35,6 +35,11 @@
<field name="type">功能刀具</field> <field name="type">功能刀具</field>
</record> </record>
<record id="res_partner_bfm" model="res.partner">
<field name="name">业务平台</field>
<!-- <field name="company_id" ref="base.main_company"/>-->
</record>
<record id="product_functional_tool_sf" model="product.product"> <record id="product_functional_tool_sf" model="product.product">
<field name="name">功能刀具</field> <field name="name">功能刀具</field>
<field name="categ_id" ref="product_category_functional_tool_sf"/> <field name="categ_id" ref="product_category_functional_tool_sf"/>

View File

@@ -9,7 +9,7 @@
""", """,
'category': 'sf', 'category': 'sf',
'website': 'https://www.sf.jikimo.com', 'website': 'https://www.sf.jikimo.com',
'depends': ['sf_sale', 'sf_dlm','sf_manufacturing'], 'depends': ['sf_sale', 'sf_dlm', 'sf_manufacturing'],
'data': [ 'data': [
'views/product_template_management_view.xml', 'views/product_template_management_view.xml',
], ],

View File

@@ -1,7 +1,2 @@
#from . import product_template # from . import product_template
#from . import product_supplierinfo # from . import product_supplierinfo
#

View File

@@ -6,7 +6,7 @@
'category': '工厂设备', 'category': '工厂设备',
'description': """ 'description': """
""", """,
'depends': ['maintenance', 'sf_base'], 'depends': ['hr_maintenance', 'sf_base'],
'data': [ 'data': [
'security/group_security.xml', 'security/group_security.xml',
'security/ir.model.access.csv', 'security/ir.model.access.csv',

View File

@@ -2,6 +2,7 @@
from odoo import api, fields, models, SUPERUSER_ID, _ from odoo import api, fields, models, SUPERUSER_ID, _
from odoo.exceptions import UserError from odoo.exceptions import UserError
class SfEquipmentSaintenanceStandards(models.Model): class SfEquipmentSaintenanceStandards(models.Model):
_name = 'equipment.maintenance.standards' _name = 'equipment.maintenance.standards'
_description = '设备维保标准' _description = '设备维保标准'
@@ -18,6 +19,7 @@ class SfEquipmentSaintenanceStandards(models.Model):
m = int(partner.code[-4:]) + 1 m = int(partner.code[-4:]) + 1
num = "%04d" % m num = "%04d" % m
return num return num
code = fields.Char(string='编码') code = fields.Char(string='编码')
remark = fields.Char('备注') remark = fields.Char('备注')
maintenance_type = fields.Selection([('保养', '保养'), ("检修", "检修")], string='类型', default='保养') maintenance_type = fields.Selection([('保养', '保养'), ("检修", "检修")], string='类型', default='保养')
@@ -69,6 +71,7 @@ class SfEquipmentSaintenanceStandards(models.Model):
# work.sequence = current_sequence # work.sequence = current_sequence
# current_sequence += 1 # current_sequence += 1
class SfSaintenanceStandards(models.Model): class SfSaintenanceStandards(models.Model):
_name = 'maintenance.standards' _name = 'maintenance.standards'
_description = '维保项目' _description = '维保项目'
@@ -92,7 +95,3 @@ class MaintenanceStandardImage(models.Model):
image = fields.Binary(string='维保图片') image = fields.Binary(string='维保图片')
standard_id = fields.Many2one('maintenance.standards', string='Standard') standard_id = fields.Many2one('maintenance.standards', string='Standard')

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):
@@ -62,9 +63,10 @@ class SfMaintenanceEquipment(models.Model):
else: else:
record.equipment_maintenance_standards_ids = False record.equipment_maintenance_standards_ids = False
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):
@@ -72,8 +74,8 @@ class SfMaintenanceEquipment(models.Model):
if record: if record:
record.equipment_type = record.category_id.equipment_type record.equipment_type = record.category_id.equipment_type
code = fields.Char('机台号') code = fields.Char('行业编码')
name = fields.Char('名称') name = fields.Char('机台号')
knife_type = fields.Selection( knife_type = fields.Selection(
[("BT40", "BT40"), ("BT30", "BT30"), ("BT50", "BT50")], [("BT40", "BT40"), ("BT30", "BT30"), ("BT50", "BT50")],
default="", string="刀把类型") default="", string="刀把类型")
@@ -152,6 +154,18 @@ class SfMaintenanceEquipment(models.Model):
result.append((parameter.id, name)) result.append((parameter.id, name))
return result return result
@api.model
def create(self, vals):
# 在创建设备之前执行一些自定义逻辑
equipment = super(SfMaintenanceEquipment, self).create(vals)
equipment.name = equipment.MTcode + '#' + equipment.category_id.name
# 在创建设备之后执行一些自定义逻辑
# ...
return equipment
# @api.constrains('rotate_speed') # @api.constrains('rotate_speed')
# def _check_rotate_speed(self): # def _check_rotate_speed(self):
# if self.rotate_speed <= 0: # if self.rotate_speed <= 0:
@@ -278,7 +292,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 +319,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('机器人环境湿度')
@@ -347,7 +364,7 @@ class SfMaintenanceEquipment(models.Model):
images_ids_names = [] images_ids_names = []
for a in self.env['maintenance.equipment.image'].search([('id', 'in', item.image_id.ids)]): for a in self.env['maintenance.equipment.image'].search([('id', 'in', item.image_id.ids)]):
images_ids_names.append(a.name) images_ids_names.append(a.name)
if item.machine_tool_picture != False: if item.machine_tool_picture:
image = base64.b64encode(item.machine_tool_picture).decode('utf-8') image = base64.b64encode(item.machine_tool_picture).decode('utf-8')
else: else:
image = False image = False
@@ -433,7 +450,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 +463,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 +494,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 +507,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 +598,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

@@ -1,6 +1,7 @@
# -*-coding:utf-8-*- # -*-coding:utf-8-*-
from odoo import fields, models from odoo import fields, models
class SfMaintenanceLogs(models.Model): class SfMaintenanceLogs(models.Model):
_name = 'sf.maintenance.logs' _name = 'sf.maintenance.logs'
_description = '设备故障日志' _description = '设备故障日志'
@@ -11,16 +12,17 @@ class SfMaintenanceLogs(models.Model):
brand = fields.Many2one('sf.machine.brand', related='maintenance_equipment_id.brand_id', string='品牌') brand = fields.Many2one('sf.machine.brand', related='maintenance_equipment_id.brand_id', string='品牌')
maintenance_equipment_id = fields.Many2one('maintenance.equipment', string='设备') maintenance_equipment_id = fields.Many2one('maintenance.equipment', string='设备')
code_location = fields.Char(string='编码位置') code_location = fields.Char(string='编码位置')
fault_type = fields.Selection([('电气类', '电气类'), ('机械类', '机械类'), ('程序类', '程序类'), ('系统类', '系统类')], string='故障类型') fault_type = fields.Selection(
[('电气类', '电气类'), ('机械类', '机械类'), ('程序类', '程序类'), ('系统类', '系统类')], string='故障类型')
fault_code = fields.Char(string='故障代码') fault_code = fields.Char(string='故障代码')
fault_alarm_info = fields.Char(string='故障报警信息') fault_alarm_info = fields.Char(string='故障报警信息')
alarm_level = fields.Selection([('一级', '一级(严重)'), ('二级', '二级(中等)'), ('三级', '三级(轻微)')], string='报警级别') alarm_level = fields.Selection([('一级', '一级(严重)'), ('二级', '二级(中等)'), ('三级', '三级(轻微)')],
string='报警级别')
alarm_time = fields.Datetime(string='报警时间') alarm_time = fields.Datetime(string='报警时间')
alarm_way = fields.Selection([('文本提示报警', '文本提示报警'), ('声光报警', '声光报警'), ('图文报警', '图文报警')], string='报警方式') alarm_way = fields.Selection([('文本提示报警', '文本提示报警'), ('声光报警', '声光报警'), ('图文报警', '图文报警')],
string='报警方式')
fault_process = fields.Text(string='故障处理方法') fault_process = fields.Text(string='故障处理方法')
operator = fields.Many2one('res.users', string='处理人') operator = fields.Many2one('res.users', string='处理人')
recovery_time = fields.Datetime(string='复原时间') recovery_time = fields.Datetime(string='复原时间')
fault_duration = fields.Float(string='故障时长') fault_duration = fields.Float(string='故障时长')
note = fields.Text(string='备注') note = fields.Text(string='备注')

View File

@@ -12,7 +12,7 @@ class SfMaintenanceEquipmentCategory(models.Model):
sf_maintenance_type = fields.Selection([('保养', '保养'), ('检修', '检修')], string='维保类别', default='保养') sf_maintenance_type = fields.Selection([('保养', '保养'), ('检修', '检修')], string='维保类别', default='保养')
equipment_maintenance_id = fields.Many2one('equipment.maintenance.standards', string='设备维保标准', equipment_maintenance_id = fields.Many2one('equipment.maintenance.standards', string='设备维保标准',
domain="[('maintenance_type','=',sf_maintenance_type)]") domain="[('maintenance_type','=',sf_maintenance_type)]")
@api.onchange('sf_maintenance_type') @api.onchange('sf_maintenance_type')
def _compute_equipment_maintenance_request_id(self): def _compute_equipment_maintenance_request_id(self):
@@ -38,8 +38,3 @@ class SfMaintenanceEquipmentCategory(models.Model):
def confirm_maintenance_done(self): def confirm_maintenance_done(self):
self.write({'stage_id': 3}) self.write({'stage_id': 3})

View File

@@ -52,11 +52,13 @@
<button type="object" class="oe_highlight" name='enroll_machine_tool' string="机床注册" <button type="object" class="oe_highlight" name='enroll_machine_tool' string="机床注册"
attrs="{'invisible': [('equipment_type', '!=', '机床'), ('brand_id','!=',False),('type_id','!=',False),('control_system_id','!=',False)]}"/> attrs="{'invisible': [('equipment_type', '!=', '机床'), ('brand_id','!=',False),('type_id','!=',False),('control_system_id','!=',False)]}"/>
</div> </div>
</xpath>
<xpath expr="//field[@name='category_id']" position="before">
<field name="MTcode"/>
</xpath> </xpath>
<xpath expr="//field[@name='category_id']" position="after"> <xpath expr="//field[@name='category_id']" position="after">
<field name="state_zc"/> <field name="state_zc"/>
<field name="code"/> <field name="code" readonly="1"/>
<field name="equipment_type" invisible="1"/> <field name="equipment_type" invisible="1"/>
<field name="brand_id" force_save="1"/> <field name="brand_id" force_save="1"/>
<field name="type_id" attrs="{'required': [('equipment_type', '=', '机床')]}" <field name="type_id" attrs="{'required': [('equipment_type', '=', '机床')]}"

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_routing_workcenter_view.xml', 'views/mrp_routing_workcenter_view.xml',
'views/production_line_view.xml', 'views/production_line_view.xml',
@@ -22,6 +23,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',
], ],
'assets': { 'assets': {

View File

@@ -8,8 +8,3 @@ from . import mrp_routing_workcenter
from . import stock from . import stock
from . import res_user from . import res_user
from . import production_line_base from . import production_line_base

View File

@@ -1,7 +1,4 @@
from odoo import fields, models,api from odoo import fields, models, api
class ModelType(models.Model): class ModelType(models.Model):
@@ -42,8 +39,6 @@ class ProductModelTypeRoutingSort(models.Model):
# if record: # if record:
# record.routing_type = record.route_workcenter_id.routing_type # record.routing_type = record.route_workcenter_id.routing_type
routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type') routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type')
workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids') workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids')
@@ -77,7 +72,6 @@ class EmbryoModelTypeRoutingSort(models.Model):
# if record: # if record:
# record.routing_type = record.route_workcenter_id.routing_type # record.routing_type = record.route_workcenter_id.routing_type
routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type') routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type')
workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids') workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids')
@@ -111,7 +105,6 @@ class SurfaceTechnicsModelTypeRoutingSort(models.Model):
# if record: # if record:
# record.routing_type = record.route_workcenter_id.routing_type # record.routing_type = record.route_workcenter_id.routing_type
routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type') routing_type = fields.Selection(string="工序类型", related='route_workcenter_id.routing_type')
workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids') workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids')

View File

@@ -67,4 +67,5 @@ class MaintenanceRequest(models.Model):
class SfMaintenanceLogs(models.Model): class SfMaintenanceLogs(models.Model):
_inherit = 'sf.maintenance.logs' _inherit = 'sf.maintenance.logs'
production_line_id = fields.Many2one('sf.production.line', string='生产线', related='maintenance_equipment_id.production_line_id', store=True) production_line_id = fields.Many2one('sf.production.line', string='生产线',
related='maintenance_equipment_id.production_line_id', store=True)

View File

@@ -12,7 +12,8 @@ class ResWorkcenter(models.Model):
equipment_id = fields.Many2one( equipment_id = fields.Many2one(
'maintenance.equipment', string="设备", 'maintenance.equipment', string="设备",
) )
production_line_id = fields.Many2one('sf.production.line', string='生产线', related='equipment_id.production_line_id', store=True) production_line_id = fields.Many2one('sf.production.line', string='生产线',
related='equipment_id.production_line_id', store=True)
is_process_outsourcing = fields.Boolean('工艺外协') is_process_outsourcing = fields.Boolean('工艺外协')
users_ids = fields.Many2many("res.users", 'users_workcenter') users_ids = fields.Many2many("res.users", 'users_workcenter')

View File

@@ -1,13 +1,12 @@
import logging
from datetime import datetime
from dateutil.relativedelta import relativedelta
import os import os
import base64 import base64
import math import math
import requests import requests
import logging
# import subprocess # import subprocess
from datetime import datetime
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, SUPERUSER_ID, _ from odoo import api, fields, models, SUPERUSER_ID, _
from odoo.exceptions import ValidationError
from odoo.addons.sf_base.commons.common import Common from odoo.addons.sf_base.commons.common import Common
from odoo.exceptions import UserError from odoo.exceptions import UserError
from odoo.addons.sf_mrs_connect.models.ftp_operate import FtpController from odoo.addons.sf_mrs_connect.models.ftp_operate import FtpController
@@ -388,7 +387,8 @@ class ResMrpWorkOrder(models.Model):
productions._create_workorder() productions._create_workorder()
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:
origin_production = production.move_dest_ids and production.move_dest_ids[ origin_production = production.move_dest_ids and production.move_dest_ids[

View File

@@ -818,9 +818,9 @@ class ResProductMo(models.Model):
# 将attach的datas内容转为glb文件 # 将attach的datas内容转为glb文件
def transition_glb_file(self, report_path, code): def transition_glb_file(self, report_path, code):
# shapes = read_step_file(report_path) shapes = read_step_file(report_path)
output_file = os.path.join('/tmp', str(code) + '.stl') output_file = os.path.join('/tmp', str(code) + '.stl')
# write_stl_file(shapes, output_file, 'binary', 0.03, 0.5) write_stl_file(shapes, output_file, 'binary', 0.03, 0.5)
# 转化为glb # 转化为glb
output_glb_file = os.path.join('/tmp', str(code) + '.glb') output_glb_file = os.path.join('/tmp', str(code) + '.glb')
util_path = get_resource_path('sf_base', 'static/util') util_path = get_resource_path('sf_base', 'static/util')

View File

@@ -1,4 +1,4 @@
from odoo import models,fields from odoo import models, fields
class ProductionLine(models.Model): class ProductionLine(models.Model):
@@ -26,8 +26,3 @@ class ProductionLine(models.Model):
name = fields.Char('生产线', size=20, required=True) name = fields.Char('生产线', size=20, required=True)
code = fields.Char('编码', default=_get_code, readonly=True) code = fields.Char('编码', default=_get_code, readonly=True)
remark = fields.Char('备注') remark = fields.Char('备注')

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

@@ -125,7 +125,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()
@@ -163,7 +164,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:
''' '''
@@ -404,8 +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 'fixture_driving_way': '' if not item.product_id.fixture_driving_way
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,
@@ -464,14 +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 'coarse_medium_fine': '' if item.product_id.cutting_tool_coarse_medium_fine is False
item.product_id.cutting_tool_coarse_medium_fine, 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 'blade_number': '' if item.product_id.cutting_tool_blade_number is False
item.product_id.cutting_tool_blade_number, 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,

View File

@@ -1,11 +1,26 @@
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,0,0,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,0,0,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,0,0,0
access_mrp_workcenter_manager,mrp_workcenter,model_mrp_workcenter,sf_base.group_sf_mrp_manager,1,1,1,0
access_mrp_workcenter_productivity,mrp_workcenter_productivity,model_mrp_workcenter_productivity,sf_base.group_sf_mrp_user,1,0,0,0
access_mrp_workcenter_productivity_manager,mrp_workcenter_productivity,model_mrp_workcenter_productivity,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 0 0 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 0 0 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 0 0 0
21 access_mrp_workcenter_manager mrp_workcenter model_mrp_workcenter sf_base.group_sf_mrp_manager 1 1 1 0
22 access_mrp_workcenter_productivity mrp_workcenter_productivity model_mrp_workcenter_productivity sf_base.group_sf_mrp_user 1 0 0 0
23 access_mrp_workcenter_productivity_manager mrp_workcenter_productivity model_mrp_workcenter_productivity sf_base.group_sf_mrp_manager 1 1 1 0
24
25
26

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

@@ -89,7 +89,7 @@
<field name="model">maintenance.equipment</field> <field name="model">maintenance.equipment</field>
<field name="inherit_id" ref="sf_maintenance.sf_hr_equipment_view_form"/> <field name="inherit_id" ref="sf_maintenance.sf_hr_equipment_view_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//field[@name='brand_id']" position="after"> <xpath expr="//field[@name='type_id']" position="after">
<field name="production_line_id"/> <field name="production_line_id"/>
</xpath> </xpath>
</field> </field>

View File

@@ -1,3 +1,2 @@
from . import controllers from . import controllers
from . import models from . import models

View File

@@ -37,7 +37,7 @@ class Sf_Mrs_Connect(http.Controller):
download_state = request.env['sf.cnc.processing'].with_user( download_state = request.env['sf.cnc.processing'].with_user(
request.env.ref("base.user_admin")).download_file_tmp( request.env.ref("base.user_admin")).download_file_tmp(
ret['folder_name'], r) ret['folder_name'], r)
if download_state == False: if not download_state:
res['status'] = -2 res['status'] = -2
res['message'] = '制造订单号为%s的CNC程序文件从FTP拉取失败' % (cnc_workorder.production_id.name) res['message'] = '制造订单号为%s的CNC程序文件从FTP拉取失败' % (cnc_workorder.production_id.name)
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)

View File

@@ -1 +1 @@
from . import models from . import models

View File

@@ -1,2 +1,2 @@
from . import calendar_base from . import calendar_base
from . import base from . import base

View File

@@ -44,7 +44,3 @@ class ProcedureEquipmentResourceSetting(models.Model):
record.working_shift_id = record.working_calendar_id.working_shift_ids record.working_shift_id = record.working_calendar_id.working_shift_ids
else: else:
record.working_shift_id = None record.working_shift_id = None

View File

@@ -10,10 +10,11 @@
""", """,
'category': 'sf', 'category': 'sf',
'website': 'https://www.sf.jikimo.com', 'website': 'https://www.sf.jikimo.com',
'depends': ['sale', 'sale_management', 'web_widget_model_viewer'], 'depends': ['sale', 'sale_management', 'web_widget_model_viewer', 'sf_base'],
'data': [ 'data': [
'security/group_security.xml', 'security/group_security.xml',
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'views/sale_team.xml',
'views/sale_order_view.xml', 'views/sale_order_view.xml',
'views/quick_easy_order_view.xml' 'views/quick_easy_order_view.xml'
], ],

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__)
@@ -24,14 +24,14 @@ class AutoQuatotion(models.Model):
def get_process_time_db_path(self): def get_process_time_db_path(self):
return get_resource_path('sf_sale', 'models', 'process_time.db') return get_resource_path('sf_sale', 'models', 'process_time.db')
def get_auto_quatotion(self, stp_url, feature_full_path, process_time_db_path, model_code): # def get_auto_quatotion(self, stp_url, feature_full_path, process_time_db_path, model_code):
''' # '''
通过打包好的.so库 # 通过打包好的.so库
以调用autoQuatotion库中Quatotion类 # 以调用autoQuatotion库中Quatotion类
初始化后调用类的analyseShape方法对模型文件进行价格预测 # 初始化后调用类的analyseShape方法对模型文件进行价格预测
''' # '''
# 初始化自动报价类(输入特征数据库和加工时间数据库) # # 初始化自动报价类(输入特征数据库和加工时间数据库)
reader = auto_quatotion.Quatotion(feature_full_path, process_time_db_path) # reader = auto_quatotion.Quatotion(feature_full_path, process_time_db_path)
# 获取价格、加工时间、尺寸、XYZ、翻面次数 # # 获取价格、加工时间、尺寸、XYZ、翻面次数
feature_info = reader.analyseShape(stp_url, InfoJson={}) # feature_info = reader.analyseShape(stp_url, InfoJson={})
return feature_info # return feature_info

View File

@@ -12,6 +12,8 @@ class ReSaleOrder(models.Model):
address_of_delivery = fields.Char('交货人地址') address_of_delivery = fields.Char('交货人地址')
payments_way = fields.Selection([('现结', '现结'), ('月结', '月结')], '结算方式', default='现结', tracking=True) payments_way = fields.Selection([('现结', '现结'), ('月结', '月结')], '结算方式', default='现结', tracking=True)
pay_way = fields.Selection([('转账', '转账'), ('微信', '微信'), ('支付宝', '支付宝')], '支付方式') pay_way = fields.Selection([('转账', '转账'), ('微信', '微信'), ('支付宝', '支付宝')], '支付方式')
check_status = fields.Selection([('unchecked', '未审核'), ('checked', '已审核')], '审核状态', default='unchecked')
payment_term_id = fields.Many2one( payment_term_id = fields.Many2one(
comodel_name='account.payment.term', comodel_name='account.payment.term',
@@ -40,6 +42,10 @@ class ReSaleOrder(models.Model):
}) })
return order_id return order_id
# 审核
def action_check(self):
self.check_status = 'checked'
def get_customer(self): def get_customer(self):
customer = self.env['res.partner'].search([('name', '=', '业务平台')]) customer = self.env['res.partner'].search([('name', '=', '业务平台')])
if customer: if customer:
@@ -68,3 +74,9 @@ class ResaleOrderLine(models.Model):
_inherit = 'sale.order.line' _inherit = 'sale.order.line'
model_glb_file = fields.Binary('模型的glb文件') model_glb_file = fields.Binary('模型的glb文件')
class ResCrmTeam(models.Model):
_inherit = 'crm.team'

View File

@@ -1,4 +1,42 @@
<odoo> <odoo>
<data> <data noupdate="1">
<record model="ir.rule" id="crm_team_rule_salemanager">
<field name="name">销售经理只可以查看本人所在的团队</field>
<field name="model_id" ref="model_crm_team"/>
<field name="domain_force">[('crm_team_member_ids.user_id','=',user.id)]</field>
<field name="groups" eval="[(4, ref('sf_base.group_sale_salemanager'))]"/>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="0"/>
<field name="perm_create" eval="0"/>
</record>
<record model="ir.rule" id="crm_team_rule_director">
<field name="name">销售总监</field>
<field name="model_id" ref="model_crm_team"/>
<field name="domain_force">[(1,'=',1)]</field>
<field name="groups" eval="[(4, ref('sf_base.group_sale_director'))]"/>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_create" eval="1"/>
</record>
<record model="ir.rule" id="sale_order_rule_director">
<field name="name">销售总监查看所有的订单</field>
<field name="model_id" ref="model_sale_order"/>
<field name="domain_force">[(1,'=',1)]</field>
<field name="groups" eval="[(4, ref('sf_base.group_sale_director'))]"/>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
</record>
<record model="ir.rule" id="sale_order_rule_salemanager">
<field name="name">销售经理查看自己的订单</field>
<field name="model_id" ref="model_sale_order"/>
<field name="domain_force">['|',('partner_id','=',user.partner_id.id),('create_uid', '=',user.id)]</field>
<field name="groups" eval="[(4, ref('sf_base.group_sale_salemanager'))]"/>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_create" eval="1"/>
</record>
</data> </data>
</odoo> </odoo>

View File

@@ -1,6 +1,15 @@
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_quick_easy_order,quick_easy_order,model_quick_easy_order,base.group_user,1,1,1,1 access_quick_easy_order,quick_easy_order,model_quick_easy_order,base.group_system,1,1,1,1
access_sf_auto_quatotion_common,sf_auto_quatotion_common,model_sf_auto_quatotion_common,base.group_user,1,1,1,1 access_sf_auto_quatotion_common,sf_auto_quatotion_common,model_sf_auto_quatotion_common,base.group_system,1,1,1,1
access_sale_order_manager,sale_order_manager,model_sale_order,sf_base.group_sale_salemanager,1,1,1,0
access_sale_order_director,sale_order_director,model_sale_order,sf_base.group_sale_director,1,1,1,0
access_sale_order_line_manager,sale_order_line_manager,model_sale_order_line,sf_base.group_sale_salemanager,1,1,1,0
access_sale_order_line_director,sale_order_line_director,model_sale_order_line,sf_base.group_sale_director,1,1,1,0
access_crm_team_member_manager,crm_team_manager,sales_team.model_crm_team,sf_base.group_sale_director,1,1,1,0
access_crm_team_member_director,crm_team_member_director,sales_team.model_crm_team_member,sf_base.group_sale_director,1,1,1,0
access_res_users,res_users,base.model_res_users,sf_base.group_sale_director,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_quick_easy_order quick_easy_order model_quick_easy_order base.group_user base.group_system 1 1 1 1
3 access_sf_auto_quatotion_common sf_auto_quatotion_common model_sf_auto_quatotion_common base.group_user base.group_system 1 1 1 1
4 access_sale_order_manager sale_order_manager model_sale_order sf_base.group_sale_salemanager 1 1 1 0
5 access_sale_order_director sale_order_director model_sale_order sf_base.group_sale_director 1 1 1 0
6 access_sale_order_line_manager sale_order_line_manager model_sale_order_line sf_base.group_sale_salemanager 1 1 1 0
7 access_sale_order_line_director sale_order_line_director model_sale_order_line sf_base.group_sale_director 1 1 1 0
8 access_crm_team_member_manager crm_team_manager sales_team.model_crm_team sf_base.group_sale_director 1 1 1 0
9 access_crm_team_member_director crm_team_member_director sales_team.model_crm_team_member sf_base.group_sale_director 1 1 1 0
10 access_res_users res_users base.model_res_users sf_base.group_sale_director 1 1 1 0
11
12
13
14
15

View File

@@ -7,6 +7,25 @@
<field name="model">sale.order</field> <field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/> <field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//form/header/button[@name='action_confirm']" position="after">
<field name="check_status" invisible="1"/>
<button name="action_check" string="审核" type="object"
attrs="{'invisible': [('check_status','=', 'checked')]}"
class="oe_highlight"/>
</xpath>
<xpath expr="//form/header/button[@name='action_check']" position="attributes">
<attribute name="groups">sf_base.group_sale_director</attribute>
</xpath>
<xpath expr="//form/header/button[@name='action_confirm'][1]" position="attributes">
<attribute name="attrs">{'invisible': [('check_status', '=', 'unchecked'),('state', 'not in',
['sent'])]}
</attribute>
</xpath>
<xpath expr="//form/header/button[@name='action_confirm'][2]" position="attributes">
<attribute name="attrs">{'invisible': [('check_status', '=', 'unchecked'),('state', 'in',
['draft'])]}
</attribute>
</xpath>
<field name="payment_term_id" position="after"> <field name="payment_term_id" position="after">
<field name="deadline_of_delivery"/> <field name="deadline_of_delivery"/>
<field name="payments_way"/> <field name="payments_way"/>
@@ -28,6 +47,7 @@
<field name="model">sale.order</field> <field name="model">sale.order</field>
<field name="inherit_id" ref="sale_management.sale_order_form_quote"/> <field name="inherit_id" ref="sale_management.sale_order_form_quote"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="date_order" position="attributes"> <field name="date_order" position="attributes">
<attribute name="string">下单日期</attribute> <attribute name="string">下单日期</attribute>
</field> </field>
@@ -57,6 +77,10 @@
<field name="create_date" position="attributes"> <field name="create_date" position="attributes">
<attribute name="string">下单时间</attribute> <attribute name="string">下单时间</attribute>
</field> </field>
<field name="state" position="after">
<field name="check_status" widget="label_selection"
options="{'classes': {'unchecked':'warning','checked': 'success'}}"/>
</field>
</field> </field>
</record> </record>

145
sf_sale/views/sale_team.xml Normal file
View File

@@ -0,0 +1,145 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<menuitem id="menu_sale_config"
name="Configuration"
groups="sales_team.group_sale_manager,sf_base.group_sale_salemanager,sf_base.group_sale_director"
sequence="50"/>
<!-- <record id="sale.sale_menu_root" model="ir.ui.menu">-->
<!-- <field name="active" eval="True"/>-->
<!-- </record>-->
<!-- <menuitem id="sale_order_menu"-->
<!-- name="Orders"-->
<!-- sequence="10">-->
<!-- <menuitem id="menu_sale_quotations"-->
<!-- action="action_quotations_with_onboarding"-->
<!-- groups="sales_team.group_sale_salesman"-->
<!-- sequence="10"/>-->
<!-- <menuitem id="menu_sale_order"-->
<!-- name="Orders"-->
<!-- action="action_orders"-->
<!-- groups="sales_team.group_sale_salesman"-->
<!-- sequence="20"/>-->
<!-- <menuitem id="report_sales_team"-->
<!-- name="Sales Teams"-->
<!-- action="sales_team.crm_team_action_sales"-->
<!-- groups="sales_team.group_sale_manager"-->
<!-- sequence="30"/>-->
<!-- <menuitem id="res_partner_menu"-->
<!-- action="account.res_partner_action_customer"-->
<!-- groups="sales_team.group_sale_salesman"-->
<!-- sequence="40"/>-->
<!-- </menuitem>-->
<!-- <menuitem id="menu_sale_invoicing"-->
<!-- name="To Invoice"-->
<!-- groups="sales_team.group_sale_salesman"-->
<!-- sequence="20">-->
<!-- <menuitem id="menu_sale_order_invoice"-->
<!-- action="action_orders_to_invoice"-->
<!-- sequence="10"/>-->
<!-- <menuitem id="menu_sale_order_upselling"-->
<!-- action="action_orders_upselling"-->
<!-- sequence="20"/>-->
<!-- </menuitem>-->
<!-- <menuitem id="product_menu_catalog"-->
<!-- name="Products"-->
<!-- groups="sales_team.group_sale_salesman"-->
<!-- sequence="30">-->
<!-- <menuitem id="menu_product_template_action"-->
<!-- action="product_template_action"-->
<!-- sequence="10"/>-->
<!-- <menuitem id="menu_products"-->
<!-- action="product.product_normal_action_sell"-->
<!-- groups="product.group_product_variant"-->
<!-- sequence="20"/>-->
<!-- <menuitem id="menu_product_pricelist_main"-->
<!-- name="Pricelists"-->
<!-- action="product.product_pricelist_action2"-->
<!-- groups="product.group_product_pricelist"-->
<!-- sequence="30"/>-->
<!-- </menuitem>-->
<!-- <menuitem id="menu_sale_report"-->
<!-- name="Reporting"-->
<!-- action="action_order_report_all"-->
<!-- groups="sales_team.group_sale_manager"-->
<!-- sequence="40"/>-->
<!-- <menuitem id="menu_sale_config"-->
<!-- name="Configuration"-->
<!-- groups="sales_team.group_sale_manager"-->
<!-- sequence="50">-->
<!-- <menuitem id="menu_sale_general_settings"-->
<!-- name="Settings"-->
<!-- sequence="10"-->
<!-- action="action_sale_config_settings"-->
<!-- groups="base.group_system"/>-->
<!-- <menuitem id="sales_team_config"-->
<!-- name="Sales Teams"-->
<!-- action="sales_team.crm_team_action_config"-->
<!-- sequence="20"/>-->
<!-- <menuitem id="menu_sales_config"-->
<!-- sequence="30"-->
<!-- name="Sales Orders">-->
<!-- <menuitem id="menu_tag_config"-->
<!-- name="Tags"-->
<!-- action="sales_team.sales_team_crm_tag_action"-->
<!-- sequence="10"/>-->
<!-- </menuitem>-->
<!-- <menuitem id="prod_config_main"-->
<!-- name="Products"-->
<!-- sequence="40">-->
<!-- <menuitem id="menu_product_attribute_action"-->
<!-- action="product.attribute_action"-->
<!-- groups="product.group_product_variant"-->
<!-- sequence="10"/>-->
<!-- </menuitem>-->
<!-- <menuitem id="next_id_16"-->
<!-- name="Units of Measure"-->
<!-- groups="uom.group_uom"-->
<!-- sequence="50">-->
<!-- <menuitem id="menu_product_uom_form_action"-->
<!-- action="uom.product_uom_form_action"-->
<!-- groups="base.group_no_one"-->
<!-- sequence="10"/>-->
<!-- <menuitem id="menu_product_uom_categ_form_action"-->
<!-- action="uom.product_uom_categ_form_action"-->
<!-- sequence="20"/>-->
<!-- </menuitem>-->
<!-- <menuitem id="sale_menu_config_activity_type"-->
<!-- action="mail_activity_type_action_config_sale"-->
<!-- groups="base.group_no_one"-->
<!-- sequence="60"-->
<!-- />-->
<!-- </menuitem>-->
<!-- </menuitem>-->
</odoo>

View File

@@ -112,6 +112,12 @@ class FunctionalCuttingToolEntity(models.Model):
result['domain'] = [('functional_tool_name_id', '=', self.functional_tool_name_id.id)] result['domain'] = [('functional_tool_name_id', '=', self.functional_tool_name_id.id)]
return result return result
def open_stock_move_line(self):
action = self.env.ref('sf_tool_management.sf_inbound_and_outbound_records_of_functional_tools_view_act')
result = action.read()[0]
result['domain'] = [('lot_id', '=', self.barcode_id.id), ('qty_done', '>', 0)]
return result
class FunctionalToolWarning(models.Model): class FunctionalToolWarning(models.Model):
_name = 'sf.functional.tool.warning' _name = 'sf.functional.tool.warning'
@@ -150,9 +156,27 @@ class FunctionalToolWarning(models.Model):
return categories.browse(machine_table_name_ids) return categories.browse(machine_table_name_ids)
class StockMoveLine(models.Model):
_inherit = 'stock.move.line'
_description = '功能刀具出入库记录'
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称')
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
group_expand='_read_group_functional_tool_type_id',
related='functional_tool_name_id.functional_tool_type_id')
diameter = fields.Integer(string='刀具直径(mm)', related='functional_tool_name_id.functional_tool_diameter')
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', related='functional_tool_name_id.knife_tip_r_angle')
install_tool_time = fields.Datetime("刀具组装时间")
@api.model
def _read_group_functional_tool_type_id(self, categories, domain, order):
names = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
return categories.browse(names)
class RealTimeDistributionOfFunctionalTools(models.Model): class RealTimeDistributionOfFunctionalTools(models.Model):
_name = 'sf.real.time.distribution.of.functional.tools' _name = 'sf.real.time.distribution.of.functional.tools'
_description = '功能刀具实时分布' _description = '功能刀具安全库存'
functional_cutting_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', readonly=True) functional_cutting_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', readonly=True)
mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=True, mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=True,
@@ -171,12 +195,9 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
if record: if record:
record.mrs_cutting_tool_type_id = record.functional_cutting_tool_id.mrs_cutting_tool_type_id.id record.mrs_cutting_tool_type_id = record.functional_cutting_tool_id.mrs_cutting_tool_type_id.id
# code = fields.Char('编码', readonly=True, related='functional_cutting_tool_id.code')
barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', readonly=True) barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', readonly=True)
name = fields.Char('名称', invisible=True, readonly=True) name = fields.Char('名称', invisible=True, readonly=True)
functional_tool_name_id = fields.Many2one('product.product', string='功能刀具名称', readonly=True) functional_tool_name_id = fields.Many2one('product.product', string='功能刀具名称', readonly=True)
# mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=True,
# related='functional_cutting_tool_id.mrs_cutting_tool_type_id')
# 整体式刀具型号 # 整体式刀具型号
cutting_tool_integral_model_id = fields.Many2one( cutting_tool_integral_model_id = fields.Many2one(
@@ -266,115 +287,6 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
self.total = record.tool_stock_total + record.return_total self.total = record.tool_stock_total + record.return_total
class InboundAndOutboundRecordsOfFunctionalTools(models.Model):
_name = 'sf.inbound.and.outbound.records.of.functional.tools'
_description = '功能刀具出入库记录'
functional_cutting_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', readonly=True)
mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=True,
group_expand='_read_mrs_cutting_tool_type_ids',
store=True,
compute='_compute_functional_cutting_tool_ids')
@api.model
def _read_mrs_cutting_tool_type_ids(self, categories, domain, order):
mrs_cutting_tool_type_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
return categories.browse(mrs_cutting_tool_type_ids)
@api.depends('functional_cutting_tool_id')
def _compute_functional_cutting_tool_ids(self):
for record in self:
if record:
record.mrs_cutting_tool_type_id = record.functional_cutting_tool_id.mrs_cutting_tool_type_id.id
# code = fields.Char('编码', readonly=True, related='functional_cutting_tool_id.code')
barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', readonly=True)
name = fields.Char('名称', invisible=True, readonly=True)
functional_tool_name_id = fields.Many2one('product.product', string='功能刀具名称', readonly=True)
# 整体式刀具型号
cutting_tool_integral_model_id = fields.Many2one('product.product', string='整体式刀具型号', readonly=True,
domain=[('cutting_tool_material_id', '=', '整体式刀具')])
# 刀片型号
cutting_tool_blade_model_id = fields.Many2one('product.product', string='刀片型号', readonly=True,
domain=[('cutting_tool_material_id', '=', '刀片')])
# 刀杆型号
cutting_tool_cutterbar_model_id = fields.Many2one('product.product', string='刀杆型号', readonly=True,
domain=[('cutting_tool_material_id', '=', '刀杆')])
# 刀盘型号
cutting_tool_cutterpad_model_id = fields.Many2one('product.product', string='刀盘型号', readonly=True,
domain=[('cutting_tool_material_id', '=', '刀盘')])
# 刀柄型号
cutting_tool_cutterhandle_model_id = fields.Many2one('product.product', string='刀柄型号', readonly=True,
domain=[('cutting_tool_material_id', '=', '刀柄')])
# 夹头型号
cutting_tool_cutterhead_model_id = fields.Many2one('product.product', string='夹头型号', readonly=True,
domain=[('cutting_tool_material_id', '=', '夹头')])
diameter = fields.Float('直径(mm)', readonly=True)
tool_grade = fields.Selection([('1', 'P1'), ('2', 'P2'), ('3', 'P3'), ('4', 'P4'), ('5', 'P5'), ('6', 'P6')],
string='刀具等级', readonly=True, compute='_compute_functional_cutting_tool_id')
machining_accuracy = fields.Float('加工精度(mm)', readonly=True)
tool_length = fields.Float('装刀长(mm)', readonly=True)
blade_number = fields.Integer('刃数', readonly=True)
integral_blade_length = fields.Float('整体刃长(mm)', readonly=True)
effective_blade_length = fields.Float('有效刃长(mm)', readonly=True)
max_life = fields.Float('最大寿命值', readonly=True)
is_standard = fields.Selection([('1', ''), ('0', '')], '是否标准刀', readonly=True,
compute='_compute_functional_cutting_tool_id')
applicable_range = fields.Char('适用范围', readonly=True)
image = fields.Binary('图片', readonly=True)
@api.depends('functional_cutting_tool_id')
def _compute_functional_cutting_tool_id(self):
if self.functional_cutting_tool_id:
self.tool_grade = self.functional_cutting_tool_id.tool_grade
self.is_standard = self.functional_cutting_tool_id.is_standard
# 功能刀具出入库记录 特有字段
current_state = fields.Char(string='当前状态', readonly=False)
current_store_area = fields.Char(string='当前库区', readonly=False)
current_store_place = fields.Char(string='当前库位', readonly=False)
tool_install_staff = fields.Char(string='装刀人', readonly=False)
tool_install_time = fields.Datetime(string='装刀时间', readonly=False)
thickness = fields.Selection([('1', ''), ('2', ''), ('3', '')], string='粗/中/精', readonly=False)
# max_life_span = fields.Char(string='最大寿命值', readonly=False)
alarm_value = fields.Char(string='报警值', readonly=False)
used_value = fields.Char(string='已使用值', readonly=False)
reason_application = fields.Char(string='申请原因', readonly=False)
applicant = fields.Char(string='申请人', readonly=False)
inbound_and_outbound_records_ids = fields.One2many('sf.inbound.and.outbound.records',
'inbound_and_outbound_tools_id', string='出入库记录')
remark = fields.Char(string='备注/说明', readonly=False)
class InboundAndOutboundRecords(models.Model):
_name = 'sf.inbound.and.outbound.records'
_description = '出入库记录'
_order = 'id DESC'
inbound_and_outbound_tools_id = fields.Many2one('sf.inbound.and.outbound.records.of.functional.tools',
string='功能刀具出入库记录')
name = fields.Char(string='出入库记录')
tool_state = fields.Selection([('0', '领用出库'), ('1', '归还入库')], string="出入库类别", readonly=False)
receive_equipment = fields.Char(string='领用机台', readonly=False)
receive_staff = fields.Char(string='领用人', readonly=False)
receive_time = fields.Datetime(string='领用出库时间', readonly=False)
return_staff = fields.Char(string='归还人', readonly=False)
return_time = fields.Datetime(string='归还入库时间', readonly=False)
current_store_area = fields.Char(string='库区', readonly=False)
current_store_place = fields.Char(string='库位', readonly=False)
number = fields.Integer(string='数量', readonly=False)
class MachineTableToolChangingApply(models.Model): class MachineTableToolChangingApply(models.Model):
_name = 'sf.machine.table.tool.changing.apply' _name = 'sf.machine.table.tool.changing.apply'
_description = '机床换刀申请' _description = '机床换刀申请'
@@ -390,12 +302,14 @@ class MachineTableToolChangingApply(models.Model):
machine_tool_code = fields.Char(string='机台号', store=True, invisible=True, readonly=True) machine_tool_code = fields.Char(string='机台号', store=True, invisible=True, readonly=True)
cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号', readonly=False, cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号', readonly=False,
required=True, domain="[('equipment_id', '=', maintenance_equipment_id)]") required=True, domain="[('equipment_id', '=', maintenance_equipment_id)]")
barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', functional_tool_name = fields.Char(string='刀具名称', related='functional_tool_name_id.name', store=True)
domain=[('product_id.name', '=', '功能刀具')]) barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', store=True,
functional_tool_name = fields.Char(string='功能刀具名称') domain=[('product_id.name', '=', '功能刀具')],
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型') related='functional_tool_name_id.barcode_id')
functional_tool_name_id = fields.Many2one('product.product', string='功能刀具', functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称')
domain=[('name', '=', '功能刀具')]) functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
related='functional_tool_name_id.functional_tool_type_id')
tool_position_interface_type = fields.Selection( tool_position_interface_type = fields.Selection(
[('BT刀柄式', 'BT刀柄式'), ('SK刀柄式', 'SK刀柄式'), ('HSK刀柄式', 'HSK刀柄式'), [('BT刀柄式', 'BT刀柄式'), ('SK刀柄式', 'SK刀柄式'), ('HSK刀柄式', 'HSK刀柄式'),
('CAT刀柄式', 'CAT刀柄式'), ('ISO刀盘式', 'ISO刀盘式'), ('DIN刀盘式', 'DIN刀盘式'), ('CAT刀柄式', 'CAT刀柄式'), ('ISO刀盘式', 'ISO刀盘式'), ('DIN刀盘式', 'DIN刀盘式'),
@@ -463,7 +377,7 @@ class MachineTableToolChangingApply(models.Model):
:return: :return:
""" """
# 更新数据到机台换刀申请界面 # 更新数据到机台换刀申请界面
if self.functional_tool_status == '报警' and self.sf_functional_tool_assembly_id == False: if self.functional_tool_status == '报警' and not self.sf_functional_tool_assembly_id:
machine_table_tool_changing_apply = self.env['sf.machine.table.tool.changing.apply'].search( machine_table_tool_changing_apply = self.env['sf.machine.table.tool.changing.apply'].search(
[('maintenance_equipment_id', '=', self.maintenance_equipment_id.id), [('maintenance_equipment_id', '=', self.maintenance_equipment_id.id),
('cutter_spacing_code_id', '=', self.cutter_spacing_code_id.id) ('cutter_spacing_code_id', '=', self.cutter_spacing_code_id.id)
@@ -601,9 +515,9 @@ class CAMWorkOrderProgramKnifePlan(models.Model):
# 将计划执行状态改为执行中 # 将计划执行状态改为执行中
self.env['sf.cam.work.order.program.knife.plan'].search( self.env['sf.cam.work.order.program.knife.plan'].search(
[('barcode_id', '=', self.barcode_id.id)]).write({ [('barcode_id', '=', self.barcode_id.id)]).write(
'plan_execute_status': '1', {'plan_execute_status': '1',
'applicant': self.env.user.name}) 'applicant': self.env.user.name})
def revocation(self): def revocation(self):
""" """
@@ -616,11 +530,10 @@ class CAMWorkOrderProgramKnifePlan(models.Model):
# 将计划执行状态改为待执行,同时清除申请人、功能刀具组装字段数据 # 将计划执行状态改为待执行,同时清除申请人、功能刀具组装字段数据
self.env['sf.cam.work.order.program.knife.plan'].search( self.env['sf.cam.work.order.program.knife.plan'].search(
[('barcode_id', '=', self.barcode_id.id)]).write({ [('barcode_id', '=', self.barcode_id.id)]).write(
'plan_execute_status': '0', {'plan_execute_status': '0',
'applicant': None, 'applicant': None,
'sf_functional_tool_assembly_id': None, 'sf_functional_tool_assembly_id': None})
})
class FunctionalToolAssembly(models.Model): class FunctionalToolAssembly(models.Model):

View File

@@ -2,8 +2,6 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sf_functional_cutting_tool_entity,sf.functional.cutting.tool.entity,model_sf_functional_cutting_tool_entity,base.group_user,1,1,1,1 access_sf_functional_cutting_tool_entity,sf.functional.cutting.tool.entity,model_sf_functional_cutting_tool_entity,base.group_user,1,1,1,1
access_sf_functional_tool_warning,sf.functional.tool.warning,model_sf_functional_tool_warning,base.group_user,1,1,1,1 access_sf_functional_tool_warning,sf.functional.tool.warning,model_sf_functional_tool_warning,base.group_user,1,1,1,1
access_sf_real_time_distribution_of_functional_tools,sf.real.time.distribution.of.functional.tools,model_sf_real_time_distribution_of_functional_tools,base.group_user,1,1,1,1 access_sf_real_time_distribution_of_functional_tools,sf.real.time.distribution.of.functional.tools,model_sf_real_time_distribution_of_functional_tools,base.group_user,1,1,1,1
access_sf_inbound_and_outbound_records_of_functional_tools,sf.inbound.and.outbound.records.of.functional.tools,model_sf_inbound_and_outbound_records_of_functional_tools,base.group_user,1,1,1,1
access_sf_inbound_and_outbound_records,sf.inbound.and.outbound.records,model_sf_inbound_and_outbound_records,base.group_user,1,1,1,1
access_sf_cam_work_order_program_knife_plan,sf.cam.work.order.program.knife.plan,model_sf_cam_work_order_program_knife_plan,base.group_user,1,1,1,1 access_sf_cam_work_order_program_knife_plan,sf.cam.work.order.program.knife.plan,model_sf_cam_work_order_program_knife_plan,base.group_user,1,1,1,1
access_sf_machine_table_tool_changing_apply,sf.machine.table.tool.changing.apply,model_sf_machine_table_tool_changing_apply,base.group_user,1,1,1,1 access_sf_machine_table_tool_changing_apply,sf.machine.table.tool.changing.apply,model_sf_machine_table_tool_changing_apply,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_sf_functional_cutting_tool_entity sf.functional.cutting.tool.entity model_sf_functional_cutting_tool_entity base.group_user 1 1 1 1
3 access_sf_functional_tool_warning sf.functional.tool.warning model_sf_functional_tool_warning base.group_user 1 1 1 1
4 access_sf_real_time_distribution_of_functional_tools sf.real.time.distribution.of.functional.tools model_sf_real_time_distribution_of_functional_tools base.group_user 1 1 1 1
access_sf_inbound_and_outbound_records_of_functional_tools sf.inbound.and.outbound.records.of.functional.tools model_sf_inbound_and_outbound_records_of_functional_tools base.group_user 1 1 1 1
access_sf_inbound_and_outbound_records sf.inbound.and.outbound.records model_sf_inbound_and_outbound_records base.group_user 1 1 1 1
5 access_sf_cam_work_order_program_knife_plan sf.cam.work.order.program.knife.plan model_sf_cam_work_order_program_knife_plan base.group_user 1 1 1 1
6 access_sf_machine_table_tool_changing_apply sf.machine.table.tool.changing.apply model_sf_machine_table_tool_changing_apply base.group_user 1 1 1 1
7 access_sf_tool_change_requirement_information sf.tool.change.requirement.information model_sf_tool_change_requirement_information base.group_user 1 1 1 1

View File

@@ -25,15 +25,15 @@
/> />
<menuitem <menuitem
sequence="6" sequence="10"
name="功能刀具实时分布" name="功能刀具安全库存"
id="menu_sf_functional_tool_real_time_distribution" id="menu_sf_functional_tool_real_time_distribution"
action="sf_real_time_distribution_of_functional_tools_view_act" action="sf_real_time_distribution_of_functional_tools_view_act"
parent="menu_sf_tool_manage" parent="menu_sf_tool_manage"
/> />
<menuitem <menuitem
sequence="10" sequence="6"
name="功能刀具出入库记录" name="功能刀具出入库记录"
id="menu_sf_function_tool_entry_exit_records" id="menu_sf_function_tool_entry_exit_records"
action="sf_inbound_and_outbound_records_of_functional_tools_view_act" action="sf_inbound_and_outbound_records_of_functional_tools_view_act"

View File

@@ -51,8 +51,16 @@
</span> </span>
</div> </div>
</button> </button>
<button name="%(stock.action_stock_report)d" icon="fa-arrow-up" class="oe_stat_button" <button class="oe_stat_button"
string="Traceability" type="action"/> name="open_stock_move_line"
icon="fa-list-ul"
type="object">
<div class="o_field_widget o_stat_info">
<span>
出库入库记录
</span>
</div>
</button>
</div> </div>
<div class="oe_title"> <div class="oe_title">
<h1> <h1>
@@ -416,136 +424,43 @@
<record id="sf_inbound_and_outbound_records_of_functional_tools_view_tree" model="ir.ui.view"> <record id="sf_inbound_and_outbound_records_of_functional_tools_view_tree" model="ir.ui.view">
<field name="name">功能刀具出入库记录</field> <field name="name">功能刀具出入库记录</field>
<field name="model">sf.inbound.and.outbound.records.of.functional.tools</field> <field name="model">stock.move.line</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="功能刀具出入库记录" create="0" edit="0" delete="0"> <tree string="功能刀具出入库记录" create="0" edit="0" delete="0">
<field name="barcode_id"/> <field name="reference" string="单据号"/>
<field name="functional_tool_name_id"/> <field name="lot_id" string="功能刀具序列号"/>
<field name="mrs_cutting_tool_type_id"/> <field name="functional_tool_name_id" string="功能刀具名称"/>
<field name="cutting_tool_integral_model_id" optional="hide"/> <field name="diameter"/>
<field name="cutting_tool_blade_model_id" optional="hide"/> <field name="knife_tip_r_angle"/>
<field name="cutting_tool_cutterbar_model_id" optional="hide"/> <field name="install_tool_time"/>
<field name="cutting_tool_cutterpad_model_id" optional="hide"/> <field name="location_id"/>
<field name="cutting_tool_cutterhandle_model_id" optional="hide"/> <field name="location_dest_id"/>
<field name="cutting_tool_cutterhead_model_id" optional="hide"/> <field name="date"/>
<field name="current_state"/> <field name="qty_done" string="数量"/>
<field name="current_store_area"/> <field name="functional_tool_type_id" invisible="True"/>
<field name="current_store_place"/>
<!-- <field name="applicant"/>-->
</tree> </tree>
</field> </field>
</record> </record>
<record id="sf_inbound_and_outbound_records_of_functional_tools_view_form" model="ir.ui.view">
<field name="name">功能刀具出入库记录</field>
<field name="model">sf.inbound.and.outbound.records.of.functional.tools</field>
<field name="arch" type="xml">
<form string="功能刀具出入库记录" create="0" edit="0" delete="0">
<sheet>
<div class="oe_title">
<h1>
<field name="barcode_id" readonly="1"/>
</h1>
</div>
<group>
<group>
<field name="functional_tool_name_id" invisible="False"/>
<field name="mrs_cutting_tool_type_id"/>
<field name="cutting_tool_integral_model_id"
options="{'no_create': True, 'no_quick_create': True}"
attrs="{'invisible': [('cutting_tool_blade_model_id', '!=', False)]}"
/>
<field name="cutting_tool_blade_model_id"
options="{'no_create': True, 'no_quick_create': True}"
attrs="{'invisible': [('cutting_tool_integral_model_id', '!=', False)]}"
/>
<field name="cutting_tool_cutterbar_model_id"
options="{'no_create': True, 'no_quick_create': True}"
attrs="{'invisible': ['|',('cutting_tool_cutterpad_model_id','!=',False),('cutting_tool_blade_model_id', '=', False)]}"
/>
<field name="cutting_tool_cutterpad_model_id"
options="{'no_create': True, 'no_quick_create': True}"
attrs="{'invisible': ['|',('cutting_tool_cutterbar_model_id','!=',False),('cutting_tool_blade_model_id', '=', False)]}"
/>
<field name="cutting_tool_cutterhandle_model_id"
options="{'no_create': True, 'no_quick_create': True}"/>
<field name="cutting_tool_cutterhead_model_id"
options="{'no_create': True, 'no_quick_create': True}"/>
</group>
<group>
<field name="image" nolabel="1" widget="image"/>
</group>
</group>
<notebook>
<page string="出入库信息">
<field name="inbound_and_outbound_records_ids"/>
</page>
<page string="参数信息">
<group>
<group>
<field name="diameter"/>
<field name="tool_grade"/>
<field name="machining_accuracy"/>
<field name="tool_length"/>
<field name="blade_number"/>
</group>
<group>
<field name="integral_blade_length"/>
<field name="effective_blade_length"/>
<field name="max_life"/>
<field name="is_standard" default="false"/>
<field name="applicable_range"/>
</group>
</group>
</page>
<page string="其他信息">
<group>
<group>
<field name="current_store_area"/>
<field name="current_store_place"/>
<field name="alarm_value"/>
<field name="tool_install_staff"/>
<field name="applicant"/>
<field name="remark"/>
</group>
<group>
<field name="current_state"/>
<field name="thickness"/>
<!-- <field name="max_life_span"/>-->
<field name="used_value"/>
<field name="tool_install_time"/>
<field name="reason_application"/>
</group>
</group>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="sf_inbound_and_outbound_records_of_functional_tools_view_search" model="ir.ui.view"> <record id="sf_inbound_and_outbound_records_of_functional_tools_view_search" model="ir.ui.view">
<field name="name">功能刀具出入库记录</field> <field name="name">功能刀具出入库记录</field>
<field name="model">sf.inbound.and.outbound.records.of.functional.tools</field> <field name="model">stock.move.line</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search> <search>
<field name="barcode_id"/> <field name="reference"/>
<field name="lot_id"/>
<field name="functional_tool_name_id"/> <field name="functional_tool_name_id"/>
<field name="mrs_cutting_tool_type_id"/> <field name="diameter"/>
<field name="cutting_tool_integral_model_id" optional="hide"/> <field name="knife_tip_r_angle"/>
<field name="cutting_tool_blade_model_id" optional="hide"/> <field name="install_tool_time"/>
<field name="cutting_tool_cutterbar_model_id" optional="hide"/> <field name="location_id"/>
<field name="cutting_tool_cutterpad_model_id" optional="hide"/> <field name="location_dest_id"/>
<field name="cutting_tool_cutterhandle_model_id" optional="hide"/> <field name="date"/>
<field name="cutting_tool_cutterhead_model_id" optional="hide"/> <field name="qty_done"/>
<field name="current_state"/> <field name="functional_tool_type_id" invisible="True"/>
<field name="current_store_area"/>
<field name="current_store_place"/>
<!-- <field name="applicant"/>-->
<searchpanel> <searchpanel>
<field name="mrs_cutting_tool_type_id" enable_counters="1" icon="fa-building"/> <field name="functional_tool_type_id" enable_counters="1" icon="fa-building"/>
</searchpanel> </searchpanel>
</search> </search>
</field> </field>
@@ -554,62 +469,13 @@
<record id="sf_inbound_and_outbound_records_of_functional_tools_view_act" model="ir.actions.act_window"> <record id="sf_inbound_and_outbound_records_of_functional_tools_view_act" model="ir.actions.act_window">
<field name="name">功能刀具出入库记录</field> <field name="name">功能刀具出入库记录</field>
<field name="type">ir.actions.act_window</field> <field name="type">ir.actions.act_window</field>
<field name="res_model">sf.inbound.and.outbound.records.of.functional.tools</field> <field name="res_model">stock.move.line</field>
<field name="view_mode">tree,form,search</field> <field name="view_mode">tree,search</field>
</record> <field name="view_id"
ref="sf_tool_management.sf_inbound_and_outbound_records_of_functional_tools_view_tree"/>
<field name="search_view_id"
<!--================================================出入库记录================================================--> ref="sf_tool_management.sf_inbound_and_outbound_records_of_functional_tools_view_search"/>
<record id="sf_inbound_and_outbound_records_view_tree" model="ir.ui.view"> <field name="domain">[('functional_tool_name_id', '!=', False)]</field>
<field name="name">出入库记录</field>
<field name="model">sf.inbound.and.outbound.records</field>
<field name="arch" type="xml">
<tree>
<field name="tool_state"/>
<field name="receive_equipment"/>
<field name="receive_staff"/>
<field name="receive_time"/>
<field name="return_staff"/>
<field name="return_time"/>
<field name="current_store_area"/>
<field name="current_store_place"/>
<field name="number"/>
</tree>
</field>
</record>
<record id="sf_inbound_and_outbound_records_view_form" model="ir.ui.view">
<field name="name">出入库记录</field>
<field name="model">sf.inbound.and.outbound.records</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<group>
<field name="tool_state"/>
<field name="receive_equipment"/>
<field name="receive_staff"/>
<field name="receive_time"/>
<field name="current_store_area"/>
</group>
<group>
<field name="number"/>
<field name="return_staff"/>
<field name="return_time"/>
<field name="inbound_and_outbound_tools_id" readonly="True"/>
<field name="current_store_place"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="sf_inbound_and_outbound_records_view_act" model="ir.actions.act_window">
<field name="name">出入库记录</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sf.inbound.and.outbound.records</field>
<field name="view_mode">tree,form</field>
</record> </record>
@@ -624,7 +490,7 @@
<field name="maintenance_equipment_id"/> <field name="maintenance_equipment_id"/>
<field name="machine_tool_code"/> <field name="machine_tool_code"/>
<field name="cutter_spacing_code_id"/> <field name="cutter_spacing_code_id"/>
<field name="functional_tool_name"/> <field name="functional_tool_name_id"/>
<field name="diameter"/> <field name="diameter"/>
<field name="knife_tip_r_angle"/> <field name="knife_tip_r_angle"/>
<field name="max_lifetime_value"/> <field name="max_lifetime_value"/>
@@ -639,9 +505,8 @@
<field name="tool_position_interface_type" invisible="1"/> <field name="tool_position_interface_type" invisible="1"/>
<field name="extension_length" invisible="1"/> <field name="extension_length" invisible="1"/>
<field name="effective_length" invisible="1"/> <field name="effective_length" invisible="1"/>
<field name="functional_tool_name_id" invisible="1"/>
<field name="whether_standard_knife" invisible="1"/>
<field name="functional_tool_name" invisible="1"/> <field name="functional_tool_name" invisible="1"/>
<field name="whether_standard_knife" invisible="1"/>
<field name="status" invisible="1"/> <field name="status" invisible="1"/>
<button string="换刀申请" <button string="换刀申请"
name="%(sf_tool_management.sf_tool_change_requirement_information_act)d" name="%(sf_tool_management.sf_tool_change_requirement_information_act)d"
@@ -654,7 +519,6 @@
'default_cutter_spacing_code_id': cutter_spacing_code_id, 'default_cutter_spacing_code_id': cutter_spacing_code_id,
'default_barcode_id': barcode_id, 'default_barcode_id': barcode_id,
'default_functional_tool_name': functional_tool_name, 'default_functional_tool_name': functional_tool_name,
'default_functional_tool_name_id': functional_tool_name_id,
'default_functional_tool_type_id': functional_tool_type_id, 'default_functional_tool_type_id': functional_tool_type_id,
'default_tool_position_interface_type': tool_position_interface_type, 'default_tool_position_interface_type': tool_position_interface_type,
'default_diameter': diameter, 'default_diameter': diameter,
@@ -690,7 +554,6 @@
'default_cutter_spacing_code_id': cutter_spacing_code_id, 'default_cutter_spacing_code_id': cutter_spacing_code_id,
'default_barcode_id': barcode_id, 'default_barcode_id': barcode_id,
'default_functional_tool_name': functional_tool_name, 'default_functional_tool_name': functional_tool_name,
'default_functional_tool_name_id': functional_tool_name_id,
'default_functional_tool_type_id': functional_tool_type_id, 'default_functional_tool_type_id': functional_tool_type_id,
'default_tool_position_interface_type': tool_position_interface_type, 'default_tool_position_interface_type': tool_position_interface_type,
'default_diameter': diameter, 'default_diameter': diameter,
@@ -730,7 +593,6 @@
'default_cutter_spacing_code_id': cutter_spacing_code_id, 'default_cutter_spacing_code_id': cutter_spacing_code_id,
'default_barcode_id': barcode_id, 'default_barcode_id': barcode_id,
'default_functional_tool_name': functional_tool_name, 'default_functional_tool_name': functional_tool_name,
'default_functional_tool_name_id': functional_tool_name_id,
'default_functional_tool_type_id': functional_tool_type_id, 'default_functional_tool_type_id': functional_tool_type_id,
'default_tool_position_interface_type': tool_position_interface_type, 'default_tool_position_interface_type': tool_position_interface_type,
'default_diameter': diameter, 'default_diameter': diameter,
@@ -766,7 +628,6 @@
'default_cutter_spacing_code_id': cutter_spacing_code_id, 'default_cutter_spacing_code_id': cutter_spacing_code_id,
'default_barcode_id': barcode_id, 'default_barcode_id': barcode_id,
'default_functional_tool_name': functional_tool_name, 'default_functional_tool_name': functional_tool_name,
'default_functional_tool_name_id': functional_tool_name_id,
'default_functional_tool_type_id': functional_tool_type_id, 'default_functional_tool_type_id': functional_tool_type_id,
'default_tool_position_interface_type': tool_position_interface_type, 'default_tool_position_interface_type': tool_position_interface_type,
'default_diameter': diameter, 'default_diameter': diameter,
@@ -803,7 +664,7 @@
</group> </group>
<field name="name" invisible="True"/> <field name="name" invisible="True"/>
<field name="machine_tool_code" invisible="True"/> <field name="machine_tool_code" invisible="True"/>
<field name="functional_tool_name_id" invisible="True"/> <field name="functional_tool_name" invisible="True"/>
<field name="whether_standard_knife" invisible="True"/> <field name="whether_standard_knife" invisible="True"/>
<field name="status" invisible="True"/> <field name="status" invisible="True"/>
<notebook> <notebook>
@@ -811,7 +672,7 @@
<group> <group>
<group> <group>
<field name="barcode_id"/> <field name="barcode_id"/>
<field name="functional_tool_name"/> <field name="functional_tool_name_id"/>
<field name="functional_tool_type_id"/> <field name="functional_tool_type_id"/>
<field name="diameter"/> <field name="diameter"/>
<field name="knife_tip_r_angle"/> <field name="knife_tip_r_angle"/>
@@ -843,7 +704,7 @@
<field name="machine_table_type_id"/> <field name="machine_table_type_id"/>
<field name="cutter_spacing_code_id" optional="hide"/> <field name="cutter_spacing_code_id" optional="hide"/>
<field name="barcode_id" invisible="1"/> <field name="barcode_id" invisible="1"/>
<field name="functional_tool_name"/> <field name="functional_tool_name_id"/>
<field name="diameter"/> <field name="diameter"/>
<field name="knife_tip_r_angle"/> <field name="knife_tip_r_angle"/>
<field name="max_lifetime_value"/> <field name="max_lifetime_value"/>

View File

@@ -339,33 +339,28 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
功能刀具组装 功能刀具组装
:return: :return:
""" """
# 对物料做必填判断
self.materials_must_be_judged()
# 创建组装入库单
# 创建功能刀具批次/序列号记录
stock_lot = self.create_assemble_warehouse_receipt()
# 创建刀具组装入库单
self.create_stocking_picking(stock_lot)
# 封装功能刀具数据
desc_1 = self.get_desc_1(stock_lot)
functional_tool_assembly = self.env['sf.functional.tool.assembly'].search([ functional_tool_assembly = self.env['sf.functional.tool.assembly'].search([
('assembly_order_code', '=', self.assembly_order_code), ('assembly_order_code', '=', self.assembly_order_code),
('machine_tool_name_id', '=', self.machine_tool_name_id.id), ('machine_tool_name_id', '=', self.machine_tool_name_id.id),
('cutter_spacing_code_id', '=', self.cutter_spacing_code_id.id), ('cutter_spacing_code_id', '=', self.cutter_spacing_code_id.id),
('assemble_status', '=', '0'), ('assemble_status', '=', '0'),
]) ])
# 对物料做必填判断
self.materials_must_be_judged()
# 创建组装入库单
# 创建功能刀具批次/序列号记录
stock_lot = self.create_assemble_warehouse_receipt(functional_tool_assembly)
# 创建刀具组装入库单
self.create_stocking_picking(stock_lot)
# 封装功能刀具数据
desc_1 = self.get_desc_1(stock_lot)
# 创建功能刀具列表记录 # 创建功能刀具列表记录
# 封装功能刀具数据 # 封装功能刀具数据
desc_2 = self.get_desc_2(stock_lot, functional_tool_assembly) desc_2 = self.get_desc_2(stock_lot, functional_tool_assembly)
# 创建功能刀具列表、功能刀具预警、功能刀具实时分布、功能刀具出入库记录 # 创建功能刀具列表、功能刀具预警、功能刀具实时分布、功能刀具出入库记录
record_1 = self.env['sf.functional.cutting.tool.entity'].create(desc_2) record_1 = self.env['sf.functional.cutting.tool.entity'].create(desc_2)
# self.env['sf.functional.tool.warning'].create({
# 'functional_cutting_tool_id': record_1.id,
# 'functional_tool_assembly_id': functional_tool_assembly.id,
# 'machine_table_name_id': self.machine_tool_name_id.id,
# })
# self.env['sf.real.time.distribution.of.functional.tools'].create({ # self.env['sf.real.time.distribution.of.functional.tools'].create({
# 'functional_cutting_tool_id': record_1.id # 'functional_cutting_tool_id': record_1.id
# }) # })
@@ -419,7 +414,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
# 将刀具组装入库单的状态更改为就绪 # 将刀具组装入库单的状态更改为就绪
picking_id.action_confirm() picking_id.action_confirm()
def create_assemble_warehouse_receipt(self): def create_assemble_warehouse_receipt(self, functional_tool_assembly):
""" """
创建功能刀具批次/序列号记录 创建功能刀具批次/序列号记录
""" """
@@ -431,11 +426,11 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
'company_id': self.env.company.id 'company_id': self.env.company.id
}) })
# 创建功能刀具该批次/序列号 库存移动和移动历史 # 创建功能刀具该批次/序列号 库存移动和移动历史
self.create_stock_quant(product_id, stock_lot) self.create_stock_quant(product_id, stock_lot, functional_tool_assembly)
return stock_lot return stock_lot
def create_stock_quant(self, product_id, stock_lot): def create_stock_quant(self, product_id, stock_lot, functional_tool_assembly):
""" """
创建功能刀具该批次/序列号 库存移动和移动历史 创建功能刀具该批次/序列号 库存移动和移动历史
""" """
@@ -445,7 +440,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
# 创建库存移动 # 创建库存移动
stock_move_id = self.env['stock.move'].create({ stock_move_id = self.env['stock.move'].create({
'name': '更新的产品数量', 'name': '功能刀具组装出库',
'product_id': product_id.id, 'product_id': product_id.id,
'location_id': location_inventory_id.id, 'location_id': location_inventory_id.id,
'location_dest_id': stock_location_id.id, 'location_dest_id': stock_location_id.id,
@@ -456,8 +451,10 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
# 创建移动历史 # 创建移动历史
stock_move_line_id = self.env['stock.move.line'].create({ stock_move_line_id = self.env['stock.move.line'].create({
'product_id': product_id.id, 'product_id': product_id.id,
'functional_tool_name_id': functional_tool_assembly.id,
'lot_id': stock_lot.id, 'lot_id': stock_lot.id,
'move_id': stock_move_id.id, 'move_id': stock_move_id.id,
'install_tool_time': fields.Datetime.now(),
'qty_done': 1.0, 'qty_done': 1.0,
'state': 'done' 'state': 'done'
}) })

View File

@@ -25,4 +25,3 @@
'application': True, 'application': True,
'images': ['static/description/banner.png'], 'images': ['static/description/banner.png'],
} }

View File

@@ -5,8 +5,10 @@ from odoo import api, fields, models, modules
class ResConfigSettings(models.TransientModel): class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings' _inherit = 'res.config.settings'
style = fields.Selection([('default', 'Default'), ('left', 'Left'), ('right', 'Right'), ('middle', 'Middle')], help='Select Background Theme') style = fields.Selection([('default', 'Default'), ('left', 'Left'), ('right', 'Right'), ('middle', 'Middle')],
background = fields.Selection([('image', 'Image'), ('color', 'Color')], default='color', help='Select Background Theme') help='Select Background Theme')
background = fields.Selection([('image', 'Image'), ('color', 'Color')], default='color',
help='Select Background Theme')
background_image = fields.Many2one('login.image', string="Image", help='Select Background Image For Login Page') background_image = fields.Many2one('login.image', string="Image", help='Select Background Image For Login Page')
color = fields.Char(string="Color", help="Choose your Background color") color = fields.Char(string="Color", help="Choose your Background color")

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from odoo import models
import ctypes import ctypes
from odoo import models
class Common(models.Model): class Common(models.Model):
@@ -19,6 +19,3 @@ class Common(models.Model):
tsclibrary.closeport(); tsclibrary.closeport();
except Exception as e: except Exception as e:
raise UserWarning("错误警告") raise UserWarning("错误警告")