Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修改机床参数bug

This commit is contained in:
qihao.gong@jikimo.com
2024-03-22 14:44:57 +08:00
77 changed files with 2426 additions and 1158 deletions

View File

@@ -10,9 +10,9 @@
""", """,
'category': 'sf', 'category': 'sf',
'website': 'https://www.sf.jikimo.com', 'website': 'https://www.sf.jikimo.com',
'depends': ['web', 'purchase'], 'depends': ['web', 'purchase', 'base_setup'],
'data': [ 'data': [
'views/bye_odoo.xml',
], ],
'demo': [ 'demo': [
], ],
@@ -23,6 +23,8 @@
'web.assets_backend': [ 'web.assets_backend': [
'jikimo_frontend/static/src/fields/custom_many2many_checkboxes/*', 'jikimo_frontend/static/src/fields/custom_many2many_checkboxes/*',
'jikimo_frontend/static/src/fields/Many2OneRadioField/*', 'jikimo_frontend/static/src/fields/Many2OneRadioField/*',
# 移除odoo相关标识
'jikimo_frontend/static/src/bye_odoo/*',
'jikimo_frontend/static/src/scss/custom_style.scss', 'jikimo_frontend/static/src/scss/custom_style.scss',
# 'jikimo_frontend/static/src/views/list_nums/list_nbCols.js', # 'jikimo_frontend/static/src/views/list_nums/list_nbCols.js',
'jikimo_frontend/static/src/views/list_nums/list_nums.xml', 'jikimo_frontend/static/src/views/list_nums/list_nums.xml',

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="partner_demo_company" model="res.partner">
<field name="name">JKM</field>
<field name="street">B-25</field>
<field name="city">USA</field>
<!-- Use the correct reference or actual ID for the country -->
<field name="country_id" ref="base.bd"/>
<field name="zip">1229</field>
<field name="phone">+8801-712901764</field>
<field name="email">info@kolpolok.com</field>
<field name="website">www.kolpoloktechnologies.com</field>
</record>
<record id="demo_company" model="res.company">
<field name="name">Custom</field>
<field name="logo" type="base64" file="kolpolok_custom_title_and_favicon/static/src/img/favicon.ico"/>
<field name="favicon" type="base64" file="kolpolok_custom_title_and_favicon/static/src/img/favicon.ico"/>
<field name="partner_id" ref="partner_demo_company"/>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,16 @@
/** @odoo-module **/
import { UserMenu } from "@web/webclient/user_menu/user_menu";
import { patch } from "@web/core/utils/patch";
import { registry } from "@web/core/registry";
const userMenuRegistry = registry.category("user_menuitems");
patch(UserMenu.prototype, "legion_hide_odoo.UserMenu", {
setup() {
this._super.apply(this, arguments);
userMenuRegistry.remove("documentation");
userMenuRegistry.remove("support");
userMenuRegistry.remove("odoo_account");
},
});

View File

@@ -0,0 +1,11 @@
/** @odoo-module **/
import { WebClient } from "@web/webclient/webclient";
import { patch } from "web.utils";
patch(WebClient.prototype, "kolpolok_custom_title_and_favicon.WebClient", {
setup() {
this._super();
this.title.setParts({ zopenerp: "JIKIMO" });
},
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -5,9 +5,44 @@ import {patch} from '@web/core/utils/patch';
import {_t} from "@web/core/l10n/translation"; import {_t} from "@web/core/l10n/translation";
import {FormStatusIndicator} from "@web/views/form/form_status_indicator/form_status_indicator"; import {FormStatusIndicator} from "@web/views/form/form_status_indicator/form_status_indicator";
import {Field} from "@web/views/fields/field";
var Dialog = require('web.Dialog'); var Dialog = require('web.Dialog');
// var {patch} = require("web.utils") 这句话也行 // var {patch} = require("web.utils") 这句话也行
const filedRequiredList = {
// 设备大模块
'control_system_id': { multiple: false, noLabel: false },
'workbench_L': { multiple: true, noLabel: false },
'number_of_axles': { multiple: true, noLabel: false },
'x_axis': { multiple: true, noLabel: false },
'number_of_knife_library': { multiple: false, noLabel: false },
'brand_id': { multiple: false, noLabel: false },
'type_id': { multiple: false, noLabel: false },
'taper_type_id': { multiple: false, noLabel: false },
'eq_maintenance_id': { multiple: false, noLabel: false },
'overhaul_id': { multiple: false, noLabel: false },
'overhaul_period': { multiple: false, noLabel: false },
'maintenance_equipment_category_id': { multiple: false, noLabel: false },
'maintenance_type': { multiple: false, noLabel: false },
// 销售大模块
'partner_id': { multiple: false, noLabel: false },
'validity_date': { multiple: false, noLabel: false },
'vat': { multiple: false, noLabel: false },
'phone': { multiple: false, noLabel: false },
'mobile': { multiple: false, noLabel: false },
'email': { multiple: false, noLabel: false },
'category_id': { multiple: false, noLabel: false },
'radio_field_1_person': { multiple: false, noLabel: true },
// 采购大模块
'date_order': { multiple: false, noLabel: false },
'picking_type_id': { multiple: false, noLabel: false },
// 制造大模块
'production_line_id': { multiple: false, noLabel: false },
'date_approve': { multiple: false, noLabel: false },
}
patch(FormStatusIndicator.prototype, 'jikimo_frontend.FormStatusIndicator', { patch(FormStatusIndicator.prototype, 'jikimo_frontend.FormStatusIndicator', {
// 你可以重写或者添加一些方法和属性 // 你可以重写或者添加一些方法和属性
async _onDiscardChanges() { async _onDiscardChanges() {
@@ -46,6 +81,38 @@ patch(FormStatusIndicator.prototype, 'jikimo_frontend.FormStatusIndicator', {
} }
); );
patch(Field.prototype, 'jikimo_frontend.Field', {
setup() {
this.FieldComponent = this.props.fieldInfo.FieldComponent;
if (!this.FieldComponent) {
const fieldType = this.props.record.fields[this.props.name].type;
this.FieldComponent = getFieldClassFromRegistry(fieldType, this.props.type);
}
owl.onMounted(this.setRequired);
},
setRequired() {
const id = this.props.id
const isRequired = filedRequiredList[id]
if(id == 'number_of_axles') {
console.log(isRequired)
}
if(isRequired) {
let dom;
dom = $(`label[for=${id}]`)
if(isRequired.multiple && dom.length > 1) {
dom = dom.eq(-1)
dom = dom.parent().parent().next().find('label')
}
if(isRequired.noLabel) {
dom = dom.parent().parent()
}
let t = dom.html()
t = '<i class="c* r" style="color: red;margin-left: -4px">*</i>' + t
dom.html(t)
}
}
})
$(function () { $(function () {
document.addEventListener('click', function () { document.addEventListener('click', function () {
@@ -82,7 +149,7 @@ $(function () {
dom.each(function () { dom.each(function () {
const requiredDom = $(this).parent().prev().find('label') const requiredDom = $(this).parent().prev().find('label')
let t = requiredDom.html() let t = requiredDom.html()
if (t.indexOf('c*') < 0) { if (t && t.indexOf('c*') < 0) {
t = '<i class="c*" style="color: red;margin-left: -4px">*</i>' + t t = '<i class="c*" style="color: red;margin-left: -4px">*</i>' + t
} }
requiredDom.html(t) requiredDom.html(t)
@@ -104,16 +171,7 @@ $(function () {
const lint = $('.o_form_view_container') const lint = $('.o_form_view_container')
if (lint.length) { if (lint.length) {
clearInterval(domTimer) clearInterval(domTimer)
const {label, table} = dom const { table} = dom
if (label.length) {
$(dom.label.join(',')).each(function () {
let t = $(this).html()
if (t.indexOf('c*') < 0) {
t = '<i class="c*" style="color: red;margin-left: -6px;margin-right: 2px">*</i>' + t
}
$(this).html(t)
})
}
if (table.length) { if (table.length) {
table.forEach(_ => { table.forEach(_ => {
@@ -133,8 +191,7 @@ $(function () {
var currentUrl = location.href var currentUrl = location.href
const customRequiredDom = { const customRequiredDom = {
label: ['label[for=production_line_id]','label[for=date_approve]','label[for=partner_id]', 'label[for=validity_date]', '.o_horizontal[role=radiogroup][aria-label="公司类别"]', 'label[for=vat]', 'label[for=phone]', 'label[for=mobile]', 'label[for=email]', 'label[for=category_id]','label[for=date_order]','label[for=picking_type_id]'], table: ['product_template_id', 'product_uom_qty', 'price_unit','product_id','product_qty', 'name', 'fault_type', 'maintenance_standards', 'Period']
table: ['product_template_id', 'product_uom_qty', 'price_unit','product_id','product_qty']
} }
const listenerUrl = setInterval(() => { const listenerUrl = setInterval(() => {
const isChange = currentUrl != location.href const isChange = currentUrl != location.href
@@ -143,9 +200,6 @@ $(function () {
customRequired() customRequired()
setRequired(customRequiredDom) setRequired(customRequiredDom)
} }
if($('label[for=production_line_id]')) {
setRequired({table: [], label: ['label[for=production_line_id]']})
}
}, 500) }, 500)
customRequired() customRequired()
setRequired(customRequiredDom) setRequired(customRequiredDom)

View File

@@ -4,6 +4,8 @@ import { registry } from "@web/core/registry";
import { url } from "@web/core/utils/urls"; import { url } from "@web/core/utils/urls";
import { ImageField, imageCacheKey } from '@web/views/fields/image/image_field'; import { ImageField, imageCacheKey } from '@web/views/fields/image/image_field';
const placeholder = "/web/static/img/placeholder.png";
export class CustomImageField extends ImageField { export class CustomImageField extends ImageField {
setup() { setup() {
super.setup(); super.setup();

View File

@@ -450,3 +450,20 @@ div:has(.o_required_modifier) > label::before {
} }
} }
// 更改表格底部按钮样式
.o_list_renderer .o_field_x2many_list_row_add a,.treeHeaderBtn,.o_x2m_control_panel .o_cp_buttons .btn{
display: inline-block;
margin: 5px 0;
font-size: 14px;
color: #71639e;
border: 1px solid #71639e;
padding: 0.2rem 0.6rem;
font-size: 1.08333333rem;
border-radius: 0.25rem;
transition: all .3s;
}
.o_list_renderer .o_field_x2many_list_row_add a:hover,.treeHeaderBtn:hover,.o_x2m_control_panel .o_cp_buttons .btn:hover{
background: #71639e;
color: #fff
}

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- 修改页面头部图标及文字 -->
<template id="favicon_icon" inherit_id="web.layout" name="Web layout">
<!-- change the title with reliance partner -->
<xpath expr="//head//title" position="before">
<title t-esc="'JIKIMO'"/>
</xpath>
<!-- change the default favicon icon with -->
<xpath expr="//head//link[@rel='shortcut icon']" position="replace">
<link type="image/x-icon" rel="shortcut icon" href="/jikimo_frontend/static/src/img/jikimo-logo.ico"/>
</xpath>
</template>
<!-- hide 登录页面 powerd by odoo 及管理数据库 -->
<template id="login_page_layout" inherit_id="web.login_layout" name="Login Page Layout">
<xpath expr="//div[@class='card-body']//div[last()]" position="replace"></xpath>
</template>
<!-- 隐藏odoo版本信息 -->
<record id="jikimo_res_config_settings_view_form" model="ir.ui.view">
<field name="name">jikimo.res.config.settings.view.form.inherit.base.setup</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base_setup.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@id='about']" position="replace">
</xpath>
</field>
</record>
</data>
</odoo>

View File

@@ -24,6 +24,7 @@
'views/tool_menu.xml', 'views/tool_menu.xml',
'views/menu_fixture_view.xml', 'views/menu_fixture_view.xml',
'views/change_base_view.xml', 'views/change_base_view.xml',
'views/Printer.xml',
], ],
'demo': [ 'demo': [

View File

@@ -0,0 +1,28 @@
from odoo import models, fields
class Printer(models.Model):
_name = 'printer'
_description = 'Printer'
name = fields.Char(string='名称', required=True)
ip_address = fields.Char(string='IP 地址', required=True)
port = fields.Integer(string='端口', default=9100)
class TableStyle(models.Model):
_name = 'table.style'
_description = '标签样式'
name = fields.Char(string='名称', required=True)
# todo
class PrinterConfiguration(models.Model):
_name = 'printer.configuration'
_description = 'Printer Configuration'
name = fields.Char(string='名称', required=True)
printer_id = fields.Many2one('printer', string='打印机')
model = fields.Many2one('ir.model', string='模型名称')
# # 其他相关字段...

View File

@@ -1 +1,2 @@
from . import common from . import common
from . import Printer

View File

@@ -2,7 +2,7 @@
import time, datetime import time, datetime
import hashlib import hashlib
from odoo import models from odoo import models
import socket
class Common(models.Model): class Common(models.Model):
_name = 'sf.sync.common' _name = 'sf.sync.common'
@@ -29,3 +29,66 @@ class Common(models.Model):
d = dt + datetime.timedelta(hours=8) d = dt + datetime.timedelta(hours=8)
nTime = d.strftime("%Y-%m-%d %H:%M:%S") nTime = d.strftime("%Y-%m-%d %H:%M:%S")
return nTime return nTime
class PrintingUtils(models.AbstractModel):
_name = 'printing.utils'
_description = 'Utility class for printing functionalities'
def generate_zpl_code(self, code):
# 实现生成ZPL代码的逻辑
# 初始化ZPL代码字符串
zpl_code = "^XA\n"
zpl_code += "^CW1,E:SIMSUN.TTF^FS\n"
zpl_code += "^CI28\n"
# 设置二维码位置
zpl_code += "^FO50,50\n" # 调整二维码位置,使其与资产编号在同一行
zpl_code += f"^BQN,2,6^FDLM,B0093{code}^FS\n"
# 设置资产编号文本位置
zpl_code += "^FO300,60\n" # 资产编号文本的位置,与二维码在同一行
zpl_code += "^A1N,45,45^FD编码名称: ^FS\n"
# 设置{code}文本位置
# 假设{code}文本需要位于资产编号和二维码下方,中间位置
# 设置{code}文本位置并启用自动换行
zpl_code += "^FO300,120\n" # {code}文本的起始位置
zpl_code += "^FB400,4,0,L,0\n" # 定义一个宽度为500点的文本框最多4行左对齐
zpl_code += f"^A1N,40,40^FD{code}^FS\n"
# 在{code}文本框周围绘制线框
# 假设线框的外部尺寸为宽度500点高度200点
# zpl_code += "^FO300,110^GB500,200,2^FS\n" # 绘制线框边框粗细为2点
zpl_code += "^PQ1,0,1,Y\n"
zpl_code += "^XZ\n"
return zpl_code
def send_to_printer(self, host, port, zpl_code):
# 实现发送ZPL代码到打印机的逻辑
# 将ZPL代码转换为字节串
print('zpl_code', zpl_code)
zpl_bytes = zpl_code.encode('utf-8')
print(zpl_bytes)
# 创建socket对象
mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
mysocket.connect((host, port)) # 连接到打印机
mysocket.send(zpl_bytes) # 发送ZPL代码
print("ZPL code sent to printer successfully.")
except Exception as e:
print(f"Error with the connection: {e}")
finally:
mysocket.close() # 关闭连接
def print_qr_code(self, lot_name, host, port):
# 实现打印二维码的逻辑
# 这里需要传入 lot_name 参数,因为我们不能直接访问 self.lot_id.name
zpl_code = self.generate_zpl_code(lot_name)
# 发送ZPL代码到打印机
# host = "192.168.50.110" # 可以作为参数传入,或者在此配置
# port = 9100 # 可以作为参数传入,或者在此配置
self.send_to_printer(host, port, zpl_code)

View File

@@ -67,186 +67,220 @@ class BasicParametersFixture(models.Model):
mounting_hole_depth = fields.Float('安装孔深度(mm)', digits=(16, 2)) mounting_hole_depth = fields.Float('安装孔深度(mm)', digits=(16, 2))
centering_diameter = fields.Float('定心直径(mm)', digits=(16, 2)) centering_diameter = fields.Float('定心直径(mm)', digits=(16, 2))
code = fields.Char('编码')
active = fields.Boolean('有效', default=True)
def _get_basic_parameters_list(self, fixture_materials_data, fixture_materials_name):
if fixture_materials_name == '零点卡盘':
return self._json_zero_chuck_param(fixture_materials_data)
elif fixture_materials_name == '零点托盘':
return self._json_zero_tray_param(fixture_materials_data)
elif fixture_materials_name == '气动夹具':
return self._json_pneumatic_fixture_param(fixture_materials_data)
elif fixture_materials_name == '虎钳夹具':
return self._json_jaw_vice_fixture_param(fixture_materials_data)
elif fixture_materials_name == '磁吸夹具':
return self._json_magnet_fixture_param(fixture_materials_data)
elif fixture_materials_name == '转接板(锁板)夹具':
return self._json_adapter_board_fixture_param(fixture_materials_data)
elif fixture_materials_name == '三爪卡盘':
return self._json_scroll_chuck_param(fixture_materials_data)
return {}
def _json_zero_chuck_param(self, obj): def _json_zero_chuck_param(self, obj):
zero_chuck_param_str = (0, '', { """零点卡盘将data数据转换成list数据"""
'name': obj['name'], return {'code': obj['code'],
'length': obj['length'], 'fixture_model_id': self.env['sf.fixture.model'].sudo().search(
'width': obj['width'], [('code', '=', obj.get('fixture_model_code'))]).id,
'height': obj['height'], 'name': obj['name'],
'diameter': obj['diameter'], 'length': obj['length'],
'weight': obj['weight'], 'width': obj['width'],
'orientation_dish_diameter': obj['orientation_dish_diameter'], 'height': obj['height'],
'clamping_diameter': obj['clamping_diameter'], 'diameter': obj['diameter'],
'clamping_num': obj['clamping_num'], 'weight': obj['weight'],
'chucking_power_max': obj['chucking_power_max'], 'orientation_dish_diameter': obj['orientation_dish_diameter'],
'repeated_positioning_accuracy': obj['repeated_positioning_accuracy'], 'clamping_diameter': obj['clamping_diameter'],
'boolean_transposing_hole': obj['boolean_transposing_hole'], 'clamping_num': obj['clamping_num'],
'unlocking_method': obj['unlocking_method'], 'chucking_power_max': obj['chucking_power_max'],
'boolean_chip_blowing_function': obj['boolean_chip_blowing_function'], 'repeated_positioning_accuracy': obj['repeated_positioning_accuracy'],
'carrying_capacity_max': obj['carrying_capacity_max'], 'boolean_transposing_hole': obj['boolean_transposing_hole'],
'rigidity': obj['rigidity'], 'unlocking_method': obj['unlocking_method'],
'materials_model_id': self.env['sf.materials.model'].sudo().search( 'boolean_chip_blowing_function': obj['boolean_chip_blowing_function'],
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id, 'carrying_capacity_max': obj['carrying_capacity_max'],
'machine_tool_type_id': self.env['sf.machine_tool.type'].sudo().search( 'rigidity': obj['rigidity'],
[('code', '=', obj['machine_tool_type_id']), ('active', '=', True)]).id, 'materials_model_id': self.env['sf.materials.model'].sudo().search(
}) [('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
return zero_chuck_param_str 'machine_tool_type_id': self.env['sf.machine_tool.type'].sudo().search(
[('code', '=', obj['machine_tool_type_id']), ('active', '=', True)]).id,
'active': obj['active']}
def _json_zero_tray_param(self, obj): def _json_zero_tray_param(self, obj):
zero_tray_param_str = (0, '', { """零点托盘将data数据转换成list数据"""
'name': obj['name'], return {'code': obj['code'],
'length': obj['length'], 'fixture_model_id': self.env['sf.fixture.model'].sudo().search(
'width': obj['width'], [('code', '=', obj.get('fixture_model_code'))]).id,
'height': obj['height'], 'name': obj['name'],
'diameter': obj['diameter'], 'length': obj['length'],
'weight': obj['weight'], 'width': obj['width'],
'clamping_diameter': obj['clamping_diameter'], 'height': obj['height'],
'connector_diameter': obj['connector_diameter'], 'diameter': obj['diameter'],
'chucking_power_max': obj['chucking_power_max'], 'weight': obj['weight'],
'repeated_positioning_accuracy': obj['repeated_positioning_accuracy'], 'clamping_diameter': obj['clamping_diameter'],
'boolean_chip_blowing_function': obj['boolean_chip_blowing_function'], 'connector_diameter': obj['connector_diameter'],
'way_to_install': obj['way_to_install'], 'chucking_power_max': obj['chucking_power_max'],
'type_of_drive': obj['type_of_drive'], 'repeated_positioning_accuracy': obj['repeated_positioning_accuracy'],
'carrying_capacity_max': obj['carrying_capacity_max'], 'boolean_chip_blowing_function': obj['boolean_chip_blowing_function'],
'materials_model_id': self.env['sf.materials.model'].sudo().search( 'way_to_install': obj['way_to_install'],
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id, 'type_of_drive': obj['type_of_drive'],
'rigidity': obj['rigidity'], 'carrying_capacity_max': obj['carrying_capacity_max'],
}) 'materials_model_id': self.env['sf.materials.model'].sudo().search(
return zero_tray_param_str [('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
'rigidity': obj['rigidity'],
'active': obj['active']}
def _json_pneumatic_fixture_param(self, obj): def _json_pneumatic_fixture_param(self, obj):
pneumatic_fixture_param_str = (0, '', { """气动夹具将data数据转换成list数据"""
'name': obj['name'], return {'code': obj['code'],
'length': obj['length'], 'fixture_model_id': self.env['sf.fixture.model'].sudo().search(
'width': obj['width'], [('code', '=', obj.get('fixture_model_code'))]).id,
'height': obj['height'], 'name': obj['name'],
'weight': obj['weight'], 'length': obj['length'],
'gripper_length_min': obj['gripper_length_min'], 'width': obj['width'],
'gripper_width_min': obj['gripper_width_min'], 'height': obj['height'],
'gripper_height_min': obj['gripper_height_min'], 'weight': obj['weight'],
'gripper_diameter_min': obj['gripper_diameter_min'], 'gripper_length_min': obj['gripper_length_min'],
'gripper_length_max': obj['gripper_length_max'], 'gripper_width_min': obj['gripper_width_min'],
'gripper_width_max': obj['gripper_width_max'], 'gripper_height_min': obj['gripper_height_min'],
'gripper_height_max': obj['gripper_height_max'], 'gripper_diameter_min': obj['gripper_diameter_min'],
'gripper_diameter_max': obj['gripper_diameter_max'], 'gripper_length_max': obj['gripper_length_max'],
'chucking_power_max': obj['chucking_power_max'], 'gripper_width_max': obj['gripper_width_max'],
'carrying_capacity_max': obj['carrying_capacity_max'], 'gripper_height_max': obj['gripper_height_max'],
'rated_air_pressure': obj['rated_air_pressure'], 'gripper_diameter_max': obj['gripper_diameter_max'],
'materials_model_id': self.env['sf.materials.model'].sudo().search( 'chucking_power_max': obj['chucking_power_max'],
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id, 'carrying_capacity_max': obj['carrying_capacity_max'],
'rigidity': obj['rigidity'], 'rated_air_pressure': obj['rated_air_pressure'],
'interface_materials_model_id': self.env['sf.materials.model'].sudo().search( 'materials_model_id': self.env['sf.materials.model'].sudo().search(
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id, [('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
'type_of_drive': obj['type_of_drive'], 'rigidity': obj['rigidity'],
}) 'interface_materials_model_id': self.env['sf.materials.model'].sudo().search(
return pneumatic_fixture_param_str [('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
'type_of_drive': obj['type_of_drive'],
'active': obj['active']}
def _json_jaw_vice_fixture_param(self, obj): def _json_jaw_vice_fixture_param(self, obj):
jaw_vice_fixture_param_str = (0, '', { """虎钳夹具将data数据转换成list数据"""
'name': obj['name'], return {'code': obj['code'],
'length': obj['length'], 'fixture_model_id': self.env['sf.fixture.model'].sudo().search(
'width': obj['width'], [('code', '=', obj.get('fixture_model_code'))]).id,
'height': obj['height'], 'name': obj['name'],
'weight': obj['weight'], 'length': obj['length'],
'gripper_length_min': obj['gripper_length_min'], 'width': obj['width'],
'gripper_width_min': obj['gripper_width_min'], 'height': obj['height'],
'gripper_height_min': obj['gripper_height_min'], 'weight': obj['weight'],
'gripper_diameter_min': obj['gripper_diameter_min'], 'gripper_length_min': obj['gripper_length_min'],
'gripper_length_max': obj['gripper_length_max'], 'gripper_width_min': obj['gripper_width_min'],
'gripper_width_max': obj['gripper_width_max'], 'gripper_height_min': obj['gripper_height_min'],
'gripper_height_max': obj['gripper_height_max'], 'gripper_diameter_min': obj['gripper_diameter_min'],
'gripper_diameter_max': obj['gripper_diameter_max'], 'gripper_length_max': obj['gripper_length_max'],
'chucking_power_max': obj['chucking_power_max'], 'gripper_width_max': obj['gripper_width_max'],
'carrying_capacity_max': obj['carrying_capacity_max'], 'gripper_height_max': obj['gripper_height_max'],
'transverse_groove': obj['transverse_groove'], 'gripper_diameter_max': obj['gripper_diameter_max'],
'longitudinal_fitting_groove': obj['longitudinal_fitting_groove'], 'chucking_power_max': obj['chucking_power_max'],
'materials_model_id': self.env['sf.materials.model'].sudo().search( 'carrying_capacity_max': obj['carrying_capacity_max'],
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id, 'transverse_groove': obj['transverse_groove'],
'rigidity': obj['rigidity'], 'longitudinal_fitting_groove': obj['longitudinal_fitting_groove'],
'interface_materials_model_id': self.env['sf.materials.model'].sudo().search( 'materials_model_id': self.env['sf.materials.model'].sudo().search(
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id, [('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
'type_of_drive': obj['type_of_drive'], 'rigidity': obj['rigidity'],
}) 'interface_materials_model_id': self.env['sf.materials.model'].sudo().search(
return jaw_vice_fixture_param_str [('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
'type_of_drive': obj['type_of_drive'],
'active': obj['active']}
def _json_magnet_fixture_param(self, obj): def _json_magnet_fixture_param(self, obj):
magnet_fixture_param_str = (0, '', { """磁吸夹具将data数据转换成list数据"""
'name': obj['name'], return {'code': obj['code'],
'length': obj['length'], 'fixture_model_id': self.env['sf.fixture.model'].sudo().search(
'width': obj['width'], [('code', '=', obj.get('fixture_model_code'))]).id,
'height': obj['height'], 'name': obj['name'],
'height_tolerance_value': obj['height_tolerance_value'], 'length': obj['length'],
'weight': obj['weight'], 'width': obj['width'],
'gripper_length_min': obj['gripper_length_min'], 'height': obj['height'],
'gripper_width_min': obj['gripper_width_min'], 'height_tolerance_value': obj['height_tolerance_value'],
'gripper_height_min': obj['gripper_height_min'], 'weight': obj['weight'],
'gripper_diameter_min': obj['gripper_diameter_min'], 'gripper_length_min': obj['gripper_length_min'],
'gripper_length_max': obj['gripper_length_max'], 'gripper_width_min': obj['gripper_width_min'],
'gripper_width_max': obj['gripper_width_max'], 'gripper_height_min': obj['gripper_height_min'],
'gripper_height_max': obj['gripper_height_max'], 'gripper_diameter_min': obj['gripper_diameter_min'],
'gripper_diameter_max': obj['gripper_diameter_max'], 'gripper_length_max': obj['gripper_length_max'],
'rated_adsorption_force': obj['rated_adsorption_force'], 'gripper_width_max': obj['gripper_width_max'],
'magnetic_field_height': obj['magnetic_field_height'], 'gripper_height_max': obj['gripper_height_max'],
'magnetic_pole_plate_grinding_allowance': obj['magnetic_pole_plate_grinding_allowance'], 'gripper_diameter_max': obj['gripper_diameter_max'],
'carrying_capacity_max': obj['carrying_capacity_max'], 'rated_adsorption_force': obj['rated_adsorption_force'],
'materials_model_id': self.env['sf.materials.model'].sudo().search( 'magnetic_field_height': obj['magnetic_field_height'],
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id, 'magnetic_pole_plate_grinding_allowance': obj['magnetic_pole_plate_grinding_allowance'],
'rigidity': obj['rigidity'], 'carrying_capacity_max': obj['carrying_capacity_max'],
'interface_materials_model_id': self.env['sf.materials.model'].sudo().search( 'materials_model_id': self.env['sf.materials.model'].sudo().search(
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id, [('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
'type_of_drive': obj['type_of_drive'], 'rigidity': obj['rigidity'],
}) 'interface_materials_model_id': self.env['sf.materials.model'].sudo().search(
return magnet_fixture_param_str [('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
'type_of_drive': obj['type_of_drive'],
'active': obj['active']}
def _json_adapter_board_fixture_param(self, obj): def _json_adapter_board_fixture_param(self, obj):
adapter_board_fixture_param_str = (0, '', { """转接板(锁板)夹具将data数据转换成list数据"""
'name': obj['name'], return {'code': obj['code'],
'length': obj['length'], 'fixture_model_id': self.env['sf.fixture.model'].sudo().search(
'width': obj['width'], [('code', '=', obj.get('fixture_model_code'))]).id,
'height': obj['height'], 'name': obj['name'],
'weight': obj['weight'], 'length': obj['length'],
'gripper_length_min': obj['gripper_length_min'], 'width': obj['width'],
'gripper_width_min': obj['gripper_width_min'], 'height': obj['height'],
'gripper_height_min': obj['gripper_height_min'], 'weight': obj['weight'],
'gripper_diameter_min': obj['gripper_diameter_min'], 'gripper_length_min': obj['gripper_length_min'],
'gripper_length_max': obj['gripper_length_max'], 'gripper_width_min': obj['gripper_width_min'],
'gripper_width_max': obj['gripper_width_max'], 'gripper_height_min': obj['gripper_height_min'],
'gripper_height_max': obj['gripper_height_max'], 'gripper_diameter_min': obj['gripper_diameter_min'],
'gripper_diameter_max': obj['gripper_diameter_max'], 'gripper_length_max': obj['gripper_length_max'],
'chucking_power_max': obj['chucking_power_max'], 'gripper_width_max': obj['gripper_width_max'],
'carrying_capacity_max': obj['carrying_capacity_max'], 'gripper_height_max': obj['gripper_height_max'],
'materials_model_id': self.env['sf.materials.model'].sudo().search( 'gripper_diameter_max': obj['gripper_diameter_max'],
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id, 'chucking_power_max': obj['chucking_power_max'],
'rigidity': obj['rigidity'], 'carrying_capacity_max': obj['carrying_capacity_max'],
'screw_size': obj['screw_size'], 'materials_model_id': self.env['sf.materials.model'].sudo().search(
'via_hole_diameter': obj['via_hole_diameter'], [('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
'type_of_drive': obj['type_of_drive'], 'rigidity': obj['rigidity'],
}) 'screw_size': obj['screw_size'],
return adapter_board_fixture_param_str 'via_hole_diameter': obj['via_hole_diameter'],
'type_of_drive': obj['type_of_drive'],
'active': obj['active']}
def _json_scroll_chuck_param(self, obj): def _json_scroll_chuck_param(self, obj):
scroll_chuck_param_str = (0, '', { """转接板(锁板)夹具将data数据转换成list数据"""
'name': obj['name'], return {'code': obj['code'],
'length': obj['length'], 'fixture_model_id': self.env['sf.fixture.model'].sudo().search(
'width': obj['width'], [('code', '=', obj.get('fixture_model_code'))]).id,
'height': obj['height'], 'name': obj['name'],
'diameter': obj['diameter'], 'length': obj['length'],
'weight': obj['weight'], 'width': obj['width'],
'gripper_length_min': obj['gripper_length_min'], 'height': obj['height'],
'gripper_width_min': obj['gripper_width_min'], 'diameter': obj['diameter'],
'gripper_height_min': obj['gripper_height_min'], 'weight': obj['weight'],
'gripper_diameter_min': obj['gripper_diameter_min'], 'gripper_length_min': obj['gripper_length_min'],
'gripper_length_max': obj['gripper_length_max'], 'gripper_width_min': obj['gripper_width_min'],
'gripper_width_max': obj['gripper_width_max'], 'gripper_height_min': obj['gripper_height_min'],
'gripper_height_max': obj['gripper_height_max'], 'gripper_diameter_min': obj['gripper_diameter_min'],
'gripper_diameter_max': obj['gripper_diameter_max'], 'gripper_length_max': obj['gripper_length_max'],
'chucking_power_max': obj['chucking_power_max'], 'gripper_width_max': obj['gripper_width_max'],
'carrying_capacity_max': obj['carrying_capacity_max'], 'gripper_height_max': obj['gripper_height_max'],
'materials_model_id': self.env['sf.materials.model'].sudo().search( 'gripper_diameter_max': obj['gripper_diameter_max'],
[('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id, 'chucking_power_max': obj['chucking_power_max'],
'rigidity': obj['rigidity'], 'carrying_capacity_max': obj['carrying_capacity_max'],
'mounting_hole_depth': obj['mounting_hole_depth'], 'materials_model_id': self.env['sf.materials.model'].sudo().search(
'centering_diameter': obj['centering_diameter'], [('materials_no', '=', obj['materials_model_id']), ('active', '=', True)]).id,
'type_of_drive': obj['type_of_drive'], 'rigidity': obj['rigidity'],
}) 'mounting_hole_depth': obj['mounting_hole_depth'],
return scroll_chuck_param_str 'centering_diameter': obj['centering_diameter'],
'type_of_drive': obj['type_of_drive'],
'active': obj['active']}

View File

@@ -61,10 +61,10 @@ class MrsMaterialModel(models.Model):
supplier_ids = fields.One2many('sf.supplier.sort', 'materials_model_id', string='供应商') supplier_ids = fields.One2many('sf.supplier.sort', 'materials_model_id', string='供应商')
active = fields.Boolean('有效', default=True) active = fields.Boolean('有效', default=True)
@api.constrains('supplier_ids') @api.onchange('gain_way')
def _check_gain_way(self): def _check_gain_way(self):
if not self.gain_way: if not self.gain_way:
raise UserError("输入获取方式") raise UserError("选择获取方式")
if self.gain_way in ['外协', '采购']: if self.gain_way in ['外协', '采购']:
if not self.supplier_ids: if not self.supplier_ids:
raise UserError("请添加供应商") raise UserError("请添加供应商")

View File

@@ -26,10 +26,10 @@ class FixtureModel(models.Model):
_name = 'sf.fixture.model' _name = 'sf.fixture.model'
_description = "夹具型号" _description = "夹具型号"
name = fields.Char(string="名称", size=50, required=True) name = fields.Char(string="名称", size=50)
fixture_material_id = fields.Many2one('sf.fixture.material', string="夹具物料", required=True) fixture_material_id = fields.Many2one('sf.fixture.material', string="夹具物料")
fixture_material_type = fields.Char(string="夹具物料类型", related='fixture_material_id.name') fixture_material_type = fields.Char(string="夹具物料类型", related='fixture_material_id.name')
multi_mounting_type_id = fields.Many2one('sf.multi_mounting.type', string="联装类型", required=True) multi_mounting_type_id = fields.Many2one('sf.multi_mounting.type', string="联装类型")
brand_id = fields.Many2one('sf.machine.brand', string="品牌") brand_id = fields.Many2one('sf.machine.brand', string="品牌")
model_file = fields.Binary(string="图片") model_file = fields.Binary(string="图片")
status = fields.Boolean('状态') status = fields.Boolean('状态')

View File

@@ -1,9 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import json from datetime import date
import requests
from odoo import fields, models, api from odoo import fields, models, api
from odoo.exceptions import ValidationError
from odoo.addons.sf_base.commons.common import Common
class CuttingToolMaterial(models.Model): class CuttingToolMaterial(models.Model):
@@ -113,6 +110,24 @@ class CuttingToolModel(models.Model):
feed_per_tooth_ids = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz(整体式刀具)') feed_per_tooth_ids = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz(整体式刀具)')
feed_per_tooth_ids_3 = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz(刀片)') feed_per_tooth_ids_3 = fields.One2many('sf.feed.per.tooth', 'standard_library_id', '每齿走刀量fz(刀片)')
material_model_id = fields.Many2one('sf.materials.model', '材料型号') material_model_id = fields.Many2one('sf.materials.model', '材料型号')
@api.onchange('cutting_tool_material_id')
def _get_code(self):
if self.is_cloud is False:
today = date.today().strftime("%Y%m%d")
today_code = 'T-DJWL-%s-%s' % (self.cutting_tool_material_id.code, today)
cutting_tool_model = self.search(
[('code', 'ilike', today_code), ('is_cloud', '=', False),
('active', 'in', [True, False])],
limit=1,
order="id desc")
if not cutting_tool_model:
num = "%03d" % 1
else:
m = int(today_code[-3:]) + 1
num = "%03d" % m
self.code = "%s%s" % (today_code, num)
# 适用夹头型号可以多选 # 适用夹头型号可以多选
# chuck_ids = fields.Many2many( # chuck_ids = fields.Many2many(
# 'sf.cutting_tool.standard.library', # 'sf.cutting_tool.standard.library',

View File

@@ -10,6 +10,7 @@ class ToolMaterialsBasicParameters(models.Model):
standard_library_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀具标准库') standard_library_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀具标准库')
cutting_tool_type = fields.Char(related='standard_library_id.cutting_tool_type', string='刀具物料类型', cutting_tool_type = fields.Char(related='standard_library_id.cutting_tool_type', string='刀具物料类型',
store=True) store=True)
is_cloud = fields.Boolean(related='standard_library_id.is_cloud', string='云端数据')
# 整体式刀具参数 # 整体式刀具参数
total_length = fields.Float('总长度(mm)') total_length = fields.Float('总长度(mm)')
@@ -21,7 +22,7 @@ class ToolMaterialsBasicParameters(models.Model):
handle_diameter = fields.Float('柄部直径(mm)') handle_diameter = fields.Float('柄部直径(mm)')
handle_length = fields.Float('柄部长度(mm)') handle_length = fields.Float('柄部长度(mm)')
blade_tip_diameter = fields.Integer('刀尖直径(mm)') blade_tip_diameter = fields.Integer('刀尖直径(mm)')
blade_tip_working_size = fields.Char('刀尖处理尺寸(R半径mm/倒角)', size=20) blade_tip_working_size = fields.Char('刀尖处理尺寸(R半径mm/倒角)', size=20)
blade_tip_taper = fields.Integer('刀尖锥度(°)') blade_tip_taper = fields.Integer('刀尖锥度(°)')
blade_diameter = fields.Float('刃部直径(mm)') blade_diameter = fields.Float('刃部直径(mm)')
blade_length = fields.Float('刃部长度(mm)') blade_length = fields.Float('刃部长度(mm)')
@@ -37,7 +38,7 @@ class ToolMaterialsBasicParameters(models.Model):
cutting_blade_length = fields.Float('切削刃长(mm)') cutting_blade_length = fields.Float('切削刃长(mm)')
relief_angle = fields.Integer('后角(°)') relief_angle = fields.Integer('后角(°)')
blade_tip_circular_arc_radius = fields.Char('刀尖圆弧半径(mm)', size=20) blade_tip_circular_arc_radius = fields.Char('刀尖圆弧半径(mm)', size=20)
inscribed_circle_diameter = fields.Float('内接圆直径(mm)') inscribed_circle_diameter = fields.Float('内接圆直径IC/D(mm)')
install_aperture_diameter = fields.Float('安装孔直径(mm)') install_aperture_diameter = fields.Float('安装孔直径(mm)')
chip_breaker_groove = fields.Selection([('', ''), ('单面', '单面'), ('双面', '双面')], chip_breaker_groove = fields.Selection([('', ''), ('单面', '单面'), ('双面', '双面')],
string='有无断屑槽') string='有无断屑槽')
@@ -170,8 +171,6 @@ class FeedPerTooth(models.Model):
feed_per_tooth = fields.Char('每齿走刀量 (mm/z)', size=20) feed_per_tooth = fields.Char('每齿走刀量 (mm/z)', size=20)
active = fields.Boolean(string='有效', default=True) active = fields.Boolean(string='有效', default=True)
# @api.depends('product_template_id') # @api.depends('product_template_id')
# def _compute_product_template_id(self): # def _compute_product_template_id(self):
# if self.product_template_id is not None: # if self.product_template_id is not None:

View File

@@ -70,11 +70,17 @@ access_sf_cutting_speed,sf_cutting_speed,model_sf_cutting_speed,base.group_user,
access_sf_cutting_speed_admin,sf_cutting_speed_admin,model_sf_cutting_speed,base.group_system,1,1,1,0 access_sf_cutting_speed_admin,sf_cutting_speed_admin,model_sf_cutting_speed,base.group_system,1,1,1,0
access_sf_cutting_speed_group_purchase_director,sf_cutting_speed_group_purchase_director,model_sf_cutting_speed,sf_base.group_purchase_director,1,1,1,0 access_sf_cutting_speed_group_purchase_director,sf_cutting_speed_group_purchase_director,model_sf_cutting_speed,sf_base.group_purchase_director,1,1,1,0
access_sf_cutting_speed_group_sale_director,sf_cutting_speed_group_sale_director,model_sf_cutting_speed,sf_base.group_sale_director,1,1,1,0 access_sf_cutting_speed_group_sale_director,sf_cutting_speed_group_sale_director,model_sf_cutting_speed,sf_base.group_sale_director,1,1,1,0
access_sf_cutting_speed_group_plan_dispatch,sf_cutting_speed_group_plan_dispatch,model_sf_cutting_speed,sf_base.group_plan_dispatch,1,0,0,0
access_sf_cutting_speed_group_plan_director,sf_cutting_speed_group_plan_director,model_sf_cutting_speed,sf_base.group_plan_director,1,1,1,0 access_sf_cutting_speed_group_plan_director,sf_cutting_speed_group_plan_director,model_sf_cutting_speed,sf_base.group_plan_director,1,1,1,0
access_sf_cutting_speed_group_quality_director,sf_cutting_speed_group_quality_director,model_sf_cutting_speed,sf_base.group_quality_director,1,1,1,0
access_sf_cutting_speed_group_quality,sf_cutting_speed_group_quality,model_sf_cutting_speed,sf_base.group_quality,1,1,1,0
access_sf_feed_per_tooth_group_purchase_director,sf_feed_per_tooth_group_purchase_director,model_sf_feed_per_tooth,sf_base.group_purchase_director,1,1,0,0 access_sf_feed_per_tooth_group_purchase_director,sf_feed_per_tooth_group_purchase_director,model_sf_feed_per_tooth,sf_base.group_purchase_director,1,1,0,0
access_sf_feed_per_tooth_group_sale_director,sf_feed_per_tooth_group_sale_director,model_sf_feed_per_tooth,sf_base.group_sale_director,1,1,0,0 access_sf_feed_per_tooth_group_sale_director,sf_feed_per_tooth_group_sale_director,model_sf_feed_per_tooth,sf_base.group_sale_director,1,1,0,0
access_sf_feed_per_tooth_group_plan_dispatch,sf_feed_per_tooth_group_plan_dispatch,model_sf_feed_per_tooth,sf_base.group_plan_dispatch,1,0,0,0
access_sf_feed_per_tooth_group_plan_director,sf_feed_per_tooth_group_plan_director,model_sf_feed_per_tooth,sf_base.group_plan_director,1,1,0,0 access_sf_feed_per_tooth_group_plan_director,sf_feed_per_tooth_group_plan_director,model_sf_feed_per_tooth,sf_base.group_plan_director,1,1,0,0
access_sf_feed_per_tooth_group_sale_salemanager,sf_feed_per_tooth_group_sale_salemanager,model_sf_feed_per_tooth,sf_base.group_sale_salemanager,1,0,0,0 access_sf_feed_per_tooth_group_sale_salemanager,sf_feed_per_tooth_group_sale_salemanager,model_sf_feed_per_tooth,sf_base.group_sale_salemanager,1,0,0,0
access_sf_feed_per_tooth_group_quality,sf_feed_per_tooth_group_quality,model_sf_feed_per_tooth,sf_base.group_quality,1,1,1,0
access_sf_feed_per_tooth_group_quality_director,sf_feed_per_tooth_group_quality_director,model_sf_feed_per_tooth,sf_base.group_quality_director,1,1,1,0
access_sf_feed_per_tooth,sf_feed_per_tooth,model_sf_feed_per_tooth,base.group_user,1,1,1,0 access_sf_feed_per_tooth,sf_feed_per_tooth,model_sf_feed_per_tooth,base.group_user,1,1,1,0
access_sf_feed_per_tooth_admin,sf_feed_per_tooth_admin,model_sf_feed_per_tooth,base.group_system,1,1,1,0 access_sf_feed_per_tooth_admin,sf_feed_per_tooth_admin,model_sf_feed_per_tooth,base.group_system,1,1,1,0
access_sf_ramping_angle,sf_ramping_angle,model_sf_ramping_angle,base.group_user,1,1,1,1 access_sf_ramping_angle,sf_ramping_angle,model_sf_ramping_angle,base.group_user,1,1,1,1
@@ -136,9 +142,7 @@ access_sf_cutting_width_depth,sf_cutting_width_depth,model_sf_cutting_width_dept
access_sf_cutting_width_depth_group_purchase,sf_cutting_width_depth_group_purchase,model_sf_cutting_width_depth,sf_base.group_purchase,1,0,0,0 access_sf_cutting_width_depth_group_purchase,sf_cutting_width_depth_group_purchase,model_sf_cutting_width_depth,sf_base.group_purchase,1,0,0,0
access_maintenance_equipment_image,maintenance_equipment_image,model_maintenance_equipment_image,base.group_user,1,1,1,1 access_maintenance_equipment_image,maintenance_equipment_image,model_maintenance_equipment_image,base.group_user,1,1,1,1
access_purchase_order_group_purchase,access_purchase_order_group_purchase,purchase.model_purchase_order,sf_base.group_purchase,1,1,1,0 access_purchase_order_group_purchase,access_purchase_order_group_purchase,purchase.model_purchase_order,sf_base.group_purchase,1,1,1,0
access_purchase_order_group_purchase_director,access_purchase_order_group_purchase_director,purchase.model_purchase_order,sf_base.group_purchase_director,1,1,1,0
access_purchase_order_line_group_purchase,access_purchase_order_line_group_purchase,purchase.model_purchase_order_line,sf_base.group_purchase,1,1,1,0 access_purchase_order_line_group_purchase,access_purchase_order_line_group_purchase,purchase.model_purchase_order_line,sf_base.group_purchase,1,1,1,0
access_purchase_order_line_group_purchase_director,access_purchase_order_line_group_purchase_director,purchase.model_purchase_order_line,sf_base.group_purchase_director,1,1,1,0
access_spindle_taper_type,spindle_taper_type,model_spindle_taper_type,base.group_user,1,1,1,1 access_spindle_taper_type,spindle_taper_type,model_spindle_taper_type,base.group_user,1,1,1,1
access_sf_tool_groups_group_plan_dispatch,sf_tool_groups,model_sf_tool_groups,sf_base.group_plan_dispatch,1,0,0,0 access_sf_tool_groups_group_plan_dispatch,sf_tool_groups,model_sf_tool_groups,sf_base.group_plan_dispatch,1,0,0,0
access_sf_tool_groups_group_sf_tool_user,sf_tool_groups,model_sf_tool_groups,sf_base.group_sf_tool_user,1,1,1,1 access_sf_tool_groups_group_sf_tool_user,sf_tool_groups,model_sf_tool_groups,sf_base.group_sf_tool_user,1,1,1,1
@@ -146,6 +150,9 @@ access_purchase_order,purchase.order,purchase.model_purchase_order,sf_base.group
access_res_partner,res.partner,base.model_res_partner,sf_base.group_plan_dispatch,1,0,0,0 access_res_partner,res.partner,base.model_res_partner,sf_base.group_plan_dispatch,1,0,0,0
access_purchase_order_line,purchase.order.line,purchase.model_purchase_order_line,sf_base.group_plan_dispatch,1,0,0,0 access_purchase_order_line,purchase.order.line,purchase.model_purchase_order_line,sf_base.group_plan_dispatch,1,0,0,0
access_account_move_line,account.move.line,account.model_account_move_line,sf_base.group_plan_dispatch,1,0,0,0 access_account_move_line,account.move.line,account.model_account_move_line,sf_base.group_plan_dispatch,1,0,0,0
access_sf_machine_tool_type_group_plan_dispatch,sf.machine_tool.type,model_sf_machine_tool_type,sf_base.group_plan_dispatch,1,0,0,0
access_sf_machine_tool,sf_machine_tool,model_sf_machine_tool,sf_base.group_sf_mrp_user,1,1,0,0 access_sf_machine_tool,sf_machine_tool,model_sf_machine_tool,sf_base.group_sf_mrp_user,1,1,0,0
access_sf_machine_tool_type,sf_machine_tool_type,model_sf_machine_tool_type,sf_base.group_sf_mrp_user,1,1,0,0 access_sf_machine_tool_type,sf_machine_tool_type,model_sf_machine_tool_type,sf_base.group_sf_mrp_user,1,1,0,0
access_sf_machine_brand,sf_machine_brand,model_sf_machine_brand,sf_base.group_sf_mrp_user,1,1,0,0 access_sf_machine_brand,sf_machine_brand,model_sf_machine_brand,sf_base.group_sf_mrp_user,1,1,0,0
@@ -181,3 +188,7 @@ access_sf_machine_brand_tags_group_sale_director,sf_machine_brand_tags_group_sal
access_sf_machine_brand_tags_group_plan_director,sf_machine_brand_tags_group_plan_director,model_sf_machine_brand_tags,sf_base.group_plan_director,1,0,0,0 access_sf_machine_brand_tags_group_plan_director,sf_machine_brand_tags_group_plan_director,model_sf_machine_brand_tags,sf_base.group_plan_director,1,0,0,0
access_sf_machine_brand_tags_group_purchase,sf_machine_brand_tags_group_purchase,model_sf_machine_brand_tags,sf_base.group_purchase,1,0,0,0 access_sf_machine_brand_tags_group_purchase,sf_machine_brand_tags_group_purchase,model_sf_machine_brand_tags,sf_base.group_purchase,1,0,0,0
access_sf_machine_brand_tags_group_purchase_director,sf_machine_brand_tags_group_purchase_director,model_sf_machine_brand_tags,sf_base.group_purchase_director,1,0,0,0 access_sf_machine_brand_tags_group_purchase_director,sf_machine_brand_tags_group_purchase_director,model_sf_machine_brand_tags,sf_base.group_purchase_director,1,0,0,0
access_printer,printer,model_printer,base.group_user,1,1,1,1
access_printer_configuration,printer.configuration,model_printer_configuration,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
70 access_sf_cutting_speed_group_sale_director sf_cutting_speed_group_sale_director model_sf_cutting_speed sf_base.group_sale_director 1 1 1 0
71 access_sf_cutting_speed_group_plan_director access_sf_cutting_speed_group_plan_dispatch sf_cutting_speed_group_plan_director sf_cutting_speed_group_plan_dispatch model_sf_cutting_speed sf_base.group_plan_director sf_base.group_plan_dispatch 1 1 0 1 0 0
72 access_sf_feed_per_tooth_group_purchase_director access_sf_cutting_speed_group_plan_director sf_feed_per_tooth_group_purchase_director sf_cutting_speed_group_plan_director model_sf_feed_per_tooth model_sf_cutting_speed sf_base.group_purchase_director sf_base.group_plan_director 1 1 0 1 0
73 access_sf_cutting_speed_group_quality_director sf_cutting_speed_group_quality_director model_sf_cutting_speed sf_base.group_quality_director 1 1 1 0
74 access_sf_feed_per_tooth_group_sale_director access_sf_cutting_speed_group_quality sf_feed_per_tooth_group_sale_director sf_cutting_speed_group_quality model_sf_feed_per_tooth model_sf_cutting_speed sf_base.group_sale_director sf_base.group_quality 1 1 0 1 0
75 access_sf_feed_per_tooth_group_purchase_director sf_feed_per_tooth_group_purchase_director model_sf_feed_per_tooth sf_base.group_purchase_director 1 1 0 0
76 access_sf_feed_per_tooth_group_sale_director sf_feed_per_tooth_group_sale_director model_sf_feed_per_tooth sf_base.group_sale_director 1 1 0 0
77 access_sf_feed_per_tooth_group_plan_director access_sf_feed_per_tooth_group_plan_dispatch sf_feed_per_tooth_group_plan_director sf_feed_per_tooth_group_plan_dispatch model_sf_feed_per_tooth sf_base.group_plan_director sf_base.group_plan_dispatch 1 1 0 0 0
78 access_sf_feed_per_tooth_group_sale_salemanager access_sf_feed_per_tooth_group_plan_director sf_feed_per_tooth_group_sale_salemanager sf_feed_per_tooth_group_plan_director model_sf_feed_per_tooth sf_base.group_sale_salemanager sf_base.group_plan_director 1 0 1 0 0
79 access_sf_feed_per_tooth_group_sale_salemanager sf_feed_per_tooth_group_sale_salemanager model_sf_feed_per_tooth sf_base.group_sale_salemanager 1 0 0 0
80 access_sf_feed_per_tooth access_sf_feed_per_tooth_group_quality sf_feed_per_tooth sf_feed_per_tooth_group_quality model_sf_feed_per_tooth base.group_user sf_base.group_quality 1 1 1 0
81 access_sf_feed_per_tooth_admin access_sf_feed_per_tooth_group_quality_director sf_feed_per_tooth_admin sf_feed_per_tooth_group_quality_director model_sf_feed_per_tooth base.group_system sf_base.group_quality_director 1 1 1 0
82 access_sf_feed_per_tooth sf_feed_per_tooth model_sf_feed_per_tooth base.group_user 1 1 1 0
83 access_sf_feed_per_tooth_admin sf_feed_per_tooth_admin model_sf_feed_per_tooth base.group_system 1 1 1 0
84 access_sf_ramping_angle sf_ramping_angle model_sf_ramping_angle base.group_user 1 1 1 1
85 access_sf_ramping_angle_admin sf_ramping_angle_admin model_sf_ramping_angle base.group_system 1 1 1 1
86 access_sf_cutting_width_depth sf_cutting_width_depth model_sf_cutting_width_depth base.group_user 1 1 1 1
142 access_purchase_order_group_purchase access_purchase_order_group_purchase purchase.model_purchase_order sf_base.group_purchase 1 1 1 0
143 access_purchase_order_group_purchase_director access_purchase_order_line_group_purchase access_purchase_order_group_purchase_director access_purchase_order_line_group_purchase purchase.model_purchase_order purchase.model_purchase_order_line sf_base.group_purchase_director sf_base.group_purchase 1 1 1 0
144 access_purchase_order_line_group_purchase access_spindle_taper_type access_purchase_order_line_group_purchase spindle_taper_type purchase.model_purchase_order_line model_spindle_taper_type sf_base.group_purchase base.group_user 1 1 1 0 1
access_purchase_order_line_group_purchase_director access_purchase_order_line_group_purchase_director purchase.model_purchase_order_line sf_base.group_purchase_director 1 1 1 0
145 access_spindle_taper_type access_sf_tool_groups_group_plan_dispatch spindle_taper_type sf_tool_groups model_spindle_taper_type model_sf_tool_groups base.group_user sf_base.group_plan_dispatch 1 1 0 1 0 1 0
access_sf_tool_groups_group_plan_dispatch sf_tool_groups model_sf_tool_groups sf_base.group_plan_dispatch 1 0 0 0
146 access_sf_tool_groups_group_sf_tool_user sf_tool_groups model_sf_tool_groups sf_base.group_sf_tool_user 1 1 1 1
147 access_purchase_order purchase.order purchase.model_purchase_order sf_base.group_plan_dispatch 1 0 0 0
148 access_res_partner res.partner base.model_res_partner sf_base.group_plan_dispatch 1 0 0 0
150 access_account_move_line account.move.line account.model_account_move_line sf_base.group_plan_dispatch 1 0 0 0
151 access_sf_machine_tool access_sf_machine_tool_type_group_plan_dispatch sf_machine_tool sf.machine_tool.type model_sf_machine_tool model_sf_machine_tool_type sf_base.group_sf_mrp_user sf_base.group_plan_dispatch 1 1 0 0 0
152 access_sf_machine_tool_type access_sf_machine_tool sf_machine_tool_type sf_machine_tool model_sf_machine_tool_type model_sf_machine_tool sf_base.group_sf_mrp_user 1 1 0 0
153 access_sf_machine_tool_type sf_machine_tool_type model_sf_machine_tool_type sf_base.group_sf_mrp_user 1 1 0 0
154 access_sf_machine_brand sf_machine_brand model_sf_machine_brand sf_base.group_sf_mrp_user 1 1 0 0
155 access_sf_machine_brand_tags sf_machine_brand_tags model_sf_machine_brand_tags sf_base.group_sf_mrp_user 1 1 0 0
156 access_sf_machine_brand access_sf_machine_control_system sf_machine_brand sf_machine_control_system model_sf_machine_brand model_sf_machine_control_system sf_base.group_sf_mrp_user 1 1 0 0
157 access_sf_machine_brand_tags access_sf_production_process sf_machine_brand_tags sf_production_process model_sf_machine_brand_tags model_sf_production_process sf_base.group_sf_mrp_user 1 1 0 0
158 access_sf_machine_control_system access_sf_production_materials sf_machine_control_system sf_production_materials model_sf_machine_control_system model_sf_production_materials sf_base.group_sf_mrp_user 1 1 0 0
188 access_sf_machine_brand_tags_group_purchase_director access_printer_configuration sf_machine_brand_tags_group_purchase_director printer.configuration model_sf_machine_brand_tags model_printer_configuration sf_base.group_purchase_director base.group_user 1 0 1 0 1 0 1
189
190
191
192
193
194

112
sf_base/views/Printer.xml Normal file
View File

@@ -0,0 +1,112 @@
<odoo>
<data>
<record id="view_printer_tree" model="ir.ui.view">
<field name="name">printer.tree</field>
<field name="model">printer</field>
<field name="arch" type="xml">
<tree string="Printer">
<field name="name"/>
<field name="ip_address"/>
<field name="port"/>
<!-- 其他字段... -->
</tree>
</field>
</record>
<record id="view_printer_form" model="ir.ui.view">
<field name="name">printer.form</field>
<field name="model">printer</field>
<field name="arch" type="xml">
<form string="Printer">
<sheet>
<group>
<field name="name"/>
<field name="ip_address"/>
<field name="port"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_printer_configuration_tree" model="ir.ui.view">
<field name="name">printer.configuration.tree</field>
<field name="model">printer.configuration</field>
<field name="arch" type="xml">
<tree string="Printer Configuration">
<field name="name"/>
<field name="printer_id"/>
<field name="model"/>
<!-- 其他字段... -->
</tree>
</field>
</record>
<record id="view_printer_configuration_form" model="ir.ui.view">
<field name="name">printer.configuration.form</field>
<field name="model">printer.configuration</field>
<field name="arch" type="xml">
<form string="Printer Configuration">
<sheet>
<group>
<field name="name"/>
<field name="printer_id"/>
<field name="model"/>
<!-- 其他字段... -->
</group>
</sheet>
</form>
</field>
</record>
<!-- 其他视图... -->
<record id="action_printer" model="ir.actions.act_window">
<field name="name">打印机</field>
<field name="res_model">printer</field>
<field name="view_mode">tree,form</field>
</record>
<!-- Action to open the printer configuration list -->
<record id="action_printer_configuration" model="ir.actions.act_window">
<field name="name">打印配置</field>
<field name="res_model">printer.configuration</field>
<field name="view_mode">tree,form</field>
</record>
<!-- Add a menu item for the printer configuration -->
<!-- <record id="menu_printer_configuration" model="ir.ui.menu"> -->
<!-- <field name="name">打印配置</field> -->
<!-- <field name="action" ref="action_printer_configuration"/> -->
<!-- <field name="parent_id" ref="base.menu_administration"/> -->
<!-- </record> -->
<!-- <record id="menu_printer" model="ir.ui.menu"> -->
<!-- <field name="name">打印机</field> -->
<!-- <field name="action" ref="action_printer"/> -->
<!-- <field name="parent_id" ref="menu_printer"/> -->
<!-- </record> -->
<menuitem
id="printer_main_menu"
name="打印配置"
sequence="10"
parent="base.menu_administration"/>
<menuitem
id="menu_printer"
name="打印机"
action="action_printer"
sequence="1"
parent="printer_main_menu"/>
<menuitem
id="menu_printer_configuration"
name="打印配置"
action="action_printer_configuration"
sequence="2"
parent="printer_main_menu"/>
</data>
</odoo>

View File

@@ -1,38 +1,39 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<odoo> <odoo>
<data> <data>
<!--表面工艺可选参数--> <!--表面工艺可选参数-->
<record model="ir.ui.view" id="mrs_production_process_parameter_tree"> <record model="ir.ui.view" id="mrs_production_process_parameter_tree">
<field name="model">sf.production.process.parameter</field> <field name="model">sf.production.process.parameter</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="表面工艺可选参数" delete="0"> <tree string="表面工艺可选参数" create="0" delete="0">
<field name="code"/> <field name="code"/>
<field name="name"/> <field name="name"/>
<field name="gain_way"/>
</tree> </tree>
</field> </field>
</record> </record>
<record model="ir.ui.view" id="mrs_production_process_parameter_form"> <record model="ir.ui.view" id="mrs_production_process_parameter_form">
<field name="model">sf.production.process.parameter</field> <field name="model">sf.production.process.parameter</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="表面工艺可选参数" edit="0" delete="0"> <form string="表面工艺可选参数" create="0" delete="0">
<sheet> <sheet>
<div class="oe_title"> <div class="oe_title">
<h1> <h1>
<field name="name" required="1" placeholder="名称" /> <field name="name" required="1" placeholder="名称"/>
</h1> </h1>
</div> </div>
<group> <group>
<group> <group>
<field name="code" readonly="1"/> <field name="code" readonly="1"/>
<field name="process_id" readonly="1"/>
<field name="gain_way" />
</group> </group>
<group>
<field name="process_id" required="1"/>
</group>
</group> </group>
<notebook> <notebook>
<page string="适用材料"> <page string="适用材料">
<field name="materials_model_ids"></field> <field name="materials_model_ids" readonly="1"></field>
</page> </page>
</notebook> </notebook>
</sheet> </sheet>
@@ -40,7 +41,7 @@
</field> </field>
</record> </record>
<record model="ir.ui.view" id="search_mrs_production_process_parameter_view"> <record model="ir.ui.view" id="search_mrs_production_process_parameter_view">
<field name="name">search.mrs.production.process.parameter</field> <field name="name">search.mrs.production.process.parameter</field>
<field name="model">sf.production.process.parameter</field> <field name="model">sf.production.process.parameter</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
@@ -74,26 +75,26 @@
<!-- </form>--> <!-- </form>-->
<!-- </field>--> <!-- </field>-->
<!-- </record>--> <!-- </record>-->
<!-- <record model="ir.ui.view" id="sf_processing_technology_tree">--> <!-- <record model="ir.ui.view" id="sf_processing_technology_tree">-->
<!-- <field name="model">sf.processing.technology</field>--> <!-- <field name="model">sf.processing.technology</field>-->
<!-- <field name="arch" type="xml">--> <!-- <field name="arch" type="xml">-->
<!-- <tree string="加工工艺" create="0" edit="0" delete="1">--> <!-- <tree string="加工工艺" create="0" edit="0" delete="1">-->
<!-- <field name="code"/>--> <!-- <field name="code"/>-->
<!-- <field name="name"/>--> <!-- <field name="name"/>-->
<!-- </tree>--> <!-- </tree>-->
<!-- </field>--> <!-- </field>-->
<!-- </record>--> <!-- </record>-->
<!-- <record model="ir.ui.view" id="search_sf_processing_technology_view">--> <!-- <record model="ir.ui.view" id="search_sf_processing_technology_view">-->
<!-- <field name="name">search.sf.processing.technology.type</field>--> <!-- <field name="name">search.sf.processing.technology.type</field>-->
<!-- <field name="model">sf.processing.technology</field>--> <!-- <field name="model">sf.processing.technology</field>-->
<!-- <field name="arch" type="xml">--> <!-- <field name="arch" type="xml">-->
<!-- <search>--> <!-- <search>-->
<!-- <field name="name" string="名称搜索" filter_domain="[('name','ilike',self)]"/>--> <!-- <field name="name" string="名称搜索" filter_domain="[('name','ilike',self)]"/>-->
<!-- <field name="code" string="编码搜索" filter_domain="[('code','ilike',self)]"/>--> <!-- <field name="code" string="编码搜索" filter_domain="[('code','ilike',self)]"/>-->
<!-- <filter name="filter_active" string="已归档" domain="[('active','=',False)]"/>--> <!-- <filter name="filter_active" string="已归档" domain="[('active','=',False)]"/>-->
<!-- </search>--> <!-- </search>-->
<!-- </field>--> <!-- </field>-->
<!-- </record>--> <!-- </record>-->
<!--表面工艺类别--> <!--表面工艺类别-->
<record model="ir.ui.view" id="sf_production_process_category_form"> <record model="ir.ui.view" id="sf_production_process_category_form">
@@ -283,7 +284,7 @@
<record model="ir.ui.view" id="sf_materials_model_tree"> <record model="ir.ui.view" id="sf_materials_model_tree">
<field name="model">sf.materials.model</field> <field name="model">sf.materials.model</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="材料型号" delete="0"> <tree string="材料型号" delete="0">
<field name="materials_no"/> <field name="materials_no"/>
<field name="materials_code"/> <field name="materials_code"/>
<field name="name"/> <field name="name"/>
@@ -392,12 +393,12 @@
<field name="res_model">sf.materials.model</field> <field name="res_model">sf.materials.model</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
</record> </record>
<!-- <record id="sf_processing_technology" model="ir.actions.act_window">--> <!-- <record id="sf_processing_technology" 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.processing.technology</field>--> <!-- <field name="res_model">sf.processing.technology</field>-->
<!-- <field name="view_mode">tree</field>--> <!-- <field name="view_mode">tree</field>-->
<!-- </record>--> <!-- </record>-->
<record id="sf_production_process_category" model="ir.actions.act_window"> <record id="sf_production_process_category" model="ir.actions.act_window">
<field name="name">表面工艺类别</field> <field name="name">表面工艺类别</field>

View File

@@ -165,6 +165,7 @@
<field name="zero_chuck_ids" <field name="zero_chuck_ids"
attrs="{'invisible': [('fixture_material_type', '!=', '零点卡盘')]}"> attrs="{'invisible': [('fixture_material_type', '!=', '零点卡盘')]}">
<tree editable="bottom" class="center" delete="0"> <tree editable="bottom" class="center" delete="0">
<field name="code" invisible="1"/>
<field name="name"/> <field name="name"/>
<field name="length"/> <field name="length"/>
<field name="width"/> <field name="width"/>
@@ -190,6 +191,7 @@
<field name="zero_tray_ids" <field name="zero_tray_ids"
attrs="{'invisible': [('fixture_material_type', '!=', '零点托盘')]}"> attrs="{'invisible': [('fixture_material_type', '!=', '零点托盘')]}">
<tree editable="bottom" class="center" delete="0"> <tree editable="bottom" class="center" delete="0">
<field name="code" invisible="1"/>
<field name="name"/> <field name="name"/>
<field name="length"/> <field name="length"/>
<field name="width"/> <field name="width"/>
@@ -213,6 +215,7 @@
<field name="pneumatic_fixture_ids" <field name="pneumatic_fixture_ids"
attrs="{'invisible': [('fixture_material_type', '!=', '气动夹具')]}"> attrs="{'invisible': [('fixture_material_type', '!=', '气动夹具')]}">
<tree editable="bottom" class="center" delete="0"> <tree editable="bottom" class="center" delete="0">
<field name="code" invisible="1"/>
<field name="name"/> <field name="name"/>
<field name="length"/> <field name="length"/>
<field name="width"/> <field name="width"/>
@@ -240,6 +243,7 @@
<field name="jaw_vice_fixture_ids" <field name="jaw_vice_fixture_ids"
attrs="{'invisible': [('fixture_material_type', '!=', '虎钳夹具')]}"> attrs="{'invisible': [('fixture_material_type', '!=', '虎钳夹具')]}">
<tree editable="bottom" class="center" delete="0"> <tree editable="bottom" class="center" delete="0">
<field name="code" invisible="1"/>
<field name="name"/> <field name="name"/>
<field name="length"/> <field name="length"/>
<field name="width"/> <field name="width"/>
@@ -268,6 +272,7 @@
<field name="magnet_fixture_ids" <field name="magnet_fixture_ids"
attrs="{'invisible': [('fixture_material_type', '!=', '磁吸夹具')]}"> attrs="{'invisible': [('fixture_material_type', '!=', '磁吸夹具')]}">
<tree editable="bottom" class="center" delete="0"> <tree editable="bottom" class="center" delete="0">
<field name="code" invisible="1"/>
<field name="name"/> <field name="name"/>
<field name="length"/> <field name="length"/>
<field name="width"/> <field name="width"/>
@@ -297,6 +302,7 @@
<field name="adapter_board_fixture_ids" <field name="adapter_board_fixture_ids"
attrs="{'invisible': [('fixture_material_type', '!=', '转接板(锁板)夹具')]}"> attrs="{'invisible': [('fixture_material_type', '!=', '转接板(锁板)夹具')]}">
<tree editable="bottom" class="center" delete="0"> <tree editable="bottom" class="center" delete="0">
<field name="code" invisible="1"/>
<field name="name"/> <field name="name"/>
<field name="length"/> <field name="length"/>
<field name="width"/> <field name="width"/>
@@ -323,6 +329,7 @@
<field name="scroll_chuck_ids" <field name="scroll_chuck_ids"
attrs="{'invisible': [('fixture_material_type', '!=', '三爪卡盘')]}"> attrs="{'invisible': [('fixture_material_type', '!=', '三爪卡盘')]}">
<tree editable="bottom" class="center" delete="0"> <tree editable="bottom" class="center" delete="0">
<field name="code" invisible="1"/>
<field name="name"/> <field name="name"/>
<field name="length"/> <field name="length"/>
<field name="width"/> <field name="width"/>

View File

@@ -1,132 +1,302 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<odoo> <odoo>
<data> <data>
<!-- ================================================刀具基础参数================================================ --> <!-- ================================================刀具基础参数================================================ -->
<record id="view_sf_tool_materials_basic_parameters_integral_tree" model="ir.ui.view"> <record id="view_sf_tool_materials_basic_parameters_integral_tree" model="ir.ui.view">
<field name="name">sf.tool.materials.basic.parameters.tree</field> <field name="name">sf.tool.materials.basic.parameters.tree</field>
<field name="model">sf.tool.materials.basic.parameters</field> <field name="model">sf.tool.materials.basic.parameters</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="基础参数" delete="0" create="0" edit="0" sample="1"> <tree string="基础参数" delete="0" create="0" edit="0" sample="1">
<field name="total_length" /> <field name="total_length"/>
<field name="blade_number" /> <field name="blade_number"/>
<field name="neck_diameter"/> <field name="neck_diameter"/>
<field name="neck_length"/> <field name="neck_length"/>
<field name="handle_diameter" /> <field name="handle_diameter"/>
<field name="handle_length" /> <field name="handle_length"/>
<field name="blade_tip_diameter"/> <field name="blade_tip_diameter"/>
<field name="blade_tip_working_size"/> <field name="blade_tip_working_size"/>
<field name="blade_tip_taper" /> <field name="blade_tip_taper"/>
<field name="blade_diameter" /> <field name="blade_diameter"/>
<field name="blade_length"/> <field name="blade_length"/>
<field name="blade_helix_angle"/> <field name="blade_helix_angle"/>
<field name="blade_width" /> <field name="blade_width"/>
<field name="blade_width" /> <field name="blade_width"/>
<field name="pitch"/> <field name="pitch"/>
<field name="cutting_depth"/> <field name="cutting_depth"/>
</tree> </tree>
</field> </field>
</record> </record>
<record id="view_sf_tool_materials_basic_parameters_blade_tree" model="ir.ui.view"> <record id="view_sf_tool_materials_basic_parameters_blade_tree" model="ir.ui.view">
<field name="name">sf.tool.materials.basic.parameters.tree</field> <field name="name">sf.tool.materials.basic.parameters.tree</field>
<field name="model">sf.tool.materials.basic.parameters</field> <field name="model">sf.tool.materials.basic.parameters</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="基础参数" delete="0" create="0"> <tree string="基础参数" delete="0" create="0">
<field name="total_length" /> <field name="total_length"/>
<field name="length" /> <field name="length"/>
<field name="thickness"/> <field name="thickness"/>
<field name="width"/> <field name="width"/>
<field name="cutting_blade_length" /> <field name="cutting_blade_length"/>
<field name="relief_angle" /> <field name="relief_angle"/>
<field name="blade_tip_circular_arc_radius"/> <field name="blade_tip_circular_arc_radius"/>
<field name="inscribed_circle_diameter"/> <field name="inscribed_circle_diameter"/>
<field name="install_aperture_diameter" /> <field name="install_aperture_diameter"/>
<field name="chip_breaker_groove" /> <field name="chip_breaker_groove"/>
<field name="blade_teeth_model"/> <field name="blade_teeth_model"/>
<field name="blade_blade_number"/> <field name="blade_blade_number"/>
<field name="main_included_angle" /> <field name="main_included_angle"/>
<field name="top_angle" /> <field name="top_angle"/>
<field name="thread_model"/> <field name="thread_model"/>
<field name="thread_num" /> <field name="thread_num"/>
<field name="blade_tip_height_tolerance" /> <field name="blade_tip_height_tolerance"/>
<field name="inscribed_circle_tolerance"/> <field name="inscribed_circle_tolerance"/>
<field name="thickness_tolerance"/> <field name="thickness_tolerance"/>
</tree> </tree>
</field> </field>
</record> </record>
<record id="view_sf_tool_materials_basic_parameters_cutter_bar_tree" model="ir.ui.view"> <record id="view_sf_tool_materials_basic_parameters_cutter_bar_tree" model="ir.ui.view">
<field name="name">sf.tool.materials.basic.parameters.tree</field> <field name="name">sf.tool.materials.basic.parameters.tree</field>
<field name="model">sf.tool.materials.basic.parameters</field> <field name="model">sf.tool.materials.basic.parameters</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="基础参数" delete="0" create="0"> <tree string="基础参数" delete="0" create="0">
<field name="total_length" /> <field name="total_length"/>
<field name="height" /> <field name="height"/>
<field name="blade_height"/> <field name="blade_height"/>
<field name="cut_depth_max"/> <field name="cut_depth_max"/>
<field name="cutter_arbor_diameter" /> <field name="cutter_arbor_diameter"/>
<field name="min_machining_aperture" /> <field name="min_machining_aperture"/>
<field name="install_blade_tip_num"/> <field name="install_blade_tip_num"/>
<field name="cutting_blade_model"/> <field name="cutting_blade_model"/>
<field name="is_cooling_hole" /> <field name="is_cooling_hole"/>
<field name="locating_slot_code" /> <field name="locating_slot_code"/>
<field name="installing_structure"/> <field name="installing_structure"/>
<field name="blade_id"/> <field name="blade_id"/>
<field name="tool_shim" /> <field name="tool_shim"/>
<field name="cotter_pin" /> <field name="cotter_pin"/>
<field name="pressing_plate"/> <field name="pressing_plate"/>
<field name="screw"/> <field name="screw"/>
<field name="spanner" /> <field name="spanner"/>
</tree> </tree>
</field> </field>
</record> </record>
<record id="view_sf_tool_materials_basic_parameters_tree" model="ir.ui.view"> <record id="view_sf_tool_materials_basic_parameters_tree" model="ir.ui.view">
<field name="name">sf.tool.materials.basic.parameters.tree</field> <field name="name">sf.tool.materials.basic.parameters.tree</field>
<field name="model">sf.tool.materials.basic.parameters</field> <field name="model">sf.tool.materials.basic.parameters</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="基础参数" > <tree string="基础参数">
<field name="total_length" /> <field name="total_length"/>
<field name="blade_number" /> <field name="blade_number"/>
<field name="neck_diameter"/> <field name="neck_diameter"/>
<field name="neck_length"/> <field name="neck_length"/>
<field name="handle_diameter" /> <field name="handle_diameter"/>
<field name="handle_length" /> <field name="handle_length"/>
<field name="blade_tip_diameter"/> <field name="blade_tip_diameter"/>
<field name="blade_tip_working_size"/> <field name="blade_tip_working_size"/>
<field name="blade_tip_taper" /> <field name="blade_tip_taper"/>
<field name="blade_diameter" /> <field name="blade_diameter"/>
<field name="blade_length"/> <field name="blade_length"/>
<field name="blade_helix_angle"/> <field name="blade_helix_angle"/>
<field name="blade_width" /> <field name="blade_width"/>
<field name="blade_width" /> <field name="blade_width"/>
<field name="pitch"/> <field name="pitch"/>
<field name="cutting_depth"/> <field name="cutting_depth"/>
</tree> </tree>
</field> </field>
</record> </record>
<record model="ir.ui.view" id="view_sf_tool_materials_basic_parameters_search"> <record model="ir.ui.view" id="view_sf_tool_materials_basic_parameters_search">
<field name="name">sf.tool.materials.basic.parameters.search</field> <field name="name">sf.tool.materials.basic.parameters.search</field>
<field name="model">sf.tool.materials.basic.parameters</field> <field name="model">sf.tool.materials.basic.parameters</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search> <search>
<field name="name"/> <field name="name"/>
</search> </search>
</field> </field>
</record> </record>
<record id="action_sf_tool_materials_basic_parameters" model="ir.actions.act_window"> <record id="view_sf_tool_materials_basic_parameters_form" model="ir.ui.view">
<field name="name">基础参数</field> <field name="name">sf.tool.materials.basic.parameters.form</field>
<field name="res_model">sf.tool.materials.basic.parameters</field> <field name="model">sf.tool.materials.basic.parameters</field>
<field name="view_mode">tree</field> <field name="arch" type="xml">
<form string="规则">
<sheet>
<field name="cutting_tool_type" invisible="1"/>
<field name="standard_library_id" invisible="1"/>
<group>
<group attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')]}">
<field name="total_length"/>
<field name="blade_diameter" class="diameter"/>
<field name="blade_length"/>
<field name="blade_number"/>
<field name="neck_length"/>
<field name="neck_diameter" class="diameter"/>
<field name="handle_diameter" class="diameter"/>
<field name="handle_length"/>
</group>
<group attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')]}">
<field name="blade_tip_working_size"/>
<field name="blade_tip_diameter" class="diameter"/>
<field name="blade_tip_taper"/>
<field name="blade_helix_angle"/>
<field name="pitch"/>
<field name="blade_width"/>
<field name="blade_depth"/>
<field name="cut_depth_max"/>
</group>
<group attrs="{'invisible': [('cutting_tool_type', '!=', '刀片')]}">
<field name="length"/>
<field name="thickness"/>
<field name="inscribed_circle_diameter" class="diameter"/>
<field name="install_aperture_diameter" class="diameter" string="安装孔直径D1(mm)"/>
<field name="blade_tip_circular_arc_radius" string="刀尖圆弧半径RE(mm)"/>
<field name="cutting_blade_length"/>
<field name="relief_angle"/>
<field name="chip_breaker_groove"/>
<field name="chip_breaker_type_code"/>
</group>
<group attrs="{'invisible': [('cutting_tool_type', '!=', '刀片')]}">
<field name="blade_teeth_model"/>
<field name="thread_model"/>
<field name="pitch"/>
<field name="thread_num"/>
<field name="cut_depth_max"/>
<field name="blade_blade_number" string="刃数"/>
<field name="blade_width" string="刃宽"/>
<field name="main_included_angle"/>
<field name="top_angle"/>
<field name="blade_tip_height_tolerance"/>
<field name="inscribed_circle_tolerance"/>
<field name="thickness_tolerance"/>
</group>
<group attrs="{'invisible': [('cutting_tool_type', '!=', '刀杆')]}">
<field name="total_length"/>
<field name="width"/>
<field name="height"/>
<label for="knife_head_length" string="刀头尺寸"/>
<div class="test_model">
<label for="knife_head_length" string="长"/>
<field name="knife_head_length" class="o_address_zip"
options="{'format': false}"/>
<label for="knife_head_width" string="宽"/>
<field name="knife_head_width" class="o_address_zip"
options="{'format': false}"/>
<label for="knife_head_height" string="高"/>
<field name="knife_head_height" class="o_address_zip"
options="{'format': false}"/>
</div>
<field name="blade_diameter" class="diameter"/>
<field name="cutter_arbor_diameter" class="diameter"/>
<field name="is_cooling_hole"/>
<field name="locating_slot_code"/>
</group>
<group attrs="{'invisible': [('cutting_tool_type', '!=', '刀杆')]}">
<field name="main_included_angle"/>
<field name="relief_angle"/>
<field name="cutting_blade_length"/>
<field name="cut_depth_max"/>
<field name="min_machining_aperture"/>
<field name="install_blade_tip_num"/>
<field name="installing_structure"/>
<field name="blade_id" options="{'no_create': True}"/>
<field name="tool_shim"/>
<field name="cotter_pin"/>
<field name="pressing_plate"/>
<field name="screw"/>
<field name="spanner"/>
</group>
<!-- <field name="context">{'selection_mode': 'single'}</field>--> <group attrs="{'invisible': [('cutting_tool_type', '!=', '刀盘')]}">
<field name="domain">[]</field> <field name="install_blade_tip_num"/>
<!-- <field name="multi">false</field>--> <field name="blade_diameter" class="diameter"/>
</record> <field name="cutter_head_diameter" class="diameter"/>
<field name="interface_diameter" class="diameter"/>
<field name="total_length"/>
<field name="blade_length"/>
<field name="cutting_blade_length"/>
<field name="cut_depth_max"/>
</group>
<group attrs="{'invisible': [('cutting_tool_type', '!=', '刀盘')]}">
<field name="main_included_angle"/>
<field name="installing_structure"/>
<field name="blade_id" options="{'no_create': True}"/>
<field name="screw"/>
<field name="spanner"/>
<field name="is_cooling_hole"/>
<field name="locating_slot_code"/>
</group>
<group attrs="{'invisible': [('cutting_tool_type', '!=', '夹头')]}">
<field name="er_size_model" string="尺寸型号"/>
<label for="min_clamping_diameter" string="夹持直径"/>
<div class="test_model">
<label for="min_clamping_diameter" string="最小"/>
<field name="min_clamping_diameter" class="o_address_zip diameter"
options="{'format': false}"/>
<label for="max_clamping_diameter" string="最大"/>
<field name="max_clamping_diameter" class="o_address_zip diameter"
options="{'format': false}"/>
</div>
<field name="total_length"/>
<field name="outer_diameter" class="diameter"/>
<field name="inner_diameter" class="diameter"/>
<field name="taper"/>
</group>
<group attrs="{'invisible': [('cutting_tool_type', '!=', '夹头')]}">
<field name="run_out_accuracy"/>
<field name="top_diameter" class="diameter"/>
<field name="weight"/>
<field name="max_load_capacity"/>
<field name="cooling_jacket"/>
</group>
<group attrs="{'invisible': [('cutting_tool_type', '!=', '刀柄')]}">
<field name="taper_shank_model"/>
<field name="total_length"/>
<field name="shank_length"/>
<field name="shank_diameter" class="diameter"/>
<field name="flange_shank_length"/>
<field name="flange_diameter" class="diameter"/>
<field name="diameter_slip_accuracy"/>
<field name="dynamic_balance_class"/>
</group>
<group attrs="{'invisible': [('cutting_tool_type', '!=', '刀柄')]}">
<label for="min_clamping_diameter" string="夹持直径"/>
<div class="test_model">
<label for="min_clamping_diameter" string="最小"/>
<field name="min_clamping_diameter" class="o_address_zip diameter"
options="{'format': false}"/>
<label for="max_clamping_diameter" string="最大"/>
<field name="max_clamping_diameter" class="o_address_zip diameter"
options="{'format': false}"/>
</div>
<field name="max_rotate_speed"/>
<field name="fit_chuck_size"/>
<field name="nut"/>
<field name="spanner"/>
<field name="clamping_mode"/>
<field name="tool_changing_time"/>
<field name="cooling_model"/>
<field name="is_quick_cutting"/>
<field name="is_safe_lock"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="action_sf_tool_materials_basic_parameters" model="ir.actions.act_window">
<field name="name">基础参数</field>
<field name="res_model">sf.tool.materials.basic.parameters</field>
<field name="view_mode">form</field>
<field name="context">{'default_cutting_tool_type': cutting_tool_type}</field>
<field name="domain">[]</field>
<!-- <field name="multi">false</field>-->
</record>
</data> </data>
</odoo> </odoo>

View File

@@ -21,6 +21,7 @@
<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.cutting_tool.standard.library</field> <field name="res_model">sf.cutting_tool.standard.library</field>
<!-- <field name="context">{'default_cutting_tool_material_id': cutting_tool_material_id}</field>-->
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
</record> </record>
<!-- 功能刀具action --> <!-- 功能刀具action -->

View File

@@ -123,19 +123,19 @@
<form string="刀具标准库" delete="0" create="0" edit="0"> <form string="刀具标准库" delete="0" create="0" edit="0">
<sheet> <sheet>
<field name="image" widget='image' class="oe_avatar" <field name="image" widget='image' class="oe_avatar"
options="{'zoom': true, 'preview_image':'image_128'}"/> required="1"/>
<div class="oe_title"> <div class="oe_title">
<h1> <h1>
<field name="code"/> <field name="code" readonly="1" force_save="1"/>
</h1> </h1>
</div> </div>
<group> <group>
<group> <group>
<field name="name"/> <field name="name"/>
<field name="cutting_tool_material_id"/> <field name="cutting_tool_material_id" readonly="1"/>
<field name="cutting_tool_type"/> <field name="cutting_tool_type" invisible="1"/>
<field name="cutting_tool_type_id"/> <field name="cutting_tool_type_id" required="1"/>
<field name="brand_id"/> <field name="brand_id" required="1"/>
<label for="integral_run_out_accuracy_min" string="端跳精度" <label for="integral_run_out_accuracy_min" string="端跳精度"
attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')]}"/> attrs="{'invisible': [('cutting_tool_type', '!=', '整体式刀具')]}"/>
<div class="o_address_format" <div class="o_address_format"
@@ -165,8 +165,7 @@
attrs="{'invisible': [('cutting_tool_type', '!=', '刀柄')]}"/> attrs="{'invisible': [('cutting_tool_type', '!=', '刀柄')]}"/>
</group> </group>
<group> <group>
<field name="material_model_id" placeholder="请选择" string="材质" <field name="material_model_id" placeholder="请选择" string="材质"/>
attrs="{'required': [('cutting_tool_type', 'not in', ['刀柄', '夹头'])]}"/>
<field name="tool_hardness" string="硬度(hrc)" options="{'format': false}" <field name="tool_hardness" string="硬度(hrc)" options="{'format': false}"
widget="integer"/> widget="integer"/>
<field name="coating_material"/> <field name="coating_material"/>

View File

@@ -62,7 +62,7 @@ class Sf_Bf_Connect(http.Controller):
request.env.ref("base.user_admin")).bom_create_line( request.env.ref("base.user_admin")).bom_create_line(
self_machining_embryo) self_machining_embryo)
if not self_machining_bom_line: if not self_machining_bom_line:
res['status'] = 2 res['status'] = -2
res['message'] = '该订单模型的材料型号在您分配的工厂里暂未有原材料,请先配置再进行分配' res['message'] = '该订单模型的材料型号在您分配的工厂里暂未有原材料,请先配置再进行分配'
request.cr.rollback() request.cr.rollback()
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
@@ -79,6 +79,11 @@ class Sf_Bf_Connect(http.Controller):
order_id, order_id,
'subcontract', 'subcontract',
i) i)
if outsource_embryo == -3:
res['status'] = -3
res['message'] = '该订单模型的材料型号在您分配的工厂里暂未设置获取方式和供应商,请先配置再进行分配'
request.cr.rollback()
return json.JSONEncoder().encode(res)
# 创建坯料的bom # 创建坯料的bom
outsource_bom = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).bom_create( outsource_bom = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).bom_create(
outsource_embryo, outsource_embryo,
@@ -87,7 +92,7 @@ class Sf_Bf_Connect(http.Controller):
outsource_bom_line = outsource_bom.with_user( outsource_bom_line = outsource_bom.with_user(
request.env.ref("base.user_admin")).bom_create_line(outsource_embryo) request.env.ref("base.user_admin")).bom_create_line(outsource_embryo)
if not outsource_bom_line: if not outsource_bom_line:
res['status'] = 2 res['status'] = -2
res['message'] = '该订单模型的材料型号在您分配的工厂里暂未有原材料,请先配置再进行分配' res['message'] = '该订单模型的材料型号在您分配的工厂里暂未有原材料,请先配置再进行分配'
request.cr.rollback() request.cr.rollback()
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)
@@ -101,6 +106,11 @@ class Sf_Bf_Connect(http.Controller):
item, item,
order_id, order_id,
'purchase', i) 'purchase', i)
if purchase_embryo == -3:
res['status'] = -3
res['message'] = '该订单模型的材料型号在您分配的工厂里暂未设置获取方式和供应商,请先配置再进行分配'
request.cr.rollback()
return json.JSONEncoder().encode(res)
# 产品配置bom # 产品配置bom
product_bom_purchase = request.env['mrp.bom'].with_user( product_bom_purchase = request.env['mrp.bom'].with_user(
request.env.ref("base.user_admin")).bom_create(product, 'normal', False) request.env.ref("base.user_admin")).bom_create(product, 'normal', False)

View File

@@ -100,7 +100,7 @@ class ResMrpBomMo(models.Model):
if rate_of_waste <= 20: if rate_of_waste <= 20:
return embryo_has return embryo_has
else: else:
return return None
# 查bom的原材料 # 查bom的原材料
def get_raw_bom(self, product): def get_raw_bom(self, product):

View File

@@ -22,7 +22,6 @@
<field name="materials_id" string="材料" placeholder="请选择" options="{'no_create': True}" <field name="materials_id" string="材料" placeholder="请选择" options="{'no_create': True}"
attrs="{'invisible': [('categ_type', 'not in', ['成品','坯料', '原材料'])],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('categ_type', 'not in', ['成品','坯料', '原材料'])],'readonly': [('id', '!=', False)]}"/>
<field name="materials_type_id" string="型号" placeholder="请选择" options="{'no_create': True}" <field name="materials_type_id" string="型号" placeholder="请选择" options="{'no_create': True}"
domain="[('materials_id', '=', materials_id)]"
attrs="{'invisible': [('categ_type', 'not in', ['成品','坯料', '原材料'])],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('categ_type', 'not in', ['成品','坯料', '原材料'])],'readonly': [('id', '!=', False)]}"/>
<field name="server_product_process_parameters_id" string="表面工艺参数" <field name="server_product_process_parameters_id" string="表面工艺参数"
options="{'no_create': True}" options="{'no_create': True}"
@@ -32,9 +31,14 @@
attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}" attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}"
placeholder="请选择"/> placeholder="请选择"/>
<field name="cutting_tool_model_id" placeholder="请选择" class="custom_required" <field name="cutting_tool_model_id" placeholder="请选择" class="custom_required"
options="{'no_create': True}" domain="[('cutting_tool_material_id','=',cutting_tool_material_id)]"
attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}"/> context="{'default_cutting_tool_material_id': cutting_tool_material_id}"
attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}">
</field>
<!-- <button name="%(sf_base.action_sf_cutting_tool_standard_library)d" string="新建" type="action"-->
<!-- context="{'default_cutting_tool_material_id': cutting_tool_material_id}"/>-->
<field name="specification_id" placeholder="请选择" class="custom_required" <field name="specification_id" placeholder="请选择" class="custom_required"
context="{'default_cutting_tool_type': cutting_tool_type,'default_standard_library_id':cutting_tool_model_id}"
attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}" attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}"
domain="[('standard_library_id','=',cutting_tool_model_id)]"/> domain="[('standard_library_id','=',cutting_tool_model_id)]"/>
<field name="fixture_material_id" attrs="{'invisible': [('categ_type', '!=', '夹具')]}" <field name="fixture_material_id" attrs="{'invisible': [('categ_type', '!=', '夹具')]}"
@@ -90,7 +94,7 @@
</field> </field>
</record> </record>
<record model="ir.ui.view" id="view_product_template_form_inherit_sf"> <record model="ir.ui.view" id="view_product_template_only_form_inherit_sf">
<field name="name">product.template.only.form.inherit.sf</field> <field name="name">product.template.only.form.inherit.sf</field>
<field name="model">product.template</field> <field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_only_form_view"/> <field name="inherit_id" ref="product.product_template_only_form_view"/>
@@ -104,7 +108,7 @@
</field> </field>
</record> </record>
<record model="ir.ui.view" id="view_product_template_only_form_inherit_sf"> <record model="ir.ui.view" id="view_product_template_only_dlm_form_inherit_sf">
<field name="name">product.template.only.form.inherit.sf</field> <field name="name">product.template.only.form.inherit.sf</field>
<field name="model">product.template</field> <field name="model">product.template</field>
<field name="inherit_id" ref="sf_dlm_management.view_sale_product_template_form_inherit_sf"/> <field name="inherit_id" ref="sf_dlm_management.view_sale_product_template_form_inherit_sf"/>
@@ -142,6 +146,10 @@
attrs="{'invisible': [('cutting_tool_type', '!=', '刀杆')],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('cutting_tool_type', '!=', '刀杆')],'readonly': [('id', '!=', False)]}"/>
<field name="tool_height" <field name="tool_height"
attrs="{'invisible': [('cutting_tool_type', '!=', '刀杆')],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('cutting_tool_type', '!=', '刀杆')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_shank_length" string="刀柄长度(mm)"
attrs="{'invisible': [('cutting_tool_type', '!=', '刀柄')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_shank_diameter" string="刀柄直径(mm)" class="diameter"
attrs="{'invisible': [('cutting_tool_type', '!=', '刀柄')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_flange_diameter" <field name="cutting_tool_flange_diameter"
attrs="{'invisible': [('cutting_tool_type', '!=', '刀柄')],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('cutting_tool_type', '!=', '刀柄')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_flange_length" <field name="cutting_tool_flange_length"
@@ -258,7 +266,7 @@
<span>(mm)&amp;nbsp;</span> <span>(mm)&amp;nbsp;</span>
</div> </div>
<field name="cutting_tool_clamping_way" <field name="cutting_tool_clamping_way"
attrs="{'invisible': [('cutting_tool_type','not in',('刀柄','夹头'))],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('cutting_tool_type','not in',('刀柄'))],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_top_diameter" class="diameter" <field name="cutting_tool_top_diameter" class="diameter"
attrs="{'invisible': [('cutting_tool_type','not in',('夹头'))],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('cutting_tool_type','not in',('夹头'))],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_outer_diameter" class="diameter" <field name="cutting_tool_outer_diameter" class="diameter"
@@ -297,7 +305,7 @@
<field name="tool_weight" <field name="tool_weight"
attrs='{"invisible": [("cutting_tool_type","not in",("夹头","刀柄"))],"readonly": [("id", "!=", False)]}'/> attrs='{"invisible": [("cutting_tool_type","not in",("夹头","刀柄"))],"readonly": [("id", "!=", False)]}'/>
<field name="cutting_tool_taper" <field name="cutting_tool_taper"
attrs="{'invisible': [('cutting_tool_type', 'not in', ('夹头','刀柄'))],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('cutting_tool_type', 'not in', ('夹头'))],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_taper_shank_model" <field name="cutting_tool_taper_shank_model"
attrs="{'invisible': [('cutting_tool_type', '!=', '刀柄')],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('cutting_tool_type', '!=', '刀柄')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_dynamic_balance_class" <field name="cutting_tool_dynamic_balance_class"
@@ -340,9 +348,9 @@
attrs="{'invisible': [('cutting_tool_type', '!=', '夹头')],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('cutting_tool_type', '!=', '夹头')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_er_size_model" <field name="cutting_tool_er_size_model"
attrs="{'invisible': [('cutting_tool_type', '!=', '夹头')],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('cutting_tool_type', '!=', '夹头')],'readonly': [('id', '!=', False)]}"/>
<field name="cutting_tool_handle_id" <!-- <field name="cutting_tool_handle_id"-->
options="{'no_create': True}" <!-- options="{'no_create': True}"-->
attrs="{'invisible': [('cutting_tool_type', '!=', '夹头')],'readonly': [('id', '!=', False)]}"/> <!-- attrs="{'invisible': [('cutting_tool_type', '!=', '夹头')],'readonly': [('id', '!=', False)]}"/>-->
<field name="cooling_suit_type_ids" <field name="cooling_suit_type_ids"
attrs="{'invisible': [('cutting_tool_type', '!=', '夹头')],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('cutting_tool_type', '!=', '夹头')],'readonly': [('id', '!=', False)]}"/>
<!-- 刀杆 --> <!-- 刀杆 -->

View File

@@ -12,14 +12,14 @@
<group> <group>
<field name="code" readonly="1" force_save="1"/> <field name="code" readonly="1" force_save="1"/>
<field name="name" readonly="1" force_save="1"/> <field name="name" readonly="1" force_save="1"/>
<field name="maintenance_equipment_category_id" required="1" class="custom_required"/> <field name="maintenance_equipment_category_id" required="1" />
<field name="eq_maintenance_ids" invisible='1'/> <field name="eq_maintenance_ids" invisible='1'/>
<field name="overhaul_ids" invisible='1'/> <field name="overhaul_ids" invisible='1'/>
</group> </group>
<group> <group>
<field name="maintenance_type" required="1" class="custom_required"/> <field name="maintenance_type" required="1"/>
<field name="created_user_id"/> <field name="created_user_id"/>
<field name="remark"/> <field name="remark"/>
</group> </group>
@@ -32,11 +32,11 @@
<page string="维保项目"> <page string="维保项目">
<field name="maintenance_standards_ids" delete="1"> <field name="maintenance_standards_ids" delete="1">
<tree editable="bottom"> <tree editable="bottom" >
<field name="name" class="table_custom_required"/> <field name="name" />
<field name="fault_type" class="table_custom_required"/> <field name="fault_type" />
<field name="maintenance_standards" class="table_custom_required"/> <field name="maintenance_standards" />
<field name="Period" class="table_custom_required"/> <field name="Period" />
</tree> </tree>
</field> </field>
</page> </page>

View File

@@ -60,9 +60,9 @@
<field name="function_type"/> <field name="function_type"/>
<field name="code" readonly="1"/> <field name="code" readonly="1"/>
<field name="equipment_type" invisible="1"/> <field name="equipment_type" invisible="1"/>
<field name="brand_id" force_save="1" class="custom_required"/> <field name="brand_id" force_save="1" />
<field name="type_id" attrs="{'required': [('equipment_type', '=', '机床')]}" <field name="type_id" attrs="{'required': [('equipment_type', '=', '机床')]}"
domain="[('brand_id', '=', brand_id)]" class="custom_required"/> domain="[('brand_id', '=', brand_id)]" />
<field name="machine_tool_category" readonly="1" attrs="{'invisible': [('type_id', '=', False)]}" <field name="machine_tool_category" readonly="1" attrs="{'invisible': [('type_id', '=', False)]}"
force_save="1"/> force_save="1"/>
<field name="run_time" force_save="1"/> <field name="run_time" force_save="1"/>
@@ -73,9 +73,9 @@
<group> <group>
<group string="基础参数"> <group string="基础参数">
<field name="control_system_id" attrs="{'required': [('equipment_type', '=', '机床')]}" <field name="control_system_id" attrs="{'required': [('equipment_type', '=', '机床')]}"
options="{'no_create': True}" class="custom_required"/> options="{'no_create': True}" />
<label for="workbench_L" string="工作台尺寸(mm)"/> <label for="workbench_L" string="工作台尺寸(mm)"/>
<div class="test_model custom_required"> <div class="test_model">
<label for="workbench_L" string="长"/> <label for="workbench_L" string="长"/>
<field name="workbench_L" class="o_address_zip" <field name="workbench_L" class="o_address_zip"
attrs="{'required': [('equipment_type', '=', '机床')]}" attrs="{'required': [('equipment_type', '=', '机床')]}"
@@ -134,7 +134,7 @@
<!-- <field name="guide_rail" required="1"/>--> <!-- <field name="guide_rail" required="1"/>-->
<field name="number_of_axles" attrs="{'required': [('equipment_type', '=', '机床')]}" <field name="number_of_axles" attrs="{'required': [('equipment_type', '=', '机床')]}"
widget="radio" widget="radio"
options="{'horizontal': true}" class="custom_required"/> options="{'horizontal': true}" />
<label for="x_axis" string="加工行程(mm)" <label for="x_axis" string="加工行程(mm)"
attrs="{'invisible': [('number_of_axles', '=', False)]}"/> attrs="{'invisible': [('number_of_axles', '=', False)]}"/>
<div class="test_model" <div class="test_model"
@@ -177,8 +177,7 @@
<group string="刀具"> <group string="刀具">
<!-- <field name="knife_type" required="1"/>--> <!-- <field name="knife_type" required="1"/>-->
<field name="number_of_knife_library" <field name="number_of_knife_library"
attrs="{'required': [('equipment_type', '=', '机床')]}" attrs="{'required': [('equipment_type', '=', '机床')]}"/>
class="custom_required"/>
<!-- <field name="tool_speed" required="1"/>--> <!-- <field name="tool_speed" required="1"/>-->
<field name="tool_full_diameter_max"/> <field name="tool_full_diameter_max"/>
<field name="tool_perimeter_diameter_max"/> <field name="tool_perimeter_diameter_max"/>
@@ -198,7 +197,7 @@
<field name="C_tool_time"/> <field name="C_tool_time"/>
</group> </group>
<group string="主轴"> <group string="主轴">
<field name="taper_type_id" attrs="{'required': [('equipment_type', '=', '机床')]}" class="custom_required"/> <field name="taper_type_id" attrs="{'required': [('equipment_type', '=', '机床')]}" />
<label for="distance_min" string="主轴端面-工作台距离(mm)"/> <label for="distance_min" string="主轴端面-工作台距离(mm)"/>
<div class="test_model"> <div class="test_model">
<label for="distance_min" string="最小(min)"/> <label for="distance_min" string="最小(min)"/>
@@ -982,16 +981,16 @@
<xpath expr="//field[@name='next_action_date']" position="before"> <xpath expr="//field[@name='next_action_date']" position="before">
<field name='eq_maintenance_id' force_save="1" widget="many2one" class="custom_required"/> <field name='eq_maintenance_id' force_save="1" widget="many2one"/>
</xpath> </xpath>
<xpath expr="//div[hasclass('o_row')][field[@name='maintenance_duration']]" position="after"> <xpath expr="//div[hasclass('o_row')][field[@name='maintenance_duration']]" position="after">
<field name='overhaul_id' class="custom_required"/> <field name='overhaul_id'/>
<field name="overhaul_date" string="下次预防检修"/> <field name="overhaul_date" string="下次预防检修"/>
<label for="overhaul_period" string="预防检修频次" class="custom_required"/> <label for="overhaul_period" string="预防检修频次"/>
<div class="o_row"> <div class="o_row">
<field name="overhaul_period"/> <field name="overhaul_period"/>
days days

View File

@@ -1 +1,2 @@
from . import controllers from . import controllers
from . import workpiece

View File

@@ -210,7 +210,7 @@ class Manufacturing_Connect(http.Controller):
'state': 'finished'}) 'state': 'finished'})
production_obj = request.env['mrp.production'].sudo().search([('name', '=', production_id)]) production_obj = request.env['mrp.production'].sudo().search([('name', '=', production_id)])
if production_obj: if production_obj:
production_obj.sudo().schedule_state = '已完成' production_obj.sudo().work_order_state = '已完成'
production_obj.write({'state': 'completed'}) production_obj.write({'state': 'completed'})
request.env['sale.order'].sudo().search( request.env['sale.order'].sudo().search(
[('name', '=', production_obj.origin)]).write({'schedule_status': 'to deliver'}) [('name', '=', production_obj.origin)]).write({'schedule_status': 'to deliver'})

View File

@@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
import logging
import json
from odoo import http
from odoo.http import request
class Workpiece(http.Controller):
@http.route('/agvApi/backfeed', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
cors="*")
def backfeed(self, **kw):
"""
agv小车反馈工单(工件)结果
:param kw:
:return:
"""
logging.info('backfeed:%s' % kw)
try:
res = {'Succeed': True}
datas = request.httprequest.data
ret = json.loads(datas)
logging.info('backfeed-ret:%s' % ret)
if 'reqCode' in ret:
if 'method' in ret:
if ret['method'] == 'end':
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
[('production_id.name', '=', ret['reqCode'])])
if workpiece_delivery:
workpiece_delivery.write({'status': '已配送', 'task_completion_time': ret['reqTime']})
else:
res = {'Succeed': False, 'ErrorCode': 203, 'Error': '该reqCode暂未查到对应的工件配送记录'}
else:
res = {'Succeed': False, 'ErrorCode': 204, 'Error': '未传method字段'}
else:
res = {'Succeed': False, 'ErrorCode': 201, 'Error': '未传reqCode字段'}
except Exception as e:
res = {'Succeed': False, 'ErrorCode': 202, 'Error': e}
logging.info('backfeed error:%s' % e)
return json.JSONEncoder().encode(res)

View File

@@ -20,6 +20,8 @@ class MrpProduction(models.Model):
model_file = fields.Binary('模型文件', related='product_id.model_file') model_file = fields.Binary('模型文件', related='product_id.model_file')
schedule_state = fields.Selection([('未排', '未排'), ('已排', '已排'), ('已完成', '已完成')], schedule_state = fields.Selection([('未排', '未排'), ('已排', '已排'), ('已完成', '已完成')],
string='排程状态', default='未排') string='排程状态', default='未排')
work_order_state = fields.Selection([('未排', '未排'), ('已排', '已排'), ('已完成', '已完成')],
string='工单状态', default='未排')
# state = fields.Selection(selection_add=[ # state = fields.Selection(selection_add=[
# ('pending_scheduling', '待排程'), # ('pending_scheduling', '待排程'),
@@ -53,8 +55,7 @@ class MrpProduction(models.Model):
production_line_id = fields.Many2one('sf.production.line', string='生产线') production_line_id = fields.Many2one('sf.production.line', string='生产线')
plan_start_processing_time = fields.Datetime('计划开始加工时间') plan_start_processing_time = fields.Datetime('计划开始加工时间')
production_line_state = fields.Selection([('待上产线', '待上产线'), ('已上产线', '已上产线'), ('已下产线', '已下产线')], production_line_state = fields.Selection([('待上产线', '待上产线'), ('已上产线', '已上产线'), ('已下产线', '已下产线')],
string='上/下产线', default='待上产线') string='上/下产线', default='待上产线')
@api.depends( @api.depends(
'move_raw_ids.state', 'move_raw_ids.quantity_done', 'move_finished_ids.state', 'move_raw_ids.state', 'move_raw_ids.quantity_done', 'move_finished_ids.state',
@@ -94,9 +95,9 @@ class MrpProduction(models.Model):
production.state = 'pending_processing' production.state = 'pending_processing'
# elif production.state == 'progress' and production.schedule_state == '已完成': # elif production.state == 'progress' and production.schedule_state == '已完成':
# production.state = 'completed' # production.state = 'completed'
elif production.state == 'pending_processing' and production.schedule_state == '已完成': elif production.state == 'pending_processing' and production.work_order_state == '已完成':
production.state = 'completed' production.state = 'completed'
elif production.state == 'progress' and production.schedule_state == '已完成': elif production.state == 'progress' and production.work_order_state == '已完成':
production.state = 'completed' production.state = 'completed'
def action_check(self): def action_check(self):

View File

@@ -236,7 +236,16 @@ class ResMrpWorkOrder(models.Model):
# if not item.workpiece_code: # if not item.workpiece_code:
# raise UserError('请对【同运工件】进行扫描') # raise UserError('请对【同运工件】进行扫描')
else: else:
item.write({'task_delivery_time': fields.Datetime.now(), 'status': '配送'}) if item.status == '下发':
return {
'name': _('确认'),
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'sf.workpiece.delivery.wizard',
'target': 'new',
'context': {
'default_workorder_id': self.id,
}}
# 拼接工单对象属性值 # 拼接工单对象属性值
def json_workorder_str(self, k, production, route): def json_workorder_str(self, k, production, route):
@@ -899,7 +908,25 @@ class WorkPieceDelivery(models.Model):
# 配送至avg小车 # 配送至avg小车
def _delivery_avg(self): def _delivery_avg(self):
self.write({'task_delivery_time': fields.Datetime.now(), 'status': '待配送'}) res = {'reqCode': self.production_id.name, 'reqTime': '', 'clientCode': '', 'tokenCode': '',
'taskTyp': 'F01', 'ctnrTyp': '', 'ctnrCode': '', 'wbCode': '', 'positionCodePath': [], 'podCode': '',
'podDir': '', 'materialLot': '', 'priority': '', 'taskCode': '', 'agvCode': '', 'materialLot': '',
'data': ''}
config = self.env['res.config.settings'].get_values()
try:
logging.info('config-AGV请求路径:%s' % config['agv_rcms_url'])
logging.info('config-json:%s' % res)
ret = requests.post((config['agv_rcms_url']), json=res)
ret = ret.json()
logging.info('config-ret:%s' % ret)
if ret['code'] == 0:
if self.production_id.name == ret['reqCode']:
self.write({'task_delivery_time': fields.Datetime.now(), 'status': '待配送'})
else:
raise UserError(ret['message'])
except Exception as e:
logging.info('config-e:%s' % e)
raise UserError("工件配送请求agv失败")
@api.depends('production_id.production_line_id') @api.depends('production_id.production_line_id')
def _compute_production_line_id(self): def _compute_production_line_id(self):

View File

@@ -6,6 +6,8 @@ import os
from odoo import models, fields, api, _ from odoo import models, fields, api, _
from odoo.exceptions import ValidationError from odoo.exceptions import ValidationError
from odoo.modules import get_resource_path from odoo.modules import get_resource_path
from OCC.Extend.DataExchange import read_step_file from OCC.Extend.DataExchange import read_step_file
from OCC.Extend.DataExchange import write_stl_file from OCC.Extend.DataExchange import write_stl_file
@@ -39,7 +41,8 @@ class ResProductMo(models.Model):
product_model_type_id = fields.Many2one('sf.model.type', string='产品模型类型') product_model_type_id = fields.Many2one('sf.model.type', string='产品模型类型')
embryo_model_type_id = fields.Many2one('sf.model.type', string='坯料模型类型') embryo_model_type_id = fields.Many2one('sf.model.type', string='坯料模型类型')
materials_id = fields.Many2one('sf.production.materials', string='材料') materials_id = fields.Many2one('sf.production.materials', string='材料')
materials_type_id = fields.Many2one('sf.materials.model', string='材料型号') materials_type_id = fields.Many2one('sf.materials.model', string='材料型号',
domain="[('materials_id', '=', materials_id)]")
server_product_process_parameters_id = fields.Many2one('sf.production.process.parameter', server_product_process_parameters_id = fields.Many2one('sf.production.process.parameter',
string='表面工艺参数(服务产品)') string='表面工艺参数(服务产品)')
model_process_parameters_ids = fields.Many2many('sf.production.process.parameter', 'process_parameter_rel', model_process_parameters_ids = fields.Many2many('sf.production.process.parameter', 'process_parameter_rel',
@@ -68,7 +71,8 @@ class ResProductMo(models.Model):
cutting_tool_shank_length = fields.Float('柄部长度(mm)', digits=(6, 1)) cutting_tool_shank_length = fields.Float('柄部长度(mm)', digits=(6, 1))
cutting_tool_blade_length = fields.Float('刃部长度(mm)') cutting_tool_blade_length = fields.Float('刃部长度(mm)')
cutting_tool_blade_number = fields.Selection( cutting_tool_blade_number = fields.Selection(
[('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'), ('8', '8')], '刃数(个)') [('0', '0'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'), ('8', '8')],
string='刃数(个)', default='0')
# 整体式刀具新增字段 # 整体式刀具新增字段
cutting_tool_neck_length = fields.Float('颈部长度(mm)', digits=(6, 1)) cutting_tool_neck_length = fields.Float('颈部长度(mm)', digits=(6, 1))
cutting_tool_neck_diameter = fields.Float('颈部直径(mm)', digits=(6, 1)) cutting_tool_neck_diameter = fields.Float('颈部直径(mm)', digits=(6, 1))
@@ -101,6 +105,10 @@ class ResProductMo(models.Model):
compaction_way_id = fields.Many2one('maintenance.equipment.image', compaction_way_id = fields.Many2one('maintenance.equipment.image',
'压紧方式', domain=[('type', '=', '压紧方式')]) '压紧方式', domain=[('type', '=', '压紧方式')])
@api.onchange('cutting_tool_model_id')
def _onchange_cutting_tool_model_id(self):
self.specification_id = False
@api.onchange('cutting_tool_material_id') @api.onchange('cutting_tool_material_id')
def _onchange_cutting_tool_material_id(self): def _onchange_cutting_tool_material_id(self):
for item in self: for item in self:
@@ -190,20 +198,24 @@ class ResProductMo(models.Model):
self.cutting_tool_blade_number = self.specification_id.blade_number self.cutting_tool_blade_number = self.specification_id.blade_number
self.cutting_tool_blade_type = self.cutting_tool_model_id.blade_type self.cutting_tool_blade_type = self.cutting_tool_model_id.blade_type
self.cutting_tool_shank_diameter = self.specification_id.handle_diameter self.cutting_tool_shank_diameter = self.specification_id.handle_diameter
self.cutting_tool_shank_length = self.specification_id.handle_length
self.cutting_tool_neck_length = self.specification_id.neck_length
self.cutting_tool_neck_diameter = self.specification_id.neck_diameter
self.cutting_tool_blade_tip_diameter = self.specification_id.blade_tip_diameter self.cutting_tool_blade_tip_diameter = self.specification_id.blade_tip_diameter
self.cutting_tool_blade_tip_taper = self.specification_id.blade_tip_taper self.cutting_tool_blade_tip_taper = self.specification_id.blade_tip_taper
self.cutting_tool_blade_helix_angle = self.specification_id.blade_helix_angle self.cutting_tool_blade_helix_angle = self.specification_id.blade_helix_angle
self.cutting_tool_blade_tip_working_size = self.specification_id.blade_tip_working_size
self.cutting_tool_pitch = self.specification_id.pitch self.cutting_tool_pitch = self.specification_id.pitch
self.cutting_tool_blade_width = self.specification_id.blade_width self.cutting_tool_blade_width = self.specification_id.blade_width
self.cutting_tool_blade_depth = self.specification_id.blade_depth self.cutting_tool_blade_depth = self.specification_id.blade_depth
self.cutting_tool_cut_depth = self.specification_id.cutting_depth self.cutting_tool_cut_depth_max = self.specification_id.cut_depth_max
self.cutting_speed_ids = self.cutting_tool_model_id.cutting_speed_ids self.cutting_speed_ids = self.cutting_tool_model_id.cutting_speed_ids
self.feed_per_tooth_ids = self.cutting_tool_model_id.feed_per_tooth_ids.filtered( self.feed_per_tooth_ids = self.cutting_tool_model_id.feed_per_tooth_ids.filtered(
lambda r: int(r.blade_diameter) == int(self.specification_id.blade_diameter)) lambda r: int(r.blade_diameter) == int(self.specification_id.blade_diameter))
elif self.cutting_tool_type == '夹头': elif self.cutting_tool_type == '夹头':
self.cutting_tool_clamping_diameter_min = self.specification_id.min_clamping_diameter self.cutting_tool_clamping_diameter_min = self.specification_id.min_clamping_diameter
self.cutting_tool_clamping_diameter_min = self.specification_id.max_clamping_diameter self.cutting_tool_clamping_diameter_max = self.specification_id.max_clamping_diameter
self.cutting_tool_clamping_way = self.specification_id.clamping_mode self.cutting_tool_taper = self.specification_id.taper
self.cutting_tool_top_diameter = self.specification_id.top_diameter self.cutting_tool_top_diameter = self.specification_id.top_diameter
self.cutting_tool_outer_diameter = self.specification_id.outer_diameter self.cutting_tool_outer_diameter = self.specification_id.outer_diameter
self.cutting_tool_inner_diameter = self.specification_id.inner_diameter self.cutting_tool_inner_diameter = self.specification_id.inner_diameter
@@ -241,6 +253,7 @@ class ResProductMo(models.Model):
self.cutting_speed_ids = self.cutting_tool_model_id.cutting_speed_ids self.cutting_speed_ids = self.cutting_tool_model_id.cutting_speed_ids
self.feed_per_tooth_ids = self.cutting_tool_model_id.feed_per_tooth_ids self.feed_per_tooth_ids = self.cutting_tool_model_id.feed_per_tooth_ids
elif self.cutting_tool_type in ('刀盘', '刀杆'): elif self.cutting_tool_type in ('刀盘', '刀杆'):
self.cutting_tool_blade_diameter = self.specification_id.blade_diameter
self.cutting_tool_total_length = self.specification_id.total_length self.cutting_tool_total_length = self.specification_id.total_length
self.tool_length = self.specification_id.length self.tool_length = self.specification_id.length
self.tool_thickness = self.specification_id.thickness self.tool_thickness = self.specification_id.thickness
@@ -271,14 +284,19 @@ class ResProductMo(models.Model):
self.cutting_tool_cutter_head_diameter = self.specification_id.cutter_head_diameter self.cutting_tool_cutter_head_diameter = self.specification_id.cutter_head_diameter
self.cutting_tool_interface_diameter = self.specification_id.interface_diameter self.cutting_tool_interface_diameter = self.specification_id.interface_diameter
else: else:
self.cutting_tool_cutter_arbor_diameter = self.specification_id.cutter_arbor_diameter
self.cutting_tool_knife_head_height = self.specification_id.knife_head_height self.cutting_tool_knife_head_height = self.specification_id.knife_head_height
self.cutting_tool_knife_head_width = self.specification_id.knife_head_width self.cutting_tool_knife_head_width = self.specification_id.knife_head_width
self.cutting_tool_knife_head_length = self.specification_id.knife_head_length self.cutting_tool_knife_head_length = self.specification_id.knife_head_length
self.cutting_tool_tool_shim = self.specification_id.tool_shim self.cutting_tool_tool_shim = self.specification_id.tool_shim
self.cutting_tool_cotter_pin = self.specification_id.cotter_pin self.cutting_tool_cotter_pin = self.specification_id.cotter_pin
self.cutting_tool_pressing_plate = self.specification_id.pressing_plate self.cutting_tool_pressing_plate = self.specification_id.pressing_plate
self.cutting_tool_min_machining_aperture = self.specification_id.min_machining_aperture
self.cutting_tool_rear_angle = self.specification_id.relief_angle
elif self.cutting_tool_type == '刀柄': elif self.cutting_tool_type == '刀柄':
self.cutting_tool_total_length = self.specification_id.total_length self.cutting_tool_total_length = self.specification_id.total_length
self.cutting_tool_shank_diameter = self.specification_id.shank_diameter
self.cutting_tool_shank_length = self.specification_id.shank_length
self.cutting_tool_speed_max = self.specification_id.max_rotate_speed self.cutting_tool_speed_max = self.specification_id.max_rotate_speed
self.cutting_tool_change_time = self.specification_id.tool_changing_time self.cutting_tool_change_time = self.specification_id.tool_changing_time
self.cutting_tool_total_length = self.specification_id.total_length self.cutting_tool_total_length = self.specification_id.total_length
@@ -295,6 +313,8 @@ class ResProductMo(models.Model):
self.cutting_tool_chuck_id = self.specification_id.chuck_id.id self.cutting_tool_chuck_id = self.specification_id.chuck_id.id
self.cutting_tool_jump_accuracy = self.specification_id.diameter_slip_accuracy self.cutting_tool_jump_accuracy = self.specification_id.diameter_slip_accuracy
self.cutting_tool_taper_shank_model = self.specification_id.taper_shank_model self.cutting_tool_taper_shank_model = self.specification_id.taper_shank_model
self.cutting_tool_cooling_type = self.specification_id.cooling_model
self.cutting_tool_clamping_way = self.specification_id.clamping_mode
self.suitable_machining_method_ids = [(6, 0, [])] if not \ self.suitable_machining_method_ids = [(6, 0, [])] if not \
self.cutting_tool_model_id.suitable_machining_method_ids \ self.cutting_tool_model_id.suitable_machining_method_ids \
else [(6, 0, self.cutting_tool_model_id.suitable_machining_method_ids.ids)] else [(6, 0, self.cutting_tool_model_id.suitable_machining_method_ids.ids)]
@@ -311,6 +331,7 @@ class ResProductMo(models.Model):
(6, 0, self.cutting_tool_model_id.suitable_coolant_ids.ids)] (6, 0, self.cutting_tool_model_id.suitable_coolant_ids.ids)]
self.compaction_way_id = self.cutting_tool_model_id.compaction_way_id.id self.compaction_way_id = self.cutting_tool_model_id.compaction_way_id.id
self.fit_blade_shape_id = self.cutting_tool_model_id.fit_blade_shape_id.id self.fit_blade_shape_id = self.cutting_tool_model_id.fit_blade_shape_id.id
self.image_1920 = self.cutting_tool_model_id.image
else: else:
self.cutting_tool_type_id = False self.cutting_tool_type_id = False
self.brand_id = False self.brand_id = False
@@ -350,30 +371,30 @@ class ResProductMo(models.Model):
self.cutting_speed_ids = False self.cutting_speed_ids = False
self.feed_per_tooth_ids = False self.feed_per_tooth_ids = False
@api.constrains('fit_blade_shape_id', 'suitable_machining_method_ids', 'blade_tip_characteristics_id', # @api.constrains('fit_blade_shape_id', 'suitable_machining_method_ids', 'blade_tip_characteristics_id',
'handle_type_id', 'cutting_direction_ids', 'suitable_coolant_ids', 'compaction_way_id') # 'handle_type_id', 'cutting_direction_ids', 'suitable_coolant_ids', 'compaction_way_id')
def _check_cutting_tool_ability(self): # def _check_cutting_tool_ability(self):
if self.cutting_tool_type in ['整体式刀具', '刀片', '刀杆', '刀盘']: # if self.cutting_tool_type in ['整体式刀具', '刀片', '刀杆', '刀盘']:
if self.cutting_tool_type in ['刀片', '刀杆', '刀盘']: # if self.cutting_tool_type in ['刀片', '刀杆', '刀盘']:
if not self.fit_blade_shape_id: # if not self.fit_blade_shape_id:
raise ValidationError("请选择适配刀片形状") # raise ValidationError("请选择适配刀片形状")
if self.cutting_tool_type in ['刀杆', '刀盘']: # if self.cutting_tool_type in ['刀杆', '刀盘']:
if not self.compaction_way_id: # if not self.compaction_way_id:
raise ValidationError("请选择压紧方式") # raise ValidationError("请选择压紧方式")
if self.cutting_tool_type == '刀片': # if self.cutting_tool_type == '刀片':
if not self.suitable_coolant_ids: # if not self.suitable_coolant_ids:
raise ValidationError("请选择适合冷却方式") # raise ValidationError("请选择适合冷却方式")
elif self.cutting_tool_type == '整体式刀具': # elif self.cutting_tool_type == '整体式刀具':
if not self.handle_type_id: # if not self.handle_type_id:
raise ValidationError("请选择柄部类型") # raise ValidationError("请选择柄部类型")
if not self.suitable_coolant_ids: # if not self.suitable_coolant_ids:
raise ValidationError("请选择适合冷却方式") # raise ValidationError("请选择适合冷却方式")
if not self.suitable_machining_method_ids: # if not self.suitable_machining_method_ids:
raise ValidationError("请选择适合加工方式") # raise ValidationError("请选择适合加工方式")
if not self.blade_tip_characteristics_id: # if not self.blade_tip_characteristics_id:
raise ValidationError("请选择刀尖特征") # raise ValidationError("请选择刀尖特征")
if not self.cutting_direction_ids: # if not self.cutting_direction_ids:
raise ValidationError("请选择走刀方向") # raise ValidationError("请选择走刀方向")
cutting_speed_ids = fields.One2many('sf.cutting.speed', 'product_template_id', string='切削速度Vc') cutting_speed_ids = fields.One2many('sf.cutting.speed', 'product_template_id', string='切削速度Vc')
feed_per_tooth_ids = fields.One2many('sf.feed.per.tooth', 'product_template_id', string='每齿走刀量fz') feed_per_tooth_ids = fields.One2many('sf.feed.per.tooth', 'product_template_id', string='每齿走刀量fz')
@@ -658,11 +679,14 @@ class ResProductMo(models.Model):
# 外协和采购生成的坯料需要根据材料型号绑定供应商 # 外协和采购生成的坯料需要根据材料型号绑定供应商
if route_type == 'subcontract' or route_type == 'purchase': if route_type == 'subcontract' or route_type == 'purchase':
no_bom_copy_product_id.purchase_ok = True no_bom_copy_product_id.purchase_ok = True
no_bom_copy_product_id.seller_ids = [ if supplier:
(0, 0, {'partner_id': supplier.partner_id.id, 'delay': 1.0})] no_bom_copy_product_id.seller_ids = [
if route_type == 'subcontract': (0, 0, {'partner_id': supplier.partner_id.id, 'delay': 1.0})]
partner = self.env['res.partner'].search([('id', '=', supplier.partner_id.id)]) if route_type == 'subcontract':
partner.is_subcontractor = True partner = self.env['res.partner'].search([('id', '=', supplier.partner_id.id)])
partner.is_subcontractor = True
else:
return -3
no_bom_copy_product_id.write(vals) no_bom_copy_product_id.write(vals)
return no_bom_copy_product_id return no_bom_copy_product_id

View File

@@ -219,7 +219,8 @@ class StockRule(models.Model):
class ProductionLot(models.Model): class ProductionLot(models.Model):
_inherit = 'stock.lot' _name = 'stock.lot'
_inherit = ['stock.lot', 'printing.utils']
@api.model @api.model
def generate_lot_names1(self, display_name, first_lot, count): def generate_lot_names1(self, display_name, first_lot, count):
@@ -263,7 +264,7 @@ class ProductionLot(models.Model):
if not last_serial: if not last_serial:
return "%s-%s%03d" % (product.cutting_tool_model_id.code[:-12], now, 1) return "%s-%s%03d" % (product.cutting_tool_model_id.code[:-12], now, 1)
else: else:
return "%s-%s%03d" % (product.cutting_tool_model_id.code[:-12], now, int(last_serial.name[-3:]) + 1) return "%s-%s%03d" % (product.cutting_tool_model_id.code[:-12], now, int(last_serial.name[-3:]) + 2)
else: else:
raise ValidationError('该刀具物料产品的型号字段为空,请补充完整!!!') raise ValidationError('该刀具物料产品的型号字段为空,请补充完整!!!')
@@ -307,36 +308,53 @@ class ProductionLot(models.Model):
record.qr_code_image = encoded_image record.qr_code_image = encoded_image
def print_qr_code(self): def print_single_method(self):
self.ensure_one() # 确保这个方法只为一个记录调用
# if not self.lot_id: self.ensure_one()
# raise UserError("没有找到序列号。")
# 假设_lot_qr_code方法已经生成了二维码并保存在字段中
qr_code_data = self.qr_code_image qr_code_data = self.qr_code_image
if not qr_code_data: if not qr_code_data:
raise UserError("没有找到二维码数据。") raise UserError("没有找到二维码数据。")
lot_name = self.name
# host = "192.168.50.110" # 可以根据实际情况修改
# port = 9100 # 可以根据实际情况修改
# 生成下载链接或直接触发下载 # 获取默认打印机配置
# 此处的实现依赖于你的具体需求,以下是触发下载的一种示例 printer_config = self.env['printer.configuration'].search([('model', '=', self._name)], limit=1)
attachment = self.env['ir.attachment'].sudo().create({ if not printer_config:
'datas': self.qr_code_image, raise UserError('请先配置打印机')
'type': 'binary', host = printer_config.printer_id.ip_address
'description': '二维码图片', port = printer_config.printer_id.port
'name': self.name + '.png', self.print_qr_code(lot_name, host, port)
# 'res_id': invoice.id,
# 'res_model': 'stock.picking', # self.ensure_one() # 确保这个方法只为一个记录调用
'public': True, # # if not self.lot_id:
'mimetype': 'application/x-png', # # raise UserError("没有找到序列号。")
# 'model_name': 'stock.picking', # # 假设_lot_qr_code方法已经生成了二维码并保存在字段中
}) # qr_code_data = self.qr_code_image
# 返回附件的下载链接 # if not qr_code_data:
download_url = '/web/content/%s?download=true' % attachment.id # raise UserError("没有找到二维码数据。")
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') #
return { # # 生成下载链接或直接触发下载
'type': 'ir.actions.act_url', # # 此处的实现依赖于你的具体需求,以下是触发下载的一种示例
'url': str(base_url) + download_url, # attachment = self.env['ir.attachment'].sudo().create({
'target': 'self', # 'datas': self.qr_code_image,
} # 'type': 'binary',
# 'description': '二维码图片',
# 'name': self.name + '.png',
# # 'res_id': invoice.id,
# # 'res_model': 'stock.picking',
# 'public': True,
# 'mimetype': 'application/x-png',
# # 'model_name': 'stock.picking',
# })
# # 返回附件的下载链接
# download_url = '/web/content/%s?download=true' % attachment.id
# base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
# return {
# 'type': 'ir.actions.act_url',
# 'url': str(base_url) + download_url,
# 'target': 'self',
# }
class StockPicking(models.Model): class StockPicking(models.Model):

View File

@@ -22,6 +22,8 @@ access_maintenance_equipment_tool_manager,maintenance_equipment_tool,model_maint
access_maintenance_equipment_tool_equipment_manager,maintenance_equipment_tool,model_maintenance_equipment_tool,sf_maintenance.sf_group_equipment_user,1,1,1,0 access_maintenance_equipment_tool_equipment_manager,maintenance_equipment_tool,model_maintenance_equipment_tool,sf_maintenance.sf_group_equipment_user,1,1,1,0
access_mrp_production_group_sf_mrp_user,mrp_production,model_mrp_production,sf_base.group_sf_mrp_user,1,0,0,0 access_mrp_production_group_sf_mrp_user,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_production_manager,mrp_production,model_mrp_production,sf_base.group_sf_mrp_manager,1,1,1,0
access_mrp_production_group_quality,mrp_production_group_quality,model_mrp_production,sf_base.group_quality,1,0,0,0
access_mrp_production_group_quality_director,mrp_production_group_quality_director,model_mrp_production,sf_base.group_quality_director,1,0,0,0
access_mrp_workorder_group_sf_mrp_user,mrp_workorder,model_mrp_workorder,sf_base.group_sf_mrp_user,1,0,0,0 access_mrp_workorder_group_sf_mrp_user,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_workorder_manager,mrp_workorder,model_mrp_workorder,sf_base.group_sf_mrp_manager,1,1,1,0
access_mrp_workcenter_group_sf_mrp_user,mrp_workcenter,model_mrp_workcenter,sf_base.group_sf_mrp_user,1,0,0,0 access_mrp_workcenter_group_sf_mrp_user,mrp_workcenter,model_mrp_workcenter,sf_base.group_sf_mrp_user,1,0,0,0
@@ -108,9 +110,9 @@ access_sf_production_line_group_plan_dispatch,sf.production.line,model_sf_produc
access_sf_production_line_group_plan_director,sf.production.line,model_sf_production_line,sf_base.group_plan_director,1,1,1,0 access_sf_production_line_group_plan_director,sf.production.line,model_sf_production_line,sf_base.group_plan_director,1,1,1,0
access_sf_production_line,sf.production.line,model_sf_production_line,sf_maintenance.sf_group_equipment_user,1,1,1,0 access_sf_production_line,sf.production.line,model_sf_production_line,sf_maintenance.sf_group_equipment_user,1,1,1,0
access_mrp_workcenter,mrp_workcenter,model_mrp_workcenter,sf_base.group_plan_dispatch,1,1,1,0 access_mrp_workcenter,mrp_workcenter,model_mrp_workcenter,sf_base.group_plan_dispatch,1,1,1,0
access_mrp_bom,mrp.bom,mrp.model_mrp_bom,sf_base.group_plan_dispatch,1,1,1,0 access_mrp_bom_group_plan_dispatch,mrp.bom,mrp.model_mrp_bom,sf_base.group_plan_dispatch,1,0,0,0
access_mrp_bom_line,mrp.bom.line,mrp.model_mrp_bom_line,sf_base.group_plan_dispatch,1,0,0,0 access_mrp_bom_line,mrp.bom.line,mrp.model_mrp_bom_line,sf_base.group_plan_dispatch,1,0,0,0
access_mrp_unbuild,mrp.unbuild,mrp.model_mrp_unbuild,sf_base.group_plan_dispatch,1,1,1,0 access_mrp_unbuild_group_plan_dispatch,mrp.unbuild,mrp.model_mrp_unbuild,sf_base.group_plan_dispatch,1,0,0,0
access_stock_scrap_group_plan_dispatch,stock.scrap,stock.model_stock_scrap,sf_base.group_plan_dispatch,1,0,0,0 access_stock_scrap_group_plan_dispatch,stock.scrap,stock.model_stock_scrap,sf_base.group_plan_dispatch,1,0,0,0
access_sf_model_type,sf.model.type,model_sf_model_type,sf_base.group_plan_dispatch,1,1,1,0 access_sf_model_type,sf.model.type,model_sf_model_type,sf_base.group_plan_dispatch,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
22 access_maintenance_equipment_tool_equipment_manager maintenance_equipment_tool model_maintenance_equipment_tool sf_maintenance.sf_group_equipment_user 1 1 1 0
23 access_mrp_production_group_sf_mrp_user mrp_production model_mrp_production sf_base.group_sf_mrp_user 1 0 0 0
24 access_mrp_production_manager mrp_production model_mrp_production sf_base.group_sf_mrp_manager 1 1 1 0
25 access_mrp_production_group_quality mrp_production_group_quality model_mrp_production sf_base.group_quality 1 0 0 0
26 access_mrp_production_group_quality_director mrp_production_group_quality_director model_mrp_production sf_base.group_quality_director 1 0 0 0
27 access_mrp_workorder_group_sf_mrp_user mrp_workorder model_mrp_workorder sf_base.group_sf_mrp_user 1 0 0 0
28 access_mrp_workorder_manager mrp_workorder model_mrp_workorder sf_base.group_sf_mrp_manager 1 1 1 0
29 access_mrp_workcenter_group_sf_mrp_user mrp_workcenter model_mrp_workcenter sf_base.group_sf_mrp_user 1 0 0 0
110 access_mrp_bom_line mrp.bom.line mrp.model_mrp_bom_line sf_base.group_plan_dispatch 1 0 0 0
111 access_mrp_unbuild access_mrp_unbuild_group_plan_dispatch mrp.unbuild mrp.model_mrp_unbuild sf_base.group_plan_dispatch 1 1 0 1 0 0
112 access_stock_scrap_group_plan_dispatch stock.scrap stock.model_stock_scrap sf_base.group_plan_dispatch 1 0 0 0
113 access_sf_model_type sf.model.type model_sf_model_type sf_base.group_plan_dispatch 1 1 1 0
114 access_mrp_routing_workcenter mrp.routing.workcenter mrp.model_mrp_routing_workcenter sf_base.group_plan_dispatch 1 1 1 0
115 access_mrp_document mrp.document mrp.model_mrp_document sf_base.group_plan_dispatch 1 0 0 0
116 access_sf_product_model_type_routing_sort sf.product.model.type.routing.sort model_sf_product_model_type_routing_sort sf_base.group_plan_dispatch 1 0 0 0
117 access_sf_embryo_model_type_routing_sort sf.embryo.model.type.routing.sort model_sf_embryo_model_type_routing_sort sf_base.group_plan_dispatch 1 0 0 0
118 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_plan_dispatch 1 0 0 0

View File

@@ -68,6 +68,7 @@
<xpath expr="//field[@name='user_id']" position="after"> <xpath expr="//field[@name='user_id']" position="after">
<field name="programming_no" readonly="1"/> <field name="programming_no" readonly="1"/>
<field name="work_state" invisible="1"/> <field name="work_state" invisible="1"/>
<field name="schedule_state" invisible='1'/>
<field name="programming_state" readonly="1"/> <field name="programming_state" readonly="1"/>
<field name="production_line_id" readonly="1"/> <field name="production_line_id" readonly="1"/>
<field name="plan_start_processing_time" readonly="1"/> <field name="plan_start_processing_time" readonly="1"/>
@@ -235,6 +236,10 @@
attrs="{'invisible': [('state', '!=', 'done')]}" data-hotkey="shift+v" attrs="{'invisible': [('state', '!=', 'done')]}" data-hotkey="shift+v"
groups="sf_base.group_sf_mrp_user"/> groups="sf_base.group_sf_mrp_user"/>
</xpath> </xpath>
<xpath expr="//sheet//notebook//page[@name='operations']" position="attributes">
<attribute name="attrs">{'invisible': [('schedule_state', '=', '未排')]}</attribute>
</xpath>
</field> </field>
</record> </record>
@@ -245,30 +250,31 @@
<field name="inherit_id" ref="mrp.mrp_production_workorder_tree_editable_view"/> <field name="inherit_id" ref="mrp.mrp_production_workorder_tree_editable_view"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//tree//button[@name='button_start']" position="replace"> <xpath expr="//tree//button[@name='button_start']" position="replace">
<field name="routing_type" invisible="True"/>
<button name="button_start" type="object" string="开始" class="btn-success" <button name="button_start" type="object" string="开始" class="btn-success"
attrs="{'invisible': ['|', '|', '|', ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')), ('is_user_working', '!=', False)]}" attrs="{'invisible': ['|', '|', '|','|', ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')), ('is_user_working', '!=', False), ('routing_type', '=', 'CNC加工')]}"
groups="sf_base.group_sf_mrp_user"/> groups="sf_base.group_sf_mrp_user"/>
</xpath> </xpath>
<xpath expr="//tree//button[@name='button_pending']" position="replace"> <xpath expr="//tree//button[@name='button_pending']" position="replace">
<button name="button_pending" type="object" string="Pause" class="btn-warning" <button name="button_pending" type="object" string="Pause" class="btn-warning"
attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False)]}" attrs="{'invisible': ['|', '|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False), ('routing_type', '=', 'CNC加工')]}"
groups="sf_base.group_sf_mrp_user"/> groups="sf_base.group_sf_mrp_user"/>
</xpath> </xpath>
<xpath expr="//tree//button[@name='button_finish']" position="replace"> <xpath expr="//tree//button[@name='button_finish']" position="replace">
<button name="button_finish" type="object" string="Done" class="btn-success" <button name="button_finish" type="object" string="Done" class="btn-success"
attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False)]}" attrs="{'invisible': ['|', '|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False), ('routing_type', '=', 'CNC加工')]}"
groups="sf_base.group_sf_mrp_user"/> groups="sf_base.group_sf_mrp_user"/>
</xpath> </xpath>
<xpath expr="//tree//button[@name='%(mrp.act_mrp_block_workcenter_wo)d']" position="replace"> <xpath expr="//tree//button[@name='%(mrp.act_mrp_block_workcenter_wo)d']" position="replace">
<button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="Block" <button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="Block"
context="{'default_workcenter_id': workcenter_id}" class="btn-danger" context="{'default_workcenter_id': workcenter_id}" class="btn-danger"
attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked')]}" attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('routing_type', '=', 'CNC加工')]}"
groups="sf_base.group_sf_mrp_user"/> groups="sf_base.group_sf_mrp_user"/>
</xpath> </xpath>
<xpath expr="//tree//button[@name='button_unblock']" position="replace"> <xpath expr="//tree//button[@name='button_unblock']" position="replace">
<button name="button_unblock" type="object" string="Unblock" <button name="button_unblock" type="object" string="Unblock"
context="{'default_workcenter_id': workcenter_id}" class="btn-danger" context="{'default_workcenter_id': workcenter_id}" class="btn-danger"
attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked')]}" attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked'), ('routing_type', '=', 'CNC加工')]}"
groups="sf_base.group_sf_mrp_user"/> groups="sf_base.group_sf_mrp_user"/>
</xpath> </xpath>
<xpath expr="//tree//button[@name='action_open_wizard']" position="replace"> <xpath expr="//tree//button[@name='action_open_wizard']" position="replace">
@@ -282,24 +288,24 @@
</xpath> </xpath>
<xpath expr="//tree//button[@name='button_pending']" position="replace"> <xpath expr="//tree//button[@name='button_pending']" position="replace">
<button name="button_pending" type="object" string="暂停" class="btn-warning" <button name="button_pending" type="object" string="暂停" class="btn-warning"
attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False)]}" attrs="{'invisible': ['|', '|','|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False), ('routing_type', '=', 'CNC加工')]}"
groups="sf_base.group_sf_mrp_user"/> groups="sf_base.group_sf_mrp_user"/>
</xpath> </xpath>
<xpath expr="//tree//button[@name='button_finish']" position="replace"> <xpath expr="//tree//button[@name='button_finish']" position="replace">
<button name="button_finish" type="object" string="完成" class="btn-success" <button name="button_finish" type="object" string="完成" class="btn-success"
attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False)]}" attrs="{'invisible': ['|', '|','|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False), ('routing_type', '=', 'CNC加工')]}"
groups="sf_base.group_sf_mrp_user"/> groups="sf_base.group_sf_mrp_user"/>
</xpath> </xpath>
<xpath expr="//tree//button[@name='%(mrp.act_mrp_block_workcenter_wo)d']" position="replace"> <xpath expr="//tree//button[@name='%(mrp.act_mrp_block_workcenter_wo)d']" position="replace">
<button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="阻塞" <button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="阻塞"
context="{'default_workcenter_id': workcenter_id}" class="btn-danger" context="{'default_workcenter_id': workcenter_id}" class="btn-danger"
attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked')]}" attrs="{'invisible': ['|','|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('routing_type', '=', 'CNC加工')]}"
groups="sf_base.group_sf_mrp_user"/> groups="sf_base.group_sf_mrp_user"/>
</xpath> </xpath>
<xpath expr="//tree//button[@name='button_unblock']" position="replace"> <xpath expr="//tree//button[@name='button_unblock']" position="replace">
<button name="button_unblock" type="object" string="取消阻塞" <button name="button_unblock" type="object" string="取消阻塞"
context="{'default_workcenter_id': workcenter_id}" class="btn-danger" context="{'default_workcenter_id': workcenter_id}" class="btn-danger"
attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked')]}" attrs="{'invisible': ['|','|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked'), ('routing_type', '=', 'CNC加工')]}"
groups="sf_base.group_sf_mrp_user"/> groups="sf_base.group_sf_mrp_user"/>
</xpath> </xpath>
<xpath expr="//tree//button[@name='action_open_wizard']" position="replace"> <xpath expr="//tree//button[@name='action_open_wizard']" position="replace">

View File

@@ -104,21 +104,22 @@
<field name='user_permissions' invisible="1"/> <field name='user_permissions' invisible="1"/>
<field name='name' invisible="1"/> <field name='name' invisible="1"/>
<field name='is_delivery' invisible="1"/> <field name='is_delivery' invisible="1"/>
<!-- 工单form页面的开始停工按钮等 -->
<button name="button_start" type="object" string="开始" class="btn-success" <button name="button_start" type="object" string="开始" class="btn-success"
attrs="{'invisible': ['|', '|', '|','|',('production_state','in', ('draft', 'done', attrs="{'invisible': ['|', '|', '|', '|','|', ('production_state','in', ('draft', 'done',
'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')), 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')),
('is_user_working', '!=', False),('user_permissions','=',False)]}" ('is_user_working', '!=', False),('user_permissions','=',False), ('routing_type', '=', 'CNC加工')]}"
groups="sf_base.group_sf_mrp_user"/> groups="sf_base.group_sf_mrp_user"/>
<button name="button_pending" type="object" string="暂停" class="btn-warning" <button name="button_pending" type="object" string="暂停" class="btn-warning"
groups="sf_base.group_sf_mrp_user" groups="sf_base.group_sf_mrp_user"
attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False)]}"/> attrs="{'invisible': ['|', '|','|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False), ('routing_type', '=', 'CNC加工')]}"/>
<button name="button_finish" type="object" string="完成" class="btn-success" <button name="button_finish" type="object" string="完成" class="btn-success"
groups="sf_base.group_sf_mrp_user" groups="sf_base.group_sf_mrp_user"
attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False)]}"/> attrs="{'invisible': ['|', '|','|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False), ('routing_type', '=', 'CNC加工')]}"/>
<button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="停工" <button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="停工"
context="{'default_workcenter_id': workcenter_id}" class="btn-danger" context="{'default_workcenter_id': workcenter_id}" class="btn-danger"
groups="sf_base.group_sf_mrp_user" groups="sf_base.group_sf_mrp_user"
attrs="{'invisible': ['|', '|','|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'),('user_permissions','=',False),('state','=','done')]}"/> attrs="{'invisible': ['|', '|','|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'),('user_permissions','=',False),('state','=','done'), ('routing_type', '=', 'CNC加工')]}"/>
<button name="button_unblock" type="object" string="Unblock" <button name="button_unblock" type="object" string="Unblock"
context="{'default_workcenter_id': workcenter_id}" class="btn-danger" context="{'default_workcenter_id': workcenter_id}" class="btn-danger"
groups="sf_base.group_sf_mrp_user" groups="sf_base.group_sf_mrp_user"
@@ -541,7 +542,7 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="工件配送"> <tree string="工件配送">
<header> <header>
<button name="button_delivery" type="object" string="配送"/> <button name="button_delivery" type="object" string="配送" class="oe_highlight"/>
</header> </header>
<field name="status" widget="badge" <field name="status" widget="badge"
decoration-success="status == '已配送'" decoration-success="status == '已配送'"

View File

@@ -10,7 +10,7 @@
</xpath> </xpath>
<xpath expr="//sheet" position="before"> <xpath expr="//sheet" position="before">
<header> <header>
<button string="打印二维码" name="print_qr_code" type="object" class="btn-primary"/> <button string="打印二维码" name="print_single_method" type="object" class="btn-primary"/>
</header> </header>
</xpath> </xpath>
</field> </field>

View File

@@ -6,6 +6,8 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form>
<field name="delivery_id" invisible="True"/> <field name="delivery_id" invisible="True"/>
<field name="workorder_id" invisible="True"/>
<div> <div>
是否确定配送? 是否确定配送?
</div> </div>

View File

@@ -10,7 +10,11 @@ class WorkpieceDeliveryWizard(models.TransientModel):
_description = '工件配送' _description = '工件配送'
delivery_id = fields.Many2one('sf.workpiece.delivery', string='配送') delivery_id = fields.Many2one('sf.workpiece.delivery', string='配送')
workorder_id = fields.Many2one('mrp.workorder', string='工单')
def confirm(self): def confirm(self):
self.delivery_id._delivery_avg() if self.workorder_id:
self.workorder_id.workpiece_delivery_ids._delivery_avg()
else:
self.delivery_id._delivery_avg()

View File

@@ -13,7 +13,9 @@ class ResConfigSettings(models.TransientModel):
token = fields.Char(string='TOKEN', default='b811ac06-3f00-11ed-9aed-0242ac110003') token = fields.Char(string='TOKEN', default='b811ac06-3f00-11ed-9aed-0242ac110003')
sf_secret_key = fields.Char(string='密钥', default='wBmxej38OkErKhD6') sf_secret_key = fields.Char(string='密钥', default='wBmxej38OkErKhD6')
sf_url = fields.Char(string='访问地址', default='https://sf.cs.jikimo.com') sf_url = fields.Char(string='访问地址', default='https://sf.cs.jikimo.com')
agv_url = fields.Char(string='avg访问地址', default='http://IP:PORT/rcms/services/rest') agv_rcms_url = fields.Char(string='avg_rcms访问地址',
default='http://IP:PORT/rcms/services/rest/hikRpcService/genAgvSchedulingTask')
agv_rcs_url = fields.Char(string='avg_rcs访问地址', default='http://IP:PORT/xxx/agv/agvCallbackService/agvCallback')
model_parser_url = fields.Char('特征识别路径') model_parser_url = fields.Char('特征识别路径')
ftp_host = fields.Char(string='FTP的ip') ftp_host = fields.Char(string='FTP的ip')
ftp_port = fields.Char(string='FTP端口') ftp_port = fields.Char(string='FTP端口')
@@ -58,6 +60,8 @@ class ResConfigSettings(models.TransientModel):
_logger.info("同步联装类型完成") _logger.info("同步联装类型完成")
self.env['sf.fixture.model'].sync_all_fixture_model() self.env['sf.fixture.model'].sync_all_fixture_model()
_logger.info("同步夹具型号完成") _logger.info("同步夹具型号完成")
self.env['sf.fixture.materials.basic.parameters'].sync_all_fixture_materials_basic_parameters()
_logger.info("同步夹具型号基本信息完成")
self.env['sf.functional.fixture.type'].sync_all_functional_fixture_type() self.env['sf.functional.fixture.type'].sync_all_functional_fixture_type()
_logger.info("同步夹具型号类型完成") _logger.info("同步夹具型号类型完成")
self.env['sf.machine_tool.type'].sync_all_machine_tool_type() self.env['sf.machine_tool.type'].sync_all_machine_tool_type()
@@ -90,6 +94,8 @@ class ResConfigSettings(models.TransientModel):
token = config.get_param('token', default='') token = config.get_param('token', default='')
sf_secret_key = config.get_param('sf_secret_key', default='') sf_secret_key = config.get_param('sf_secret_key', default='')
sf_url = config.get_param('sf_url', default='') sf_url = config.get_param('sf_url', default='')
agv_rcms_url = config.get_param('agv_rcms_url', default='')
agv_rcs_url = config.get_param('agv_rcs_url', default='')
ftp_host = config.get_param('ftp_host', default='') ftp_host = config.get_param('ftp_host', default='')
ftp_port = config.get_param('ftp_port', default='') ftp_port = config.get_param('ftp_port', default='')
ftp_user = config.get_param('ftp_user', default='') ftp_user = config.get_param('ftp_user', default='')
@@ -99,6 +105,8 @@ class ResConfigSettings(models.TransientModel):
token=token, token=token,
sf_secret_key=sf_secret_key, sf_secret_key=sf_secret_key,
sf_url=sf_url, sf_url=sf_url,
agv_rcms_url=agv_rcms_url,
agv_rcs_url=agv_rcs_url,
ftp_host=ftp_host, ftp_host=ftp_host,
ftp_port=ftp_port, ftp_port=ftp_port,
ftp_user=ftp_user, ftp_user=ftp_user,
@@ -112,6 +120,8 @@ class ResConfigSettings(models.TransientModel):
ir_config.set_param("token", self.token or "") ir_config.set_param("token", self.token or "")
ir_config.set_param("sf_secret_key", self.sf_secret_key or "") ir_config.set_param("sf_secret_key", self.sf_secret_key or "")
ir_config.set_param("sf_url", self.sf_url or "") ir_config.set_param("sf_url", self.sf_url or "")
ir_config.set_param("agv_rcms_url", self.agv_rcms_url or "")
ir_config.set_param("agv_rcs_url", self.agv_rcs_url or "")
ir_config.set_param("ftp_host", self.ftp_host or "") ir_config.set_param("ftp_host", self.ftp_host or "")
ir_config.set_param("ftp_port", self.ftp_port or "") ir_config.set_param("ftp_port", self.ftp_port or "")
ir_config.set_param("ftp_user", self.ftp_user or "") ir_config.set_param("ftp_user", self.ftp_user or "")

View File

@@ -50,6 +50,10 @@ class MrStaticResourceDataSync(models.Model):
logging.info("联装类型已每日同步成功") logging.info("联装类型已每日同步成功")
self.env['sf.fixture.model'].sync_fixture_model_yesterday() self.env['sf.fixture.model'].sync_fixture_model_yesterday()
logging.info("夹具型号已每日同步成功") logging.info("夹具型号已每日同步成功")
self.env['sf.fixture.materials.basic.parameters'].sync_fixture_materials_basic_parameters_yesterday()
logging.info("夹具型号基本参数已每日同步成功")
self.env['sf.functional.fixture.type'].sync_fixture_materials_basic_parameters_yesterday()
logging.info("夹具型号基本参数已每日同步成功")
self.env['sf.functional.fixture.type'].sync_functional_fixture_type_yesterday() self.env['sf.functional.fixture.type'].sync_functional_fixture_type_yesterday()
logging.info("功能夹具类型已每日同步成功") logging.info("功能夹具类型已每日同步成功")
self.env['sf.cutting.tool.material'].sync_cutting_tool_material_yesterday() self.env['sf.cutting.tool.material'].sync_cutting_tool_material_yesterday()
@@ -827,7 +831,8 @@ class MachineToolType(models.Model):
brand = self.env['sf.machine.brand'].search([('code', '=', item['brand_id'])]) brand = self.env['sf.machine.brand'].search([('code', '=', item['brand_id'])])
jg_image_id = self.env['maintenance.equipment.image'].search([('name', 'in', item['jg_image_id'])]).ids jg_image_id = self.env['maintenance.equipment.image'].search([('name', 'in', item['jg_image_id'])]).ids
lq_image_id = self.env['maintenance.equipment.image'].search([('name', 'in', item['lq_image_id'])]).ids lq_image_id = self.env['maintenance.equipment.image'].search([('name', 'in', item['lq_image_id'])]).ids
category = self.env['sf.machine_tool.category'].search([('code', '=', item['machine_tool_category']), ('active', '=', True)], limit=1) category = self.env['sf.machine_tool.category'].search(
[('code', '=', item['machine_tool_category']), ('active', '=', True)], limit=1)
if not machine_tool_type: if not machine_tool_type:
self.create({ self.create({
@@ -1475,90 +1480,23 @@ class SyncFixtureModel(models.Model):
for item in result['fixture_model_yesterday_list']: for item in result['fixture_model_yesterday_list']:
if item: if item:
fixture_model = self.search([("code", '=', item['code']), ('active', 'in', [True, False])]) fixture_model = self.search([("code", '=', item['code']), ('active', 'in', [True, False])])
zero_chuck_list = [] val = {
for zero_chuck_id in item['zero_chuck_ids']: "name": item['name'],
zero_chuck_list.append( "code": item['code'],
self.env['sf.fixture.materials.basic.parameters']._json_zero_chuck_param(zero_chuck_id)) "fixture_material_id": self.env['sf.fixture.material'].search(
zero_tray_list = [] [('code', '=', item['fixture_material_code'])]).id,
for zero_tray_id in item['zero_tray_ids']: "multi_mounting_type_id": self.env['sf.multi_mounting.type'].search(
zero_tray_list.append( [('code', '=', item['multi_mounting_type_code'])]).id,
self.env['sf.fixture.materials.basic.parameters']._json_zero_tray_param(zero_tray_id)) "brand_id": self.env['sf.machine.brand'].search([('code', '=', item['brand_code'])]).id,
pneumatic_fixture_list = [] "model_file": '' if not item['model_file'] else base64.b64decode(item['model_file']),
for pneumatic_fixture_id in item['pneumatic_fixture_ids']: "status": item['status'],
pneumatic_fixture_list.append( "active": item['active'],
self.env['sf.fixture.materials.basic.parameters']._json_pneumatic_fixture_param( }
pneumatic_fixture_id))
jaw_vice_fixture_list = []
for jaw_vice_fixture_id in item['jaw_vice_fixture_ids']:
jaw_vice_fixture_list.append(
self.env['sf.fixture.materials.basic.parameters']._json_jaw_vice_fixture_param(
jaw_vice_fixture_id))
magnet_fixture_list = []
for magnet_fixture_id in item['magnet_fixture_ids']:
magnet_fixture_list.append(
self.env['sf.fixture.materials.basic.parameters']._json_magnet_fixture_param(
magnet_fixture_id))
adapter_board_fixture_list = []
for adapter_board_fixture_id in item['adapter_board_fixture_ids']:
adapter_board_fixture_list.append(
self.env['sf.fixture.materials.basic.parameters']._json_adapter_board_fixture_param(
adapter_board_fixture_id))
scroll_chuck_list = []
for scroll_chuck_id in item['scroll_chuck_ids']:
scroll_chuck_list.append(
self.env['sf.fixture.materials.basic.parameters']._json_scroll_chuck_param(
scroll_chuck_id))
if not fixture_model: if not fixture_model:
self.create({ self.create(val)
"name": item['name'],
"code": item['code'],
"fixture_material_id": self.env['sf.fixture.material'].search(
[('code', '=', item['fixture_material_code'])]).id,
"multi_mounting_type_id": self.env['sf.multi_mounting.type'].search(
[('code', '=', item['multi_mounting_type_code'])]).id,
"brand_id": self.env['sf.machine.brand'].search([('code', '=', item['brand_code'])]).id,
"model_file": '' if not item['model_file'] else base64.b64decode(item['model_file']),
"zero_chuck_ids": zero_chuck_list,
"zero_tray_ids": zero_tray_list,
"pneumatic_fixture_ids": pneumatic_fixture_list,
"jaw_vice_fixture_ids": jaw_vice_fixture_list,
"magnet_fixture_ids": magnet_fixture_list,
"adapter_board_fixture_ids": adapter_board_fixture_list,
"scroll_chuck_ids": scroll_chuck_list,
"status": item['status'],
"active": item['active'],
})
else: else:
fixture_model.write({ fixture_model.write(val)
"zero_chuck_ids": [(5, 0, 0)],
"zero_tray_ids": [(5, 0, 0)],
"pneumatic_fixture_ids": [(5, 0, 0)],
"jaw_vice_fixture_ids": [(5, 0, 0)],
"magnet_fixture_ids": [(5, 0, 0)],
"adapter_board_fixture_ids": [(5, 0, 0)],
"scroll_chuck_ids": [(5, 0, 0)],
})
self.env['sf.fixture.materials.basic.parameters'].sudo().search(
[('fixture_model_id', '=', False)]).unlink()
fixture_model.write({
"name": item['name'],
"code": item['code'],
"fixture_material_id": self.env['sf.fixture.material'].search(
[('code', '=', item['fixture_material_code'])]).id,
"multi_mounting_type_id": self.env['sf.multi_mounting.type'].search(
[('code', '=', item['multi_mounting_type_code'])]).id,
"brand_id": self.env['sf.machine.brand'].search([('code', '=', item['brand_code'])]).id,
"model_file": '' if not item['model_file'] else base64.b64decode(item['model_file']),
"zero_chuck_ids": zero_chuck_list,
"zero_tray_ids": zero_tray_list,
"pneumatic_fixture_ids": pneumatic_fixture_list,
"jaw_vice_fixture_ids": jaw_vice_fixture_list,
"magnet_fixture_ids": magnet_fixture_list,
"adapter_board_fixture_ids": adapter_board_fixture_list,
"scroll_chuck_ids": scroll_chuck_list,
"status": item['status'],
"active": item['active'],
})
else: else:
raise ValidationError("夹具型号认证未通过") raise ValidationError("夹具型号认证未通过")
@@ -1576,94 +1514,98 @@ class SyncFixtureModel(models.Model):
for item in result['fixture_model_all_list']: for item in result['fixture_model_all_list']:
if item: if item:
fixture_model = self.search([('code', '=', item['code']), ('active', 'in', [True, False])]) fixture_model = self.search([('code', '=', item['code']), ('active', 'in', [True, False])])
zero_chuck_list = [] val = {
for zero_chuck_id in item['zero_chuck_ids']: "name": item['name'],
zero_chuck_list.append( "code": item['code'],
self.env['sf.fixture.materials.basic.parameters']._json_zero_chuck_param(zero_chuck_id)) "fixture_material_id": self.env['sf.fixture.material'].search(
zero_tray_list = [] [('code', '=', item['fixture_material_code'])]).id,
for zero_tray_id in item['zero_tray_ids']: "multi_mounting_type_id": self.env['sf.multi_mounting.type'].search(
zero_tray_list.append( [('code', '=', item['multi_mounting_type_code'])]).id,
self.env['sf.fixture.materials.basic.parameters']._json_zero_tray_param(zero_tray_id)) "brand_id": self.env['sf.machine.brand'].search([('code', '=', item['brand_code'])]).id,
pneumatic_fixture_list = [] "model_file": '' if not item['model_file'] else base64.b64decode(item['model_file']),
for pneumatic_fixture_id in item['pneumatic_fixture_ids']: "status": item['status'],
pneumatic_fixture_list.append( "active": item['active'],
self.env['sf.fixture.materials.basic.parameters']._json_pneumatic_fixture_param( }
pneumatic_fixture_id))
jaw_vice_fixture_list = []
for jaw_vice_fixture_id in item['jaw_vice_fixture_ids']:
jaw_vice_fixture_list.append(
self.env['sf.fixture.materials.basic.parameters']._json_jaw_vice_fixture_param(
jaw_vice_fixture_id))
magnet_fixture_list = []
for magnet_fixture_id in item['magnet_fixture_ids']:
magnet_fixture_list.append(
self.env['sf.fixture.materials.basic.parameters']._json_magnet_fixture_param(
magnet_fixture_id))
adapter_board_fixture_list = []
for adapter_board_fixture_id in item['adapter_board_fixture_ids']:
adapter_board_fixture_list.append(
self.env['sf.fixture.materials.basic.parameters']._json_adapter_board_fixture_param(
adapter_board_fixture_id))
scroll_chuck_list = []
for scroll_chuck_id in item['scroll_chuck_ids']:
scroll_chuck_list.append(
self.env['sf.fixture.materials.basic.parameters']._json_scroll_chuck_param(
scroll_chuck_id))
if not fixture_model: if not fixture_model:
self.create({ self.create(val)
"name": item['name'],
"code": item['code'],
"fixture_material_id": self.env['sf.fixture.material'].search(
[('code', '=', item['fixture_material_code'])]).id,
"multi_mounting_type_id": self.env['sf.multi_mounting.type'].search(
[('code', '=', item['multi_mounting_type_code'])]).id,
"brand_id": self.env['sf.machine.brand'].search([('code', '=', item['brand_code'])]).id,
"model_file": '' if not item['model_file'] else base64.b64decode(item['model_file']),
"zero_chuck_ids": zero_chuck_list,
"zero_tray_ids": zero_tray_list,
"pneumatic_fixture_ids": pneumatic_fixture_list,
"jaw_vice_fixture_ids": jaw_vice_fixture_list,
"magnet_fixture_ids": magnet_fixture_list,
"adapter_board_fixture_ids": adapter_board_fixture_list,
"scroll_chuck_ids": scroll_chuck_list,
"status": item['status'],
"active": item['active'],
})
else: else:
fixture_model.write({ fixture_model.write(val)
"zero_chuck_ids": [(5, 0, 0)],
"zero_tray_ids": [(5, 0, 0)],
"pneumatic_fixture_ids": [(5, 0, 0)],
"jaw_vice_fixture_ids": [(5, 0, 0)],
"magnet_fixture_ids": [(5, 0, 0)],
"adapter_board_fixture_ids": [(5, 0, 0)],
"scroll_chuck_ids": [(5, 0, 0)],
})
self.env['sf.fixture.materials.basic.parameters'].sudo().search(
[('fixture_model_id', '=', False)]).unlink()
fixture_model.write({
"name": item['name'],
"code": item['code'],
"fixture_material_id": self.env['sf.fixture.material'].search(
[('code', '=', item['fixture_material_code'])]).id,
"multi_mounting_type_id": self.env['sf.multi_mounting.type'].search(
[('code', '=', item['multi_mounting_type_code'])]).id,
"brand_id": self.env['sf.machine.brand'].search([('code', '=', item['brand_code'])]).id,
"model_file": '' if not item['model_file'] else base64.b64decode(item['model_file']),
"zero_chuck_ids": zero_chuck_list,
"zero_tray_ids": zero_tray_list,
"pneumatic_fixture_ids": pneumatic_fixture_list,
"jaw_vice_fixture_ids": jaw_vice_fixture_list,
"magnet_fixture_ids": magnet_fixture_list,
"adapter_board_fixture_ids": adapter_board_fixture_list,
"scroll_chuck_ids": scroll_chuck_list,
"status": item['status'],
"active": item['active'],
})
else: else:
raise ValidationError("夹具型号认证未通过") raise ValidationError("夹具型号认证未通过")
class SyncfixtureMaterialsBasicParameters(models.Model):
_inherit = 'sf.fixture.materials.basic.parameters'
_description = '同步夹具型号基本参数列表'
url = '/api/fixture_parameters/list'
# 定时同步夹具型号基本信息
def sync_fixture_materials_basic_parameters_yesterday(self):
config = self.env['res.config.settings'].get_values()
headers = Common.get_headers(self, config['token'], config['sf_secret_key'])
strUrl = config['sf_url'] + self.url
r = requests.post(strUrl, json={}, data=None, headers=headers)
r = r.json()
result = json.loads(r['result'])
if result['status'] == 1:
if result.get('fixture_parameters_yesterday_list'):
all_list = result.get('fixture_parameters_yesterday_list')
if all_list.get('zero_chuck_all_list'):
self._write_or_create(all_list.get('zero_chuck_yesterday_list'), '零点卡盘')
if all_list.get('zero_tray_all_list'):
self._write_or_create(all_list.get('zero_tray_yesterday_list'), '零点托盘')
if all_list.get('pneumatic_fixture_all_list'):
self._write_or_create(all_list.get('pneumatic_fixture_yesterday_list'), '气动夹具')
if all_list.get('jaw_vice_all_list'):
self._write_or_create(all_list.get('jaw_vice_yesterday_list'), '虎钳夹具')
if all_list.get('magnet_fixture_all_list'):
self._write_or_create(all_list.get('magnet_fixture_yesterday_list'), '磁吸夹具')
if all_list.get('adapter_board_all_list'):
self._write_or_create(all_list.get('adapter_board_yesterday_list'), '转接板(锁板)夹具')
if all_list.get('scroll_chuck_all_list'):
self._write_or_create(all_list.get('scroll_chuck_yesterday_list'), '三爪卡盘')
else:
raise ValidationError("夹具型号基本参数认证未通过")
# 定时同步所有夹具型号基本信息
def sync_all_fixture_materials_basic_parameters(self):
config = self.env['res.config.settings'].get_values()
headers = Common.get_headers(self, config['token'], config['sf_secret_key'])
strUrl = config['sf_url'] + self.url
r = requests.post(strUrl, json={}, data=None, headers=headers)
r = r.json()
result = json.loads(r['result'])
if result['status'] == 1:
if result.get('fixture_parameters_all_list'):
all_list = result.get('fixture_parameters_all_list')
if all_list.get('zero_chuck_all_list'):
self._write_or_create(all_list.get('zero_chuck_all_list'), '零点卡盘')
if all_list.get('zero_tray_all_list'):
self._write_or_create(all_list.get('zero_tray_all_list'), '零点托盘')
if all_list.get('pneumatic_fixture_all_list'):
self._write_or_create(all_list.get('pneumatic_fixture_all_list'), '气动夹具')
if all_list.get('jaw_vice_all_list'):
self._write_or_create(all_list.get('jaw_vice_all_list'), '虎钳夹具')
if all_list.get('magnet_fixture_all_list'):
self._write_or_create(all_list.get('magnet_fixture_all_list'), '磁吸夹具')
if all_list.get('adapter_board_all_list'):
self._write_or_create(all_list.get('adapter_board_all_list'), '转接板(锁板)夹具')
if all_list.get('scroll_chuck_all_list'):
self._write_or_create(all_list.get('scroll_chuck_all_list'), '三爪卡盘')
else:
raise ValidationError("夹具型号基本参数认证未通过")
def _write_or_create(self, fixture_parameters_list, material_name):
for item in fixture_parameters_list:
if item:
basic_parameters = self.search([('code', '=', item.get('code')), ('active', 'in', [True, False])])
if not basic_parameters:
self.create(self._get_basic_parameters_list(item, material_name))
else:
basic_parameters.write(self._get_basic_parameters_list(item, material_name))
class SyncFunctionalFixtureType(models.Model): class SyncFunctionalFixtureType(models.Model):
_inherit = 'sf.functional.fixture.type' _inherit = 'sf.functional.fixture.type'
_description = '同步功能夹具类型列表' _description = '同步功能夹具类型列表'
@@ -2457,8 +2399,9 @@ class CuttingToolBasicParameters(models.Model):
'cutting_tool_type': '整体式刀具', 'cutting_tool_type': '整体式刀具',
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search( 'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
[( [(
'code', '=', integral_tool_item['standard_library_code'].replace("JKM", result[ 'code', '=',
'factory_short_name']))]).id, integral_tool_item['standard_library_code'].replace("JKM", result[
'factory_short_name']))]).id,
'total_length': integral_tool_item['total_length'], 'total_length': integral_tool_item['total_length'],
'blade_diameter': integral_tool_item['blade_diameter'], 'blade_diameter': integral_tool_item['blade_diameter'],
'blade_length': integral_tool_item['blade_length'], 'blade_length': integral_tool_item['blade_length'],
@@ -2825,8 +2768,9 @@ class CuttingToolBasicParameters(models.Model):
'cutting_tool_type': '整体式刀具', 'cutting_tool_type': '整体式刀具',
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search( 'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
[( [(
'code', '=', integral_tool_item['standard_library_code'].replace("JKM", result[ 'code', '=',
'factory_short_name']))]).id, integral_tool_item['standard_library_code'].replace("JKM", result[
'factory_short_name']))]).id,
'total_length': integral_tool_item['total_length'], 'total_length': integral_tool_item['total_length'],
'blade_diameter': integral_tool_item['blade_diameter'], 'blade_diameter': integral_tool_item['blade_diameter'],
'blade_length': integral_tool_item['blade_length'], 'blade_length': integral_tool_item['blade_length'],

View File

@@ -74,9 +74,26 @@
</div> </div>
</div> </div>
</div> </div>
<div>
<h2>AGV参数配置</h2>
<div class="row mt16 o_settings_container">
<div class="col-12 col-lg-6 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<div class="text-muted">
<label for="agv_rcms_url" string="调度系统(cms)访问地址"/>
<field name="agv_rcms_url"/>
</div>
<div class="text-muted">
<label for="agv_rcs_url" string="RCS-2000系统访问地址"/>
<field name="agv_rcs_url"/>
</div>
</div>
</div>
</div>
</div>
</xpath> </xpath>
</field> </field>
</record> </record>
</data> </data>
</odoo> </odoo>

View File

@@ -44,8 +44,9 @@ class sf_production_plan(models.Model):
production_id = fields.Many2one('mrp.production', '关联制造订单') production_id = fields.Many2one('mrp.production', '关联制造订单')
product_qty = fields.Float(string='数量', digits='Product Unit of Measure', required=True, default=0.0) product_qty = fields.Float(string='数量', digits='Product Unit of Measure', required=True, default=0.0)
production_line_id = fields.Many2one('sf.production.line', string='生产线') production_line_id = fields.Many2one('sf.production.line', string='生产线')
date_planned_start = fields.Datetime(string='计划开始时间', required=True, index=True, copy=False, # date_planned_start = fields.Datetime(string='计划开始时间', required=True, index=True, copy=False,
default=fields.Datetime.now) # default=fields.Datetime.now)
date_planned_start = fields.Datetime(string='计划开始时间')
date_planned_finished = fields.Datetime(string='计划结束时间') date_planned_finished = fields.Datetime(string='计划结束时间')
# 排程设置selection(倒排,顺排,默认倒排) # 排程设置selection(倒排,顺排,默认倒排)
schedule_setting = fields.Selection([ schedule_setting = fields.Selection([
@@ -80,7 +81,7 @@ class sf_production_plan(models.Model):
def _compute_production_line_id(self): def _compute_production_line_id(self):
for item in self: for item in self:
item.sudo().production_id.production_line_id = item.production_line_id.id item.sudo().production_id.production_line_id = item.production_line_id.id
item.sudo().production_id.plan_start_processing_time = item.date_planned_start # item.sudo().production_id.plan_start_processing_time = item.date_planned_start
# @api.onchange('state') # @api.onchange('state')
# def _onchange_state(self): # def _onchange_state(self):
@@ -198,7 +199,9 @@ class sf_production_plan(models.Model):
for item in record.production_id.workorder_ids: for item in record.production_id.workorder_ids:
if item.name == 'CNC加工': if item.name == 'CNC加工':
item.date_planned_finished = datetime.now() + timedelta(days=100) item.date_planned_finished = datetime.now() + timedelta(days=100)
item.date_planned_start = record.date_planned_start # item.date_planned_start = record.date_planned_start
item.date_planned_start = datetime.now()
record.sudo().production_id.plan_start_processing_time = item.date_planned_start
item.date_planned_finished = item.date_planned_start + timedelta( item.date_planned_finished = item.date_planned_start + timedelta(
minutes=record.env['mrp.routing.workcenter'].sudo().search( minutes=record.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', 'CNC加工')]).time_cycle) [('name', '=', 'CNC加工')]).time_cycle)
@@ -291,6 +294,7 @@ class sf_production_plan(models.Model):
print('时间设置失败,请检查是否为工序分配工作中心,%s' % e) print('时间设置失败,请检查是否为工序分配工作中心,%s' % e)
def cancel_production_schedule(self): def cancel_production_schedule(self):
self.date_planned_start = False
self.date_planned_finished = False self.date_planned_finished = False
self.state = 'draft' self.state = 'draft'
self.production_line_id = False self.production_line_id = False

View File

@@ -10,7 +10,7 @@
<header> <header>
<!-- <button name="do_production_schedule" type="object" string="批量排程"/> --> <!-- <button name="do_production_schedule" type="object" string="批量排程"/> -->
<button string="批量排程" name="%(sf_plan.action_plan_some)d" type="action" <button string="批量排程" name="%(sf_plan.action_plan_some)d" type="action"
class="btn-primary"/> class="treeHeaderBtn"/>
</header> </header>
<field name="state" widget="badge" decoration-warning="state == 'draft'" <field name="state" widget="badge" decoration-warning="state == 'draft'"
decoration-success="state == 'done'" decoration-info="state == 'processing'" decoration-success="state == 'done'" decoration-info="state == 'processing'"
@@ -88,7 +88,7 @@
<group string="加工信息"> <group string="加工信息">
<field name="date_planned_start"/> <field name="date_planned_start" placeholder="如果不选择计划开始时间,会取当前时间来做排程"/>
<field name="date_planned_finished"/> <field name="date_planned_finished"/>
<field name="actual_process_time"/> <field name="actual_process_time"/>
<field name="actual_start_time"/> <field name="actual_start_time"/>

View File

@@ -11,26 +11,3 @@ class SfQualityPoint(models.Model):
"('product', 'consu')), '|', ('company_id', '=', False), ('company_id', '=', company_id)]", help= "('product', 'consu')), '|', ('company_id', '=', False), ('company_id', '=', company_id)]", help=
"Quality Point will apply to every selected Products.") "Quality Point will apply to every selected Products.")
check_state = fields.Selection([
('enable', '启用'),
('close', '关闭')
], string='审核状态', default='close')
# 审核
def action_check(self):
self.check_state = 'enable'
# picking_type_ids = fields.Many2many(
# 'stock.picking.type', string='执行节点', required=True, check_company=True)
class ResQualityAlertTeam(models.Model):
_inherit = 'quality.alert.team'
check_state = fields.Selection([
('enable', '启用'),
('close', '关闭')
], string='审核状态', default='close')
# 审核
def action_check(self):
self.check_state = 'enable'

View File

@@ -39,13 +39,6 @@
<field name="model">quality.point</field> <field name="model">quality.point</field>
<field name="inherit_id" ref="quality.quality_point_view_form"/> <field name="inherit_id" ref="quality.quality_point_view_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//header" position="inside">
<field name="check_state" invisible="1"/>
<button name="action_check" string="审核" type="object"
attrs="{'invisible': [('check_state','=', 'enable')]}"
groups="sf_base.group_quality_director"
class="oe_highlight"/>
</xpath>
<!-- <xpath expr="//sheet//group//group//field[@name='title']" position="replace"> --> <!-- <xpath expr="//sheet//group//group//field[@name='title']" position="replace"> -->
<!-- <field name="title" class="custom_required" required="1"/> --> <!-- <field name="title" class="custom_required" required="1"/> -->
<!-- </xpath> --> <!-- </xpath> -->
@@ -67,26 +60,10 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//field[@name='measure_on']" position="attributes"> <xpath expr="//field[@name='measure_on']" position="attributes">
<attribute name="class">custom_required</attribute> <attribute name="class">custom_required</attribute>
</xpath> </xpath>
<xpath expr="//field[@name='measure_frequency_type']" position="attributes"> <xpath expr="//field[@name='measure_frequency_type']" position="attributes">
<attribute name="class">custom_required</attribute> <attribute name="class">custom_required</attribute>
</xpath> </xpath>
</field> </field>
</record> </record>
<record model="ir.ui.view" id="quality_alert_team_view_form_inherit_sf">
<field name="name">quality.alert.team.form.inherit.sf</field>
<field name="model">quality.alert.team</field>
<field name="inherit_id" ref="quality_control.quality_alert_team_view_form"/>
<field name="arch" type="xml">
<xpath expr="//header" position="inside">
<field name="check_state" invisible="1"/>
<button name="action_check" string="审核" type="object"
attrs="{'invisible': [('check_state','=', 'enable')]}"
groups="sf_base.group_quality_director"
class="oe_highlight"/>
</xpath>
</field>
</record>
</odoo> </odoo>

View File

@@ -1,7 +1,12 @@
import datetime import datetime
import base64 import base64
from odoo import models, fields, api, _ from odoo import models, fields, api, _
from odoo.exceptions import UserError from odoo.exceptions import UserError, ValidationError
READONLY_FIELD_STATES = {
state: [('readonly', True)]
for state in {'sale', 'done', 'cancel'}
}
class ReSaleOrder(models.Model): class ReSaleOrder(models.Model):
@@ -39,6 +44,12 @@ class ReSaleOrder(models.Model):
domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]") domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]")
remark = fields.Text('备注') remark = fields.Text('备注')
validity_date = fields.Date(
string="Expiration",
compute='_compute_validity_date',
store=True, readonly=False, copy=False, precompute=True,
states=READONLY_FIELD_STATES, default=fields.Datetime.now)
# 业务平台分配工厂后在智能工厂先创建销售订单 # 业务平台分配工厂后在智能工厂先创建销售订单
def sale_order_create(self, company_id, delivery_name, delivery_telephone, delivery_address, def sale_order_create(self, company_id, delivery_name, delivery_telephone, delivery_address,
deadline_of_delivery, payments_way, pay_way): deadline_of_delivery, payments_way, pay_way):
@@ -99,7 +110,7 @@ class ReSaleOrder(models.Model):
def check_order_line(self): def check_order_line(self):
for item in self: for item in self:
if not item.order_line: if not item.order_line:
raise UserError('请选择【订单行】中的【产品】') raise ValidationError('请选择【订单行】中的【产品】')
for line in item.order_line: for line in item.order_line:
if not line.product_template_id: if not line.product_template_id:
raise UserError('请对【订单行】中的【产品】进行选择') raise UserError('请对【订单行】中的【产品】进行选择')

View File

@@ -24,6 +24,9 @@ access_stock_picking_group_sale_salemanager,stock_picking_group_sale_salemanager
access_stock_picking_group_sale_director,stock_picking_group_sale_director,stock.model_stock_picking,sf_base.group_sale_director,1,0,0,0 access_stock_picking_group_sale_director,stock_picking_group_sale_director,stock.model_stock_picking,sf_base.group_sale_director,1,0,0,0
access_stock_picking_group_purchase,stock_picking_group_purchase,stock.model_stock_picking,sf_base.group_purchase,1,1,1,0 access_stock_picking_group_purchase,stock_picking_group_purchase,stock.model_stock_picking,sf_base.group_purchase,1,1,1,0
access_stock_picking_group_purchase_director,stock_picking_group_purchase_director,stock.model_stock_picking,sf_base.group_purchase_director,1,1,1,0 access_stock_picking_group_purchase_director,stock_picking_group_purchase_director,stock.model_stock_picking,sf_base.group_purchase_director,1,1,1,0
access_stock_picking_group_quality,stock_picking_group_quality,stock.model_stock_picking,sf_base.group_quality,1,0,0,0
access_stock_picking_group_quality_director,stock_picking_group_quality_director,stock.model_stock_picking,sf_base.group_quality_director,1,0,0,0
access_account_move_group_sale_salemanager,account_move_group_sale_salemanager,account.model_account_move,sf_base.group_sale_salemanager,1,0,0,0 access_account_move_group_sale_salemanager,account_move_group_sale_salemanager,account.model_account_move,sf_base.group_sale_salemanager,1,0,0,0
access_account_move_group_sale_director,account_move_group_sale_director,account.model_account_move,sf_base.group_sale_director,1,0,0,0 access_account_move_group_sale_director,account_move_group_sale_director,account.model_account_move,sf_base.group_sale_director,1,0,0,0
access_resource_resource_group_sale_director,resource_resource_group_sale_director,resource.model_resource_resource,sf_base.group_sale_director,1,1,1,0 access_resource_resource_group_sale_director,resource_resource_group_sale_director,resource.model_resource_resource,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
24 access_stock_picking_group_sale_director stock_picking_group_sale_director stock.model_stock_picking sf_base.group_sale_director 1 0 0 0
25 access_stock_picking_group_purchase stock_picking_group_purchase stock.model_stock_picking sf_base.group_purchase 1 1 1 0
26 access_stock_picking_group_purchase_director stock_picking_group_purchase_director stock.model_stock_picking sf_base.group_purchase_director 1 1 1 0
27 access_stock_picking_group_quality stock_picking_group_quality stock.model_stock_picking sf_base.group_quality 1 0 0 0
28 access_stock_picking_group_quality_director stock_picking_group_quality_director stock.model_stock_picking sf_base.group_quality_director 1 0 0 0
29 access_account_move_group_sale_salemanager account_move_group_sale_salemanager account.model_account_move sf_base.group_sale_salemanager 1 0 0 0
30 access_account_move_group_sale_salemanager access_account_move_group_sale_director account_move_group_sale_salemanager account_move_group_sale_director account.model_account_move sf_base.group_sale_salemanager sf_base.group_sale_director 1 0 0 0
31 access_account_move_group_sale_director access_resource_resource_group_sale_director account_move_group_sale_director resource_resource_group_sale_director account.model_account_move resource.model_resource_resource sf_base.group_sale_director 1 0 1 0 1 0
32 access_resource_resource_group_sale_director access_mrp_bom_group_sale_salemanager resource_resource_group_sale_director mrp_bom_group_sale_salemanager resource.model_resource_resource mrp.model_mrp_bom sf_base.group_sale_director sf_base.group_sale_salemanager 1 1 0 1 0 0

View File

@@ -23,7 +23,8 @@
</xpath> </xpath>
<xpath expr="//form/header/button[@name='button_confirm'][2]" position="replace"> <xpath expr="//form/header/button[@name='button_confirm'][2]" position="replace">
<button name="button_confirm" type="object" context="{'validate_analytic': True}" <button name="button_confirm" type="object" context="{'validate_analytic': True}"
string="确认订单" id="draft_confirm" groups="sf_base.group_purchase,sf_base.group_purchase_director" string="确认订单" id="draft_confirm"
groups="sf_base.group_purchase,sf_base.group_purchase_director"
attrs="{'invisible': ['|','&amp;','&amp;', ('state', 'in', ['purchase','draft']), ('check_status', 'in', ['approved']), ('date_approve', '!=', False),'&amp;', '&amp;',('state', 'in', ['purchase', 'draft']),('check_status', 'in', [False, 'pending', 'fail']),('date_approve', '=', False)]}" attrs="{'invisible': ['|','&amp;','&amp;', ('state', 'in', ['purchase','draft']), ('check_status', 'in', ['approved']), ('date_approve', '!=', False),'&amp;', '&amp;',('state', 'in', ['purchase', 'draft']),('check_status', 'in', [False, 'pending', 'fail']),('date_approve', '=', False)]}"
/> />
<button name="button_confirming" type="object" <button name="button_confirming" type="object"
@@ -32,13 +33,19 @@
/> />
</xpath> </xpath>
<xpath expr="//form/header/button[@name='action_rfq_send'][1]" position="replace"> <xpath expr="//form/header/button[@name='action_rfq_send'][1]" position="replace">
<button name="action_rfq_send" states="draft" string="通过Email发送采购单" type="object" context="{'send_rfq':True}" class="oe_highlight" data-hotkey="g" groups="sf_base.group_purchase,sf_base.group_purchase_director"/> <button name="action_rfq_send" states="draft" string="通过Email发送采购单" type="object"
context="{'send_rfq':True}" class="oe_highlight" data-hotkey="g"
groups="sf_base.group_purchase,sf_base.group_purchase_director"/>
</xpath> </xpath>
<xpath expr="//form/header/button[@name='action_rfq_send'][2]" position="replace"> <xpath expr="//form/header/button[@name='action_rfq_send'][2]" position="replace">
<button name="action_rfq_send" states="sent" string="通过Email重新发送采购单" type="object" context="{'send_rfq':True}" data-hotkey="g" groups="sf_base.group_purchase,sf_base.group_purchase_director"/> <button name="action_rfq_send" states="sent" string="通过Email重新发送采购单" type="object"
context="{'send_rfq':True}" data-hotkey="g"
groups="sf_base.group_purchase,sf_base.group_purchase_director"/>
</xpath> </xpath>
<xpath expr="//form/header/button[@name='action_rfq_send'][3]" position="replace"> <xpath expr="//form/header/button[@name='action_rfq_send'][3]" position="replace">
<button name="action_rfq_send" states="purchase" string="通过Email发送订单" type="object" context="{'send_rfq':False}" data-hotkey="g" groups="sf_base.group_purchase,sf_base.group_purchase_director"/> <button name="action_rfq_send" states="purchase" string="通过Email发送订单" type="object"
context="{'send_rfq':False}" data-hotkey="g"
groups="sf_base.group_purchase,sf_base.group_purchase_director"/>
</xpath> </xpath>
<!-- <xpath expr="//form/header/button[@name='print_quotation[1]']" position="attributes">--> <!-- <xpath expr="//form/header/button[@name='print_quotation[1]']" position="attributes">-->
@@ -51,17 +58,20 @@
<attribute name="groups">sf_base.group_purchase,sf_base.group_purchase_director</attribute> <attribute name="groups">sf_base.group_purchase,sf_base.group_purchase_director</attribute>
</xpath> </xpath>
<xpath expr="//form/header/button[@name='action_create_invoice']" position="replace"> <xpath expr="//form/header/button[@name='action_create_invoice']" position="replace">
<!-- <attribute name="groups">sf_base.group_purchase,sf_base.group_purchase_director</attribute> --> <!-- <attribute name="groups">sf_base.group_purchase,sf_base.group_purchase_director</attribute> -->
<button name="action_create_invoice" string="创建账单" type="object" class="oe_highlight" context="{'create_bill':True}" attrs="{'invisible': ['|', ('state', 'not in', ('purchase', 'done')), ('invoice_status', 'in', ('no', 'invoiced'))]}" data-hotkey="w" groups="sf_base.group_purchase,sf_base.group_purchase_director"/> <button name="action_create_invoice" string="创建账单" type="object" class="oe_highlight"
</xpath> context="{'create_bill':True}"
<xpath expr="//form/header/button[@name='action_create_invoice'][2]" position="attributes"> attrs="{'invisible': ['|', ('state', 'not in', ('purchase', 'done')), ('invoice_status', 'in', ('no', 'invoiced'))]}"
<attribute name="groups">sf_base.group_purchase,sf_base.group_purchase_director</attribute> data-hotkey="w" groups="sf_base.group_purchase,sf_base.group_purchase_director"/>
</xpath> </xpath>
<xpath expr="//form/header/button[@name='button_confirm']" position="attributes"> <xpath expr="//form/header/button[@name='action_create_invoice'][2]" position="attributes">
<attribute name="groups">sf_base.group_purchase,sf_base.group_purchase_director</attribute> <attribute name="groups">sf_base.group_purchase,sf_base.group_purchase_director</attribute>
<!-- <button name="action_create_invoice" string="创建账单" type="object" class="oe_highlight" context="{'create_bill':True}" attrs="{'invisible': ['|', ('state', 'not in', ('purchase', 'done')), ('invoice_status', 'in', ('no', 'invoiced'))]}" data-hotkey="w" groups="sf_base.group_purchase,sf_base.group_purchase_director"/> --> </xpath>
</xpath> <xpath expr="//form/header/button[@name='button_confirm']" position="attributes">
<attribute name="groups">sf_base.group_purchase,sf_base.group_purchase_director</attribute>
<!-- <button name="action_create_invoice" string="创建账单" type="object" class="oe_highlight" context="{'create_bill':True}" attrs="{'invisible': ['|', ('state', 'not in', ('purchase', 'done')), ('invoice_status', 'in', ('no', 'invoiced'))]}" data-hotkey="w" groups="sf_base.group_purchase,sf_base.group_purchase_director"/> -->
</xpath>
<!-- <xpath expr="//form/header/button[@name='action_create_invoice[2]']" position="attributes">--> <!-- <xpath expr="//form/header/button[@name='action_create_invoice[2]']" position="attributes">-->
<!-- <attribute name="groups">sf_base.group_purchase,sf_base.group_purchase_director</attribute>--> <!-- <attribute name="groups">sf_base.group_purchase,sf_base.group_purchase_director</attribute>-->
<!-- </xpath>--> <!-- </xpath>-->
@@ -171,5 +181,16 @@
</field> </field>
</field> </field>
</record> </record>
<record id="purchase_order_search_inherit_sf" model="ir.ui.view">
<field name="name">purchase.order.list.select.inherit.sf</field>
<field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.view_purchase_order_filter"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="replace">
<field name="name" string="单据编码" filter_domain="[('name', 'ilike', self)]"/>
</xpath>
</field>
</record>
</data> </data>
</odoo> </odoo>

View File

@@ -243,6 +243,10 @@
<form position="attributes"> <form position="attributes">
<attribute name="delete">False</attribute> <attribute name="delete">False</attribute>
</form> </form>
<field name="name" position="replace">
<field name='name' placeholder="例如:奶酪汉堡" attrs="{'readonly': [('id', '!=', False)]}"/>
</field>
<field name="categ_id" position="replace"> <field name="categ_id" position="replace">
<field name='categ_id' invisible="1"/> <field name='categ_id' invisible="1"/>
</field> </field>

View File

@@ -20,6 +20,7 @@
'views/sf_maintenance_equipment.xml', 'views/sf_maintenance_equipment.xml',
'views/menu_view.xml', 'views/menu_view.xml',
'views/tool_material_search.xml', 'views/tool_material_search.xml',
'views/fixture_material_search_views.xml',
], ],
'demo': [ 'demo': [
], ],

View File

@@ -2,4 +2,7 @@ from . import base
from . import tool_material_search from . import tool_material_search
from . import maintenance_equipment from . import maintenance_equipment
from . import mrp_workorder from . import mrp_workorder
from . import functional_tool_enroll
from . import fixture_material_search
from . import fixture_enroll

View File

@@ -14,9 +14,9 @@ class FunctionalCuttingToolEntity(models.Model):
_description = '功能刀具列表' _description = '功能刀具列表'
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id') tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id')
code = fields.Char('编码', related='functional_tool_name_id.code') code = fields.Char('编码')
rfid = fields.Char('rfid', readonly=True) rfid = fields.Char('rfid', readonly=True)
name = fields.Char(related='functional_tool_name_id.name') name = fields.Char('名称')
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称', readonly=True) functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称', readonly=True)
barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', readonly=True) barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', readonly=True)
sf_cutting_tool_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀具型号') sf_cutting_tool_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀具型号')
@@ -69,22 +69,15 @@ class FunctionalCuttingToolEntity(models.Model):
""" """
for obj in self: for obj in self:
if obj.current_location_id: if obj.current_location_id:
obj.tool_room_num = 0
obj.line_edge_knife_library_num = 0
obj.machine_knife_library_num = 0
if obj.current_location in ['刀具房']: if obj.current_location in ['刀具房']:
obj.tool_room_num = 1 obj.tool_room_num = 1
obj.line_edge_knife_library_num = 0
obj.machine_knife_library_num = 0
elif "线边刀库" in obj.current_location: elif "线边刀库" in obj.current_location:
obj.tool_room_num = 0
obj.line_edge_knife_library_num = 1 obj.line_edge_knife_library_num = 1
obj.machine_knife_library_num = 0
elif "机内刀库" in obj.current_location: elif "机内刀库" in obj.current_location:
obj.tool_room_num = 0
obj.line_edge_knife_library_num = 0
obj.machine_knife_library_num = 1 obj.machine_knife_library_num = 1
else:
obj.tool_room_num = 0
obj.line_edge_knife_library_num = 0
obj.machine_knife_library_num = 0
@api.model @api.model
def _read_group_mrs_cutting_tool_type_id(self, categories, domain, order): def _read_group_mrs_cutting_tool_type_id(self, categories, domain, order):
@@ -136,7 +129,6 @@ class FunctionalCuttingToolEntity(models.Model):
@api.depends('cutting_tool_integral_model_id', 'cutting_tool_blade_model_id') @api.depends('cutting_tool_integral_model_id', 'cutting_tool_blade_model_id')
def _compute_maintenance_equipment_image(self): def _compute_maintenance_equipment_image(self):
for record in self: for record in self:
print('111')
if record.cutting_tool_integral_model_id: if record.cutting_tool_integral_model_id:
print(record.cutting_tool_integral_model_id) print(record.cutting_tool_integral_model_id)
record.sudo().suitable_machining_method_ids = record.cutting_tool_integral_model_id.suitable_machining_method_ids.ids record.sudo().suitable_machining_method_ids = record.cutting_tool_integral_model_id.suitable_machining_method_ids.ids
@@ -194,36 +186,35 @@ class FunctionalCuttingToolEntity(models.Model):
stock_location_id = self.env['stock.location'].search([('name', '=', '制造前')]) stock_location_id = self.env['stock.location'].search([('name', '=', '制造前')])
# 创建功能刀具该批次/序列号 库存移动和移动历史 # 创建功能刀具该批次/序列号 库存移动和移动历史
self.barcode_id.create_stock_quant(location_inventory_id, stock_location_id, self.barcode_id.create_stock_quant(location_inventory_id, stock_location_id,
self.functional_tool_name_id.id, '机床装刀') self.functional_tool_name_id.id, '机床装刀', self.functional_tool_name_id)
# ==========刀具组接口==========
# def _register_functional_tool_groups(self, obj):
# create_url = '/AutoDeviceApi/ToolGroup'
# 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(obj, token, sf_secret_key)
# strurl = sf_sync_config['sf_url'] + create_url
# val = {
# 'ToolName': obj.name,
# 'GroupName': obj.tool_groups_id.name,
# 'ToolId': obj.code
# }
# kw = json.dumps(val, ensure_ascii=False)
# r = requests.post(strurl, json={}, data={'kw': kw, 'token': token}, headers=headers)
# ret = r.json()
# if r == 200:
# return "刀具组发送成功"
# else:
# raise ValidationError("刀具组发送失败")
# ==========刀具组接口========== # @api.model_create_multi
# def _register_functional_tool_groups(self, obj): # def create(self, vals):
# create_url = '/AutoDeviceApi/ToolGroup' # obj = super(FunctionalCuttingToolEntity, self).create(vals)
# sf_sync_config = self.env['res.config.settings'].get_values() # # 调用刀具组接口
# token = sf_sync_config['token'] # self._register_functional_tool_groups(obj)
# sf_secret_key = sf_sync_config['sf_secret_key'] # return obj
# headers = Common.get_headers(obj, token, sf_secret_key)
# strurl = sf_sync_config['sf_url'] + create_url
# val = {
# 'ToolName': obj.name,
# 'GroupName': obj.tool_groups_id.name,
# 'ToolId': obj.code
# }
# kw = json.dumps(val, ensure_ascii=False)
# r = requests.post(strurl, json={}, data={'kw': kw, 'token': token}, headers=headers)
# ret = r.json()
# if r == 200:
# return "刀具组发送成功"
# else:
# raise ValidationError("刀具组发送失败")
# @api.model_create_multi
# def create(self, vals):
# obj = super(FunctionalCuttingToolEntity, self).create(vals)
# # 调用刀具组接口
# self._register_functional_tool_groups(obj)
# return obj
class FunctionalToolWarning(models.Model): class FunctionalToolWarning(models.Model):
@@ -239,7 +230,8 @@ class FunctionalToolWarning(models.Model):
group_expand='_read_group_machine_table_name_ids') group_expand='_read_group_machine_table_name_ids')
maintenance_equipment_id = fields.Many2one('maintenance.equipment', string='CNC机床') maintenance_equipment_id = fields.Many2one('maintenance.equipment', string='CNC机床')
machine_tool_code = fields.Char(string='机台号', related='maintenance_equipment_id.name') machine_tool_code = fields.Char(string='机台号', related='maintenance_equipment_id.name')
machine_table_type_id = fields.Many2one('maintenance.equipment.category', string='机床类型') machine_table_type_id = fields.Many2one('maintenance.equipment.category', string='机床类型',
related='maintenance_equipment_id.category_id')
cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号', cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号',
domain="[('equipment_id', '=', maintenance_equipment_id)]") domain="[('equipment_id', '=', maintenance_equipment_id)]")
# 功能刀具信息 # 功能刀具信息
@@ -298,14 +290,14 @@ class StockMoveLine(models.Model):
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称') 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, functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
group_expand='_read_group_functional_tool_type_id', group_expand='_read_group_functional_tool_type_id')
related='functional_tool_name_id.functional_tool_type_id') functional_tool_name = fields.Char('刀具名称')
diameter = fields.Integer(string='刀具直径(mm)', related='functional_tool_name_id.functional_tool_diameter') diameter = fields.Integer(string='刀具直径(mm)')
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', related='functional_tool_name_id.knife_tip_r_angle') knife_tip_r_angle = fields.Float(string='刀尖R角(mm)')
install_tool_time = fields.Datetime("刀具组装时间", related='functional_tool_name_id.tool_loading_time') install_tool_time = fields.Datetime("刀具组装时间", default=fields.Datetime.now())
code = fields.Char('编码', related='functional_tool_name_id.code') code = fields.Char('编码')
rfid = fields.Char('rfid', related='functional_tool_name_id.rfid') rfid = fields.Char('rfid')
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id') tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组')
@api.model @api.model
def _read_group_functional_tool_type_id(self, categories, domain, order): def _read_group_functional_tool_type_id(self, categories, domain, order):
@@ -442,17 +434,17 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
计算刀具房数量、线边刀库数量、机内刀库数量 计算刀具房数量、线边刀库数量、机内刀库数量
""" """
if tool: if tool:
tool.sudo().tool_stock_num = 0 tool.tool_stock_num = 0
tool.sudo().side_shelf_num = 0 tool.side_shelf_num = 0
tool.sudo().on_tool_stock_num = 0 tool.on_tool_stock_num = 0
if tool.sf_functional_cutting_tool_entity_ids: if tool.sf_functional_cutting_tool_entity_ids:
for cutting_tool in tool.sf_functional_cutting_tool_entity_ids: for cutting_tool in tool.sf_functional_cutting_tool_entity_ids:
if cutting_tool.tool_room_num > 0: if cutting_tool.tool_room_num > 0:
tool.sudo().tool_stock_num += 1 tool.tool_stock_num += 1
elif cutting_tool.line_edge_knife_library_num > 0: elif cutting_tool.line_edge_knife_library_num > 0:
tool.sudo().side_shelf_num += 1 tool.side_shelf_num += 1
elif cutting_tool.machine_knife_library_num > 0: elif cutting_tool.machine_knife_library_num > 0:
tool.sudo().on_tool_stock_num += 1 tool.on_tool_stock_num += 1
def create_or_edit_safety_stock(self, vals, sf_functional_cutting_tool_entity_ids): def create_or_edit_safety_stock(self, vals, sf_functional_cutting_tool_entity_ids):
""" """
@@ -479,6 +471,14 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
records = super(RealTimeDistributionOfFunctionalTools, self).create(vals_list) records = super(RealTimeDistributionOfFunctionalTools, self).create(vals_list)
return records return records
def write(self, vals):
res = super().write(vals)
for item in self:
if item:
if vals.get('min_stock_num') or vals.get('max_stock_num'):
item.enroll_functional_tool_real_time_distribution()
return res
class MachineTableToolChangingApply(models.Model): class MachineTableToolChangingApply(models.Model):
_name = 'sf.machine.table.tool.changing.apply' _name = 'sf.machine.table.tool.changing.apply'

View File

@@ -0,0 +1,82 @@
import json
import base64
import requests
from odoo import models, api
from odoo.addons.sf_base.commons.common import Common
from odoo.exceptions import UserError
class StockLot(models.Model):
_inherit = 'stock.lot'
_description = '夹具物料序列号注册'
def enroll_fixture_material_stock(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)
str_url = sf_sync_config['sf_url'] + "/api/fixture_material_stock/create"
objs_all = self.env['stock.lot'].search([('id', '=', self.id)])
fixture_material_stock_list = []
if objs_all:
for item in objs_all:
val = {
'name': item.name,
'tool_material_status': item.tool_material_status,
'location': [] if not item.quant_ids else item.quant_ids[-1].location_id.name,
'fixture_material_search_id': item.fixture_material_search_id.id,
}
fixture_material_stock_list.append(val)
kw = json.dumps(fixture_material_stock_list, ensure_ascii=False)
r = requests.post(str_url, json={}, data={'kw': kw, 'token': token}, headers=headers)
ret = r.json()
if ret.get('code') == 200:
return '夹具物料序列号注册成功'
else:
raise UserError("没有注册夹具物料序列号信息")
class FixtureMaterialSearch(models.Model):
_inherit = 'sf.fixture.material.search'
_description = '夹具物料搜索注册'
crea_url = "/api/fixture_material/create"
def enroll_fixture_material(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)
str_url = sf_sync_config['sf_url'] + self.crea_url
objs_all = self.search([('id', '=', self.id)])
fixture_material_list = []
if objs_all:
for obj in objs_all:
val = {
'name': obj.name,
'id': obj.id,
'fixture_material_code': obj.fixture_material_id.code,
'fixture_model_code': obj.fixture_model_id.code,
'specification_name': obj.specification_fixture_id.name,
'image': '' if not obj.image else base64.b64encode(obj.image).decode('utf-8'),
'number': obj.number,
'usable_num': obj.usable_num,
'have_been_used_num': obj.have_been_used_num,
'scrap_num': obj.scrap_num
}
fixture_material_list.append(val)
kw = json.dumps(fixture_material_list, ensure_ascii=False)
r = requests.post(str_url, json={}, data={'kw': kw, 'token': token}, headers=headers)
ret = r.json()
if ret.get('code') == 200:
return '夹具物料注册成功'
else:
raise UserError("没有注册夹具物料信息")
@api.model_create_multi
def create(self, vals_list):
records = super(FixtureMaterialSearch, self).create(vals_list)
for record in records:
if record:
record.enroll_fixture_material()
return records

View File

@@ -0,0 +1,55 @@
from odoo import models, fields, api, SUPERUSER_ID
class FixtureMaterialSearch(models.Model):
_name = 'sf.fixture.material.search'
_description = '夹具物料搜索'
product_id = fields.Many2one('product.product', string='夹具物料产品')
name = fields.Char('名称', related='product_id.name')
code = fields.Char('编码')
fixture_material_id = fields.Many2one('sf.fixture.material', '夹具物料',
related='product_id.fixture_material_id',
store=True,
group_expand='_read_group_fixture_material_id')
fixture_material_name = fields.Char('物料名称', related='product_id.fixture_material_id.name')
fixture_model_id = fields.Many2one('sf.fixture.model', '夹具型号',
related='product_id.fixture_model_id')
specification_fixture_id = fields.Many2one('sf.fixture.materials.basic.parameters', '规格',
related='product_id.specification_fixture_id')
image = fields.Binary('图片', related='product_id.image_1920')
number = fields.Integer('总数量', compute='_compute_number')
usable_num = fields.Integer('可用数量', compute='_compute_number')
have_been_used_num = fields.Integer('在用数量', compute='_compute_number')
scrap_num = fields.Integer('报废数量', compute='_compute_number')
barcode_ids = fields.One2many('stock.lot', 'fixture_material_search_id', string='序列号', readonly=True)
@api.depends('barcode_ids')
def _compute_number(self):
for record in self:
usable_num = 0
have_been_used_num = 0
scrap_num = 0
if record.barcode_ids:
record.number = len(record.barcode_ids)
for barcode_id in record.barcode_ids:
if barcode_id.quant_ids:
if barcode_id.quant_ids[-1].location_id.name not in '夹具房':
have_been_used_num = have_been_used_num + 1
else:
usable_num = usable_num + 1
record.usable_num = usable_num
record.have_been_used_num = have_been_used_num
record.scrap_num = scrap_num
else:
record.number = 0
record.usable_num = 0
record.have_been_used_num = 0
record.scrap_num = 0
@api.model
def _read_group_fixture_material_id(self, categories, domain, order):
fixture_material_id = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
return categories.browse(fixture_material_id)

View File

@@ -0,0 +1,364 @@
import json
import base64
import requests
from odoo import models, api
from odoo.addons.sf_base.commons.common import Common
from odoo.exceptions import UserError
def get_suitable_machining_method_names(item):
suitable_machining_method_names = []
for suitable_machining_method_id in item.suitable_machining_method_ids:
if suitable_machining_method_id:
suitable_machining_method_names.append(suitable_machining_method_id.name)
return suitable_machining_method_names
def get_cutting_direction_names(item):
cutting_direction_names = []
for cutting_direction_id in item.cutting_direction_ids:
if cutting_direction_id:
cutting_direction_names.append(cutting_direction_id.name)
return cutting_direction_names
def get_suitable_coolant_names(item):
suitable_coolant_names = []
for suitable_coolant_id in item.suitable_coolant_ids:
if suitable_coolant_id:
suitable_coolant_names.append(suitable_coolant_id.name)
return suitable_coolant_names
class StockLot(models.Model):
_inherit = 'stock.lot'
_description = '刀具物料序列号注册'
def enroll_tool_material_stock(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)
str_url = sf_sync_config['sf_url'] + "/api/tool_material_stock/create"
objs_all = self.env['stock.lot'].search([('id', '=', self.id)])
tool_material_stock_list = []
if objs_all:
for item in objs_all:
val = {
'name': item.name,
'tool_material_status': item.tool_material_status,
'location': [] if not item.quant_ids else item.quant_ids[-1].location_id.name,
'tool_material_search_id': item.tool_material_search_id.id,
}
tool_material_stock_list.append(val)
kw = json.dumps(tool_material_stock_list, ensure_ascii=False)
r = requests.post(str_url, json={}, data={'kw': kw, 'token': token}, headers=headers)
ret = r.json()
if ret.get('code') == 200:
return '刀具物料序列号注册成功'
else:
raise UserError("没有注册刀具物料序列号信息")
class ToolMaterial(models.Model):
_inherit = 'sf.tool.material.search'
_description = '刀具物料注册'
crea_url = '/api/tool_material/create'
def enroll_tool_material(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)
str_url = sf_sync_config['sf_url'] + self.crea_url
objs_all = self.search([('id', '=', self.id)])
tool_material_list = []
if objs_all:
for item in objs_all:
val = {
'name': item.name,
'id': item.id,
'cutting_tool_material_code': item.cutting_tool_material_id.code,
'cutting_tool_standard_library_code': item.cutting_tool_standard_library_id.code,
'specification_name': item.specification_id.name,
'image': '' if not item.image else base64.b64encode(item.image).decode('utf-8'),
'number': item.number,
'usable_num': item.usable_num,
'have_been_used_num': item.have_been_used_num,
'scrap_num': item.scrap_num
}
tool_material_list.append(val)
kw = json.dumps(tool_material_list, ensure_ascii=False)
r = requests.post(str_url, json={}, data={'kw': kw, 'token': token}, headers=headers)
ret = r.json()
if ret.get('code') == 200:
return '刀具物料注册成功'
else:
raise UserError("没有注册刀具物料信息")
@api.model_create_multi
def create(self, vals_list):
records = super(ToolMaterial, self).create(vals_list)
for record in records:
if record:
record.enroll_tool_material()
return records
class FunctionalCuttingToolEntity(models.Model):
_inherit = 'sf.functional.cutting.tool.entity'
_description = '功能刀具列表注册'
crea_url = "/api/functional_tool_entity/create"
# 注册同步功能刀具列表
def enroll_functional_tool_entity(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)
str_url = sf_sync_config['sf_url'] + self.crea_url
objs_all = self.env['sf.functional.cutting.tool.entity'].search([('id', '=', self.id)])
functional_tool_list = []
if objs_all:
for item in objs_all:
val = {
'id': item.id,
'code': item.code,
'name': item.name,
'rfid': item.rfid,
'tool_groups_name': item.tool_groups_id.name,
'barcode': item.barcode_id.name,
'cutting_tool_type_code': item.sf_cutting_tool_type_id.code,
'functional_tool_diameter': item.functional_tool_diameter,
'knife_tip_r_angle': item.knife_tip_r_angle,
'coarse_middle_thin': item.coarse_middle_thin,
'new_former': item.new_former,
'tool_loading_length': item.tool_loading_length,
'functional_tool_length': item.functional_tool_length,
'effective_length': item.effective_length,
'max_lifetime_value': item.max_lifetime_value,
'alarm_value': item.alarm_value,
'used_value': item.used_value,
'functional_tool_status': item.functional_tool_status,
'current_location': item.current_location,
'image': '' if not item.image else base64.b64encode(item.image).decode('utf-8'),
'whether_standard_knife': item.whether_standard_knife,
'L_D_number': item.L_D_number,
'hiding_length': item.hiding_length,
'cut_time': item.cut_time,
'cut_length': item.cut_length,
'cut_number': item.cut_number,
'cutting_tool_integral_model_id': item.cutting_tool_integral_model_id.tool_material_id,
'cutting_tool_blade_model_id': item.cutting_tool_blade_model_id.tool_material_id,
'cutting_tool_cutterbar_model_id': item.cutting_tool_cutterbar_model_id.tool_material_id,
'cutting_tool_cutterpad_model_id': item.cutting_tool_cutterpad_model_id.tool_material_id,
'cutting_tool_cutterhandle_model_id': item.cutting_tool_cutterhandle_model_id.tool_material_id,
'cutting_tool_cutterhead_model_id': item.cutting_tool_cutterhead_model_id.tool_material_id,
'suitable_machining_method_names': get_suitable_machining_method_names(item),
'blade_tip_characteristics_name': item.blade_tip_characteristics_id.name,
'handle_type_name': item.handle_type_id.name,
'cutting_direction_names': get_cutting_direction_names(item),
'suitable_coolant_names': get_suitable_coolant_names(item),
'active': item.active,
}
functional_tool_list.append(val)
kw = json.dumps(functional_tool_list, ensure_ascii=False)
r = requests.post(str_url, json={}, data={'kw': kw, 'token': token}, headers=headers)
ret = r.json()
if ret.get('code') == 200:
return "功能刀具注册成功"
else:
raise UserError("没有注册功能刀具信息")
@api.model_create_multi
def create(self, vals_list):
records = super(FunctionalCuttingToolEntity, self).create(vals_list)
for record in records:
if record:
record.enroll_functional_tool_entity()
return records
def write(self, vals):
res = super().write(vals)
if vals.get('current_location'):
self.enroll_functional_tool_entity()
return res
class FunctionalToolWarning(models.Model):
_inherit = 'sf.functional.tool.warning'
_description = '功能刀具预警注册'
crea_url = "/api/functional_tool_warning/create"
# 注册同步功能刀具预警
def enroll_functional_tool_warning(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)
str_url = sf_sync_config['sf_url'] + self.crea_url
objs_all = self.env['sf.functional.tool.warning'].search([('id', '=', self.id)])
tool_warning_list = []
if objs_all:
for item in objs_all:
val = {
'id': item.id,
'name': item.name,
'code': item.code,
'rfid': item.rfid,
'tool_groups_name': item.tool_groups_id.name,
'production_line': item.production_line_id.name,
'machine_tool_id': item.maintenance_equipment_id.code,
'machine_tool_code': item.machine_tool_code,
'cutter_spacing_code': item.cutter_spacing_code_id.code,
'functional_tool_name': item.name,
'barcode': item.barcode_id.name,
'mrs_cutting_tool_type_code': item.mrs_cutting_tool_type_id.code,
'diameter': item.diameter,
'knife_tip_r_angle': item.knife_tip_r_angle,
'install_tool_time': item.install_tool_time.strftime('%Y-%m-%d %H:%M:%S'),
'on_board_time': item.on_board_time.strftime('%Y-%m-%d %H:%M:%S'),
'max_lifetime_value': item.max_lifetime_value,
'alarm_value': item.alarm_value,
'used_value': item.used_value,
'functional_tool_status': item.functional_tool_status,
'alarm_time': item.alarm_time.strftime('%Y-%m-%d %H:%M:%S'),
'dispose_user': item.dispose_user,
'dispose_time': item.dispose_time,
'dispose_func': item.dispose_func,
}
tool_warning_list.append(val)
kw = json.dumps(tool_warning_list, ensure_ascii=False)
r = requests.post(str_url, json={}, data={'kw': kw, 'token': token}, headers=headers)
ret = r.json()
if ret.get('code') == 200:
return "功能刀具预警注册成功"
else:
raise UserError("没有注册功能刀具预警信息")
@api.model_create_multi
def create(self, vals_list):
records = super(FunctionalToolWarning, self).create(vals_list)
for record in records:
if record:
record.enroll_functional_tool_warning()
return records
class StockMoveLine(models.Model):
_inherit = 'stock.move.line'
_description = '功能刀具出入库记录注册'
crea_url = "/api/functional_tool_move/create"
# 注册同步功能刀具出入库记录
def enroll_functional_tool_move(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)
str_url = sf_sync_config['sf_url'] + self.crea_url
objs_all = self.env['stock.move.line'].search([('id', '=', self.id), ('functional_tool_name_id', '!=', False)])
tool_stock_list = []
if objs_all:
for item in objs_all:
val = {
'id': item.id,
'name': item.functional_tool_name,
'code': item.code,
'rfid': item.rfid,
'tool_groups_name': item.tool_groups_id.name,
'reference': item.reference,
'barcode': item.lot_id.name,
'functional_tool_type_code': item.functional_tool_type_id.code,
'diameter': item.diameter,
'knife_tip_r_angle': item.knife_tip_r_angle,
'install_tool_time': item.install_tool_time.strftime('%Y-%m-%d %H:%M:%S'),
'location_id': item.location_id.name,
'location_dest_name': item.location_dest_id.name,
'date': item.date.strftime('%Y-%m-%d %H:%M:%S'),
'qty_done': item.qty_done,
}
tool_stock_list.append(val)
kw = json.dumps(tool_stock_list, ensure_ascii=False)
r = requests.post(str_url, json={}, data={'kw': kw, 'token': token}, headers=headers)
ret = r.json()
if ret.get('code') == 200:
return "功能刀具出入库记录注册成功"
else:
raise UserError("没有注册功能刀具出入库记录信息")
@api.model_create_multi
def create(self, vals_list):
records = super(StockMoveLine, self).create(vals_list)
for record in records:
if record.functional_tool_name_id:
record.enroll_functional_tool_move()
return records
class RealTimeDistributionFunctionalTools(models.Model):
_inherit = 'sf.real.time.distribution.of.functional.tools'
_description = '功能刀具安全库存注册'
crea_url = "/api/functional_tool_distribution/create"
# 注册同步功能刀具预警
def enroll_functional_tool_real_time_distribution(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)
str_url = sf_sync_config['sf_url'] + self.crea_url
objs_all = self.env['sf.real.time.distribution.of.functional.tools'].search([('id', '=', self.id)])
tool_distribution_list = []
if objs_all:
for item in objs_all:
functional_tool_codes = []
for obj in item.sf_functional_cutting_tool_entity_ids:
functional_tool_codes.append(obj.code)
val = {
'id': item.id,
'name': item.name,
'tool_groups_name': item.tool_groups_id.name,
'cutting_tool_type_code': item.sf_cutting_tool_type_id.code,
'diameter': item.diameter,
'knife_tip_r_angle': item.knife_tip_r_angle,
'tool_stock_num': item.tool_stock_num,
'side_shelf_num': item.side_shelf_num,
'on_tool_stock_num': item.on_tool_stock_num,
'tool_stock_total': item.tool_stock_total,
'min_stock_num': item.min_stock_num,
'max_stock_num': item.max_stock_num,
'batch_replenishment_num': item.batch_replenishment_num,
'unit': item.unit,
'image': '' if not item.image else base64.b64encode(item.image).decode('utf-8'),
'functional_tool_codes': str(functional_tool_codes),
'coarse_middle_thin': item.coarse_middle_thin,
'whether_standard_knife': item.whether_standard_knife,
'suitable_machining_method_names': get_suitable_machining_method_names(item),
'blade_tip_characteristics_name': item.blade_tip_characteristics_id.name,
'handle_type_name': item.handle_type_id.name,
'cutting_direction_names': get_cutting_direction_names(item),
'suitable_coolant_names': get_suitable_coolant_names(item),
'active': item.active
}
tool_distribution_list.append(val)
kw = json.dumps(tool_distribution_list, ensure_ascii=False)
r = requests.post(str_url, json={}, data={'kw': kw, 'token': token}, headers=headers)
ret = r.json()
if ret.get('code') == 200:
return "功能刀具出入库记录注册成功"
else:
raise UserError("没有注册功能刀具出入库记录信息")
@api.model_create_multi
def create(self, vals_list):
records = super(RealTimeDistributionFunctionalTools, self).create(vals_list)
for record in records:
if record:
record.enroll_functional_tool_real_time_distribution()
return records

View File

@@ -97,17 +97,29 @@ class StockLot(models.Model):
_inherit = 'stock.lot' _inherit = 'stock.lot'
tool_material_search_id = fields.Many2one('sf.tool.material.search', string='刀具物料搜索') tool_material_search_id = fields.Many2one('sf.tool.material.search', string='刀具物料搜索')
tool_material_status = fields.Selection([('可用', '可用'), ('在用', '在用'), ('报废', '报废')], string='状态', fixture_material_search_id = fields.Many2one('sf.fixture.material.search', string='夹具物料搜索')
compute='_compute_tool_material_status') tool_material_status = fields.Selection(
[('未入库', '未入库'), ('可用', '可用'), ('在用', '在用'), ('报废', '报废')], string='状态',
compute='_compute_tool_material_status', store=True)
@api.depends('quant_ids') @api.depends('quant_ids')
def _compute_tool_material_status(self): def _compute_tool_material_status(self):
for record in self: for record in self:
if record: if record:
if record.quant_ids[-1].location_id.name == '刀具组装位置': if record.product_id.categ_id.name in ['刀具', '夹具']:
record.tool_material_status = '在用' if record.quant_ids:
else: if record.quant_ids[-1].location_id.name in ['刀具房', '夹具房']:
record.tool_material_status = '可用' record.tool_material_status = '可用'
elif record.quant_ids[-1].location_id.name == '刀具组装位置':
record.tool_material_status = '在用'
else:
record.tool_material_status = '未入库'
if record.tool_material_search_id:
# 注册刀具物料状态到cloud平台
record.enroll_tool_material_stock()
elif record.fixture_material_search_id:
# 注册夹具物料状态到cloud平台
record.enroll_fixture_material_stock()
@api.model @api.model
def name_search(self, name='', args=None, operator='ilike', limit=100): def name_search(self, name='', args=None, operator='ilike', limit=100):
@@ -136,23 +148,37 @@ class StockLot(models.Model):
for record in records: for record in records:
if record.product_id.categ_id.name == '刀具': if record.product_id.categ_id.name == '刀具':
tool_material_search = self.env['sf.tool.material.search'].sudo().search( tool_material_search = self.env['sf.tool.material.search'].sudo().search(
[('cutting_tool_material_id', '=', record.product_id.cutting_tool_material_id.id), [('id', '=', record.product_id.tool_material_id)])
('cutting_tool_standard_library_id', '=', record.product_id.cutting_tool_model_id.id),
('specification_id', '=', record.product_id.specification_id.id)])
if tool_material_search: if tool_material_search:
record.tool_material_search_id = tool_material_search record.tool_material_status = '未入库'
record.tool_material_search_id = tool_material_search.id
elif record.product_id.categ_id.name == '夹具':
fixture_material_search = self.env['sf.fixture.material.search'].sudo().search(
[('id', '=', record.product_id.fixture_material_search_id)])
if fixture_material_search:
record.tool_material_status = '未入库'
record.fixture_material_search_id = fixture_material_search.id
return records return records
class ProductProduct(models.Model): class ProductProduct(models.Model):
_inherit = 'product.product' _inherit = 'product.product'
tool_material_id = fields.Char('刀具物料搜索模型ID')
fixture_material_search_id = fields.Char('夹具物料搜索模型ID')
@api.model_create_multi @api.model_create_multi
def create(self, vals_list): def create(self, vals_list):
records = super(ProductProduct, self).create(vals_list) records = super(ProductProduct, self).create(vals_list)
for record in records: for record in records:
if record.categ_id.name == '刀具': if record.categ_id.name == '刀具':
self.env['sf.tool.material.search'].sudo().create({ tool_material = self.env['sf.tool.material.search'].sudo().create({
'product_id': record.id 'product_id': record.id
}) })
record.tool_material_id = tool_material.id
elif record.categ_id.name == '夹具':
fixture_material = self.env['sf.fixture.material.search'].sudo().create({
'product_id': record.id
})
record.fixture_material_search_id = fixture_material.id
return records return records

View File

@@ -2,308 +2,6 @@
from odoo import fields, models, api, SUPERUSER_ID from odoo import fields, models, api, SUPERUSER_ID
# from odoo.exceptions import ValidationError
# 刀具物料搜索(待删除)
class SfToolMaterialSearch(models.Model):
_name = 'sf.tool.material.search'
_description = '刀具物料搜索'
sequence = fields.Integer('序号')
code = fields.Char('编码')
name = fields.Char('名称', required=True)
# 关联刀具类型
mrs_cutting_tool_type_id = fields.Many2one(
'sf.cutting.tool.type', '刀具类型',
domain="[('cutting_tool_material_id.name', '=', cutting_tool_material_name)]", required=True)
# 关联刀具物料名称
mrs_cutting_tool_material_name = fields.Char(related='mrs_cutting_tool_material_id.name', string='刀具物料名称',
store=True)
cutting_tool_type = fields.Char(related='mrs_cutting_tool_material_id.name', string='刀具物料类型', store=True)
mrs_machine_brand_id = fields.Many2one('sf.machine.brand', '品牌', required=True,
domain="[('tag_ids.name', 'ilike', '刀具')]")
# 关联刀具型号
# mrs_cutting_tool_model_id = fields.Many2one('sf.cutting.tool.model', '刀具型号')
# 关联刀具物料模型
mrs_cutting_tool_material_id = fields.Many2one('sf.cutting.tool.material', '刀具物料',
group_expand='_read_group_mrs_cutting_tool_material_ids',
required=True)
cutting_tool_material_name = fields.Char(string='物料名称', invisible=True)
@api.onchange('mrs_cutting_tool_material_id')
def _onchange_mrs_cutting_tool_material_id(self):
for record in self:
if record:
record.cutting_tool_material_name = record.mrs_cutting_tool_material_id.name
@api.model
def _read_group_mrs_cutting_tool_material_ids(self, categories, domain, order):
mrs_cutting_tool_material_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
return categories.browse(mrs_cutting_tool_material_ids)
# 刀片特有字段
blade_code = fields.Char('刀片编码', readonly=True)
blade_length = fields.Float('刀片长度L(mm)')
blade_width = fields.Float('刀片宽度D(mm)')
blade_height = fields.Float('刀片高度T(mm)')
blade_top_angle = fields.Float('刀片顶角(°)')
blade_front_angle = fields.Float('刀片前角(°)')
blade_rear_angle = fields.Float('刀片后角(°)')
blade_main_included_angle = fields.Float('刀片主偏角(°)')
blade_r_angle = fields.Float('刀片R角(°)')
blade_hardness = fields.Integer('刀片加工硬度')
blade_accuracy = fields.Char('刀片精度等级')
blade_coating_material_id = fields.Char('刀片涂层材质')
blade_radius = fields.Float('刀片刀尖半径(mm)')
blade_nut = fields.Float('刀片配对螺母(mm)')
mrs_cutting_tool_model_blade_cutter_bar_ids = fields.Many2many(
'sf.cutting_tool.standard.library',
relation='sf_tool_material_search_blade_cutter_bar_rel',
column1='model_id_1',
column2='model_id_2',
domain="[('cutting_tool_type', '=', '刀杆')]",
string='适用刀杆型号',
default=lambda self: [], # 使用空列表作为默认值
)
mrs_cutting_tool_model_blade_cutter_pad_ids = fields.Many2many(
'sf.cutting_tool.standard.library',
relation='sf_tool_material_search_blade_cutter_pad_rel',
column1='model_id_1',
column2='model_id_2',
domain="[('cutting_tool_type', '=', '刀盘')]",
string='适用刀盘型号',
default=lambda self: [], # 使用空列表作为默认值
)
# 整体式刀具特有字段
integral_code = fields.Char('整体式刀具编码', readonly=True)
integral_total_length = fields.Float('整体式刀具总长度(mm)', digits=(6, 1))
integral_shank_length = fields.Float('整体式刀具柄部长度(mm)', digits=(6, 1))
integral_blade_length = fields.Float('整体式刀具刃部长度(mm)', digits=(6, 1))
integral_neck_length = fields.Float('整体式刀具颈部长度(mm)', digits=(6, 1))
integral_shank_diameter = fields.Float('整体式刀具柄部直径(mm)', digits=(6, 1))
integral_blade_diameter = fields.Float('整体式刀具刃部直径(mm)', digits=(6, 1))
integral_neck_diameter = fields.Float('整体式刀具颈部直径(mm)', digits=(6, 1))
integral_blade_number = fields.Integer('整体式刀具刃数(个)')
integral_blade_tip_diameter = fields.Float('整体式刀具刀尖直径(mm)', digits=(6, 1))
integral_blade_tip_taper = fields.Float('整体式刀具刀尖锥度(°)', digits=(6, 1))
integral_blade_helix_angle = fields.Float('整体式刀具刃部螺旋角(°)', digits=(6, 1))
integral_blade_type = fields.Char('整体式刀具刃部类型')
integral_coarse_medium_fine = fields.Selection([('', ''), ('', ''), ('', '')], '整体式刀具粗/中/精')
# integral_blade_material = fields.Selection([('碳素钢', '碳素钢'), ('硬质合金', '硬质合金')], '整体式刀具刀具材质')
integral_hardness = fields.Integer('整体式刀具硬度(HRC)')
integral_coating_material = fields.Char('整体式刀具涂层材质')
integral_run_out_accuracy_max = fields.Float('整体式刀具端跳精度max', digits=(6, 1))
integral_run_out_accuracy_min = fields.Float('整体式刀具端跳精度min', digits=(6, 1))
suitable_machining_method_ids = fields.Many2many('maintenance.equipment.image',
'rel_machining_product_template_material_search', '适合加工方式',
domain=[('type', '=', '加工能力')])
blade_tip_characteristics_id = fields.Many2one('maintenance.equipment.image', '刀尖特征',
domain=[('type', '=', '刀尖特征')])
handle_type_id = fields.Many2one('maintenance.equipment.image', '柄部类型', domain=[('type', '=', '柄部类型')])
cutting_direction_ids = fields.Many2many('maintenance.equipment.image',
'rel_cutting_product_template_material_search', '走刀方向',
domain=[('type', '=', '走刀方向')])
suitable_coolant_ids = fields.Many2many('maintenance.equipment.image',
'rel_coolants_product_template_material_search', '适合冷却方式',
domain=[('type', '=', '冷却方式')])
cutting_speed_ids = fields.Many2many('sf.cutting.speed', string='切削速度Vc')
feed_per_tooth_ids = fields.Many2many('sf.feed.per.tooth', 'rel_feed_per_tooth_ids', '每齿走刀量fz')
# @api.constrains('suitable_machining_method_ids')
# def _check_suitable_machining_method_ids(self):
# for record in self:
# if len(record.suitable_machining_method_ids) == 0 and self.cutting_tool_type == '整体式刀具':
# raise ValidationError("适合加工方式不能为空!")
#
# @api.constrains('blade_tip_characteristics_ids')
# def _check_blade_tip_characteristics_ids(self):
# for record in self:
# if len(record.blade_tip_characteristics_ids) == 0 and self.cutting_tool_type == '整体式刀具':
# raise ValidationError("刀尖特征不能为空!")
# if len(record.blade_tip_characteristics_ids) > 1 and self.cutting_tool_type == '整体式刀具':
# raise ValidationError("刀尖特征只能单选!")
#
# @api.constrains('handle_type_ids')
# def _check_handle_type_ids(self):
# for record in self:
# if len(record.handle_type_ids) == 0 and self.cutting_tool_type == '整体式刀具':
# raise ValidationError("柄部类型不能为空!")
# if len(record.handle_type_ids) > 1 and self.cutting_tool_type == '整体式刀具':
# raise ValidationError("柄部类型只能单选!")
#
# @api.constrains('cutting_direction_ids')
# def _check_cutting_direction_ids(self):
# for record in self:
# if len(record.cutting_direction_ids) == 0 and self.cutting_tool_type == '整体式刀具':
# raise ValidationError("走刀方向不能为空!")
#
# @api.constrains('suitable_coolant_ids')
# def _check_suitable_coolant_ids(self):
# for record in self:
# if not record.suitable_coolant_ids and self.cutting_tool_type == '整体式刀具':
# raise ValidationError("适合冷却液不能为空!")
#
# @api.constrains('integral_total_length')
# def _check_integral_total_length(self):
# if self.integral_total_length <= 0 and self.cutting_tool_type == '整体式刀具':
# raise ValidationError("总长度不能为0")
#
# @api.constrains('integral_shank_length')
# def _check_integral_shank_length(self):
# if self.integral_shank_length <= 0 and self.cutting_tool_type == '整体式刀具':
# raise ValidationError("柄部长度不能为0")
#
# @api.constrains('integral_blade_length')
# def _check_integral_blade_length(self):
# if self.integral_blade_length <= 0 and self.cutting_tool_type == '整体式刀具':
# raise ValidationError("刃部长度不能为0")
#
# @api.constrains('integral_blade_number')
# def _check_integral_blade_number(self):
# if self.integral_blade_number <= 0 and self.cutting_tool_type == '整体式刀具':
# raise ValidationError("刃数不能为0")
#
# @api.constrains('integral_shank_diameter')
# def _check_integral_shank_diameter(self):
# if self.integral_shank_diameter <= 0 and self.cutting_tool_type == '整体式刀具':
# raise ValidationError("柄部直径不能为0")
#
# @api.constrains('integral_blade_diameter')
# def _check_integral_blade_diameter(self):
# if self.integral_blade_diameter <= 0 and self.cutting_tool_type == '整体式刀具':
# raise ValidationError("刃部直径不能为0")
#
# @api.constrains('integral_run_out_accuracy_min')
# def _check_integral_blade_diameter(self):
# if self.integral_run_out_accuracy_min <= 0 and self.cutting_tool_type == '整体式刀具':
# raise ValidationError("端跳精度最小(min)不能为0")
#
# @api.constrains('integral_run_out_accuracy_max')
# def _check_integral_run_out_accuracy_max(self):
# if self.integral_run_out_accuracy_max <= 0 and self.cutting_tool_type == '整体式刀具':
# raise ValidationError("端跳精度最大(max)不能为0")
# integral_front_angle = fields.Float('整体式刀具前角(°)')
# integral_rear_angle = fields.Float('整体式刀具后角(°)')
# integral_main_included_angle = fields.Float('整体式刀具主偏角(°)')
# integral_accuracy = fields.Float('整体式刀具精度等级')
# integral_hardness = fields.Float('整体式刀具加工硬度(HRC)')
# integral_coating_material = fields.Char('整体式刀具涂层材质')
# integral_nut = fields.Float('整体式刀具配对螺母(mm)')
# integral_scope = fields.Char('整体式刀具适用范围')
# 刀杆特有字段
bar_code = fields.Char('刀杆编码', readonly=True)
# bar_name = fields.Char('刀杆名称', required=True)
bar_c_diameter = fields.Float('刀杆C柄径(mm)')
bar_total_length = fields.Float('刀杆L总长(mm)')
bar_blade_number = fields.Integer('刀杆刃数')
bar_d_diameter = fields.Float('刀杆D刃径(mm)')
mrs_cutting_tool_model_bar_blade_ids = fields.Many2many(
'sf.cutting_tool.standard.library',
relation='sf_tool_material_search_bar_blade_rel',
column1='model_id_1',
column2='model_id_2',
domain="[('cutting_tool_type', '=', '刀片')]",
string='刀杆适用刀片型号'
)
bar_wrench = fields.Float('刀杆配对扳手(mm)')
bar_screw = fields.Float('刀杆配备螺丝(mm)')
bar_radius = fields.Float('刀杆刀尖圆角半径')
bar_accuracy = fields.Char('刀杆精度等级')
bar_hardness = fields.Integer('刀杆硬度(°)')
bar_scope = fields.Char('刀杆适用范围')
# 刀盘特有字段
pad_code = fields.Char('刀盘编码', readonly=True)
# pad_name = fields.Char('刀盘名称', required=True)
pad_c_diameter = fields.Float('刀盘C柄径(mm)')
pad_total_length = fields.Float('刀盘L总长(mm)')
pad_blade_number = fields.Integer('刀盘刃数')
pad_d_diameter = fields.Float('刀盘D刃径(mm)')
mrs_cutting_tool_model_pad_blade_ids = fields.Many2many(
'sf.cutting_tool.standard.library',
relation='sf_tool_material_search_pad_blade_rel',
column1='model_id_1',
column2='model_id_2',
domain="[('cutting_tool_type', '=', '刀片')]",
string='刀盘适用刀片型号'
)
pad_wrench = fields.Float('刀盘配对扳手(mm)')
pad_screw = fields.Float('刀盘配备螺丝(mm)')
pad_radius = fields.Float('刀盘刀尖圆角半径')
pad_accuracy = fields.Char('刀盘精度等级')
pad_hardness = fields.Integer('刀盘硬度(°)')
pad_scope = fields.Char('刀盘适用范围')
# 刀柄特有字段
handle_code = fields.Char('刀柄编码', readonly=True)
# 柄长L(mm)、法兰柄长L1(mm)、法兰直径D1(mm)
handle_length = fields.Float('刀柄柄长L(mm)')
handle_diameter = fields.Float('刀柄直径D(mm)')
handle_flange_length = fields.Float('刀柄法兰柄长L1(mm)')
handle_flange_diameter = fields.Float('刀柄法兰直径D1(mm)')
# 夹持直径min、夹持直径max、径跳精度、最大转速n/min、3D模型图
handle_clamping_diameter_min = fields.Float('刀柄夹持直径min')
handle_clamping_diameter_max = fields.Float('刀柄夹持直径max')
handle_jump_accuracy = fields.Float('刀柄径跳精度')
handle_max_speed = fields.Float('刀柄最大转速n/min')
handle_weight = fields.Float('刀柄重量(kg)')
handle_body_accuracy = fields.Float('刀柄本体精度(mm)')
handle_nut = fields.Float('刀柄配对螺母(mm)')
mrs_cutting_tool_model_handle_chuck_model_ids = fields.Many2many(
'sf.cutting_tool.standard.library',
relation='sf_tool_material_search_handle_chuck_rel',
column1='model_id_1',
column2='model_id_2',
domain="[('cutting_tool_type', '=', '夹头')]",
string='适用夹头型号'
)
handle_clamping_range = fields.Float('刀柄夹持范围(mm)')
handle_detection_accuracy = fields.Float('刀柄检测精度')
handle_detection_hardness = fields.Integer('刀柄检测硬度')
handle_standard_speed = fields.Float('刀柄标准转速')
# 夹头特有字段
chuck_code = fields.Char('夹头编码', readonly=True)
# chuck_name = fields.Char('夹头名称', required=True)
chuck_accuracy = fields.Float('夹头精度(mm)')
# 夹持直径min、夹持直径max、3D模型图
chuck_clamping_diameter_min = fields.Float('夹头夹持直径min(mm)')
chuck_clamping_diameter_max = fields.Float('夹头夹持直径max(mm)')
chuck_diameter = fields.Float('夹头外径(mm)')
chuck_inner_diameter = fields.Float('夹头内径(mm)')
chuck_height = fields.Float('夹头高度(mm)')
chuck_nut = fields.Float('夹头配对螺母(mm)')
mrs_cutting_tool_model_chuck_handle_model_ids = fields.Many2many(
'sf.cutting_tool.standard.library',
relation='sf_tool_material_search_chuck_handle_rel',
column1='model_id_1',
column2='model_id_2',
domain="[('cutting_tool_type', '=', '刀柄')]",
string='适用刀柄型号'
)
chuck_clamping_range = fields.Float('夹头夹持范围(mm)')
chuck_feature = fields.Char('夹头特性')
image = fields.Binary('夹头图片')
# 数量、采购入库日期、采购批次、供应商、仓库名称、库区、库位、3D模型
number = fields.Integer('数量')
mrs_materials_model_id = fields.Many2one('sf.materials.model', '材料型号')
purchase_date = fields.Date('采购入库日期')
purchase_batch = fields.Char('采购批次')
supplier = fields.Char('供应商')
warehouse_name = fields.Char('仓库名称')
warehouse_area = fields.Char('库区')
warehouse_location = fields.Char('库位')
three_d_model = fields.Many2one('ir.attachment', '3D模型')
class ToolMaterial(models.Model): class ToolMaterial(models.Model):
_name = 'sf.tool.material.search' _name = 'sf.tool.material.search'
_description = '刀具物料搜索' _description = '刀具物料搜索'
@@ -311,6 +9,7 @@ class ToolMaterial(models.Model):
product_id = fields.Many2one('product.product', string='刀具物料产品') product_id = fields.Many2one('product.product', string='刀具物料产品')
name = fields.Char('名称', related='product_id.name') name = fields.Char('名称', related='product_id.name')
code = fields.Char('编码')
cutting_tool_material_id = fields.Many2one('sf.cutting.tool.material', '刀具物料', cutting_tool_material_id = fields.Many2one('sf.cutting.tool.material', '刀具物料',
related='product_id.cutting_tool_material_id', related='product_id.cutting_tool_material_id',
store=True, store=True,
@@ -328,8 +27,6 @@ class ToolMaterial(models.Model):
barcode_ids = fields.One2many('stock.lot', 'tool_material_search_id', string='序列号', readonly=True) barcode_ids = fields.One2many('stock.lot', 'tool_material_search_id', string='序列号', readonly=True)
active = fields.Boolean(string='已归档', default=True)
@api.depends('barcode_ids') @api.depends('barcode_ids')
def _compute_number(self): def _compute_number(self):
for record in self: for record in self:

View File

@@ -13,6 +13,7 @@ access_sf_tool_transfer_request_information,sf.tool.transfer.request.information
access_sf_functional_tool_assembly,sf.functional.tool.assembly,model_sf_functional_tool_assembly,sf_base.group_sf_tool_user,1,1,1,0 access_sf_functional_tool_assembly,sf.functional.tool.assembly,model_sf_functional_tool_assembly,sf_base.group_sf_tool_user,1,1,1,0
access_sf_functional_tool_assembly_order,sf.functional.tool.assembly.order,model_sf_functional_tool_assembly_order,sf_base.group_sf_tool_user,1,1,1,0 access_sf_functional_tool_assembly_order,sf.functional.tool.assembly.order,model_sf_functional_tool_assembly_order,sf_base.group_sf_tool_user,1,1,1,0
access_sf_tool_material_search,sf.tool.material.search,model_sf_tool_material_search,sf_base.group_sf_tool_user,1,1,1,0 access_sf_tool_material_search,sf.tool.material.search,model_sf_tool_material_search,sf_base.group_sf_tool_user,1,1,1,0
access_sf_fixture_material_search,sf.fixture.material.search,model_sf_fixture_material_search,sf_base.group_sf_tool_user,1,1,1,0
access_sf_functional_cutting_tool_entity_group_plan_dispatch,sf.functional.cutting.tool.entity,model_sf_functional_cutting_tool_entity,sf_base.group_plan_dispatch,1,0,0,0 access_sf_functional_cutting_tool_entity_group_plan_dispatch,sf.functional.cutting.tool.entity,model_sf_functional_cutting_tool_entity,sf_base.group_plan_dispatch,1,0,0,0
@@ -29,3 +30,4 @@ access_sf_tool_transfer_request_information_group_plan_dispatch,sf.tool.transfer
access_sf_functional_tool_assembly_group_plan_dispatch,sf.functional.tool.assembly,model_sf_functional_tool_assembly,sf_base.group_plan_dispatch,1,0,0,0 access_sf_functional_tool_assembly_group_plan_dispatch,sf.functional.tool.assembly,model_sf_functional_tool_assembly,sf_base.group_plan_dispatch,1,0,0,0
access_sf_functional_tool_assembly_order_group_plan_dispatch,sf.functional.tool.assembly.order,model_sf_functional_tool_assembly_order,sf_base.group_plan_dispatch,1,0,0,0 access_sf_functional_tool_assembly_order_group_plan_dispatch,sf.functional.tool.assembly.order,model_sf_functional_tool_assembly_order,sf_base.group_plan_dispatch,1,0,0,0
access_sf_tool_material_search_group_plan_dispatch,sf.tool.material.search,model_sf_tool_material_search,sf_base.group_plan_dispatch,1,0,0,0 access_sf_tool_material_search_group_plan_dispatch,sf.tool.material.search,model_sf_tool_material_search,sf_base.group_plan_dispatch,1,0,0,0
access_sf_fixture_material_search_group_plan_dispatch,sf.fixture.material.search,model_sf_fixture_material_search,sf_base.group_plan_dispatch,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
13 access_sf_functional_tool_warning_group_plan_dispatch access_sf_functional_cutting_tool_entity_group_plan_dispatch sf.functional.tool.warning sf.functional.cutting.tool.entity model_sf_functional_tool_warning model_sf_functional_cutting_tool_entity sf_base.group_plan_dispatch 1 0 0 0
14 access_sf_real_time_distribution_of_functional_tools_group_plan_dispatch access_sf_functional_tool_warning_group_plan_dispatch sf.real.time.distribution.of.functional.tools sf.functional.tool.warning model_sf_real_time_distribution_of_functional_tools model_sf_functional_tool_warning sf_base.group_plan_dispatch 1 0 0 0
15 access_sf_cam_work_order_program_knife_plan_group_plan_dispatch access_sf_real_time_distribution_of_functional_tools_group_plan_dispatch sf.cam.work.order.program.knife.plan sf.real.time.distribution.of.functional.tools model_sf_cam_work_order_program_knife_plan model_sf_real_time_distribution_of_functional_tools sf_base.group_plan_dispatch 1 0 0 0
16 access_sf_cam_work_order_program_knife_plan_group_plan_dispatch sf.cam.work.order.program.knife.plan model_sf_cam_work_order_program_knife_plan sf_base.group_plan_dispatch 1 0 0 0
17 access_sf_machine_table_tool_changing_apply_group_plan_dispatch sf.machine.table.tool.changing.apply model_sf_machine_table_tool_changing_apply sf_base.group_plan_dispatch 1 0 0 0
18 access_sf_tool_change_requirement_information_group_plan_dispatch sf.tool.change.requirement.information model_sf_tool_change_requirement_information sf_base.group_plan_dispatch 1 0 0 0
19 access_sf_tool_transfer_request_information_group_plan_dispatch sf.tool.transfer.request.information model_sf_tool_transfer_request_information sf_base.group_plan_dispatch 1 0 0 0
30
31
32
33

View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="sf_fixture_material_search_tree" model="ir.ui.view">
<field name="name">sf.fixture.material.search.tree</field>
<field name="model">sf.fixture.material.search</field>
<field name="arch" type="xml">
<tree string="夹具物料查询" create="0">
<field name="name"/>
<field name="fixture_material_id"/>
<field name="fixture_model_id"/>
<field name="specification_fixture_id"/>
<field name="number"/>
<field name="usable_num"/>
<field name="image" type="image"/>
</tree>
</field>
</record>
<record id="sf_fixture_material_search_form" model="ir.ui.view">
<field name="name">sf.fixture.material.search.form</field>
<field name="model">sf.fixture.material.search</field>
<field name="arch" type="xml">
<form string="夹具物料查询" create="0">
<!-- <header>-->
<!-- <button string="夹具物料注册" name="enroll_fixture_material" type="object" class="btn-primary"/>-->
<!-- </header>-->
<sheet>
<div class="oe_title">
<h1>
<field name="product_id" readonly="1"/>
</h1>
</div>
<group>
<group>
<field name="name" invisible="1"/>
<field name="fixture_material_id"/>
<field name="fixture_model_id"/>
<field name="specification_fixture_id"/>
<field name="number"/>
</group>
<group>
<field name="image" type="image"/>
</group>
</group>
<group>
<group col="3">
<group>
<field name="usable_num"/>
</group>
<group>
<field name="have_been_used_num"/>
</group>
<group>
<field name="scrap_num"/>
</group>
</group>
</group>
<notebook>
<page string="序列号">
<field name="barcode_ids">
<tree create="0">
<field name="name"/>
<field name="tool_material_status"/>
<!-- <button string="序列号注册" name="enroll_fixture_material_stock" type="object"-->
<!-- class="btn-primary"/>-->
</tree>
</field>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="sf_fixture_material_search_search" model="ir.ui.view">
<field name="name">sf.fixture.material.search.search</field>
<field name="model">sf.fixture.material.search</field>
<field name="arch" type="xml">
<search string="夹具物料搜索">
<field name="name" string="名称搜索" filter_domain="[('name','ilike',self)]"/>
<field name="fixture_material_id" string="夹具型号搜索"/>
<field name="specification_fixture_id" string="规格搜索"/>
<searchpanel>
<field name="fixture_material_id" icon="fa-building" enable_counters="1"/>
</searchpanel>
</search>
</field>
</record>
<record id="action_sf_fixture_material_search" model="ir.actions.act_window">
<field name="name">夹具物料查询</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sf.fixture.material.search</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem
sequence="25"
name="夹具物料查询"
id="menu_sf_fixture_material_search"
action="action_sf_fixture_material_search"
parent="menu_sf_tool_manage"
/>
</odoo>

View File

@@ -10,8 +10,8 @@
<menuitem <menuitem
id="menu_sf_functional_cutting_tool" id="menu_sf_functional_cutting_tool"
parent="menu_sf_tool_manage" parent="menu_sf_tool_manage"
name="功能刀具列表" name="功能刀具"
sequence="4" sequence="2"
action="sf_function_tool_entry_list_view_act" action="sf_function_tool_entry_list_view_act"
/> />
@@ -34,7 +34,7 @@
<menuitem <menuitem
sequence="6" 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"
parent="menu_sf_tool_manage" parent="menu_sf_tool_manage"
@@ -64,7 +64,7 @@
/> />
<menuitem <menuitem
sequence="2" sequence="4"
name="功能刀具组装" name="功能刀具组装"
id="menu_sf_functional_tool_assembly" id="menu_sf_functional_tool_assembly"
action="sf_functional_tool_assembly_view_act" action="sf_functional_tool_assembly_view_act"

View File

@@ -40,6 +40,8 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<form create="0" edit="0" delete="0"> <form create="0" edit="0" delete="0">
<header> <header>
<!-- <button name="enroll_functional_tool_entity" string="功能刀具注册" type="object"-->
<!-- class="btn-primary"/>-->
<field name="functional_tool_status" widget="statusbar" statusbar_visible="正常,报警,已拆除"/> <field name="functional_tool_status" widget="statusbar" statusbar_visible="正常,报警,已拆除"/>
</header> </header>
<sheet> <sheet>
@@ -243,6 +245,8 @@
<field name="dispose_user"/> <field name="dispose_user"/>
<field name="dispose_time"/> <field name="dispose_time"/>
<field name="dispose_func"/> <field name="dispose_func"/>
<!-- <button name="enroll_functional_tool_warning" string="刀具预警注册" type="object"-->
<!-- class="btn-primary"/>-->
</tree> </tree>
</field> </field>
</record> </record>
@@ -318,6 +322,10 @@
<field name="model">sf.real.time.distribution.of.functional.tools</field> <field name="model">sf.real.time.distribution.of.functional.tools</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form>
<!-- <header>-->
<!-- <button name="enroll_functional_tool_real_time_distribution" string="安全库存注册" type="object"-->
<!-- class="btn-primary"/>-->
<!-- </header>-->
<sheet> <sheet>
<div class="oe_title"> <div class="oe_title">
<h1> <h1>
@@ -454,6 +462,7 @@
<field name="date"/> <field name="date"/>
<field name="qty_done" string="数量"/> <field name="qty_done" string="数量"/>
<field name="functional_tool_type_id" invisible="True"/> <field name="functional_tool_type_id" invisible="True"/>
<!-- <button name="enroll_functional_tool_move" string="安全库存注册" type="object" class="btn-primary"/>-->
</tree> </tree>
</field> </field>
</record> </record>

View File

@@ -22,6 +22,9 @@
<field name="model">sf.tool.material.search</field> <field name="model">sf.tool.material.search</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="刀具物料查询" create="0"> <form string="刀具物料查询" create="0">
<!-- <header>-->
<!-- <button string="刀具物料注册" name="enroll_tool_material" type="object" class="btn-primary"/>-->
<!-- </header>-->
<sheet> <sheet>
<div class="oe_title"> <div class="oe_title">
<h1> <h1>
@@ -59,6 +62,7 @@
<tree> <tree>
<field name="name"/> <field name="name"/>
<field name="tool_material_status"/> <field name="tool_material_status"/>
<!-- <button name="enroll_tool_material_stock" string="序列号注册" type="object" class="btn-primary"/>-->
</tree> </tree>
</field> </field>
</page> </page>
@@ -78,7 +82,6 @@
<field name="name" string="名称搜索" filter_domain="[('name','ilike',self)]"/> <field name="name" string="名称搜索" filter_domain="[('name','ilike',self)]"/>
<field name="cutting_tool_standard_library_id" string="刀具型号搜索"/> <field name="cutting_tool_standard_library_id" string="刀具型号搜索"/>
<field name="specification_id" string="规格搜索"/> <field name="specification_id" string="规格搜索"/>
<filter string="已归档" name="inactive" domain="[('active', '=', False)]"/>
<searchpanel> <searchpanel>
<field name="cutting_tool_material_id" icon="fa-building" enable_counters="1"/> <field name="cutting_tool_material_id" icon="fa-building" enable_counters="1"/>
</searchpanel> </searchpanel>

View File

@@ -225,8 +225,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
# 整体式刀具型号 # 整体式刀具型号
integral_code_id = fields.Many2one('stock.lot', string='整体式刀具序列号', integral_code_id = fields.Many2one('stock.lot', string='整体式刀具序列号',
domain=[('product_id.cutting_tool_material_id.name', '=', '整体式刀具'), domain=[('product_id.cutting_tool_material_id.name', '=', '整体式刀具'),
('quant_ids.location_id.name', 'in', ['刀具房']), ('tool_material_status', '=', '可用')])
('quant_ids.quantity', '>', 0)])
cutting_tool_integral_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='整体式刀具型号', cutting_tool_integral_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='整体式刀具型号',
related='integral_code_id.product_id.cutting_tool_model_id') related='integral_code_id.product_id.cutting_tool_model_id')
integral_name = fields.Char('整体式刀具名称', related='integral_code_id.product_id.name') integral_name = fields.Char('整体式刀具名称', related='integral_code_id.product_id.name')
@@ -238,8 +237,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
# 刀片型号 # 刀片型号
blade_code_id = fields.Many2one('stock.lot', '刀片序列号', blade_code_id = fields.Many2one('stock.lot', '刀片序列号',
domain=[('product_id.cutting_tool_material_id.name', '=', '刀片'), domain=[('product_id.cutting_tool_material_id.name', '=', '刀片'),
('quant_ids.location_id.name', 'in', ['刀具房']), ('tool_material_status', '=', '可用')])
('quant_ids.quantity', '>', 0)])
cutting_tool_blade_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀片型号', cutting_tool_blade_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀片型号',
related='blade_code_id.product_id.cutting_tool_model_id') related='blade_code_id.product_id.cutting_tool_model_id')
blade_name = fields.Char('刀片名称', related='blade_code_id.product_id.name') blade_name = fields.Char('刀片名称', related='blade_code_id.product_id.name')
@@ -250,8 +248,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
# 刀杆型号 # 刀杆型号
bar_code_id = fields.Many2one('stock.lot', '刀杆序列号', bar_code_id = fields.Many2one('stock.lot', '刀杆序列号',
domain=[('product_id.cutting_tool_material_id.name', '=', '刀杆'), domain=[('product_id.cutting_tool_material_id.name', '=', '刀杆'),
('quant_ids.location_id.name', 'in', ['刀具房']), ('tool_material_status', '=', '可用')])
('quant_ids.quantity', '>', 0)])
cutting_tool_cutterbar_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀杆型号', cutting_tool_cutterbar_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀杆型号',
related='bar_code_id.product_id.cutting_tool_model_id') related='bar_code_id.product_id.cutting_tool_model_id')
bar_name = fields.Char('刀杆名称', related='bar_code_id.product_id.name') bar_name = fields.Char('刀杆名称', related='bar_code_id.product_id.name')
@@ -262,8 +259,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
# 刀盘型号 # 刀盘型号
pad_code_id = fields.Many2one('stock.lot', '刀盘序列号', pad_code_id = fields.Many2one('stock.lot', '刀盘序列号',
domain=[('product_id.cutting_tool_material_id.name', '=', '刀盘'), domain=[('product_id.cutting_tool_material_id.name', '=', '刀盘'),
('quant_ids.location_id.name', 'in', ['刀具房']), ('tool_material_status', '=', '可用')])
('quant_ids.quantity', '>', 0)])
cutting_tool_cutterpad_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀盘型号', cutting_tool_cutterpad_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀盘型号',
related='pad_code_id.product_id.cutting_tool_model_id') related='pad_code_id.product_id.cutting_tool_model_id')
pad_name = fields.Char('刀盘名称', related='pad_code_id.product_id.name') pad_name = fields.Char('刀盘名称', related='pad_code_id.product_id.name')
@@ -274,8 +270,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
# 刀柄型号 # 刀柄型号
handle_code_id = fields.Many2one('stock.lot', '刀柄序列号', required=True, handle_code_id = fields.Many2one('stock.lot', '刀柄序列号', required=True,
domain=[('product_id.cutting_tool_material_id.name', '=', '刀柄'), domain=[('product_id.cutting_tool_material_id.name', '=', '刀柄'),
('quant_ids.location_id.name', 'in', ['刀具房']), ('tool_material_status', '=', '可用')])
('quant_ids.quantity', '>', 0)])
cutting_tool_cutterhandle_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀柄型号', cutting_tool_cutterhandle_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀柄型号',
related='handle_code_id.product_id.cutting_tool_model_id') related='handle_code_id.product_id.cutting_tool_model_id')
handle_name = fields.Char('刀柄名称', related='handle_code_id.product_id.name') handle_name = fields.Char('刀柄名称', related='handle_code_id.product_id.name')
@@ -286,8 +281,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
# 夹头型号 # 夹头型号
chuck_code_id = fields.Many2one('stock.lot', '夹头序列号', required=True, chuck_code_id = fields.Many2one('stock.lot', '夹头序列号', required=True,
domain=[('product_id.cutting_tool_material_id.name', '=', '夹头'), domain=[('product_id.cutting_tool_material_id.name', '=', '夹头'),
('quant_ids.location_id.name', 'in', ['刀具房']), ('tool_material_status', '=', '可用')])
('quant_ids.quantity', '>', 0)])
cutting_tool_cutterhead_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='夹头型号', cutting_tool_cutterhead_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='夹头型号',
related='chuck_code_id.product_id.cutting_tool_model_id') related='chuck_code_id.product_id.cutting_tool_model_id')
chuck_name = fields.Char('夹头名称', related='chuck_code_id.product_id.name') chuck_name = fields.Char('夹头名称', related='chuck_code_id.product_id.name')
@@ -481,9 +475,9 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
product_id = self.env['product.product'].search([('name', '=', '功能刀具')]) product_id = self.env['product.product'].search([('name', '=', '功能刀具')])
# 创建组装入库单 # 创建组装入库单
# 创建功能刀具批次/序列号记录 # 创建功能刀具批次/序列号记录
stock_lot = product_id.create_assemble_warehouse_receipt(self.id, functional_tool_assembly) stock_lot = product_id.create_assemble_warehouse_receipt(self.id, functional_tool_assembly, self)
# 创建刀具组装入库单 # 创建刀具组装入库单
self.env['stock.picking'].create_stocking_picking(stock_lot, functional_tool_assembly) self.env['stock.picking'].create_stocking_picking(stock_lot, functional_tool_assembly, self)
# 刀具物料出库 # 刀具物料出库
if self.integral_code_id: if self.integral_code_id:
product_id.tool_material_stock_moves(self.integral_code_id) product_id.tool_material_stock_moves(self.integral_code_id)
@@ -583,6 +577,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
return { return {
'barcode_id': stock_lot.id, 'barcode_id': stock_lot.id,
'code': self.tool_code, 'code': self.tool_code,
'name': self.after_assembly_functional_tool_name,
'rfid': self.rfid, 'rfid': self.rfid,
'tool_groups_id': self.tool_groups_id.id, 'tool_groups_id': self.tool_groups_id.id,
'functional_tool_name_id': functional_tool_assembly_id.id, 'functional_tool_name_id': functional_tool_assembly_id.id,
@@ -618,7 +613,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
class StockPicking(models.Model): class StockPicking(models.Model):
_inherit = 'stock.picking' _inherit = 'stock.picking'
def create_stocking_picking(self, stock_lot, functional_tool_assembly): def create_stocking_picking(self, stock_lot, functional_tool_assembly, obj):
""" """
创建刀具组装入库单 创建刀具组装入库单
""" """
@@ -639,7 +634,14 @@ class StockPicking(models.Model):
'location_dest_id': picking_id.location_dest_id.id, 'location_dest_id': picking_id.location_dest_id.id,
'lot_id': stock_lot.id, 'lot_id': stock_lot.id,
'qty_done': 1, 'qty_done': 1,
'functional_tool_name_id': functional_tool_assembly.id 'functional_tool_name_id': functional_tool_assembly.id,
'functional_tool_type_id': obj.functional_tool_type_id.id,
'diameter': obj.after_assembly_functional_tool_diameter,
'knife_tip_r_angle': obj.after_assembly_knife_tip_r_angle,
'code': obj.tool_code,
'rfid': obj.rfid,
'functional_tool_name': obj.after_assembly_functional_tool_name,
'tool_groups_id': obj.tool_groups_id.id
}) })
# 将刀具组装入库单的状态更改为就绪 # 将刀具组装入库单的状态更改为就绪
picking_id.action_confirm() picking_id.action_confirm()
@@ -664,7 +666,7 @@ class StockPicking(models.Model):
class ProductProduct(models.Model): class ProductProduct(models.Model):
_inherit = 'product.product' _inherit = 'product.product'
def create_assemble_warehouse_receipt(self, tool_assembly_order_id, functional_tool_assembly): def create_assemble_warehouse_receipt(self, tool_assembly_order_id, functional_tool_assembly, obj):
""" """
创建功能刀具批次/序列号记录 创建功能刀具批次/序列号记录
""" """
@@ -680,7 +682,7 @@ class ProductProduct(models.Model):
stock_location_id = self.env['stock.location'].search([('name', '=', '组装后')]) stock_location_id = self.env['stock.location'].search([('name', '=', '组装后')])
# 创建功能刀具该批次/序列号 库存移动和移动历史 # 创建功能刀具该批次/序列号 库存移动和移动历史
stock_lot.create_stock_quant(location_inventory_id, stock_location_id, functional_tool_assembly.id, stock_lot.create_stock_quant(location_inventory_id, stock_location_id, functional_tool_assembly.id,
'功能刀具组装') '功能刀具组装', obj)
return stock_lot return stock_lot
@@ -714,13 +716,13 @@ class ProductProduct(models.Model):
location_inventory_id = tool_material.quant_ids.location_id[-1] location_inventory_id = tool_material.quant_ids.location_id[-1]
stock_location_id = self.env['stock.location'].search([('name', '=', '刀具组装位置')]) stock_location_id = self.env['stock.location'].search([('name', '=', '刀具组装位置')])
# 创建功能刀具该批次/序列号 库存移动和移动历史 # 创建功能刀具该批次/序列号 库存移动和移动历史
tool_material.create_stock_quant(location_inventory_id, stock_location_id, None, '功能刀具组装') tool_material.create_stock_quant(location_inventory_id, stock_location_id, None, '功能刀具组装', False)
class StockLot(models.Model): class StockLot(models.Model):
_inherit = 'stock.lot' _inherit = 'stock.lot'
def create_stock_quant(self, location_inventory_id, stock_location_id, functional_tool_assembly_id, name): def create_stock_quant(self, location_inventory_id, stock_location_id, functional_tool_assembly_id, name, obj):
""" """
对功能刀具组装过程的功能刀具和刀具物料进行库存移动,以及创建移动历史 对功能刀具组装过程的功能刀具和刀具物料进行库存移动,以及创建移动历史
""" """
@@ -743,6 +745,25 @@ class StockLot(models.Model):
'move_id': stock_move_id.id, 'move_id': stock_move_id.id,
'install_tool_time': fields.Datetime.now(), 'install_tool_time': fields.Datetime.now(),
'qty_done': 1.0, 'qty_done': 1.0,
'state': 'done' 'state': 'done',
'functional_tool_type_id': False if not obj else obj.functional_tool_type_id.id,
'diameter': None if not obj else obj.after_assembly_functional_tool_diameter,
'knife_tip_r_angle': None if not obj else obj.after_assembly_knife_tip_r_angle,
'code': '' if not obj else obj.tool_code,
'rfid': '' if not obj else obj.rfid,
'functional_tool_name': '' if not obj else obj.after_assembly_functional_tool_name,
'tool_groups_id': False if not obj else obj.tool_groups_id.id
}) })
return stock_move_id, stock_move_line_id return stock_move_id, stock_move_line_id
class StockQuant(models.Model):
_inherit = 'stock.quant'
@api.model_create_multi
def create(self, vals_list):
records = super(StockQuant, self).create(vals_list)
for record in records:
if record.lot_id.product_id.categ_id.name == '刀具':
record.lot_id.enroll_tool_material_stock()
return records

View File

@@ -9,7 +9,7 @@ import requests
from odoo import api, fields, models, _ from odoo import api, fields, models, _
from odoo.osv import expression from odoo.osv import expression
from odoo.exceptions import UserError from odoo.exceptions import UserError, ValidationError
class SfLocation(models.Model): class SfLocation(models.Model):
@@ -388,7 +388,6 @@ class ShelfLocation(models.Model):
record.product_id = False record.product_id = False
# record.location_status = '空闲' # record.location_status = '空闲'
# 调取获取货位信息接口 # 调取获取货位信息接口
def get_sf_shelf_location_info(self): def get_sf_shelf_location_info(self):
# sf_sync_config = self.env['res.config.settings'].get_values() # sf_sync_config = self.env['res.config.settings'].get_values()
@@ -414,7 +413,8 @@ class ShelfLocation(models.Model):
class Sf_stock_move_line(models.Model): class Sf_stock_move_line(models.Model):
_inherit = 'stock.move.line' _name = 'stock.move.line'
_inherit = ['stock.move.line', 'printing.utils']
current_location_id = fields.Many2one( current_location_id = fields.Many2one(
'sf.shelf.location', string='当前货位', compute='_compute_current_location_id', store=True) 'sf.shelf.location', string='当前货位', compute='_compute_current_location_id', store=True)
@@ -424,6 +424,14 @@ class Sf_stock_move_line(models.Model):
# lot_qr_code = fields.Binary(string='二维码', compute='_compute_lot_qr_code', store=True) # lot_qr_code = fields.Binary(string='二维码', compute='_compute_lot_qr_code', store=True)
lot_qr_code = fields.Binary(string='二维码', compute='_compute_lot_qr_code', store=True) lot_qr_code = fields.Binary(string='二维码', compute='_compute_lot_qr_code', store=True)
def action_revert_inventory(self):
# 检查用户是否有执行操作的权限
if not self.env.user.has_group('sf_warehouse.group_sf_stock_user'):
raise UserError(_('抱歉,只有库管人员可以执行此动作'))
# 如果用户有权限,调用父类方法
return super(CustomStockMoveLine, self).action_revert_inventory()
@api.depends('lot_name') @api.depends('lot_name')
def _compute_lot_qr_code(self): def _compute_lot_qr_code(self):
for record in self: for record in self:
@@ -457,36 +465,127 @@ class Sf_stock_move_line(models.Model):
else: else:
record.lot_qr_code = False record.lot_qr_code = False
def print_qr_code(self): def print_single_method(self):
self.ensure_one() # 确保这个方法只为一个记录调用 self.ensure_one()
# if not self.lot_id:
# raise UserError("没有找到序列号。")
# 假设_lot_qr_code方法已经生成了二维码并保存在字段中
qr_code_data = self.lot_qr_code qr_code_data = self.lot_qr_code
if not qr_code_data: if not qr_code_data:
raise UserError("没有找到二维码数据。") raise UserError("没有找到二维码数据。")
lot_name = self.lot_name
# host = "192.168.50.110" # 可以根据实际情况修改
# port = 9100 # 可以根据实际情况修改
# 生成下载链接或直接触发下载 # 获取默认打印机配置
# 此处的实现依赖于你的具体需求,以下是触发下载的一种示例 printer_config = self.env['printer.configuration'].search([('model', '=', self._name)], limit=1)
attachment = self.env['ir.attachment'].sudo().create({ if not printer_config:
'datas': self.lot_qr_code, raise UserError('请先配置打印机')
'type': 'binary', host = printer_config.printer_id.ip_address
'description': '二维码图片', port = printer_config.printer_id.port
'name': self.lot_name + '.png', self.print_qr_code(lot_name, host, port)
# 'res_id': invoice.id,
# 'res_model': 'stock.picking', # 返回当前wizard页面
'public': True, # base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
'mimetype': 'application/x-png', # return {
# 'model_name': 'stock.picking', # 'type': 'ir.actions.act_url',
}) # 'url': str(base_url) + download_url,
# 返回附件的下载链接 # 'target': 'self',
download_url = '/web/content/%s?download=true' % attachment.id # }
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') # 获取当前wizard的视图ID或其他标识信息
return { view_id = self.env.context.get('view_id')
'type': 'ir.actions.act_url', # 构造返回wizard页面的action字典
'url': str(base_url) + download_url, action = {
'target': 'self', 'type': 'ir.actions.act_window',
'name': '返回 Wizard',
'res_model': 'stock.move', # 替换为你的wizard模型名称
'view_mode': 'form',
'view_id': view_id, # 如果需要基于特定的视图返回
'target': 'new', # 如果需要在新的窗口或标签页打开
'res_id': self.id, # 如果你想要返回当前记录的视图
} }
return action
# def generate_zpl_code(self, code):
# # 初始化ZPL代码字符串
# zpl_code = "^XA\n"
# zpl_code += "^CW1,E:SIMSUN.TTF^FS\n"
# zpl_code += "^CI28\n"
#
# # 设置二维码位置
# zpl_code += "^FO50,50\n" # 调整二维码位置,使其与资产编号在同一行
# zpl_code += f"^BQN,2,6^FDLM,B0093{code}^FS\n"
#
# # 设置资产编号文本位置
# zpl_code += "^FO300,60\n" # 资产编号文本的位置,与二维码在同一行
# zpl_code += "^A1N,45,45^FD编码名称: ^FS\n"
#
# # 设置{code}文本位置
# # 假设{code}文本需要位于资产编号和二维码下方,中间位置
# # 设置{code}文本位置并启用自动换行
# zpl_code += "^FO300,120\n" # {code}文本的起始位置
# zpl_code += "^FB500,4,0,L,0\n" # 定义一个宽度为500点的文本框最多4行左对齐
# zpl_code += f"^A1N,40,40^FD{code}^FS\n"
#
# # 在{code}文本框周围绘制线框
# # 假设线框的外部尺寸为宽度500点高度200点
# # zpl_code += "^FO300,110^GB500,200,2^FS\n" # 绘制线框边框粗细为2点
#
# zpl_code += "^PQ1,0,1,Y\n"
# zpl_code += "^XZ\n"
# return zpl_code
#
# def send_to_printer(self, host, port, zpl_code):
# # 将ZPL代码转换为字节串
# print('zpl_code', zpl_code)
# zpl_bytes = zpl_code.encode('utf-8')
# print(zpl_bytes)
#
# # 创建socket对象
# mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# try:
# mysocket.connect((host, port)) # 连接到打印机
# mysocket.send(zpl_bytes) # 发送ZPL代码
# print("ZPL code sent to printer successfully.")
# except Exception as e:
# print(f"Error with the connection: {e}")
# finally:
# mysocket.close() # 关闭连接
#
# def print_qr_code(self):
# self.ensure_one() # 确保这个方法只为一个记录调用
# # if not self.lot_id:
# # raise UserError("没有找到序列号。")
# # 假设_lot_qr_code方法已经生成了二维码并保存在字段中
# qr_code_data = self.lot_qr_code
# if not qr_code_data:
# raise UserError("没有找到二维码数据。")
# # 生成ZPL代码
# zpl_code = self.generate_zpl_code(self.lot_id.name)
# # 设置打印机的IP地址和端口号
# host = "192.168.50.110"
# port = 9100
# # 发送ZPL代码到打印机
# self.send_to_printer(host, port, zpl_code)
#
# # # 生成下载链接或直接触发下载
# # # 此处的实现依赖于你的具体需求,以下是触发下载的一种示例
# # attachment = self.env['ir.attachment'].sudo().create({
# # 'datas': self.lot_qr_code,
# # 'type': 'binary',
# # 'description': '二维码图片',
# # 'name': self.lot_name + '.png',
# # # 'res_id': invoice.id,
# # # 'res_model': 'stock.picking',
# # 'public': True,
# # 'mimetype': 'application/x-png',
# # # 'model_name': 'stock.picking',
# # })
# # # 返回附件的下载链接
# # download_url = '/web/content/%s?download=true' % attachment.id
# # base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
# # return {
# # 'type': 'ir.actions.act_url',
# # 'url': str(base_url) + download_url,
# # 'target': 'self',
# # }
# # # 定义一个方法,用于根据序列号生成二维码 # # # 定义一个方法,用于根据序列号生成二维码
# # @api.depends('lot_id') # # @api.depends('lot_id')
@@ -622,6 +721,17 @@ class Sf_stock_move_line(models.Model):
class SfStockPicking(models.Model): class SfStockPicking(models.Model):
_inherit = 'stock.picking' _inherit = 'stock.picking'
check_in = fields.Char(string='查询是否为入库单', compute='_check_is_in')
@api.depends('name')
def _check_is_in(self):
"""
判断是否为出库单
"""
if self.name:
is_check_in = self.name.split('/')
self.check_in = is_check_in[1]
def button_validate(self): def button_validate(self):
""" """
重写验证方法,当验证时意味着调拨单已经完成,已经移动到了目标货位,所以需要将当前货位的状态改为空闲 重写验证方法,当验证时意味着调拨单已经完成,已经移动到了目标货位,所以需要将当前货位的状态改为空闲
@@ -634,6 +744,20 @@ class SfStockPicking(models.Model):
line.current_location_id.location_status = '空闲' line.current_location_id.location_status = '空闲'
return res return res
# def print_all_barcode(self):
# """
# 打印所有编码
# """
# print('================')
# for record in self.move_ids_without_package:
# print('record', record)
# print('record.move_line_ids', record.move_line_ids)
#
# # record.move_line_ids.print_qr_code()
#
# print('record.move_line_ids.lot_id', record.move_line_ids.lot_id)
# print('record.move_line_ids.lot_id.name', record.move_line_ids.lot_id.name)
class SfProcurementGroup(models.Model): class SfProcurementGroup(models.Model):
_inherit = 'procurement.group' _inherit = 'procurement.group'
@@ -807,7 +931,8 @@ class SfStockScrap(models.Model):
class CustomStockMove(models.Model): class CustomStockMove(models.Model):
_inherit = 'stock.move' _name = 'stock.move'
_inherit = ['stock.move', 'printing.utils']
def action_assign_serial_show_details(self): def action_assign_serial_show_details(self):
# 首先执行原有逻辑 # 首先执行原有逻辑
@@ -836,3 +961,31 @@ class CustomStockMove(models.Model):
binary_data = buffer.getvalue() binary_data = buffer.getvalue()
data = base64.b64encode(binary_data).decode() # 确保返回的是字符串形式的数据 data = base64.b64encode(binary_data).decode() # 确保返回的是字符串形式的数据
return data return data
def print_all_barcode(self):
"""
打印所有编码
"""
print('================')
for record in self.move_line_ids:
print('record', record)
if not record.lot_name:
continue
record.ensure_one()
# qr_code_data = record.lot_qr_code
# if not qr_code_data:
# raise UserError("没有找到二维码数据。")
lot_name = record.lot_name
# todo 待控制
if not lot_name:
raise ValidationError("请先分配序列号")
# host = "192.168.50.110" # 可以根据实际情况修改
# port = 9100 # 可以根据实际情况修改
# 获取默认打印机配置
printer_config = self.env['printer.configuration'].search([('model', '=', self._name)], limit=1)
if not printer_config:
raise UserError('请先配置打印机')
host = printer_config.printer_id.ip_address
port = printer_config.printer_id.port
record.print_qr_code(lot_name, host, port)

View File

@@ -129,6 +129,8 @@ access_stock_scrap_group_purchase,stock_scrap_group_purchase,stock.model_stock_s
access_stock_scrap_group_purchase_director,stock_scrap_group_purchase_director,stock.model_stock_scrap,sf_base.group_purchase_director,1,0,0,0 access_stock_scrap_group_purchase_director,stock_scrap_group_purchase_director,stock.model_stock_scrap,sf_base.group_purchase_director,1,0,0,0
access_stock_lot_group_purchase,stock_lot_group_purchase,stock.model_stock_lot,sf_base.group_purchase,1,0,0,0 access_stock_lot_group_purchase,stock_lot_group_purchase,stock.model_stock_lot,sf_base.group_purchase,1,0,0,0
access_stock_lot_group_purchase_director,stock_lot_group_purchase_director,stock.model_stock_lot,sf_base.group_purchase_director,1,0,0,0 access_stock_lot_group_purchase_director,stock_lot_group_purchase_director,stock.model_stock_lot,sf_base.group_purchase_director,1,0,0,0
access_stock_lot_group_quality,stock_lot_group_quality,stock.model_stock_lot,sf_base.group_quality,1,0,0,0
access_stock_lot_group_quality_director,stock_lot_group_quality_director,stock.model_stock_lot,sf_base.group_quality_director,1,0,0,0
access_mrp_workcenter_productivity_group_purchase,mrp_workcenter_productivity_group_purchase,mrp.model_mrp_workcenter_productivity,sf_base.group_purchase,1,0,0,0 access_mrp_workcenter_productivity_group_purchase,mrp_workcenter_productivity_group_purchase,mrp.model_mrp_workcenter_productivity,sf_base.group_purchase,1,0,0,0
access_mrp_workcenter_productivity_group_purchase_director,mrp_workcenter_productivity_group_purchase_director,mrp.model_mrp_workcenter_productivity,sf_base.group_purchase_director,1,0,0,0 access_mrp_workcenter_productivity_group_purchase_director,mrp_workcenter_productivity_group_purchase_director,mrp.model_mrp_workcenter_productivity,sf_base.group_purchase_director,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
129 access_sf_cutting_tool_standard_library_group_sf_stock_manager access_sf_feed_per_tooth_group_sf_stock_manager sf_cutting_tool_standard_library_group_sf_stock_manager sf_feed_per_tooth_group_sf_stock_manager sf_base.model_sf_cutting_tool_standard_library sf_base.model_sf_feed_per_tooth sf_warehouse.group_sf_stock_manager 1 0 1 0
130 access_sf_tool_materials_basic_parameters_group_sf_stock_manager access_sf_cutting_tool_material_group_sf_stock_manager sf_tool_materials_basic_parameters_group_sf_stock_manager sf_cutting_tool_material_group_sf_stock_manager sf_base.model_sf_tool_materials_basic_parameters sf_base.model_sf_cutting_tool_material sf_warehouse.group_sf_stock_manager 1 0 1 0
131 access_sf_cutting_tool_standard_library_group_sf_stock_manager sf_cutting_tool_standard_library_group_sf_stock_manager sf_base.model_sf_cutting_tool_standard_library sf_warehouse.group_sf_stock_manager 1 0 1 0
132 access_sf_tool_materials_basic_parameters_group_sf_stock_manager sf_tool_materials_basic_parameters_group_sf_stock_manager sf_base.model_sf_tool_materials_basic_parameters sf_warehouse.group_sf_stock_manager 1 0 1 0
133
134
135
136

View File

@@ -65,7 +65,7 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//field[@name='product_uom_id']" position="after"> <xpath expr="//field[@name='product_uom_id']" position="after">
<field name="lot_qr_code" widget="image"/> <field name="lot_qr_code" widget="image"/>
<button name="print_qr_code" string="打印编码" type="object" class="oe_highlight"/> <button name="print_single_method" string="打印编码" type="object" class="oe_highlight"/>
</xpath> </xpath>
</field> </field>
</record> </record>
@@ -103,6 +103,11 @@
groups="sf_warehouse.group_sf_stock_user" data-hotkey="k"/> groups="sf_warehouse.group_sf_stock_user" data-hotkey="k"/>
</xpath> </xpath>
<!-- <xpath expr="//form//sheet//notebook//page//field[@name='move_ids_without_package']" position="before"> -->
<!-- <field name="check_in" invisible="True"/> -->
<!-- <button name="print_all_barcode" string="打印所有编码" type="object" attrs="{'invisible': [('check_in', '!=', 'IN')]}"/> -->
<!-- </xpath> -->
</field> </field>
</record> </record>
@@ -135,5 +140,19 @@
</field> </field>
</record> </record>
<record id="sf_view_stock_move_operations" model="ir.ui.view">
<field name="name">sf.stock.move.operations.form</field>
<field name="model">stock.move</field>
<field name="inherit_id" ref="stock.view_stock_move_operations"/>
<field name="arch" type="xml">
<!-- <xpath expr="//form//field[@name='move_line_ids']" position="before"> -->
<!-- <button name="print_all_barcode" type="object" string="打印所有编码"/> -->
<!-- </xpath> -->
<xpath expr="//form//field[@name='product_id']" position="before">
<button name="print_all_barcode" type="object" string="打印所有编码" class="oe_highlight"/> -->
</xpath>
</field>
</record>
</data> </data>
</odoo> </odoo>

View File

@@ -19,7 +19,7 @@
], ],
'assets': { 'assets': {
'web.assets_backend': [ 'web.assets_backend': [
'jikimo_sfs/zpl_print/static/src/scss/changes.scss' # 'jikimo_sfs/zpl_print/static/src/scss/changes.scss'
] ]
}, },
'license': 'LGPL-3', 'license': 'LGPL-3',

Binary file not shown.

BIN
zpl_print/libs/TSCLIB11.dll Normal file

Binary file not shown.

View File

@@ -8,14 +8,27 @@ class Common(models.Model):
_description = u'公用类' _description = u'公用类'
def print_zpl(self, zpl_str): def print_zpl(self, zpl_str):
WinDll_path = "D://桌面//pythonZPL//zebra_zpl//libs//TSCLIB.dll" # WinDll_path = "D://桌面//pythonZPL//tsc_python_sdk_example//TSC_Python_SDK_Example//tsc_sample//libs//TSCLIB.dll"
WinDll_path = "D://jikimo-dev//jikimo//SF//zpl_print//libs//TSCLIB.dll"
# WinDll_path = "D://桌面//pythonZPL//zebra_zpl//libs//TSCLIB.dll"
try: try:
tsclibrary = ctypes.WinDLL(WinDll_path) tsclibrary = ctypes.WinDLL(WinDll_path)
tsclibrary.openportW("USB") tsclibrary.openportW("USB")
print(type(zpl_str))
print(zpl_str) print(zpl_str)
tsclibrary.sendcommandW(zpl_str) original_string = "^XA\n^FO100,50\n^A0N,44,33^FD[PO-2023-1226-0215-1] P-S00001-1^FS\n^FO100,100\n^A0N,44,33^FDLN/SN: P-S00001-1-12348啊a^FS\n^FO100,150^BY3\n^BCN,100,Y,N,N\n^FDP-S00001-1-12348啊a^FS\n^XZ"
# 使用加号操作符
new_string = original_string + "^CW1,E:SIMSUN.FNT #绑定字体\n^CI28 #UTF-8编码"
# 使用字符串格式化方法
new_string = "{}^CW1,E:SIMSUN.FNT #绑定字体\n^CI28 #UTF-8编码".format(original_string)
print(new_string)
tsclibrary.sendcommandW(new_string)
print('111222') print('111222')
tsclibrary.printlabelW("0", "1"); tsclibrary.printlabelW("0", "1")
tsclibrary.closeport(); tsclibrary.closeport()
except Exception as e: except Exception as e:
raise UserWarning("错误警告:%s" % e) raise UserWarning("错误警告:%s" % e)