diff --git a/jikimo_frontend/static/src/js/custom_form_status_indicator.js b/jikimo_frontend/static/src/js/custom_form_status_indicator.js
index 2bed0804..35f0f3e2 100644
--- a/jikimo_frontend/static/src/js/custom_form_status_indicator.js
+++ b/jikimo_frontend/static/src/js/custom_form_status_indicator.js
@@ -4,6 +4,7 @@ import {patch} from '@web/core/utils/patch';
// import { Dialog } from "@web/core/dialog/dialog";
import {_t} from "@web/core/l10n/translation";
import {FormStatusIndicator} from "@web/views/form/form_status_indicator/form_status_indicator";
+import {ListRenderer} from "@web/views/list/list_renderer";
import {Field} from "@web/views/fields/field";
@@ -42,7 +43,14 @@ const filedRequiredList = {
// 制造大模块
'production_line_id': { multiple: false, noLabel: false },
'date_approve': { multiple: false, noLabel: false },
+ 'date_planned_start': { multiple: false, noLabel: false },
+ 'date_planned_finished': { multiple: false, noLabel: false },
}
+const tableRequiredList = [
+ 'product_template_id', 'product_uom_qty', 'price_unit','product_id','product_qty',
+ 'name', 'fault_type', 'maintenance_standards', 'Period'
+]
+
patch(FormStatusIndicator.prototype, 'jikimo_frontend.FormStatusIndicator', {
// 你可以重写或者添加一些方法和属性
async _onDiscardChanges() {
@@ -83,12 +91,8 @@ 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);
+ return this._super(...arguments);
},
setRequired() {
const id = this.props.id
@@ -112,7 +116,39 @@ patch(Field.prototype, 'jikimo_frontend.Field', {
}
}
})
-
+patch(ListRenderer.prototype, 'jikimo_frontend.ListRenderer', {
+ setup(){
+ owl.onMounted(() => {
+ this.activeElement = this.uiService.activeElement;
+ this.setRequired()
+ })
+ return this._super(...arguments);
+ },
+ setRequired() {
+ this.allColumns.forEach(_ => {
+ if( tableRequiredList.indexOf(_.name) >= 0 ) {
+ const dom = $(`th[data-name=${_.name}]`)
+ dom.addClass('addRequired')
+ }
+ })
+ try {
+ const dom = this.tableRef.el
+ if(dom ) {
+ const tfoot = $(dom).children('tfoot')
+ const tbooy = $(dom).children('tbody')
+ if(tfoot.length) {
+ const tfoot_tr = tfoot.children().eq(0)
+ const tbody_tr = tbooy.children().eq(0)
+ if(tfoot_tr.children().length < tbody_tr.children().length) {
+ tfoot_tr.prepend('
')
+ }
+ }
+ }
+ } catch (e) {
+ console.log(e)
+ }
+ }
+})
$(function () {
document.addEventListener('click', function () {
@@ -162,45 +198,13 @@ $(function () {
}, 500)
}
- function setRequired(dom = {label: [], table: []}) {
- let domTimer = null
- let timer_count = 0
- clearInterval(domTimer)
- domTimer = setInterval(() => {
- timer_count++
- const lint = $('.o_form_view_container')
- if (lint.length) {
- clearInterval(domTimer)
- const { table} = dom
-
- if (table.length) {
- table.forEach(_ => {
- const th = $(`th[data-name=${_}]`)
- const t = th.find('span').eq(0).text().replace('*','')
- th.find('span').eq(0).html('*' + t)
-
- })
-
- }
- }
- if (timer_count == 20) {
- clearInterval(domTimer)
- }
- }, 500)
- }
-
var currentUrl = location.href
- const customRequiredDom = {
- table: ['product_template_id', 'product_uom_qty', 'price_unit','product_id','product_qty', 'name', 'fault_type', 'maintenance_standards', 'Period']
- }
const listenerUrl = setInterval(() => {
const isChange = currentUrl != location.href
if (isChange) {
currentUrl = location.href
customRequired()
- setRequired(customRequiredDom)
}
}, 500)
customRequired()
- setRequired(customRequiredDom)
})
diff --git a/jikimo_frontend/static/src/js/custom_image_temp.js b/jikimo_frontend/static/src/js/custom_image_temp.js
index fba97121..16f7dab0 100644
--- a/jikimo_frontend/static/src/js/custom_image_temp.js
+++ b/jikimo_frontend/static/src/js/custom_image_temp.js
@@ -3,6 +3,13 @@
import { registry } from "@web/core/registry";
import { url } from "@web/core/utils/urls";
import { ImageField, imageCacheKey } from '@web/views/fields/image/image_field';
+import { isBinarySize } from "@web/core/utils/binary";
+export const fileTypeMagicWordMap = {
+ "/": "jpg",
+ R: "gif",
+ i: "png",
+ P: "svg+xml",
+};
const placeholder = "/web/static/img/placeholder.png";
@@ -15,7 +22,7 @@ export class CustomImageField extends ImageField {
getUrl(previewFieldName) {
console.log('8888888888886666666666666666666')
if (this.state.isValid && this.props.value) {
- if (1) {
+ if (isBinarySize(this.props.value) || this.props.value.length < 50) {
if (!this.rawCacheKey) {
this.rawCacheKey = this.props.record.data.__last_update;
}
diff --git a/jikimo_frontend/static/src/scss/custom_style.scss b/jikimo_frontend/static/src/scss/custom_style.scss
index bc1be730..d3a44da4 100644
--- a/jikimo_frontend/static/src/scss/custom_style.scss
+++ b/jikimo_frontend/static/src/scss/custom_style.scss
@@ -467,3 +467,28 @@ div:has(.o_required_modifier) > label::before {
background: #71639e;
color: #fff
}
+
+// 修改时间输入框宽度
+.o_datepicker_input.o_input.datetimepicker-input {
+ width: 200px;
+}
+
+
+.o_form_view .o_form_editable .o_row > .o_field_widget, .o_form_view .o_form_editable .o_row > .o_field_widget.o_field_float_time {
+ width: auto !important;
+ flex: unset;
+}
+.addRequired {
+ padding-left: calc(0.3rem + 2px)!important;
+}
+.addRequired:before {
+ content: '*';
+ color: red;
+ position: absolute;
+ left: 0;
+ top: 50%;
+ transform: translateY(-50%);
+}
+.o_list_renderer .o_list_table tfoot .o_list_number {
+ text-align: left;
+}
\ No newline at end of file
diff --git a/sf_base/models/tool_base_new.py b/sf_base/models/tool_base_new.py
index a3a9e172..3aa85ceb 100644
--- a/sf_base/models/tool_base_new.py
+++ b/sf_base/models/tool_base_new.py
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from datetime import date
from odoo import fields, models, api
+from odoo.exceptions import UserError
class CuttingToolMaterial(models.Model):
@@ -308,3 +309,41 @@ class ToolGroups(models.Model):
# records = super(ToolGroups, self).create(vals_list)
# self._register_tool_groups(records)
# return records
+
+
+class ToolInventory(models.Model):
+ _name = 'sf.tool.inventory'
+ _description = '功能刀具清单'
+
+ name = fields.Char('功能刀具名称', required=True)
+ type = fields.Char('类型')
+ functional_cutting_tool_model_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型')
+ prefix = fields.Char('前缀')
+ postfix = fields.Char('后缀')
+ diameter = fields.Float('直径(mm)')
+ angle = fields.Float('R角(mm)')
+ tool_length = fields.Float('刀具总长(mm)')
+ blade_length = fields.Float('避空长/刃长(mm)')
+ knife_head_name = fields.Char('刀头名称')
+ cutter_number = fields.Char('刀号')
+ blade_number = fields.Integer('刃数(个)')
+ extension = fields.Float('伸出长度(mm)')
+ work_material = fields.Selection([('钢', '钢'), ('铝', '铝')], string='加工材料')
+ life_span = fields.Float('寿命(h)')
+
+ tool_groups_id = fields.Many2one('sf.tool.groups', string='刀具组')
+
+ active = fields.Boolean('已归档', default=True)
+
+ @api.model_create_multi
+ def create(self, vals_list):
+ # 名称重复校验
+ name_list = []
+ for val in vals_list:
+ tool_inventory = self.search([('name', '=', val['name'])])
+ if tool_inventory:
+ name_list.append(val['name'])
+ if name_list:
+ raise UserError("功能刀具名称%s已存在,请重新输入" % name_list)
+ records = super(ToolInventory, self).create(vals_list)
+ return records
diff --git a/sf_base/security/group_security.xml b/sf_base/security/group_security.xml
index 478d41b9..1321bae2 100644
--- a/sf_base/security/group_security.xml
+++ b/sf_base/security/group_security.xml
@@ -65,7 +65,7 @@
计划调度岗
-
+
diff --git a/sf_base/security/ir.model.access.csv b/sf_base/security/ir.model.access.csv
index 4eaddff0..3795e69b 100644
--- a/sf_base/security/ir.model.access.csv
+++ b/sf_base/security/ir.model.access.csv
@@ -9,16 +9,25 @@ access_sf_machine_brand_tags,sf_machine_brand_tags,model_sf_machine_brand_tags,b
access_sf_machine_brand_tags_admin,sf_machine_brand_tags_admin,model_sf_machine_brand_tags,base.group_system,1,1,1,0
access_sf_machine_control_system,sf_machine_control_system,model_sf_machine_control_system,base.group_user,1,1,1,0
access_sf_machine_control_system_admin,sf_machine_control_system_admin,model_sf_machine_control_system,base.group_system,1,1,1,0
+access_sf_production_process_group_sale_director,sf_production_process_group_sale_director,model_sf_production_process,sf_base.group_sale_director,1,0,0,0
+access_sf_production_process_group_sale_salemanager,sf_production_process_group_sale_salemanager,model_sf_production_process,sf_base.group_sale_salemanager,1,0,0,0
access_sf_production_process,sf_production_process,model_sf_production_process,base.group_user,1,1,1,0
access_sf_production_process_admin,sf_production_process_admin,model_sf_production_process,base.group_system,1,1,1,0
access_sf_production_materials,sf_production_materials,model_sf_production_materials,base.group_user,1,1,1,0
+access_sf_production_materials_group_sale_director,sf_production_materials_group_sale_director,model_sf_production_materials,sf_base.group_sale_director,1,0,0,0
+access_sf_production_materials_group_sale_salemanager,sf_production_materials_group_sale_salemanager,model_sf_production_materials,sf_base.group_sale_salemanager,1,0,0,0
+
access_sf_production_materials_admin,sf_production_materials_admin,model_sf_production_materials,base.group_system,1,1,1,0
access_sf_materials_model,sf_materials_model,model_sf_materials_model,base.group_user,1,1,1,0
access_sf_materials_model_admin,sf_materials_model_admin,model_sf_materials_model,base.group_system,1,1,1,0
access_sf_supplier_sort,sf_supplier_sort,model_sf_supplier_sort,base.group_user,1,1,1,0
access_sf_supplier_sort_admin,sf_supplier_sort_admin,model_sf_supplier_sort,base.group_system,1,1,1,0
access_sf_production_process_parameter,sf_production_process_parameter,model_sf_production_process_parameter,base.group_user,1,1,1,0
+access_sf_production_process_parameter_group_sale_director,sf_production_process_parameter_group_sale_director,model_sf_production_process_parameter,sf_base.group_sale_director,1,0,0,0
+access_sf_production_process_parameter_group_sale_salemanager,sf_production_process_parameter_group_sale_salemanager,model_sf_production_process_parameter,sf_base.group_sale_salemanager,1,0,0,0
+
+
access_sf_production_process_parameter_group_plan_director,sf_production_process_parameter_group_plan_director,model_sf_production_process_parameter,sf_base.group_plan_director,1,0,0,0
access_sf_production_process_parameter_group_purchase_director,sf_production_process_parameter_group_purchase_director,model_sf_production_process_parameter,sf_base.group_purchase_director,1,0,0,0
access_sf_production_process_parameter_group_sale_director,sf_production_process_parameter_group_sale_director,model_sf_production_process_parameter,sf_base.group_sale_director,1,0,0,0
@@ -101,6 +110,10 @@ access_sf_production_materials_group_plan_director,sf_production_materials_group
access_sf_production_materials_group_purchase_director,sf_production_materials_group_purchase_director,model_sf_production_materials,sf_base.group_purchase_director,1,1,0,0
access_sf_production_materials_group_sale_director,sf_production_materials_group_sale_director,model_sf_production_materials,sf_base.group_sale_director,1,1,0,0
access_sf_materials_model,sf_materials_model,model_sf_materials_model,sf_base.group_sf_mrp_user,1,0,0,0
+access_sf_materials_model_group_sale_salemanager,sf_materials_model_group_sale_salemanager,model_sf_materials_model,sf_base.group_sale_salemanager,1,0,0,0
+access_sf_materials_model_group_sale_director,sf_materials_model_group_sale_director,model_sf_materials_model,sf_base.group_sale_director,1,0,0,0
+
+
access_sf_materials_model_group_plan_director,sf_materials_model_group_plan_director,model_sf_materials_model,sf_base.group_plan_director,1,0,0,0
access_sf_materials_model_group_purchase_director,sf_materials_model_group_purchase_director,model_sf_materials_model,sf_base.group_purchase_director,1,0,0,0
access_sf_materials_model_group_sale_director,sf_materials_model_group_sale_director,model_sf_materials_model,sf_base.group_sale_director,1,0,0,0
@@ -145,6 +158,7 @@ access_purchase_order_group_purchase,access_purchase_order_group_purchase,purcha
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_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_director,sf_tool_groups,model_sf_tool_groups,sf_base.group_plan_director,1,1,1,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_purchase_order,purchase.order,purchase.model_purchase_order,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
@@ -191,4 +205,25 @@ access_sf_machine_brand_tags_group_purchase_director,sf_machine_brand_tags_group
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
\ No newline at end of file
+access_printer_configuration,printer.configuration,model_printer_configuration,base.group_user,1,1,1,1
+
+access_group_sf_mrp_user,sf_tool_inventory,model_sf_tool_inventory,base.group_user,1,1,1,0
+access_group_sf_mrp_user_admin,sf_tool_inventory_admin,model_sf_tool_inventory,base.group_system,1,1,1,0
+access_group_sf_mrp_user_group_purchase_director,sf_tool_inventory_group_purchase_director,model_sf_tool_inventory,sf_base.group_purchase_director,1,0,1,0
+access_group_sf_mrp_user_group_sale_director,sf_tool_inventory_group_sale_director,model_sf_tool_inventory,sf_base.group_sale_director,1,0,1,0
+access_sf_cutting_tool_material_group_plan_director,sf_tool_inventory_group_plan_director,model_sf_tool_inventory,sf_base.group_plan_director,1,0,1,0
+access_group_sf_mrp_user_group_sf_mrp_user,sf_tool_inventory_group_sf_mrp_user,model_sf_tool_inventory,sf_base.group_sf_mrp_user,1,1,0,0
+
+
+access_sf_fixture_material_group_purchase_director,sf_fixture_material_group_purchase_director,model_sf_fixture_material,sf_base.group_purchase_director,1,0,0,0
+access_sf_multi_mounting_type_group_purchase_director,sf_multi_mounting_type_group_purchase_director,model_sf_multi_mounting_type,sf_base.group_purchase_director,1,0,0,0
+access_sf_fixture_model_group_purchase_director,sf_fixture_model_group_purchase_director,model_sf_fixture_model,sf_base.group_purchase_director,1,0,0,0
+access_sf_fixture_materials_basic_parameters_group_purchase_director,sf_fixture_materials_basic_parameters_group_purchase_director,model_sf_fixture_materials_basic_parameters,sf_base.group_purchase_director,1,0,0,0
+access_sf_machine_tool_type_group_purchase_director,sf_machine_tool_type_group_purchase_director,model_sf_machine_tool_type,sf_base.group_purchase_director,1,0,0,0
+
+access_sf_fixture_material_group_sale_director,sf_fixture_material_group_sale_director,model_sf_fixture_material,sf_base.group_sale_director,1,0,0,0
+access_sf_multi_mounting_type_group_sale_director,sf_multi_mounting_type_group_sale_director,model_sf_multi_mounting_type,sf_base.group_sale_director,1,0,0,0
+access_sf_fixture_model_group_sale_director,sf_fixture_model_group_sale_director,model_sf_fixture_model,sf_base.group_sale_director,1,0,0,0
+access_sf_fixture_materials_basic_parameters_group_sale_director,sf_fixture_materials_basic_parameters_group_sale_director,model_sf_fixture_materials_basic_parameters,sf_base.group_sale_director,1,0,0,0
+access_sf_machine_tool_type_group_sale_director,sf_machine_tool_type_group_sale_director,model_sf_machine_tool_type,sf_base.group_sale_director,1,0,0,0
+
diff --git a/sf_base/static/src/scss/test.scss b/sf_base/static/src/scss/test.scss
index fdc5821e..c91a8a77 100644
--- a/sf_base/static/src/scss/test.scss
+++ b/sf_base/static/src/scss/test.scss
@@ -189,3 +189,6 @@ td.o_required_modifier {
flex-direction: row !important;
}
+.supplier_ids_set_css thead th[data-name=partner_id]{
+ width: 500px!important;
+}
\ No newline at end of file
diff --git a/sf_base/views/common_view.xml b/sf_base/views/common_view.xml
index bf9201b8..e829274a 100644
--- a/sf_base/views/common_view.xml
+++ b/sf_base/views/common_view.xml
@@ -27,7 +27,7 @@
-
+
@@ -231,6 +231,9 @@
+
+
+
@@ -266,7 +269,7 @@
-
+
diff --git a/sf_base/views/tool_menu.xml b/sf_base/views/tool_menu.xml
index 506a73df..263d11fa 100644
--- a/sf_base/views/tool_menu.xml
+++ b/sf_base/views/tool_menu.xml
@@ -21,7 +21,7 @@
刀具标准库
ir.actions.act_window
sf.cutting_tool.standard.library
-
+
tree,form
@@ -59,46 +59,54 @@
id="menu_sf_cutting_tool_type"
parent="menu_sf_cutting_tool"
name="刀具类型"
- sequence="2"
+ sequence="10"
action="action_sf_cutting_tool_type"
/>
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ id="menu_sf_maintenance_equipment_image"
+ name="能力特征库"
+ parent="menu_sf_cutting_tool"
+ action="action_maintenance_equipment_image"
+ sequence="40"/>
+ id="menu_sf_tool_groups"
+ name="刀具组"
+ parent="menu_sf_cutting_tool"
+ action="sf_tool_groups_view_act"
+ sequence="50"/>
diff --git a/sf_base/views/tool_views.xml b/sf_base/views/tool_views.xml
index 34b87a41..1e82b8c2 100644
--- a/sf_base/views/tool_views.xml
+++ b/sf_base/views/tool_views.xml
@@ -123,7 +123,7 @@
@@ -540,7 +559,7 @@
工件配送
sf.workpiece.delivery
-
+
@@ -550,11 +569,13 @@
decoration-danger="status == '待配送'"/>
-
-
-
-
-
+
+
+
+
+
+
+
@@ -567,16 +588,19 @@
-
+
-
+
+
+
+
diff --git a/sf_manufacturing/views/sf_maintenance_equipment.xml b/sf_manufacturing/views/sf_maintenance_equipment.xml
index b398f994..5ddf59b0 100644
--- a/sf_manufacturing/views/sf_maintenance_equipment.xml
+++ b/sf_manufacturing/views/sf_maintenance_equipment.xml
@@ -1,23 +1,38 @@
- 设备增加刀具库位table
+
sf_manufacturing_equipment.form
maintenance.equipment
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sf_manufacturing/views/stock_lot_views.xml b/sf_manufacturing/views/stock_lot_views.xml
index bd04005c..aef50e55 100644
--- a/sf_manufacturing/views/stock_lot_views.xml
+++ b/sf_manufacturing/views/stock_lot_views.xml
@@ -13,6 +13,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sf_manufacturing/wizard/workpiece_delivery_views.xml b/sf_manufacturing/wizard/workpiece_delivery_views.xml
index 49e80d52..34625878 100644
--- a/sf_manufacturing/wizard/workpiece_delivery_views.xml
+++ b/sf_manufacturing/wizard/workpiece_delivery_views.xml
@@ -5,14 +5,18 @@
sf.workpiece.delivery.wizard
diff --git a/sf_manufacturing/wizard/workpiece_delivery_wizard.py b/sf_manufacturing/wizard/workpiece_delivery_wizard.py
index 7101410d..1de3e84c 100644
--- a/sf_manufacturing/wizard/workpiece_delivery_wizard.py
+++ b/sf_manufacturing/wizard/workpiece_delivery_wizard.py
@@ -11,10 +11,11 @@ class WorkpieceDeliveryWizard(models.TransientModel):
delivery_id = fields.Many2one('sf.workpiece.delivery', string='配送')
workorder_id = fields.Many2one('mrp.workorder', string='工单')
+ route_id = fields.Many2one('sf.agv.task.route', '任务路线')
+ is_ok = fields.Boolean('确认上述信息正确无误.')
def confirm(self):
if self.workorder_id:
self.workorder_id.workpiece_delivery_ids._delivery_avg()
else:
self.delivery_id._delivery_avg()
-
diff --git a/sf_mrs_connect/controllers/controllers.py b/sf_mrs_connect/controllers/controllers.py
index 18381f3d..6efc4b82 100644
--- a/sf_mrs_connect/controllers/controllers.py
+++ b/sf_mrs_connect/controllers/controllers.py
@@ -44,12 +44,18 @@ class Sf_Mrs_Connect(http.Controller):
return json.JSONEncoder().encode(res)
logging.info('创建cnc工单')
program_path_tmp = os.path.join('/tmp', ret['folder_name'], 'return', r)
+ # program_path_tmp = "C://Users//43484//Desktop//机企猫工作文档//其他//model_analysis"
files = os.listdir(program_path_tmp)
for f in files:
program_path = os.path.join(program_path_tmp, f)
logging.info('cnc程序路径 :%s' % program_path)
+ if f.endswith(".doc"):
+ # 插入cmm程序数据
+ request.env['sf.cmm.program'].with_user(
+ request.env.ref("base.user_admin")).cmm_program_create(ret, program_path, program_path_tmp)
request.env['sf.cnc.processing'].with_user(
- request.env.ref("base.user_admin")).cnc_processing_create(cnc_production, ret, program_path,program_path_tmp)
+ request.env.ref("base.user_admin")).cnc_processing_create(cnc_production, ret, program_path,
+ program_path_tmp)
return json.JSONEncoder().encode(res)
else:
res = {'status': 0, 'message': '该制造订单暂未开始'}
diff --git a/sf_mrs_connect/models/ftp_operate.py b/sf_mrs_connect/models/ftp_operate.py
index c8d0abb6..98e6d504 100644
--- a/sf_mrs_connect/models/ftp_operate.py
+++ b/sf_mrs_connect/models/ftp_operate.py
@@ -21,14 +21,32 @@ class FtpController():
except Exception:
logging.info("ftp连接失败")
+ def file_exists(self, path):
+ # 检查文件是否存在于FTP服务器上
+ try:
+ self.ftp.cwd(os.path.dirname(path))
+ files = self.ftp.nlst()
+ return os.path.basename(path) in files
+ except Exception as e:
+ logging.error(f"Error checking file: {e}")
+ return False
+
# 下载目录下的文件
def download_file_tree(self, target_dir, serverdir):
if not os.path.exists(serverdir):
os.makedirs(serverdir)
try:
logging.info("进入FTP目录 ")
- self.ftp.cwd(target_dir) # 切换工作路径
- logging.info('FTP目录:%s' % target_dir)
+ logging.info('目录:%s' % target_dir)
+ target_dir1 = target_dir.split('/')
+ logging.info('目录1:%s' % target_dir1[1])
+ self.ftp.cwd(target_dir1[1]) # 切换工作路径
+ logging.info('目录2:%s' % target_dir1[2])
+ self.ftp.cwd(target_dir1[2]) # 切换工作路径
+ logging.info('目录3:%s' % target_dir1[3])
+ self.ftp.cwd(target_dir1[3]) # 切换工作路径
+ logging.info('目录4:%s' % target_dir1[4])
+ self.ftp.cwd(target_dir1[4]) # 切换工作路径
remotenames = self.ftp.nlst()
logging.info('FTP目录文件:%s' % remotenames)
for file in remotenames:
@@ -38,6 +56,9 @@ class FtpController():
return 1
except Exception:
return 0
+ finally:
+ self.ftp.quit()
+ logging.info("ftp已关闭")
# 下载目录下的检测文件
def download_reportfile_tree(self, target_dir, serverdir, reportpath):
@@ -51,6 +72,8 @@ class FtpController():
self.ftp.cwd(target_dir1[1]) # 切换工作路径
logging.info('目录2:%s' % target_dir1[2])
self.ftp.cwd(target_dir1[2]) # 切换工作路径
+ logging.info('目录2:%s' % target_dir1[3])
+ self.ftp.cwd(target_dir1[3]) # 切换工作路径
remotenames = self.ftp.nlst()
logging.info('FTP目录检测报告文件:%s' % remotenames)
for filename in remotenames:
diff --git a/sf_mrs_connect/models/res_config_setting.py b/sf_mrs_connect/models/res_config_setting.py
index 7c10f8b1..ef2d93d8 100644
--- a/sf_mrs_connect/models/res_config_setting.py
+++ b/sf_mrs_connect/models/res_config_setting.py
@@ -13,9 +13,13 @@ class ResConfigSettings(models.TransientModel):
token = fields.Char(string='TOKEN', default='b811ac06-3f00-11ed-9aed-0242ac110003')
sf_secret_key = fields.Char(string='密钥', default='wBmxej38OkErKhD6')
sf_url = fields.Char(string='访问地址', default='https://sf.cs.jikimo.com')
- 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')
+ agv_rcs_url = fields.Char(string='avg_rcs访问地址',
+ default='http://172.16.10.114:8182/rcms/services/rest/hikRpcService/genAgvSchedulingTask')
+ center_control_url = fields.Char(string='中控访问地址',
+ default='http://172.16.21.50:8001')
+ wbcode = fields.Char('地码')
+ agv_code = fields.Char(string='agv编号')
+ task_type_no = fields.Char('任务单类型编号')
model_parser_url = fields.Char('特征识别路径')
ftp_host = fields.Char(string='FTP的ip')
ftp_port = fields.Char(string='FTP端口')
@@ -94,8 +98,10 @@ class ResConfigSettings(models.TransientModel):
token = config.get_param('token', default='')
sf_secret_key = config.get_param('sf_secret_key', 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='')
+ wbcode = config.get_param('wbcode', default='')
+ agv_code = config.get_param('agv_code', default='')
+ center_control_url = config.get_param('center_control_url', default='')
ftp_host = config.get_param('ftp_host', default='')
ftp_port = config.get_param('ftp_port', default='')
ftp_user = config.get_param('ftp_user', default='')
@@ -105,8 +111,10 @@ class ResConfigSettings(models.TransientModel):
token=token,
sf_secret_key=sf_secret_key,
sf_url=sf_url,
- agv_rcms_url=agv_rcms_url,
agv_rcs_url=agv_rcs_url,
+ wbcode=wbcode,
+ agv_code=agv_code,
+ center_control_url=center_control_url,
ftp_host=ftp_host,
ftp_port=ftp_port,
ftp_user=ftp_user,
@@ -120,8 +128,10 @@ class ResConfigSettings(models.TransientModel):
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_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("wbcode", self.wbcode or "")
+ ir_config.set_param("agv_code", self.agv_code or "")
+ ir_config.set_param("center_control_url", self.center_control_url 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_user", self.ftp_user or "")
diff --git a/sf_mrs_connect/models/sync_common.py b/sf_mrs_connect/models/sync_common.py
index 49956f4b..2795047a 100644
--- a/sf_mrs_connect/models/sync_common.py
+++ b/sf_mrs_connect/models/sync_common.py
@@ -52,8 +52,6 @@ class MrStaticResourceDataSync(models.Model):
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()
logging.info("功能夹具类型已每日同步成功")
self.env['sf.cutting.tool.material'].sync_cutting_tool_material_yesterday()
@@ -593,6 +591,7 @@ class MachineBrand(models.Model):
if not brand:
self.create({
"name": item['name'],
+ "active": item['active'],
"code": item['code'],
"remark": item['remark'],
"image_brand": '' if not item['image_brand'] else base64.b64decode(item['image_brand']),
@@ -601,6 +600,7 @@ class MachineBrand(models.Model):
})
else:
brand.name = item['name']
+ brand.active = item['active']
brand.remark = item['remark']
brand.image_brand = '' if not item['image_brand'] else base64.b64decode(item['image_brand'])
brand.tag_ids = self.env['sf.machine.brand.tags'].search(
@@ -1952,24 +1952,22 @@ class CuttingSpeed(models.Model):
'active': item['active'],
})
else:
- if item['active'] is False:
- item.write({'active': False})
- else:
- self.write({
- 'execution_standard_id': self.env['sf.international.standards'].search(
- [('code', '=', item['execution_standard_code'])]).id,
- 'material_name_id': self.env['sf.materials.model'].search(
- [('materials_no', '=', item['material_name'])]).id,
- 'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
- [('name', '=', item['cutting_width_depth'])]).id,
- 'ability_feature_library': self.env['maintenance.equipment.image'].search(
- [('name', '=', item['ability_feature_library']), ('type', '=', '加工能力')]).id,
- 'material_code': item['material_code'],
- 'material_grade': item['material_grade'],
- 'tensile_strength': item['tensile_strength'],
- 'hardness': item['hardness'],
- 'cutting_speed': item['cutting_speed'],
- 'application': item['application'], })
+ cutting_speed.write({
+ 'execution_standard_id': self.env['sf.international.standards'].search(
+ [('code', '=', item['execution_standard_code'])]).id,
+ 'material_name_id': self.env['sf.materials.model'].search(
+ [('materials_no', '=', item['material_name'])]).id,
+ 'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
+ [('name', '=', item['cutting_width_depth'])]).id,
+ 'ability_feature_library': self.env['maintenance.equipment.image'].search(
+ [('name', '=', item['ability_feature_library']), ('type', '=', '加工能力')]).id,
+ 'material_code': item['material_code'],
+ 'material_grade': item['material_grade'],
+ 'tensile_strength': item['tensile_strength'],
+ 'hardness': item['hardness'],
+ 'cutting_speed': item['cutting_speed'],
+ 'application': item['application'],
+ 'active': item['active']})
else:
raise ValidationError("切削速度认证未通过")
@@ -2006,24 +2004,22 @@ class CuttingSpeed(models.Model):
'active': item['active'],
})
else:
- if item['active'] is False:
- item.write({'active': False})
- else:
- self.write({
- 'execution_standard_id': self.env['sf.international.standards'].search(
- [('code', '=', item['execution_standard_code'])]).id,
- 'material_name_id': self.env['sf.materials.model'].search(
- [('materials_no', '=', item['material_name'])]).id,
- 'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
- [('name', '=', item['cutting_width_depth'])]).id,
- 'ability_feature_library': self.env['maintenance.equipment.image'].search(
- [('name', '=', item['ability_feature_library']), ('type', '=', '加工能力')]).id,
- 'material_code': item['material_code'],
- 'material_grade': item['material_grade'],
- 'tensile_strength': item['tensile_strength'],
- 'hardness': item['hardness'],
- 'cutting_speed': item['cutting_speed'],
- 'application': item['application'], })
+ cutting_speed.write({
+ 'execution_standard_id': self.env['sf.international.standards'].search(
+ [('code', '=', item['execution_standard_code'])]).id,
+ 'material_name_id': self.env['sf.materials.model'].search(
+ [('materials_no', '=', item['material_name'])]).id,
+ 'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
+ [('name', '=', item['cutting_width_depth'])]).id,
+ 'ability_feature_library': self.env['maintenance.equipment.image'].search(
+ [('name', '=', item['ability_feature_library']), ('type', '=', '加工能力')]).id,
+ 'material_code': item['material_code'],
+ 'material_grade': item['material_grade'],
+ 'tensile_strength': item['tensile_strength'],
+ 'hardness': item['hardness'],
+ 'cutting_speed': item['cutting_speed'],
+ 'application': item['application'],
+ 'active': item['active']})
else:
raise ValidationError("切削速度认证未通过")
@@ -2098,16 +2094,14 @@ class CuttingSpeed(models.Model):
'active': item['active'],
})
else:
- if item['active'] is False:
- item.write({'active': False})
- else:
- self.write({
- 'materials_type_id': self.env['sf.materials.model'].search(
- [('materials_no', '=', item['materials_type_code'])]).id,
- 'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
- [('name', '=', item['cutting_width_depth'])]).id,
- 'blade_diameter': item['blade_diameter'],
- 'feed_per_tooth': item['feed_per_tooth'], })
+ feed_per_tooth.write({
+ 'materials_type_id': self.env['sf.materials.model'].search(
+ [('materials_no', '=', item['materials_type_code'])]).id,
+ 'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
+ [('name', '=', item['cutting_width_depth'])]).id,
+ 'blade_diameter': item['blade_diameter'],
+ 'feed_per_tooth': item['feed_per_tooth'],
+ 'active': item['active']})
else:
raise ValidationError("每齿走刀量认证未通过")
@@ -2136,16 +2130,14 @@ class CuttingSpeed(models.Model):
'active': item['active'],
})
else:
- if item['active'] is False:
- item.write({'active': False})
- else:
- self.write({
- 'materials_type_id': self.env['sf.materials.model'].search(
- [('materials_no', '=', item['materials_type_code'])]).id,
- 'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
- [('name', '=', item['cutting_width_depth'])]).id,
- 'blade_diameter': item['blade_diameter'],
- 'feed_per_tooth': item['feed_per_tooth'], })
+ feed_per_tooth.write({
+ 'materials_type_id': self.env['sf.materials.model'].search(
+ [('materials_no', '=', item['materials_type_code'])]).id,
+ 'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
+ [('name', '=', item['cutting_width_depth'])]).id,
+ 'blade_diameter': item['blade_diameter'],
+ 'feed_per_tooth': item['feed_per_tooth'],
+ 'active': item['active']})
else:
raise ValidationError("每齿走刀量认证未通过")
@@ -2383,6 +2375,7 @@ class CuttingToolBasicParameters(models.Model):
r = requests.post(strUrl, json={}, data=None, headers=headers)
r = r.json()
result = json.loads(r['result'])
+ logging.info(result)
if result['status'] == 1:
if 'basic_parameters_integral_tool' in result['cutting_tool_basic_parameters_all_list']:
if result['cutting_tool_basic_parameters_all_list']['basic_parameters_integral_tool']:
@@ -2421,7 +2414,7 @@ class CuttingToolBasicParameters(models.Model):
'active': integral_tool_item['active'],
})
else:
- self.write({
+ self.search([('code', '=', integral_tool_item['code'])]).write({
'name': integral_tool_item['name'],
'total_length': integral_tool_item['total_length'],
'blade_diameter': integral_tool_item['blade_diameter'],
@@ -2482,7 +2475,7 @@ class CuttingToolBasicParameters(models.Model):
'active': blade_item['active'],
})
else:
- self.write({
+ self.search([('code', '=', blade_item['code'])]).write({
'name': blade_item['name'],
'length': blade_item['length'],
'thickness': blade_item['thickness'],
@@ -2539,7 +2532,7 @@ class CuttingToolBasicParameters(models.Model):
'active': chuck_item['active'],
})
else:
- self.write({
+ self.search([('code', '=', chuck_item['code'])]).write({
'name': chuck_item['name'],
'er_size_model': chuck_item['size_model'],
'min_clamping_diameter': chuck_item['clamping_diameter_min'],
@@ -2598,7 +2591,7 @@ class CuttingToolBasicParameters(models.Model):
'active': cutter_arbor_item['active'],
})
else:
- self.write({
+ self.search([('code', '=', cutter_arbor_item['code'])]).write({
'name': cutter_arbor_item['name'],
'height': cutter_arbor_item['height'],
'width': cutter_arbor_item['width'],
@@ -2662,7 +2655,7 @@ class CuttingToolBasicParameters(models.Model):
'active': cutter_head_item['active'],
})
else:
- self.write({
+ self.search([('code', '=', cutter_head_item['code'])]).write({
'name': cutter_head_item['name'],
'install_blade_tip_num': cutter_head_item['number_blade_installed'],
'blade_diameter': cutter_head_item['blade_diameter'],
@@ -2691,57 +2684,38 @@ class CuttingToolBasicParameters(models.Model):
for knife_handle_item in basic_parameters_knife_handle_list:
knife_handle = self.search(
[('code', '=', knife_handle_item['code']), ('active', 'in', [True, False])])
+ val = {
+ 'name': knife_handle_item['name'],
+ 'taper_shank_model': knife_handle_item['taper_shank_model'],
+ 'total_length': knife_handle_item['total_length'],
+ 'flange_shank_length': knife_handle_item['flange_length'],
+ 'flange_diameter': knife_handle_item['flange_diameter'],
+ 'shank_length': knife_handle_item['shank_length'],
+ 'shank_diameter': knife_handle_item['shank_diameter'],
+ 'min_clamping_diameter': knife_handle_item['clamping_diameter_min'],
+ 'max_clamping_diameter': knife_handle_item['clamping_diameter_max'],
+ 'clamping_mode': knife_handle_item['clamping_way'],
+ 'tool_changing_time': knife_handle_item['tool_changing_time'],
+ 'max_rotate_speed': knife_handle_item['rotate_speed_max'],
+ 'diameter_slip_accuracy': knife_handle_item['diameter_slip_accuracy'],
+ 'cooling_model': knife_handle_item['cooling_model'],
+ 'fit_chuck_size': knife_handle_item['fit_chuck_size'],
+ 'is_quick_cutting': knife_handle_item['is_quick_cutting'],
+ 'is_safe_lock': knife_handle_item['is_safe_lock'],
+ 'screw': knife_handle_item['fit_wrench_model'],
+ 'nut': knife_handle_item['fit_nut_model'],
+ 'dynamic_balance_class': knife_handle_item['dynamic_balance_class'],
+ 'active': knife_handle_item['active'],
+ }
if not knife_handle:
- self.create({
- 'name': knife_handle_item['name'],
- 'code': knife_handle_item['code'],
- 'cutting_tool_type': '刀柄',
- 'taper_shank_model': knife_handle_item['taper_shank_model'],
- 'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
- [('code', '=', knife_handle_item['standard_library_code'].replace("JKM", result[
- 'factory_short_name']))]).id,
- 'total_length': knife_handle_item['total_length'],
- 'flange_shank_length': knife_handle_item['flange_length'],
- 'flange_diameter': knife_handle_item['flange_diameter'],
- 'shank_length': knife_handle_item['shank_length'],
- 'shank_diameter': knife_handle_item['shank_diameter'],
- 'min_clamping_diameter': knife_handle_item['clamping_diameter_min'],
- 'max_clamping_diameter': knife_handle_item['clamping_diameter_max'],
- 'clamping_mode': knife_handle_item['clamping_way'],
- 'tool_changing_time': knife_handle_item['tool_changing_time'],
- 'max_rotate_speed': knife_handle_item['rotate_speed_max'],
- 'diameter_slip_accuracy': knife_handle_item['diameter_slip_accuracy'],
- 'cooling_model': knife_handle_item['cooling_model'],
- 'is_quick_cutting': knife_handle_item['is_quick_cutting'],
- 'is_safe_lock': knife_handle_item['is_safe_lock'],
- 'screw': knife_handle_item['fit_wrench_model'],
- 'nut': knife_handle_item['fit_nut_model'],
- 'dynamic_balance_class': knife_handle_item['dynamic_balance_class'],
- 'active': knife_handle_item['active'],
- })
+ val['code'] = knife_handle_item['code']
+ val['cutting_tool_type'] = '刀柄'
+ val['standard_library_id'] = self.env['sf.cutting_tool.standard.library'].search(
+ [('code', '=', knife_handle_item['standard_library_code'].replace("JKM", result[
+ 'factory_short_name']))]).id
+ self.create(val)
else:
- self.write({
- 'name': knife_handle_item['name'],
- 'taper_shank_model': knife_handle_item['taper_shank_model'],
- 'total_length': knife_handle_item['total_length'],
- 'flange_shank_length': knife_handle_item['flange_length'],
- 'flange_diameter': knife_handle_item['flange_diameter'],
- 'shank_length': knife_handle_item['shank_length'],
- 'shank_diameter': knife_handle_item['shank_diameter'],
- 'min_clamping_diameter': knife_handle_item['clamping_diameter_min'],
- 'max_clamping_diameter': knife_handle_item['clamping_diameter_max'],
- 'clamping_mode': knife_handle_item['clamping_way'],
- 'tool_changing_time': knife_handle_item['tool_changing_time'],
- 'max_rotate_speed': knife_handle_item['rotate_speed_max'],
- 'diameter_slip_accuracy': knife_handle_item['diameter_slip_accuracy'],
- 'cooling_model': knife_handle_item['cooling_model'],
- 'is_quick_cutting': knife_handle_item['is_quick_cutting'],
- 'is_safe_lock': knife_handle_item['is_safe_lock'],
- 'screw': knife_handle_item['fit_wrench_model'],
- 'nut': knife_handle_item['fit_nut_model'],
- 'dynamic_balance_class': knife_handle_item['dynamic_balance_class'],
- 'active': knife_handle_item['active'],
- })
+ self.search([('code', '=', knife_handle_item['code'])]).write(val)
else:
raise ValidationError("刀具物料基本参数认证未通过")
@@ -2790,29 +2764,26 @@ class CuttingToolBasicParameters(models.Model):
'active': integral_tool_item['active'],
})
else:
- if integral_tool_item['active'] is False:
- integral_tool.write({'active': False})
- else:
- self.write({
- 'name': integral_tool_item['name'],
- 'total_length': integral_tool_item['total_length'],
- 'blade_diameter': integral_tool_item['blade_diameter'],
- 'blade_length': integral_tool_item['blade_length'],
- 'blade_number': integral_tool_item['blade_number'],
- 'neck_length': integral_tool_item['neck_length'],
- 'neck_diameter': integral_tool_item['neck_diameter'],
- 'handle_diameter': integral_tool_item['shank_diameter'],
- 'handle_length': integral_tool_item['shank_length'],
- 'blade_tip_diameter': integral_tool_item['tip_diameter'],
- 'blade_tip_working_size': integral_tool_item['tip_handling_size'],
- 'blade_tip_taper': integral_tool_item['knife_tip_taper'],
- 'blade_helix_angle': integral_tool_item['blade_helix_angle'],
- 'blade_width': integral_tool_item['blade_width'],
- 'blade_depth': integral_tool_item['blade_depth'],
- 'pitch': integral_tool_item['pitch'],
- 'cutting_depth': integral_tool_item['cutting_depth_max'],
- 'active': integral_tool_item['active'],
- })
+ integral_tool.write({
+ 'name': integral_tool_item['name'],
+ 'total_length': integral_tool_item['total_length'],
+ 'blade_diameter': integral_tool_item['blade_diameter'],
+ 'blade_length': integral_tool_item['blade_length'],
+ 'blade_number': integral_tool_item['blade_number'],
+ 'neck_length': integral_tool_item['neck_length'],
+ 'neck_diameter': integral_tool_item['neck_diameter'],
+ 'handle_diameter': integral_tool_item['shank_diameter'],
+ 'handle_length': integral_tool_item['shank_length'],
+ 'blade_tip_diameter': integral_tool_item['tip_diameter'],
+ 'blade_tip_working_size': integral_tool_item['tip_handling_size'],
+ 'blade_tip_taper': integral_tool_item['knife_tip_taper'],
+ 'blade_helix_angle': integral_tool_item['blade_helix_angle'],
+ 'blade_width': integral_tool_item['blade_width'],
+ 'blade_depth': integral_tool_item['blade_depth'],
+ 'pitch': integral_tool_item['pitch'],
+ 'cutting_depth': integral_tool_item['cutting_depth_max'],
+ 'active': integral_tool_item['active'],
+ })
if 'basic_parameters_blade' in result['cutting_tool_basic_parameters_yesterday_list']:
if result['cutting_tool_basic_parameters_yesterday_list']['basic_parameters_blade']:
basic_parameters_blade_list = json.loads(
@@ -2854,35 +2825,33 @@ class CuttingToolBasicParameters(models.Model):
'active': blade_item['active'],
})
else:
- if blade_item['active'] is False:
- blade.write({'active': False})
- else:
- self.write({
- 'name': blade_item['name'],
- 'length': blade_item['length'],
- 'thickness': blade_item['thickness'],
- 'cutting_blade_length': blade_item['cutting_blade_length'],
- 'relief_angle': blade_item['relief_angle'],
- 'blade_tip_circular_arc_radius': blade_item['radius_tip_re'],
- 'inscribed_circle_diameter': blade_item['diameter_inner_circle'],
- 'install_aperture_diameter': blade_item['diameter_mounting_hole'],
- 'pitch': blade_item['pitch'],
- 'chip_breaker_groove': blade_item['is_chip_breaker'],
- 'chip_breaker_type_code': blade_item['chip_breaker_type_code'],
- 'blade_teeth_model': '无' if not blade_item['blade_profile'] else blade_item[
- 'blade_profile'],
- 'blade_blade_number': blade_item['blade_number'],
- 'cutting_depth': blade_item['cutting_depth_max'],
- 'blade_width': blade_item['blade_width'],
- 'main_included_angle': blade_item['edge_angle'],
- 'top_angle': blade_item['top_angle'],
- 'thread_model': '无' if not blade_item['thread_type'] else blade_item[
- 'thread_type'],
- 'thread_num': blade_item['threads_per_inch'],
- 'blade_tip_height_tolerance': blade_item['tip_height_tolerance'],
- 'inscribed_circle_tolerance': blade_item['internal_circle_tolerance'],
- 'thickness_tolerance': blade_item['thickness_tolerance'],
- })
+ blade.write({
+ 'name': blade_item['name'],
+ 'length': blade_item['length'],
+ 'thickness': blade_item['thickness'],
+ 'cutting_blade_length': blade_item['cutting_blade_length'],
+ 'relief_angle': blade_item['relief_angle'],
+ 'blade_tip_circular_arc_radius': blade_item['radius_tip_re'],
+ 'inscribed_circle_diameter': blade_item['diameter_inner_circle'],
+ 'install_aperture_diameter': blade_item['diameter_mounting_hole'],
+ 'pitch': blade_item['pitch'],
+ 'chip_breaker_groove': blade_item['is_chip_breaker'],
+ 'chip_breaker_type_code': blade_item['chip_breaker_type_code'],
+ 'blade_teeth_model': '无' if not blade_item['blade_profile'] else blade_item[
+ 'blade_profile'],
+ 'blade_blade_number': blade_item['blade_number'],
+ 'cutting_depth': blade_item['cutting_depth_max'],
+ 'blade_width': blade_item['blade_width'],
+ 'main_included_angle': blade_item['edge_angle'],
+ 'top_angle': blade_item['top_angle'],
+ 'thread_model': '无' if not blade_item['thread_type'] else blade_item[
+ 'thread_type'],
+ 'thread_num': blade_item['threads_per_inch'],
+ 'blade_tip_height_tolerance': blade_item['tip_height_tolerance'],
+ 'inscribed_circle_tolerance': blade_item['internal_circle_tolerance'],
+ 'thickness_tolerance': blade_item['thickness_tolerance'],
+ 'active': blade_item['active']
+ })
if 'basic_parameters_chuck' in result['cutting_tool_basic_parameters_yesterday_list']:
if result['cutting_tool_basic_parameters_yesterday_list']['basic_parameters_chuck']:
basic_parameters_chuck_list = json.loads(
@@ -2913,24 +2882,22 @@ class CuttingToolBasicParameters(models.Model):
'active': chuck_item['active'],
})
else:
- if chuck_item['active'] is False:
- chuck.write({'active': False})
- else:
- self.write({
- 'name': chuck_item['name'],
- 'er_size_model': chuck_item['size_model'],
- 'min_clamping_diameter': chuck_item['clamping_diameter_min'],
- 'max_clamping_diameter': chuck_item['clamping_diameter_max'],
- 'outer_diameter': chuck_item['outer_diameter'],
- 'inner_diameter': chuck_item['inner_diameter'],
- 'run_out_accuracy': chuck_item['run_out_accuracy'],
- 'total_length': chuck_item['total_length'],
- 'taper': chuck_item['taper'],
- 'top_diameter': chuck_item['top_diameter'],
- 'weight': chuck_item['weight'],
- 'max_load_capacity': chuck_item['load_capacity_max'],
- 'cooling_jacket': chuck_item['cooling_sleeve_model'],
- })
+ chuck.write({
+ 'name': chuck_item['name'],
+ 'er_size_model': chuck_item['size_model'],
+ 'min_clamping_diameter': chuck_item['clamping_diameter_min'],
+ 'max_clamping_diameter': chuck_item['clamping_diameter_max'],
+ 'outer_diameter': chuck_item['outer_diameter'],
+ 'inner_diameter': chuck_item['inner_diameter'],
+ 'run_out_accuracy': chuck_item['run_out_accuracy'],
+ 'total_length': chuck_item['total_length'],
+ 'taper': chuck_item['taper'],
+ 'top_diameter': chuck_item['top_diameter'],
+ 'weight': chuck_item['weight'],
+ 'max_load_capacity': chuck_item['load_capacity_max'],
+ 'cooling_jacket': chuck_item['cooling_sleeve_model'],
+ 'active': chuck_item['active']
+ })
if 'basic_parameters_cutter_arbor' in result['cutting_tool_basic_parameters_yesterday_list']:
if result['cutting_tool_basic_parameters_yesterday_list']['basic_parameters_cutter_arbor']:
basic_parameters_cutter_arbor_list = json.loads(
@@ -2974,38 +2941,36 @@ class CuttingToolBasicParameters(models.Model):
'active': cutter_arbor_item['active'],
})
else:
- if cutter_arbor_item['active'] is False:
- cutter_arbor.write({'active': False})
- else:
- self.write({
- 'name': cutter_arbor_item['name'],
- 'height': cutter_arbor_item['height'],
- 'width': cutter_arbor_item['width'],
- 'total_length': cutter_arbor_item['total_length'],
- 'knife_head_height': cutter_arbor_item['head_length'],
- 'knife_head_width': cutter_arbor_item['head_width'],
- 'knife_head_length': cutter_arbor_item['head_length'],
- 'cutter_arbor_diameter': cutter_arbor_item['arbor_diameter'],
- 'main_included_angle': cutter_arbor_item['edge_angle'],
- 'relief_angle': cutter_arbor_item['relief_angle'],
- 'cutting_depth': cutter_arbor_item['cutting_depth_max'],
- 'min_machining_aperture': cutter_arbor_item['machining_aperture_min'],
- 'install_blade_tip_num': cutter_arbor_item['number_blade_installed'],
- 'is_cooling_hole': cutter_arbor_item['is_cooling_hole'],
- 'locating_slot_code': cutter_arbor_item['locator_slot_code'],
- 'installing_structure': cutter_arbor_item['mounting_structure'],
- 'blade_id': False if not cutter_arbor_item['fit_blade_model_code'] else
- self.env[
- 'sf.cutting_tool.standard.library'].search(
- [('code', '=',
- cutter_arbor_item['fit_blade_model_code'].replace("JKM", result[
- 'factory_short_name']))]).id,
- 'tool_shim': cutter_arbor_item['fit_knife_pad_model'],
- 'cotter_pin': cutter_arbor_item['fit_pin_model'],
- 'pressing_plate': cutter_arbor_item['fit_plate_model'],
- 'screw': cutter_arbor_item['fit_screw_model'],
- 'spanner': cutter_arbor_item['fit_wrench_model'],
- })
+ cutter_arbor.write({
+ 'name': cutter_arbor_item['name'],
+ 'height': cutter_arbor_item['height'],
+ 'width': cutter_arbor_item['width'],
+ 'total_length': cutter_arbor_item['total_length'],
+ 'knife_head_height': cutter_arbor_item['head_length'],
+ 'knife_head_width': cutter_arbor_item['head_width'],
+ 'knife_head_length': cutter_arbor_item['head_length'],
+ 'cutter_arbor_diameter': cutter_arbor_item['arbor_diameter'],
+ 'main_included_angle': cutter_arbor_item['edge_angle'],
+ 'relief_angle': cutter_arbor_item['relief_angle'],
+ 'cutting_depth': cutter_arbor_item['cutting_depth_max'],
+ 'min_machining_aperture': cutter_arbor_item['machining_aperture_min'],
+ 'install_blade_tip_num': cutter_arbor_item['number_blade_installed'],
+ 'is_cooling_hole': cutter_arbor_item['is_cooling_hole'],
+ 'locating_slot_code': cutter_arbor_item['locator_slot_code'],
+ 'installing_structure': cutter_arbor_item['mounting_structure'],
+ 'blade_id': False if not cutter_arbor_item['fit_blade_model_code'] else
+ self.env[
+ 'sf.cutting_tool.standard.library'].search(
+ [('code', '=',
+ cutter_arbor_item['fit_blade_model_code'].replace("JKM", result[
+ 'factory_short_name']))]).id,
+ 'tool_shim': cutter_arbor_item['fit_knife_pad_model'],
+ 'cotter_pin': cutter_arbor_item['fit_pin_model'],
+ 'pressing_plate': cutter_arbor_item['fit_plate_model'],
+ 'screw': cutter_arbor_item['fit_screw_model'],
+ 'spanner': cutter_arbor_item['fit_wrench_model'],
+ 'active': cutter_arbor_item['active']
+ })
if 'basic_parameters_cutter_head' in result['cutting_tool_basic_parameters_yesterday_list']:
if result['cutting_tool_basic_parameters_yesterday_list']['basic_parameters_cutter_head']:
basic_parameters_cutter_head_list = json.loads(
@@ -3042,30 +3007,28 @@ class CuttingToolBasicParameters(models.Model):
'active': cutter_head_item['active'],
})
else:
- if cutter_head_item['active'] is False:
- cutter_head.write({'active': False})
- else:
- self.write({
- 'name': cutter_head_item['name'],
- 'install_blade_tip_num': cutter_head_item['number_blade_installed'],
- 'blade_diameter': cutter_head_item['blade_diameter'],
- 'cutter_head_diameter': cutter_head_item['cutter_diameter'],
- 'interface_diameter': cutter_head_item['interface_diameter'],
- 'total_length': cutter_head_item['total_length'],
- 'blade_length': cutter_head_item['blade_length'],
- 'cutting_depth': cutter_head_item['cutting_depth_max'],
- 'main_included_angle': cutter_head_item['edge_angle'],
- 'installing_structure': cutter_head_item['mounting_structure'],
- 'blade_id': False if not cutter_head_item['fit_blade_model_code'] else self.env[
- 'sf.cutting_tool.standard.library'].search(
- [('code', '=',
- cutter_head_item['fit_blade_model_code'].replace("JKM", result[
- 'factory_short_name']))]).id,
- 'screw': cutter_head_item['fit_screw_model'],
- 'spanner': cutter_head_item['fit_wrench_model'],
- 'is_cooling_hole': cutter_head_item['is_cooling_hole'],
- 'locating_slot_code': cutter_head_item['locator_slot_code'],
- })
+ cutter_head.write({
+ 'name': cutter_head_item['name'],
+ 'install_blade_tip_num': cutter_head_item['number_blade_installed'],
+ 'blade_diameter': cutter_head_item['blade_diameter'],
+ 'cutter_head_diameter': cutter_head_item['cutter_diameter'],
+ 'interface_diameter': cutter_head_item['interface_diameter'],
+ 'total_length': cutter_head_item['total_length'],
+ 'blade_length': cutter_head_item['blade_length'],
+ 'cutting_depth': cutter_head_item['cutting_depth_max'],
+ 'main_included_angle': cutter_head_item['edge_angle'],
+ 'installing_structure': cutter_head_item['mounting_structure'],
+ 'blade_id': False if not cutter_head_item['fit_blade_model_code'] else self.env[
+ 'sf.cutting_tool.standard.library'].search(
+ [('code', '=',
+ cutter_head_item['fit_blade_model_code'].replace("JKM", result[
+ 'factory_short_name']))]).id,
+ 'screw': cutter_head_item['fit_screw_model'],
+ 'spanner': cutter_head_item['fit_wrench_model'],
+ 'is_cooling_hole': cutter_head_item['is_cooling_hole'],
+ 'locating_slot_code': cutter_head_item['locator_slot_code'],
+ 'active': cutter_head_item['active']
+ })
if 'basic_parameters_knife_handle' in result['cutting_tool_basic_parameters_yesterday_list']:
if result['cutting_tool_basic_parameters_yesterday_list']['basic_parameters_knife_handle']:
basic_parameters_knife_handle_list = json.loads(
@@ -3097,35 +3060,35 @@ class CuttingToolBasicParameters(models.Model):
'cooling_model': knife_handle_item['cooling_model'],
'is_quick_cutting': knife_handle_item['is_quick_cutting'],
'is_safe_lock': knife_handle_item['is_safe_lock'],
+ 'fit_chuck_size': knife_handle_item['fit_chuck_size'],
'screw': knife_handle_item['fit_wrench_model'],
'nut': knife_handle_item['fit_nut_model'],
'dynamic_balance_class': knife_handle_item['dynamic_balance_class'],
'active': knife_handle_item['active'],
})
else:
- if knife_handle_item['active'] is False:
- knife_handle.write({'active': False})
- else:
- self.write({
- 'name': knife_handle_item['name'],
- 'total_length': knife_handle_item['total_length'],
- 'taper_shank_model': knife_handle_item['taper_shank_model'],
- 'flange_shank_length': knife_handle_item['flange_length'],
- 'flange_diameter': knife_handle_item['flange_diameter'],
- 'shank_length': knife_handle_item['shank_length'],
- 'shank_diameter': knife_handle_item['shank_diameter'],
- 'min_clamping_diameter': knife_handle_item['clamping_diameter_min'],
- 'max_clamping_diameter': knife_handle_item['clamping_diameter_max'],
- 'clamping_mode': knife_handle_item['clamping_way'],
- 'tool_changing_time': knife_handle_item['tool_changing_time'],
- 'max_rotate_speed': knife_handle_item['rotate_speed_max'],
- 'diameter_slip_accuracy': knife_handle_item['diameter_slip_accuracy'],
- 'cooling_model': knife_handle_item['cooling_model'],
- 'is_quick_cutting': knife_handle_item['is_quick_cutting'],
- 'is_safe_lock': knife_handle_item['is_safe_lock'],
- 'screw': knife_handle_item['fit_wrench_model'],
- 'nut': knife_handle_item['fit_nut_model'],
- 'dynamic_balance_class': knife_handle_item['dynamic_balance_class'],
- })
+ knife_handle.write({
+ 'name': knife_handle_item['name'],
+ 'total_length': knife_handle_item['total_length'],
+ 'taper_shank_model': knife_handle_item['taper_shank_model'],
+ 'flange_shank_length': knife_handle_item['flange_length'],
+ 'flange_diameter': knife_handle_item['flange_diameter'],
+ 'shank_length': knife_handle_item['shank_length'],
+ 'shank_diameter': knife_handle_item['shank_diameter'],
+ 'min_clamping_diameter': knife_handle_item['clamping_diameter_min'],
+ 'max_clamping_diameter': knife_handle_item['clamping_diameter_max'],
+ 'clamping_mode': knife_handle_item['clamping_way'],
+ 'tool_changing_time': knife_handle_item['tool_changing_time'],
+ 'max_rotate_speed': knife_handle_item['rotate_speed_max'],
+ 'diameter_slip_accuracy': knife_handle_item['diameter_slip_accuracy'],
+ 'cooling_model': knife_handle_item['cooling_model'],
+ 'fit_chuck_size': knife_handle_item['fit_chuck_size'],
+ 'is_quick_cutting': knife_handle_item['is_quick_cutting'],
+ 'is_safe_lock': knife_handle_item['is_safe_lock'],
+ 'screw': knife_handle_item['fit_wrench_model'],
+ 'nut': knife_handle_item['fit_nut_model'],
+ 'dynamic_balance_class': knife_handle_item['dynamic_balance_class'],
+ 'active': knife_handle_item['active']
+ })
else:
raise ValidationError("刀具物料基本参数认证未通过")
diff --git a/sf_mrs_connect/views/res_config_settings_views.xml b/sf_mrs_connect/views/res_config_settings_views.xml
index b879b1f8..0d1ccc3e 100644
--- a/sf_mrs_connect/views/res_config_settings_views.xml
+++ b/sf_mrs_connect/views/res_config_settings_views.xml
@@ -81,12 +81,30 @@
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+ 中控参数配置
+
+
diff --git a/sf_plan/views/view.xml b/sf_plan/views/view.xml
index 1e7ff0f6..68772142 100644
--- a/sf_plan/views/view.xml
+++ b/sf_plan/views/view.xml
@@ -71,7 +71,7 @@
-
+
diff --git a/sf_plan/wizard/action_plan_some.xml b/sf_plan/wizard/action_plan_some.xml
index 2c52658a..b659da03 100644
--- a/sf_plan/wizard/action_plan_some.xml
+++ b/sf_plan/wizard/action_plan_some.xml
@@ -6,7 +6,7 @@
-
+
+
+
+
+
+
+
+
+
diff --git a/sf_sale/views/res_partner_view.xml b/sf_sale/views/res_partner_view.xml
index 4b2d55d6..cc8f49fb 100644
--- a/sf_sale/views/res_partner_view.xml
+++ b/sf_sale/views/res_partner_view.xml
@@ -26,7 +26,7 @@
+ attrs="{'readonly': [('id','!=', False)]}"/>
{'required': [('phone', '=', False)],'readonly': [('id','!=', False)]}
@@ -37,19 +37,19 @@
- {'required': [('supplier_rank','>', 0)],'readonly': [('id','!=', False)]}
+ {'readonly': [('id','!=', False)]}
- {'required': [('supplier_rank','>', 0)],'readonly': [('id','!=', False)]}
+ {'readonly': [('id','!=', False)]}
- {'required': [('supplier_rank','>', 0)],'readonly': [('id','!=', False)]}
+ {'readonly': [('id','!=', False)]}
- {'required': [('supplier_rank','>', 0)],'readonly': [('id','!=', False)]}
+ {'readonly': [('id','!=', False)]}
diff --git a/sf_sale/views/sale_order_view.xml b/sf_sale/views/sale_order_view.xml
index b7a1ef96..f998887a 100644
--- a/sf_sale/views/sale_order_view.xml
+++ b/sf_sale/views/sale_order_view.xml
@@ -103,7 +103,7 @@
+ options='{"always_reload": True,"no_create": True}'/>
{'readonly': [('state', 'in', ['cancel','sale'])]}
diff --git a/sf_tool_management/__manifest__.py b/sf_tool_management/__manifest__.py
index a7750f69..fc556283 100644
--- a/sf_tool_management/__manifest__.py
+++ b/sf_tool_management/__manifest__.py
@@ -16,11 +16,13 @@
'security/ir.model.access.csv',
'wizard/wizard_view.xml',
'views/tool_base_views.xml',
+ 'views/functional_tool_views.xml',
'views/mrp_workcenter_views.xml',
'views/sf_maintenance_equipment.xml',
'views/menu_view.xml',
'views/tool_material_search.xml',
'views/fixture_material_search_views.xml',
+ 'data/tool_data.xml',
],
'demo': [
],
diff --git a/sf_tool_management/controllers/controllers.py b/sf_tool_management/controllers/controllers.py
index 0b003dc6..c8d6ee3f 100644
--- a/sf_tool_management/controllers/controllers.py
+++ b/sf_tool_management/controllers/controllers.py
@@ -22,14 +22,14 @@ class Manufacturing_Connect(http.Controller):
ret = json.loads(datas)
# ret = json.loads(ret['result'])
logging.info('DeviceId:%s' % ret)
- functional_tools = request.env['sf.functional.cutting.tool.entity'].sudo().search([])
+ functional_tools = request.env['sf.tool.inventory'].sudo().search([])
res = {'Succeed': True, 'Datas': []}
if functional_tools:
for item in functional_tools:
res['Datas'].append({
'GroupName': item.tool_groups_id.name,
- 'ToolId': item.code,
+ 'ToolId': item.functional_cutting_tool_model_id.name,
'ToolName': item.name
})
except Exception as e:
diff --git a/sf_tool_management/data/tool_data.xml b/sf_tool_management/data/tool_data.xml
index 714d03ee..282f8c2a 100644
--- a/sf_tool_management/data/tool_data.xml
+++ b/sf_tool_management/data/tool_data.xml
@@ -1,8 +1,12 @@
-
-
-
-
-
+
+ 定时同步刀具物料、功能刀具信息到cloud
+
+ code
+ model._cron_tool_datasync_all()
+ 1
+ days
+ -1
+
\ No newline at end of file
diff --git a/sf_tool_management/models/__init__.py b/sf_tool_management/models/__init__.py
index f73f5e3d..b589e095 100644
--- a/sf_tool_management/models/__init__.py
+++ b/sf_tool_management/models/__init__.py
@@ -1,4 +1,5 @@
from . import base
+from . import functional_tool
from . import tool_material_search
from . import maintenance_equipment
from . import mrp_workorder
diff --git a/sf_tool_management/models/base.py b/sf_tool_management/models/base.py
index 2c4b4364..83b4b550 100644
--- a/sf_tool_management/models/base.py
+++ b/sf_tool_management/models/base.py
@@ -1,483 +1,10 @@
# -*- coding: utf-8 -*-
-import re
-import json
-import requests
+import logging
+
from datetime import timedelta
from odoo import SUPERUSER_ID
from odoo import fields, models, api
from odoo.exceptions import ValidationError
-from odoo.addons.sf_base.commons.common import Common
-
-
-class FunctionalCuttingToolEntity(models.Model):
- _name = 'sf.functional.cutting.tool.entity'
- _description = '功能刀具列表'
-
- tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id')
- code = fields.Char('编码')
- rfid = fields.Char('rfid', readonly=True)
- name = fields.Char('名称')
- functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', 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_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型',
- group_expand='_read_group_mrs_cutting_tool_type_id', compute_sudo=True)
-
- functional_tool_diameter = fields.Integer(string='刀具直径(mm)', readonly=True)
- knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=True)
- coarse_middle_thin = fields.Selection([("1", "粗"), ('2', '中'), ('3', '精')], string='粗/中/精', readonly=True)
- new_former = fields.Selection([('0', '新'), ('1', '旧')], string='新/旧', readonly=True)
- tool_loading_length = fields.Float(string='总长度(mm)', readonly=True)
- functional_tool_length = fields.Float(string='伸出长(mm)', readonly=True)
- effective_length = fields.Float(string='有效长(mm)', readonly=True)
- tool_room_num = fields.Integer(string='刀具房数量', readonly=True)
- line_edge_knife_library_num = fields.Integer(string='线边刀库数量', readonly=True)
- machine_knife_library_num = fields.Integer(string='机内刀库数量', readonly=True)
- max_lifetime_value = fields.Integer(string='最大寿命值(min)', readonly=True)
- alarm_value = fields.Integer(string='报警值(min)', readonly=True)
- used_value = fields.Integer(string='已使用值(min)', readonly=True)
- functional_tool_status = fields.Selection([('正常', '正常'), ('报警', '报警'), ('已拆除', '已拆除')],
- string='状态', store=True, default='正常')
- current_location_id = fields.Many2one('stock.location', string='当前位置', readonly=True)
- current_location = fields.Selection(
- [('组装后', '组装后'), ('刀具房', '刀具房'), ('线边刀库', '线边刀库'), ('机内刀库', '机内刀库')],
- string='位置', compute='_compute_current_location_id', store=True)
- image = fields.Binary('图片', readonly=True)
-
- active = fields.Boolean(string='已归档', default=True)
-
- @api.depends('barcode_id.quant_ids')
- def _compute_current_location_id(self):
- for record in self:
- if record.barcode_id.quant_ids:
- for quant_id in record.barcode_id.quant_ids:
- if quant_id.inventory_quantity_auto_apply > 0:
- record.current_location_id = quant_id.location_id
- if quant_id.location_id.name == '制造前':
- record.current_location = '机内刀库'
- else:
- record.current_location = quant_id.location_id.name
- if record.current_location_id:
- record.sudo().get_location_num()
- else:
- record.current_location_id = False
- record.current_location = False
-
- def get_location_num(self):
- """
- 计算库存位置数量
- """
- for obj in self:
- 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 ['刀具房']:
- obj.tool_room_num = 1
- elif "线边刀库" in obj.current_location:
- obj.line_edge_knife_library_num = 1
- elif "机内刀库" in obj.current_location:
- obj.machine_knife_library_num = 1
-
- @api.model
- def _read_group_mrs_cutting_tool_type_id(self, categories, domain, order):
- mrs_cutting_tool_type_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
- return categories.browse(mrs_cutting_tool_type_ids)
-
- # 整体式刀具型号
- cutting_tool_integral_model_id = fields.Many2one('product.product', string='整体式刀具型号', readonly=True,
- domain=[('cutting_tool_material_id', '=', '整体式刀具')])
- # 刀片型号
- cutting_tool_blade_model_id = fields.Many2one('product.product', string='刀片型号', readonly=True,
- domain=[('cutting_tool_material_id', '=', '刀片')])
- # 刀杆型号
- cutting_tool_cutterbar_model_id = fields.Many2one('product.product', string='刀杆型号', readonly=True,
- domain=[('cutting_tool_material_id', '=', '刀杆')])
- # 刀盘型号
- cutting_tool_cutterpad_model_id = fields.Many2one('product.product', string='刀盘型号', readonly=True,
- domain=[('cutting_tool_material_id', '=', '刀盘')])
- # 刀柄型号
- cutting_tool_cutterhandle_model_id = fields.Many2one('product.product', string='刀柄型号', readonly=True,
- domain=[('cutting_tool_material_id', '=', '刀柄')])
- # 夹头型号
- cutting_tool_cutterhead_model_id = fields.Many2one('product.product', string='夹头型号', readonly=True,
- domain=[('cutting_tool_material_id', '=', '夹头')])
-
- whether_standard_knife = fields.Boolean(string='是否标准刀', default=True, readonly=True)
- L_D_number = fields.Float(string='L/D值(mm)', readonly=True)
- hiding_length = fields.Float(string='避空长(mm)', readonly=True)
- cut_time = fields.Integer(string='已切削时间(min)', readonly=True)
- cut_length = fields.Float(string='已切削长度(mm)', readonly=True)
- cut_number = fields.Integer(string='已切削次数', readonly=True)
-
- suitable_machining_method_ids = fields.Many2many(
- 'maintenance.equipment.image', 'rel_machining_product_template_tool_entity', '适合加工方式',
- domain=[('type', '=', '加工能力')], compute='_compute_maintenance_equipment_image')
- 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_tool_entity', '走刀方向',
- domain=[('type', '=', '走刀方向')])
- suitable_coolant_ids = fields.Many2many(
- 'maintenance.equipment.image', 'rel_coolants_product_template_tool_entity', '适合冷却方式',
- domain=[('type', '=', '冷却方式')])
-
- @api.depends('cutting_tool_integral_model_id', 'cutting_tool_blade_model_id')
- def _compute_maintenance_equipment_image(self):
- for record in self:
- if 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().blade_tip_characteristics_id = record.cutting_tool_integral_model_id.blade_tip_characteristics_id.id
- record.sudo().handle_type_id = record.cutting_tool_integral_model_id.handle_type_id.id
- record.sudo().cutting_direction_ids = record.cutting_tool_integral_model_id.cutting_direction_ids.ids
- record.sudo().suitable_coolant_ids = record.cutting_tool_integral_model_id.suitable_coolant_ids.ids
- print(record.cutting_tool_integral_model_id.blade_tip_characteristics_id.ids)
- elif record.cutting_tool_blade_model_id:
- record.sudo().suitable_machining_method_ids = record.cutting_tool_blade_model_id.suitable_machining_method_ids.ids
- record.sudo().blade_tip_characteristics_id = record.cutting_tool_blade_model_id.blade_tip_characteristics_id.id
- record.sudo().handle_type_id = record.cutting_tool_blade_model_id.handle_type_id.id
- record.sudo().cutting_direction_ids = record.cutting_tool_blade_model_id.cutting_direction_ids.ids
- record.sudo().suitable_coolant_ids = record.cutting_tool_blade_model_id.suitable_coolant_ids.ids
- else:
- record.sudo().suitable_machining_method_ids = []
- record.sudo().blade_tip_characteristics_id = None
- record.sudo().handle_type_id = None
- record.sudo().cutting_direction_ids = []
- record.sudo().suitable_coolant_ids = []
-
- def _get_functional_tool_model_ids(self, functional_tool_model_code):
- functional_tool_model_ids = []
- for item in functional_tool_model_code:
- functional_tool_model = self.env['sf.cutting_tool.standard.library'].search([('code', '=', item)])
- functional_tool_model_ids.append(functional_tool_model.id)
- return [(6, 0, functional_tool_model_ids)]
-
- def open_functional_tool_warning(self):
- action = self.env.ref('sf_tool_management.action_sf_functional_tool_warning')
- result = action.read()[0]
- result['domain'] = [('functional_tool_name_id', '=', self.functional_tool_name_id.id)]
- return result
-
- def open_stock_move_line(self):
- action = self.env.ref('sf_tool_management.sf_inbound_and_outbound_records_of_functional_tools_view_act')
- result = action.read()[0]
- result['domain'] = [('lot_id', '=', self.barcode_id.id), ('qty_done', '>', 0)]
- return result
-
- def open_safety_stock(self):
- action = self.env.ref('sf_tool_management.sf_real_time_distribution_of_functional_tools_view_act')
- result = action.read()[0]
- result['domain'] = [('name', '=', self.name), ('diameter', '=', self.functional_tool_diameter),
- ('knife_tip_r_angle', '=', self.knife_tip_r_angle),
- ('coarse_middle_thin', '=', self.coarse_middle_thin)]
- return result
-
- def tool_inventory_displacement_out(self):
- """
- 机床当前刀库实时信息接口,功能刀具出库
- """
- # 获取位置对象
- location_inventory_id = self.current_location_id
- stock_location_id = self.env['stock.location'].search([('name', '=', '制造前')])
- # 创建功能刀具该批次/序列号 库存移动和移动历史
- self.barcode_id.create_stock_quant(location_inventory_id, stock_location_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 create(self, vals):
- # obj = super(FunctionalCuttingToolEntity, self).create(vals)
- # # 调用刀具组接口
- # self._register_functional_tool_groups(obj)
- # return obj
-
-
-class FunctionalToolWarning(models.Model):
- _name = 'sf.functional.tool.warning'
- _description = '功能刀具预警'
-
- code = fields.Char('编码', related='functional_tool_name_id.code')
- rfid = fields.Char('rfid', related='functional_tool_name_id.rfid')
- tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id')
- name = fields.Char('名称', invisible=True, readonly=True, related='functional_tool_name_id.name')
- # 机床信息
- production_line_id = fields.Many2one('sf.production.line', string='生产线',
- group_expand='_read_group_machine_table_name_ids')
- maintenance_equipment_id = fields.Many2one('maintenance.equipment', string='CNC机床')
- machine_tool_code = fields.Char(string='机台号', related='maintenance_equipment_id.name')
- 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='刀位号',
- domain="[('equipment_id', '=', maintenance_equipment_id)]")
- # 功能刀具信息
- functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称')
- barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', related='functional_tool_name_id.barcode_id')
- mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型')
- diameter = fields.Integer(string='刀具直径(mm)')
- knife_tip_r_angle = fields.Float(string='刀尖R角(mm)')
- # 其他信息
- install_tool_time = fields.Datetime("刀具组装时间", related='functional_tool_name_id.tool_loading_time')
- on_board_time = fields.Datetime('上机装刀时间')
- max_lifetime_value = fields.Integer(string='最大寿命值(min)')
- alarm_value = fields.Integer(string='报警值(min)')
- used_value = fields.Integer(string='已使用值(min)')
- functional_tool_status = fields.Selection([('正常', '正常'), ('报警', '报警'), ('已拆除', '已拆除')], string='状态')
- alarm_time = fields.Datetime('报警时间')
- dispose_user = fields.Char('处理人')
- dispose_time = fields.Char('处理时间')
- dispose_func = fields.Char('处理方法/措施', readonly=False)
-
- active = fields.Boolean(string='已归档', default=True)
-
- @api.model
- def _read_group_machine_table_name_ids(self, categories, domain, order):
- machine_table_name_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
- return categories.browse(machine_table_name_ids)
-
- def create_tool_warning_record(self, obj):
- """
- 机台换刀申请报警状态时,创建功能刀具预警记录
- """
- if obj:
- for tool in obj.get('tool_changing_apply_id'):
- self.env['sf.functional.tool.warning'].create({
- 'production_line_id': tool.production_line_id.id,
- 'maintenance_equipment_id': tool.maintenance_equipment_id.id,
- 'machine_tool_code': tool.machine_tool_code,
- 'machine_table_type_id': tool.machine_table_type_id.id,
- 'cutter_spacing_code_id': tool.cutter_spacing_code_id.id,
- 'functional_tool_name_id': tool.functional_tool_name_id.id,
- 'barcode_id': tool.barcode_id.id,
- 'diameter': tool.diameter,
- 'knife_tip_r_angle': tool.knife_tip_r_angle,
- 'max_lifetime_value': tool.max_lifetime_value,
- 'alarm_value': tool.alarm_value,
- 'used_value': tool.used_value,
- 'functional_tool_status': tool.functional_tool_status,
- 'alarm_time': fields.Datetime.now(),
- })
-
-
-class StockMoveLine(models.Model):
- _inherit = 'stock.move.line'
- _description = '功能刀具出入库记录'
- _order = 'date desc'
-
- functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称')
- functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
- group_expand='_read_group_functional_tool_type_id')
- functional_tool_name = fields.Char('刀具名称')
- diameter = fields.Integer(string='刀具直径(mm)')
- knife_tip_r_angle = fields.Float(string='刀尖R角(mm)')
- install_tool_time = fields.Datetime("刀具组装时间", default=fields.Datetime.now())
- code = fields.Char('编码')
- rfid = fields.Char('rfid')
- tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组')
-
- @api.model
- def _read_group_functional_tool_type_id(self, categories, domain, order):
- names = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
- return categories.browse(names)
-
-
-class RealTimeDistributionOfFunctionalTools(models.Model):
- _name = 'sf.real.time.distribution.of.functional.tools'
- _description = '功能刀具安全库存'
-
- name = fields.Char('功能刀具名称', readonly=True, compute='_compute_name')
- tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', readonly=False, required=True)
- sf_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=False,
- group_expand='_read_mrs_cutting_tool_type_ids', store=True)
- diameter = fields.Integer(string='刀具直径(mm)', readonly=False)
- knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=False)
- tool_stock_num = fields.Integer(string='刀具房数量')
- side_shelf_num = fields.Integer(string='线边刀库数量')
- on_tool_stock_num = fields.Integer(string='机内刀库数量')
- tool_stock_total = fields.Integer(string='当前库存量', readonly=True)
- min_stock_num = fields.Integer('最低库存量')
- max_stock_num = fields.Integer('最高库存量')
- batch_replenishment_num = fields.Integer('批次补货量', readonly=True, compute='_compute_batch_replenishment_num')
- unit = fields.Char('单位')
- image = fields.Binary('图片', readonly=False)
-
- coarse_middle_thin = fields.Selection([("1", "粗"), ('2', '中'), ('3', '精')], string='粗/中/精', readonly=False)
- whether_standard_knife = fields.Boolean(string='是否标准刀', default=True, readonly=False)
- # 能力特征信息
- suitable_machining_method_ids = fields.Many2many(
- 'maintenance.equipment.image', 'rel_machining_product_template_distribution', '适合加工方式',
- domain=[('type', '=', '加工能力')],
- related='sf_functional_cutting_tool_entity_ids.suitable_machining_method_ids')
- blade_tip_characteristics_id = fields.Many2one(
- 'maintenance.equipment.image', '刀尖特征',
- domain=[('type', '=', '刀尖特征')],
- related='sf_functional_cutting_tool_entity_ids.blade_tip_characteristics_id')
- handle_type_id = fields.Many2one(
- 'maintenance.equipment.image', '柄部类型',
- domain=[('type', '=', '柄部类型')], related='sf_functional_cutting_tool_entity_ids.handle_type_id')
- cutting_direction_ids = fields.Many2many(
- 'maintenance.equipment.image', 'rel_cutting_product_template_distribution', '走刀方向',
- domain=[('type', '=', '走刀方向')], related='sf_functional_cutting_tool_entity_ids.cutting_direction_ids')
- suitable_coolant_ids = fields.Many2many(
- 'maintenance.equipment.image', 'rel_coolants_product_template_distribution', '适合冷却方式',
- domain=[('type', '=', '冷却方式')], related='sf_functional_cutting_tool_entity_ids.suitable_coolant_ids')
-
- sf_functional_cutting_tool_entity_ids = fields.Many2many('sf.functional.cutting.tool.entity',
- 'sf_functional_cutting_tool_entity_ref',
- string='功能刀具列表信息', readonly=True)
-
- sf_functional_tool_assembly_ids = fields.Many2many('sf.functional.tool.assembly', 'sf_functional_tool_assembly_ref',
- '功能刀具组装单', readonly=True)
-
- active = fields.Boolean(string='已归档', default=True)
-
- @api.depends('tool_groups_id', 'diameter', 'knife_tip_r_angle')
- def _compute_name(self):
- for obj in self:
- if obj.tool_groups_id:
- obj.sudo().name = '%s-D%sR%s' % (obj.tool_groups_id.name, obj.diameter, obj.knife_tip_r_angle)
- else:
- obj.sudo().name = None
-
- @api.constrains('min_stock_num', 'max_stock_num')
- def _check_stock_num(self):
- for obj in self:
- if obj.min_stock_num > obj.max_stock_num:
- raise ValidationError('【最低安全库存】不能高于【最高安全库存】!!!')
-
- @api.model
- def _read_mrs_cutting_tool_type_ids(self, categories, domain, order):
- mrs_cutting_tool_type_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
- return categories.browse(mrs_cutting_tool_type_ids)
-
- @api.depends('sf_functional_cutting_tool_entity_ids', 'min_stock_num', 'max_stock_num')
- def _compute_batch_replenishment_num(self):
- for tool in self:
- if tool:
- # 判断功能刀具组装单是否已经完成
- tool.sudo().estimate_functional_tool_assembly_ids(tool)
- tool.sudo().get_stock_num(tool)
- # 计算当前库存量
- tool.sudo().tool_stock_total = tool.tool_stock_num + tool.side_shelf_num + tool.on_tool_stock_num
- # 如果当前库存量小于最低库存量,计算批次补货量
- tool.sudo().open_batch_replenishment_num(tool)
-
- def open_batch_replenishment_num(self, tool):
- """
- 计算批次补货量
- """
- if tool.tool_stock_total < tool.min_stock_num:
- tool.sudo().batch_replenishment_num = tool.max_stock_num - tool.tool_stock_total
- # 根据判断创建功能刀具组装单
- if not tool.sf_functional_tool_assembly_ids and re.match(r'^\d+$', str(tool.id)):
- for i in range(tool.batch_replenishment_num):
- tool.sudo().create_functional_tool_assembly(tool)
- print(i, ": ", tool.sf_functional_tool_assembly_ids)
- else:
- tool.sudo().batch_replenishment_num = 0
-
- def create_functional_tool_assembly(self, tool):
- """
- 创建功能刀具组装单
- """
- functional_tool_assembly = tool.env['sf.functional.tool.assembly'].sudo().create({
- 'functional_tool_name': tool.name,
- 'functional_tool_type_id': tool.sf_cutting_tool_type_id.id,
- 'tool_groups_id': tool.tool_groups_id.id,
- 'functional_tool_diameter': tool.diameter,
- 'knife_tip_r_angle': tool.knife_tip_r_angle,
- 'coarse_middle_thin': tool.coarse_middle_thin,
- 'loading_task_source': '2',
- 'use_tool_time': fields.Datetime.now() + timedelta(hours=4),
- 'applicant': '系统自动',
- 'apply_time': fields.Datetime.now(),
- 'whether_standard_knife': tool.whether_standard_knife,
- 'reason_for_applying': '安全库存',
- })
- tool.sudo().sf_functional_tool_assembly_ids = [(4, functional_tool_assembly.id)]
-
- def estimate_functional_tool_assembly_ids(self, tool):
- """
- 判断功能刀具组装单是否完成,如果全部完成清空sf_functional_tool_assembly_ids的数据
- """
- for sf_functional_tool_assembly_id in tool.sf_functional_tool_assembly_ids:
- if sf_functional_tool_assembly_id.assemble_status == '0':
- return False
- tool.sudo().sf_functional_tool_assembly_ids = []
-
- def get_stock_num(self, tool):
- """
- 计算刀具房数量、线边刀库数量、机内刀库数量
- """
- if tool:
- tool.tool_stock_num = 0
- tool.side_shelf_num = 0
- tool.on_tool_stock_num = 0
- if 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:
- tool.tool_stock_num += 1
- elif cutting_tool.line_edge_knife_library_num > 0:
- tool.side_shelf_num += 1
- elif cutting_tool.machine_knife_library_num > 0:
- tool.on_tool_stock_num += 1
-
- def create_or_edit_safety_stock(self, vals, sf_functional_cutting_tool_entity_ids):
- """
- 根据传入的信息新增或者更新功能刀具安全库存的信息
- """
- # 根据功能刀具名称、刀具组、直径或尖刀R角、粗/中/精查询该功能刀具是否已经存在
- record = self.env['sf.real.time.distribution.of.functional.tools'].search(
- [('name', '=', vals['name']), ('sf_cutting_tool_type_id', '=', vals['sf_cutting_tool_type_id']),
- ('diameter', '=', vals['diameter']), ('knife_tip_r_angle', '=', vals['knife_tip_r_angle']),
- ('coarse_middle_thin', '=', vals['coarse_middle_thin']), ('tool_groups_id', '=', vals['tool_groups_id'])])
- if len(record) > 0:
- for obj in record:
- obj.write({'sf_functional_cutting_tool_entity_ids': [(4, sf_functional_cutting_tool_entity_ids.id)]})
- else:
- vals['sf_functional_cutting_tool_entity_ids'] = sf_functional_cutting_tool_entity_ids.ids
- self.env['sf.real.time.distribution.of.functional.tools'].create(vals)
-
- status_create = fields.Boolean('是否是新增状态', default=True)
-
- @api.model_create_multi
- def create(self, vals_list):
- for vals in vals_list:
- vals['status_create'] = False
- records = super(RealTimeDistributionOfFunctionalTools, self).create(vals_list)
- 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):
@@ -502,7 +29,7 @@ class MachineTableToolChangingApply(models.Model):
barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', store=True,
domain=[('product_id.name', '=', '功能刀具')],
related='functional_tool_name_id.barcode_id')
- rfid = fields.Char('rfid', related='functional_tool_name_id.rfid')
+ rfid = fields.Char('Rfid', related='functional_tool_name_id.rfid')
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', domain=[('assemble_status', '=', '1')],
string='功能刀具名称')
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
@@ -666,7 +193,7 @@ class CAMWorkOrderProgramKnifePlan(models.Model):
machine_table_name_id = fields.Many2one('maintenance.equipment', string='机床名称',
domain="[('production_line_id', '=', production_line_id)]")
machine_table_name = fields.Char(string='机台号', readonly=True, related='machine_table_name_id.name')
- cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号', required=True,
+ cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号',
domain="[('equipment_id', '=', machine_table_name_id)]")
whether_standard_knife = fields.Boolean(string='是否标准刀', default=True)
need_knife_time = fields.Datetime(string='用刀时间', readonly=False)
@@ -676,19 +203,20 @@ class CAMWorkOrderProgramKnifePlan(models.Model):
barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号',
domain=[('product_id.name', '=', '功能刀具')])
- functional_tool_name = fields.Char(string='功能刀具名称', compute='_compute_functional_tool_name')
- functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=False)
- tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组')
- diameter = fields.Integer(string='刀具直径(mm)', readonly=False)
- tool_included_angle = fields.Float(string='刀尖R角(mm)', readonly=False)
- tool_loading_length = fields.Float(string='总长度(mm)', readonly=False)
+ functional_tool_name = fields.Char(string='功能刀具名称', readonly=True)
+ functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型',
+ compute='_compute_tool_number', store=True)
+ tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_tool_number', store=True)
+ diameter = fields.Integer(string='刀具直径(mm)', compute='_compute_tool_number', store=True)
+ tool_included_angle = fields.Float(string='刀尖R角(mm)', compute='_compute_tool_number', store=True)
+ tool_loading_length = fields.Float(string='总长度(mm)', compute='_compute_tool_number', store=True)
extension_length = fields.Float(string='伸出长(mm)')
effective_length = fields.Float(string='有效长(mm)')
new_former = fields.Selection([('0', '新'), ('1', '旧')], string='新/旧', readonly=False, default='0')
coarse_middle_thin = fields.Selection([("1", "粗"), ('2', '中'), ('3', '精')], default='3',
string='粗/中/精', readonly=False)
L_D = fields.Float(string='L/D值', readonly=False)
- clearance_length = fields.Float(string='避空长(mm)', readonly=False)
+ clearance_length = fields.Float(string='避空长(mm)', compute='_compute_tool_number', store=True)
required_cutting_time = fields.Integer(string='需切削时长', readonly=False)
process_type = fields.Char('加工类型')
margin_x_y = fields.Float('余量_X/Y')
@@ -704,15 +232,24 @@ class CAMWorkOrderProgramKnifePlan(models.Model):
active = fields.Boolean(string='已归档', default=True)
- @api.depends('diameter', 'tool_included_angle', 'tool_groups_id')
- def _compute_functional_tool_name(self):
- for obj in self:
- if obj.tool_groups_id:
- obj.functional_tool_name = '%s-D%sR%s' % (
- obj.tool_groups_id.name, obj.diameter,
- obj.tool_included_angle)
+ @api.depends('functional_tool_name')
+ def _compute_tool_number(self):
+ for item in self:
+ inventory = self.env['sf.tool.inventory'].sudo().search([('name', '=', item.functional_tool_name)])
+ if inventory:
+ item.functional_tool_type_id = inventory.functional_cutting_tool_model_id.id
+ item.tool_groups_id = inventory.tool_groups_id.id
+ item.diameter = int(inventory.diameter)
+ item.tool_included_angle = inventory.angle
+ item.tool_loading_length = inventory.tool_length
+ item.clearance_length = inventory.blade_length
else:
- obj.functional_tool_name = None
+ item.functional_tool_type_id = False
+ item.tool_groups_id = False
+ item.diameter = 0
+ item.tool_included_angle = 0
+ item.tool_loading_length = 0
+ item.clearance_length = 0
@api.model
def _read_group_names(self, categories, domain, order):
@@ -786,10 +323,9 @@ class CAMWorkOrderProgramKnifePlan(models.Model):
根据传入的工单信息,查询是否有需要的功能刀具,如果没有则生成CAM工单程序用刀计划
"""
status = False
- if cnc_processing.functional_tool_type_id and cnc_processing.cutting_tool_name:
+ if cnc_processing.cutting_tool_name:
functional_tools = self.env['sf.real.time.distribution.of.functional.tools'].sudo().search(
- [('sf_cutting_tool_type_id', '=', cnc_processing.functional_tool_type_id.id),
- ('name', '=', cnc_processing.cutting_tool_name)])
+ [('name', '=', cnc_processing.cutting_tool_name)])
if functional_tools:
for functional_tool in functional_tools:
if functional_tool.on_tool_stock_num == 0:
@@ -802,7 +338,6 @@ class CAMWorkOrderProgramKnifePlan(models.Model):
'name': cnc_processing.workorder_id.production_id.name,
'cam_procedure_code': cnc_processing.program_name,
'filename': cnc_processing.cnc_id.name,
- 'functional_tool_type_id': cnc_processing.functional_tool_type_id.id,
'functional_tool_name': cnc_processing.cutting_tool_name,
'cam_cutter_spacing_code': cnc_processing.cutting_tool_no,
'process_type': cnc_processing.processing_type,
@@ -813,8 +348,11 @@ class CAMWorkOrderProgramKnifePlan(models.Model):
'shank_model': cnc_processing.cutting_tool_handle_type,
'estimated_processing_time': cnc_processing.estimated_processing_time,
})
+ logging.info('CAM工单程序用刀计划创建成功!!!')
# 创建装刀请求
knife_plan.apply_for_tooling()
+ else:
+ logging.info('功能刀具【%s】满足CNC用刀需求!!!')
class FunctionalToolAssembly(models.Model):
@@ -825,10 +363,10 @@ class FunctionalToolAssembly(models.Model):
@api.depends('functional_tool_name')
def _compute_name(self):
for obj in self:
- obj.name = obj.after_assembly_functional_tool_name
+ obj.name = obj.assembly_order_code
code = fields.Char('功能刀具编码', readonly=True)
- rfid = fields.Char('rfid', readonly=True)
+ rfid = fields.Char('Rfid', readonly=True)
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', readonly=True)
name = fields.Char(string='名称', readonly=True, compute='_compute_name')
assembly_order_code = fields.Char(string='组装单编码', readonly=True)
@@ -870,56 +408,141 @@ class FunctionalToolAssembly(models.Model):
return categories.browse(functional_tool_type_ids)
# 刀具物料信息
- # 整体式刀具型号
- integral_code_id = fields.Many2one('stock.lot', string='整体式刀具序列号', readonly=True)
+ # ==============整体式刀具型号============
+ integral_freight_barcode = fields.Char('整体式刀具货位')
+ integral_product_id = fields.Many2one('product.product', string='整体式刀具名称',
+ compute='_compute_integral_product_id', store=True)
cutting_tool_integral_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='整体式刀具型号',
- related='integral_code_id.product_id.cutting_tool_model_id')
- integral_name = fields.Char('整体式刀具名称', related='integral_code_id.product_id.name')
+ related='integral_product_id.cutting_tool_model_id')
integral_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='整体式刀具规格',
- related='integral_code_id.product_id.specification_id')
+ related='integral_product_id.specification_id')
sf_tool_brand_id_1 = fields.Many2one('sf.machine.brand', string='整体式刀具品牌',
- related='integral_code_id.product_id.brand_id')
- # 刀片型号
- blade_code_id = fields.Many2one('stock.lot', '刀片序列号', readonly=True)
- cutting_tool_blade_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀片型号',
- related='blade_code_id.product_id.cutting_tool_model_id')
- blade_name = fields.Char('刀片名称', related='blade_code_id.product_id.name')
- blade_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀片规格',
- related='blade_code_id.product_id.specification_id')
- sf_tool_brand_id_2 = fields.Many2one('sf.machine.brand', '刀片品牌', related='blade_code_id.product_id.brand_id')
- # 刀杆型号
- bar_code_id = fields.Many2one('stock.lot', '刀杆序列号', readonly=True)
- cutting_tool_cutterbar_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀杆型号',
- related='bar_code_id.product_id.cutting_tool_model_id')
- bar_name = fields.Char('刀杆名称', related='bar_code_id.product_id.name')
- bar_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀杆规格',
- related='bar_code_id.product_id.specification_id')
- sf_tool_brand_id_3 = fields.Many2one('sf.machine.brand', '刀杆品牌', related='bar_code_id.product_id.brand_id')
- # 刀盘型号
- pad_code_id = fields.Many2one('stock.lot', '刀盘序列号', readonly=True)
- cutting_tool_cutterpad_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀盘型号',
- related='pad_code_id.product_id.cutting_tool_model_id')
- pad_name = fields.Char('刀盘名称', related='pad_code_id.product_id.name')
- pad_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀盘规格',
- related='pad_code_id.product_id.specification_id')
- sf_tool_brand_id_4 = fields.Many2one('sf.machine.brand', '刀盘品牌', related='pad_code_id.product_id.brand_id')
- # 刀柄型号
- handle_code_id = fields.Many2one('stock.lot', '刀柄序列号', readonly=True)
- cutting_tool_cutterhandle_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀柄型号',
- related='handle_code_id.product_id.cutting_tool_model_id')
- handle_name = fields.Char('刀柄名称', related='handle_code_id.product_id.name')
- handle_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀柄规格',
- related='handle_code_id.product_id.specification_id')
- sf_tool_brand_id_5 = fields.Many2one('sf.machine.brand', '刀柄品牌', related='handle_code_id.product_id.brand_id')
- # 夹头型号
- chuck_code_id = fields.Many2one('stock.lot', '夹头序列号', readonly=True)
- cutting_tool_cutterhead_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='夹头型号',
- related='chuck_code_id.product_id.cutting_tool_model_id')
- chuck_name = fields.Char('夹头名称', related='chuck_code_id.product_id.name')
- chuck_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='夹头规格',
- related='chuck_code_id.product_id.specification_id')
- sf_tool_brand_id_6 = fields.Many2one('sf.machine.brand', '夹头品牌', related='chuck_code_id.product_id.brand_id')
+ related='integral_product_id.brand_id')
+ @api.depends('integral_freight_barcode')
+ def _compute_integral_product_id(self):
+ for item in self:
+ if item.integral_freight_barcode:
+ location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.integral_freight_barcode)])
+ if location:
+ item.integral_product_id = location.product_id.id
+ else:
+ item.integral_product_id = False
+
+ # =================刀片型号=============
+ blade_freight_barcode = fields.Char('刀片货位')
+ blade_product_id = fields.Many2one('product.product', string='刀片名称', compute='_compute_blade_product_id',
+ store=True)
+ cutting_tool_blade_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀片型号',
+ related='blade_product_id.cutting_tool_model_id')
+ blade_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀片规格',
+ related='blade_product_id.specification_id')
+ sf_tool_brand_id_2 = fields.Many2one('sf.machine.brand', '刀片品牌', related='blade_product_id.brand_id')
+
+ @api.depends('blade_freight_barcode')
+ def _compute_blade_product_id(self):
+ for item in self:
+ if item.integral_freight_barcode:
+ location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.blade_freight_barcode)])
+ if location:
+ item.blade_product_id = location.product_id.id
+ else:
+ item.blade_product_id = False
+
+ # ==============刀杆型号================
+ bar_freight_barcode = fields.Char('刀杆货位')
+ bar_product_id = fields.Many2one('product.product', string='刀杆名称', compute='_compute_bar_product_id',
+ store=True)
+ cutting_tool_cutterbar_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀杆型号',
+ related='bar_product_id.cutting_tool_model_id')
+ bar_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀杆规格',
+ related='bar_product_id.specification_id')
+ sf_tool_brand_id_3 = fields.Many2one('sf.machine.brand', '刀杆品牌', related='bar_product_id.brand_id')
+
+ @api.depends('bar_freight_barcode')
+ def _compute_bar_product_id(self):
+ for item in self:
+ if item.integral_freight_barcode:
+ location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.bar_freight_barcode)])
+ if location:
+ item.bar_product_id = location.product_id.id
+ else:
+ item.bar_product_id = False
+
+ # =============刀盘型号================
+ pad_freight_barcode = fields.Char('刀盘货位')
+ pad_product_id = fields.Many2one('product.product', string='刀盘名称', compute='_compute_pad_product_id',
+ store=True)
+ cutting_tool_cutterpad_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀盘型号',
+ related='pad_product_id.cutting_tool_model_id')
+ pad_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀盘规格',
+ related='pad_product_id.specification_id')
+ sf_tool_brand_id_4 = fields.Many2one('sf.machine.brand', '刀盘品牌', related='pad_product_id.brand_id')
+
+ @api.depends('pad_freight_barcode')
+ def _compute_pad_product_id(self):
+ for item in self:
+ if item.integral_freight_barcode:
+ location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.pad_freight_barcode)])
+ if location:
+ item.pad_product_id = location.product_id.id
+ else:
+ item.pad_product_id = False
+
+ # ==============刀柄型号==============
+ handle_freight_rfid = fields.Char('刀柄Rfid', compute='_compute_handle_product_id', store=True)
+ handle_code_id = fields.Many2one('stock.lot', '刀柄序列号')
+ handle_product_id = fields.Many2one('product.product', string='刀柄名称', compute='_compute_handle_product_id',
+ store=True)
+ cutting_tool_cutterhandle_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀柄型号',
+ related='handle_product_id.cutting_tool_model_id')
+ handle_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀柄规格',
+ related='handle_product_id.specification_id')
+ sf_tool_brand_id_5 = fields.Many2one('sf.machine.brand', '刀柄品牌', related='handle_product_id.brand_id')
+
+ @api.depends('handle_code_id')
+ def _compute_handle_product_id(self):
+ for item in self:
+ if item.handle_code_id:
+ item.handle_product_id = item.handle_code_id.product_id.id
+ item.handle_freight_rfid = item.handle_code_id.rfid
+ else:
+ item.handle_product_id = False
+ item.handle_freight_rfid = False
+
+ # ==============夹头型号==============
+ chuck_freight_barcode = fields.Char('夹头货位')
+ chuck_product_id = fields.Many2one('product.product', string='夹头名称', compute='_compute_chuck_product_id',
+ store=True)
+ cutting_tool_cutterhead_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='夹头型号',
+ related='chuck_product_id.cutting_tool_model_id')
+ chuck_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='夹头规格',
+ related='chuck_product_id.specification_id')
+ sf_tool_brand_id_6 = fields.Many2one('sf.machine.brand', '夹头品牌', related='chuck_product_id.brand_id')
+
+ @api.depends('chuck_freight_barcode')
+ def _compute_chuck_product_id(self):
+ for item in self:
+ if item.integral_freight_barcode:
+ location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.chuck_freight_barcode)])
+ if location:
+ item.chuck_product_id = location.product_id.id
+ else:
+ item.chuck_product_id = False
+
+ # ==================待删除字段==================
+ blade_name = fields.Char('')
+ integral_name = fields.Char('')
+ blade_code_id = fields.Many2one('stock.lot', '刀片序列号')
+ integral_code_id = fields.Many2one('stock.lot', '整体式刀具序列号')
+ bar_code_id = fields.Many2one('stock.lot', '刀杆序列号')
+ bar_name = fields.Char('')
+ pad_code_id = fields.Many2one('stock.lot', '刀盘序列号')
+ pad_name = fields.Char('')
+ handle_name = fields.Char('')
+ chuck_code_id = fields.Many2one('stock.lot', '夹头序列号')
+ chuck_name = fields.Char('')
+ # ==============================================
# 组装功能刀具参数信息
barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', readonly=True)
after_assembly_functional_tool_name = fields.Char(string='组装后功能刀具名称', readonly=True)
diff --git a/sf_tool_management/models/functional_tool.py b/sf_tool_management/models/functional_tool.py
new file mode 100644
index 00000000..c37d5317
--- /dev/null
+++ b/sf_tool_management/models/functional_tool.py
@@ -0,0 +1,481 @@
+# -*- coding: utf-8 -*-
+import re
+from datetime import timedelta
+from odoo import SUPERUSER_ID
+from odoo import fields, models, api
+from odoo.exceptions import ValidationError
+
+
+class FunctionalCuttingToolEntity(models.Model):
+ _name = 'sf.functional.cutting.tool.entity'
+ _description = '功能刀具列表'
+
+ functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具组装单', readonly=True)
+ tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id')
+ code = fields.Char('编码')
+ rfid = fields.Char('Rfid', readonly=True)
+ name = fields.Char('名称')
+ tool_name_id = fields.Many2one('sf.tool.inventory', '功能刀具名称')
+ sf_cutting_tool_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀具型号')
+ barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', readonly=True)
+ sf_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型',
+ group_expand='_read_group_mrs_cutting_tool_type_id', compute_sudo=True)
+
+ functional_tool_diameter = fields.Integer(string='刀具直径(mm)', readonly=True)
+ knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=True)
+ coarse_middle_thin = fields.Selection([("1", "粗"), ('2', '中'), ('3', '精')], string='粗/中/精', readonly=True)
+ new_former = fields.Selection([('0', '新'), ('1', '旧')], string='新/旧', readonly=True)
+ tool_loading_length = fields.Float(string='总长度(mm)', readonly=True)
+ functional_tool_length = fields.Float(string='伸出长(mm)', readonly=True)
+ effective_length = fields.Float(string='有效长(mm)', readonly=True)
+ tool_room_num = fields.Integer(string='刀具房数量', readonly=True)
+ line_edge_knife_library_num = fields.Integer(string='线边刀库数量', readonly=True)
+ machine_knife_library_num = fields.Integer(string='机内刀库数量', readonly=True)
+ max_lifetime_value = fields.Integer(string='最大寿命值(min)', readonly=True)
+ alarm_value = fields.Integer(string='报警值(min)', readonly=True)
+ used_value = fields.Integer(string='已使用值(min)', readonly=True)
+ functional_tool_status = fields.Selection([('正常', '正常'), ('报警', '报警'), ('已拆除', '已拆除')],
+ string='状态', store=True, default='正常')
+ current_location_id = fields.Many2one('stock.location', string='当前位置', readonly=True)
+ current_location = fields.Selection(
+ [('组装后', '组装后'), ('刀具房', '刀具房'), ('线边刀库', '线边刀库'), ('机内刀库', '机内刀库')],
+ string='位置', compute='_compute_current_location_id', store=True)
+ image = fields.Binary('图片', readonly=True)
+
+ active = fields.Boolean(string='已归档', default=True)
+
+ @api.depends('barcode_id.quant_ids')
+ def _compute_current_location_id(self):
+ for record in self:
+ if record.barcode_id.quant_ids:
+ for quant_id in record.barcode_id.quant_ids:
+ if quant_id.inventory_quantity_auto_apply > 0:
+ record.current_location_id = quant_id.location_id
+ if quant_id.location_id.name == '制造前':
+ record.current_location = '机内刀库'
+ else:
+ record.current_location = quant_id.location_id.name
+ if record.current_location_id:
+ record.sudo().get_location_num()
+ else:
+ record.current_location_id = False
+ record.current_location = False
+
+ def get_location_num(self):
+ """
+ 计算库存位置数量
+ """
+ for obj in self:
+ 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 ['刀具房']:
+ obj.tool_room_num = 1
+ elif "线边刀库" in obj.current_location:
+ obj.line_edge_knife_library_num = 1
+ elif "机内刀库" in obj.current_location:
+ obj.machine_knife_library_num = 1
+
+ @api.model
+ def _read_group_mrs_cutting_tool_type_id(self, categories, domain, order):
+ mrs_cutting_tool_type_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
+ return categories.browse(mrs_cutting_tool_type_ids)
+
+ # 整体式刀具型号
+ cutting_tool_integral_model_id = fields.Many2one('product.product', string='整体式刀具型号', readonly=True,
+ domain=[('cutting_tool_material_id', '=', '整体式刀具')])
+ # 刀片型号
+ cutting_tool_blade_model_id = fields.Many2one('product.product', string='刀片型号', readonly=True,
+ domain=[('cutting_tool_material_id', '=', '刀片')])
+ # 刀杆型号
+ cutting_tool_cutterbar_model_id = fields.Many2one('product.product', string='刀杆型号', readonly=True,
+ domain=[('cutting_tool_material_id', '=', '刀杆')])
+ # 刀盘型号
+ cutting_tool_cutterpad_model_id = fields.Many2one('product.product', string='刀盘型号', readonly=True,
+ domain=[('cutting_tool_material_id', '=', '刀盘')])
+ # 刀柄型号
+ cutting_tool_cutterhandle_model_id = fields.Many2one('product.product', string='刀柄型号', readonly=True,
+ domain=[('cutting_tool_material_id', '=', '刀柄')])
+ # 夹头型号
+ cutting_tool_cutterhead_model_id = fields.Many2one('product.product', string='夹头型号', readonly=True,
+ domain=[('cutting_tool_material_id', '=', '夹头')])
+
+ whether_standard_knife = fields.Boolean(string='是否标准刀', default=True, readonly=True)
+ L_D_number = fields.Float(string='L/D值(mm)', readonly=True)
+ hiding_length = fields.Float(string='避空长(mm)', readonly=True)
+ cut_time = fields.Integer(string='已切削时间(min)', readonly=True)
+ cut_length = fields.Float(string='已切削长度(mm)', readonly=True)
+ cut_number = fields.Integer(string='已切削次数', readonly=True)
+
+ suitable_machining_method_ids = fields.Many2many(
+ 'maintenance.equipment.image', 'rel_machining_product_template_tool_entity', '适合加工方式',
+ domain=[('type', '=', '加工能力')], compute='_compute_maintenance_equipment_image')
+ 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_tool_entity', '走刀方向',
+ domain=[('type', '=', '走刀方向')])
+ suitable_coolant_ids = fields.Many2many(
+ 'maintenance.equipment.image', 'rel_coolants_product_template_tool_entity', '适合冷却方式',
+ domain=[('type', '=', '冷却方式')])
+
+ @api.depends('cutting_tool_integral_model_id', 'cutting_tool_blade_model_id')
+ def _compute_maintenance_equipment_image(self):
+ for record in self:
+ if 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().blade_tip_characteristics_id = record.cutting_tool_integral_model_id.blade_tip_characteristics_id.id
+ record.sudo().handle_type_id = record.cutting_tool_integral_model_id.handle_type_id.id
+ record.sudo().cutting_direction_ids = record.cutting_tool_integral_model_id.cutting_direction_ids.ids
+ record.sudo().suitable_coolant_ids = record.cutting_tool_integral_model_id.suitable_coolant_ids.ids
+ print(record.cutting_tool_integral_model_id.blade_tip_characteristics_id.ids)
+ elif record.cutting_tool_blade_model_id:
+ record.sudo().suitable_machining_method_ids = record.cutting_tool_blade_model_id.suitable_machining_method_ids.ids
+ record.sudo().blade_tip_characteristics_id = record.cutting_tool_blade_model_id.blade_tip_characteristics_id.id
+ record.sudo().handle_type_id = record.cutting_tool_blade_model_id.handle_type_id.id
+ record.sudo().cutting_direction_ids = record.cutting_tool_blade_model_id.cutting_direction_ids.ids
+ record.sudo().suitable_coolant_ids = record.cutting_tool_blade_model_id.suitable_coolant_ids.ids
+ else:
+ record.sudo().suitable_machining_method_ids = []
+ record.sudo().blade_tip_characteristics_id = None
+ record.sudo().handle_type_id = None
+ record.sudo().cutting_direction_ids = []
+ record.sudo().suitable_coolant_ids = []
+
+ def _get_functional_tool_model_ids(self, functional_tool_model_code):
+ functional_tool_model_ids = []
+ for item in functional_tool_model_code:
+ functional_tool_model = self.env['sf.cutting_tool.standard.library'].search([('code', '=', item)])
+ functional_tool_model_ids.append(functional_tool_model.id)
+ return [(6, 0, functional_tool_model_ids)]
+
+ def open_functional_tool_warning(self):
+ action = self.env.ref('sf_tool_management.action_sf_functional_tool_warning')
+ result = action.read()[0]
+ result['domain'] = [('functional_tool_name_id', '=', self.functional_tool_name_id.id)]
+ return result
+
+ def open_stock_move_line(self):
+ action = self.env.ref('sf_tool_management.sf_inbound_and_outbound_records_of_functional_tools_view_act')
+ result = action.read()[0]
+ result['domain'] = [('lot_id', '=', self.barcode_id.id), ('qty_done', '>', 0)]
+ return result
+
+ def open_safety_stock(self):
+ action = self.env.ref('sf_tool_management.sf_real_time_distribution_of_functional_tools_view_act')
+ result = action.read()[0]
+ result['domain'] = [('name', '=', self.name), ('diameter', '=', self.functional_tool_diameter),
+ ('knife_tip_r_angle', '=', self.knife_tip_r_angle),
+ ('coarse_middle_thin', '=', self.coarse_middle_thin)]
+ return result
+
+ def tool_inventory_displacement_out(self):
+ """
+ 机床当前刀库实时信息接口,功能刀具出库
+ """
+ # 获取位置对象
+ location_inventory_id = self.current_location_id
+ stock_location_id = self.env['stock.location'].search([('name', '=', '制造前')])
+ # 创建功能刀具该批次/序列号 库存移动和移动历史
+ self.barcode_id.create_stock_quant(location_inventory_id, stock_location_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 create(self, vals):
+ # obj = super(FunctionalCuttingToolEntity, self).create(vals)
+ # # 调用刀具组接口
+ # self._register_functional_tool_groups(obj)
+ # return obj
+
+
+class FunctionalToolWarning(models.Model):
+ _name = 'sf.functional.tool.warning'
+ _description = '功能刀具预警'
+
+ code = fields.Char('编码', related='functional_tool_name_id.code')
+ rfid = fields.Char('Rfid', related='functional_tool_name_id.rfid')
+ tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id')
+ name = fields.Char('名称', invisible=True, readonly=True, related='functional_tool_name_id.name')
+ # 机床信息
+ production_line_id = fields.Many2one('sf.production.line', string='生产线',
+ group_expand='_read_group_machine_table_name_ids')
+ maintenance_equipment_id = fields.Many2one('maintenance.equipment', string='CNC机床')
+ machine_tool_code = fields.Char(string='机台号', related='maintenance_equipment_id.name')
+ 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='刀位号',
+ domain="[('equipment_id', '=', maintenance_equipment_id)]")
+ # 功能刀具信息
+ functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称')
+ barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', related='functional_tool_name_id.barcode_id')
+ mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型')
+ diameter = fields.Integer(string='刀具直径(mm)')
+ knife_tip_r_angle = fields.Float(string='刀尖R角(mm)')
+ # 其他信息
+ install_tool_time = fields.Datetime("刀具组装时间", related='functional_tool_name_id.tool_loading_time')
+ on_board_time = fields.Datetime('上机装刀时间')
+ max_lifetime_value = fields.Integer(string='最大寿命值(min)')
+ alarm_value = fields.Integer(string='报警值(min)')
+ used_value = fields.Integer(string='已使用值(min)')
+ functional_tool_status = fields.Selection([('正常', '正常'), ('报警', '报警'), ('已拆除', '已拆除')], string='状态')
+ alarm_time = fields.Datetime('报警时间')
+ dispose_user = fields.Char('处理人')
+ dispose_time = fields.Char('处理时间')
+ dispose_func = fields.Char('处理方法/措施', readonly=False)
+
+ active = fields.Boolean(string='已归档', default=True)
+
+ @api.model
+ def _read_group_machine_table_name_ids(self, categories, domain, order):
+ machine_table_name_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
+ return categories.browse(machine_table_name_ids)
+
+ def create_tool_warning_record(self, obj):
+ """
+ 机台换刀申请报警状态时,创建功能刀具预警记录
+ """
+ if obj:
+ for tool in obj.get('tool_changing_apply_id'):
+ self.env['sf.functional.tool.warning'].create({
+ 'production_line_id': tool.production_line_id.id,
+ 'maintenance_equipment_id': tool.maintenance_equipment_id.id,
+ 'machine_tool_code': tool.machine_tool_code,
+ 'machine_table_type_id': tool.machine_table_type_id.id,
+ 'cutter_spacing_code_id': tool.cutter_spacing_code_id.id,
+ 'functional_tool_name_id': tool.functional_tool_name_id.id,
+ 'barcode_id': tool.barcode_id.id,
+ 'diameter': tool.diameter,
+ 'knife_tip_r_angle': tool.knife_tip_r_angle,
+ 'max_lifetime_value': tool.max_lifetime_value,
+ 'alarm_value': tool.alarm_value,
+ 'used_value': tool.used_value,
+ 'functional_tool_status': tool.functional_tool_status,
+ 'alarm_time': fields.Datetime.now(),
+ })
+
+
+class StockMoveLine(models.Model):
+ _inherit = 'stock.move.line'
+ _description = '功能刀具出入库记录'
+ _order = 'date desc'
+
+ functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具组装单')
+ functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
+ group_expand='_read_group_functional_tool_type_id')
+ functional_tool_name = fields.Char('刀具名称')
+ diameter = fields.Integer(string='刀具直径(mm)')
+ knife_tip_r_angle = fields.Float(string='刀尖R角(mm)')
+ install_tool_time = fields.Datetime("刀具组装时间", default=fields.Datetime.now())
+ code = fields.Char('编码')
+ rfid = fields.Char('Rfid')
+ tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组')
+
+ @api.model
+ def _read_group_functional_tool_type_id(self, categories, domain, order):
+ names = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
+ return categories.browse(names)
+
+
+class RealTimeDistributionOfFunctionalTools(models.Model):
+ _name = 'sf.real.time.distribution.of.functional.tools'
+ _description = '功能刀具安全库存'
+
+ name = fields.Char('名称', readonly=True, compute='_compute_name', store=True)
+ functional_name_id = fields.Many2one('sf.tool.inventory', string='功能刀具名称', required=True)
+ tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', readonly=False, required=True)
+ sf_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=False,
+ group_expand='_read_mrs_cutting_tool_type_ids', store=True)
+ diameter = fields.Integer(string='刀具直径(mm)', readonly=False)
+ knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=False)
+ tool_stock_num = fields.Integer(string='刀具房数量')
+ side_shelf_num = fields.Integer(string='线边刀库数量')
+ on_tool_stock_num = fields.Integer(string='机内刀库数量')
+ tool_stock_total = fields.Integer(string='当前库存量', readonly=True)
+ min_stock_num = fields.Integer('最低库存量')
+ max_stock_num = fields.Integer('最高库存量')
+ batch_replenishment_num = fields.Integer('批次补货量', readonly=True, compute='_compute_batch_replenishment_num')
+ unit = fields.Char('单位')
+ image = fields.Binary('图片', readonly=False)
+
+ coarse_middle_thin = fields.Selection([("1", "粗"), ('2', '中'), ('3', '精')], string='粗/中/精', readonly=False)
+ whether_standard_knife = fields.Boolean(string='是否标准刀', default=True, readonly=False)
+ # 能力特征信息
+ suitable_machining_method_ids = fields.Many2many(
+ 'maintenance.equipment.image', 'rel_machining_product_template_distribution', '适合加工方式',
+ domain=[('type', '=', '加工能力')],
+ related='sf_functional_cutting_tool_entity_ids.suitable_machining_method_ids')
+ blade_tip_characteristics_id = fields.Many2one(
+ 'maintenance.equipment.image', '刀尖特征',
+ domain=[('type', '=', '刀尖特征')],
+ related='sf_functional_cutting_tool_entity_ids.blade_tip_characteristics_id')
+ handle_type_id = fields.Many2one(
+ 'maintenance.equipment.image', '柄部类型',
+ domain=[('type', '=', '柄部类型')], related='sf_functional_cutting_tool_entity_ids.handle_type_id')
+ cutting_direction_ids = fields.Many2many(
+ 'maintenance.equipment.image', 'rel_cutting_product_template_distribution', '走刀方向',
+ domain=[('type', '=', '走刀方向')], related='sf_functional_cutting_tool_entity_ids.cutting_direction_ids')
+ suitable_coolant_ids = fields.Many2many(
+ 'maintenance.equipment.image', 'rel_coolants_product_template_distribution', '适合冷却方式',
+ domain=[('type', '=', '冷却方式')], related='sf_functional_cutting_tool_entity_ids.suitable_coolant_ids')
+
+ sf_functional_cutting_tool_entity_ids = fields.Many2many('sf.functional.cutting.tool.entity',
+ 'sf_functional_cutting_tool_entity_ref',
+ string='功能刀具列表信息', readonly=True)
+
+ sf_functional_tool_assembly_ids = fields.Many2many('sf.functional.tool.assembly', 'sf_functional_tool_assembly_ref',
+ '功能刀具组装单', readonly=True)
+
+ active = fields.Boolean(string='已归档', default=True)
+
+ @api.onchange('functional_name_id')
+ def _onchange_num(self):
+ for item in self:
+ if item.functional_name_id:
+ item.tool_groups_id = item.functional_name_id.tool_groups_id.id
+ item.sf_cutting_tool_type_id = item.functional_name_id.functional_cutting_tool_model_id.id
+ item.diameter = item.functional_name_id.diameter
+ item.knife_tip_r_angle = item.functional_name_id.angle
+
+ @api.depends('functional_name_id')
+ def _compute_name(self):
+ for obj in self:
+ if obj.tool_groups_id:
+ obj.name = obj.functional_name_id.name
+ else:
+ obj.sudo().name = ''
+
+ @api.constrains('min_stock_num', 'max_stock_num')
+ def _check_stock_num(self):
+ for obj in self:
+ if obj.min_stock_num > obj.max_stock_num:
+ raise ValidationError('【最低安全库存】不能高于【最高安全库存】!!!')
+
+ @api.model
+ def _read_mrs_cutting_tool_type_ids(self, categories, domain, order):
+ mrs_cutting_tool_type_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
+ return categories.browse(mrs_cutting_tool_type_ids)
+
+ @api.depends('sf_functional_cutting_tool_entity_ids', 'min_stock_num', 'max_stock_num')
+ def _compute_batch_replenishment_num(self):
+ for tool in self:
+ if tool:
+ # 判断功能刀具组装单是否已经完成
+ tool.sudo().estimate_functional_tool_assembly_ids(tool)
+ tool.sudo().get_stock_num(tool)
+ # 计算当前库存量
+ tool.sudo().tool_stock_total = tool.tool_stock_num + tool.side_shelf_num + tool.on_tool_stock_num
+ # 如果当前库存量小于最低库存量,计算批次补货量
+ tool.sudo().open_batch_replenishment_num(tool)
+
+ def open_batch_replenishment_num(self, tool):
+ """
+ 计算批次补货量
+ """
+ if tool.tool_stock_total < tool.min_stock_num:
+ tool.sudo().batch_replenishment_num = tool.max_stock_num - tool.tool_stock_total
+ # 根据判断创建功能刀具组装单
+ if not tool.sf_functional_tool_assembly_ids and re.match(r'^\d+$', str(tool.id)):
+ for i in range(tool.batch_replenishment_num):
+ tool.sudo().create_functional_tool_assembly(tool)
+ print(i, ": ", tool.sf_functional_tool_assembly_ids)
+ else:
+ tool.sudo().batch_replenishment_num = 0
+
+ def create_functional_tool_assembly(self, tool):
+ """
+ 创建功能刀具组装单
+ """
+ functional_tool_assembly = tool.env['sf.functional.tool.assembly'].sudo().create({
+ 'functional_tool_name': tool.name,
+ 'functional_tool_type_id': tool.sf_cutting_tool_type_id.id,
+ 'tool_groups_id': tool.tool_groups_id.id,
+ 'functional_tool_diameter': tool.diameter,
+ 'knife_tip_r_angle': tool.knife_tip_r_angle,
+ 'coarse_middle_thin': tool.coarse_middle_thin,
+ 'loading_task_source': '2',
+ 'use_tool_time': fields.Datetime.now() + timedelta(hours=4),
+ 'applicant': '系统自动',
+ 'apply_time': fields.Datetime.now(),
+ 'whether_standard_knife': tool.whether_standard_knife,
+ 'reason_for_applying': '安全库存',
+ })
+ tool.sudo().sf_functional_tool_assembly_ids = [(4, functional_tool_assembly.id)]
+
+ def estimate_functional_tool_assembly_ids(self, tool):
+ """
+ 判断功能刀具组装单是否完成,如果全部完成清空sf_functional_tool_assembly_ids的数据
+ """
+ for sf_functional_tool_assembly_id in tool.sf_functional_tool_assembly_ids:
+ if sf_functional_tool_assembly_id.assemble_status == '0':
+ return False
+ tool.sudo().sf_functional_tool_assembly_ids = []
+
+ def get_stock_num(self, tool):
+ """
+ 计算刀具房数量、线边刀库数量、机内刀库数量
+ """
+ if tool:
+ tool.tool_stock_num = 0
+ tool.side_shelf_num = 0
+ tool.on_tool_stock_num = 0
+ if 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:
+ tool.tool_stock_num += 1
+ elif cutting_tool.line_edge_knife_library_num > 0:
+ tool.side_shelf_num += 1
+ elif cutting_tool.machine_knife_library_num > 0:
+ tool.on_tool_stock_num += 1
+
+ def create_or_edit_safety_stock(self, vals, sf_functional_cutting_tool_entity_ids):
+ """
+ 根据传入的信息新增或者更新功能刀具安全库存的信息
+ """
+ # 根据功能刀具名称、刀具组、直径或尖刀R角、粗/中/精查询该功能刀具是否已经存在
+ record = self.env['sf.real.time.distribution.of.functional.tools'].search(
+ [('functional_name_id', '=', vals['functional_name_id']),
+ ('sf_cutting_tool_type_id', '=', vals['sf_cutting_tool_type_id']),
+ ('diameter', '=', vals['diameter']), ('knife_tip_r_angle', '=', vals['knife_tip_r_angle']),
+ ('coarse_middle_thin', '=', vals['coarse_middle_thin']), ('tool_groups_id', '=', vals['tool_groups_id'])])
+ if len(record) > 0:
+ for obj in record:
+ obj.write({'sf_functional_cutting_tool_entity_ids': [(4, sf_functional_cutting_tool_entity_ids.id)]})
+ else:
+ vals['sf_functional_cutting_tool_entity_ids'] = sf_functional_cutting_tool_entity_ids.ids
+ self.env['sf.real.time.distribution.of.functional.tools'].create(vals)
+
+ status_create = fields.Boolean('是否是新增状态', default=True)
+
+ @api.model_create_multi
+ def create(self, vals_list):
+ for vals in vals_list:
+ vals['status_create'] = False
+ records = super(RealTimeDistributionOfFunctionalTools, self).create(vals_list)
+ return records
diff --git a/sf_tool_management/models/functional_tool_enroll.py b/sf_tool_management/models/functional_tool_enroll.py
index c1687cde..61ca4731 100644
--- a/sf_tool_management/models/functional_tool_enroll.py
+++ b/sf_tool_management/models/functional_tool_enroll.py
@@ -1,9 +1,10 @@
import json
import base64
import requests
+import logging
from odoo import models, api
from odoo.addons.sf_base.commons.common import Common
-from odoo.exceptions import UserError
+from odoo.exceptions import UserError, ValidationError
def get_suitable_machining_method_names(item):
@@ -30,6 +31,30 @@ def get_suitable_coolant_names(item):
return suitable_coolant_names
+class ToolDatasync(models.Model):
+ _name = 'sf.tool.datasync'
+ _description = '定时同步所有刀具'
+
+ def _cron_tool_datasync_all(self):
+ try:
+ self.env['stock.lot'].sudo().sync_enroll_tool_material_stock_all()
+ logging.info("刀具物料序列号每日同步成功")
+ self.env['sf.tool.material.search'].sudo().sync_enroll_tool_material_all()
+ logging.info("刀具物料每日同步成功")
+ self.env['sf.functional.cutting.tool.entity'].sudo().esync_enroll_functional_tool_entity_all()
+ logging.info("功能刀具列表每日同步成功")
+ self.env['sf.functional.tool.warning'].sudo().sync_enroll_functional_tool_warning_all()
+ logging.info("功能刀具预警每日同步成功")
+ self.env['stock.move.line'].sudo().sync_enroll_functional_tool_move_all()
+ logging.info("功能刀具出入库记录每日同步成功")
+ self.env[
+ 'sf.real.time.distribution.of.functional.tools'].sudo().sync_enroll_functional_tool_real_time_distribution_all()
+ logging.info("功能刀具安全库存每日同步成功")
+ except Exception as e:
+ logging.info("捕获错误信息:%s" % e)
+ raise ValidationError("数据错误导致同步失败,请联系管理员")
+
+
class StockLot(models.Model):
_inherit = 'stock.lot'
_description = '刀具物料序列号注册'
@@ -40,7 +65,19 @@ class StockLot(models.Model):
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)])
+ objs_all = self.env['stock.lot'].search([('id', '=', self.id), ('active', 'in', [True, False])])
+ self._get_sync_stock_lot(objs_all, str_url, token, headers)
+
+ def sync_enroll_tool_material_stock_all(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([('rfid', '!=', False)])
+ self._get_sync_stock_lot(objs_all, str_url, token, headers)
+
+ def _get_sync_stock_lot(self, objs_all, str_url, token, headers):
tool_material_stock_list = []
if objs_all:
for item in objs_all:
@@ -57,7 +94,7 @@ class StockLot(models.Model):
if ret.get('code') == 200:
return '刀具物料序列号注册成功'
else:
- raise UserError("没有注册刀具物料序列号信息")
+ logging.info("没有注册刀具物料序列号信息")
class ToolMaterial(models.Model):
@@ -73,6 +110,18 @@ class ToolMaterial(models.Model):
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)])
+ self._get_sync_tool_material_search(objs_all, str_url, token, headers)
+
+ def sync_enroll_tool_material_all(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([])
+ self._get_sync_tool_material_search(objs_all, str_url, token, headers)
+
+ def _get_sync_tool_material_search(self, objs_all, str_url, token, headers):
tool_material_list = []
if objs_all:
for item in objs_all:
@@ -95,7 +144,7 @@ class ToolMaterial(models.Model):
if ret.get('code') == 200:
return '刀具物料注册成功'
else:
- raise UserError("没有注册刀具物料信息")
+ logging.info('没有注册刀具物料信息')
@api.model_create_multi
def create(self, vals_list):
@@ -120,6 +169,18 @@ class FunctionalCuttingToolEntity(models.Model):
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)])
+ self._get_sync_functional_cutting_tool_entity(objs_all, str_url, token, headers)
+
+ def esync_enroll_functional_tool_entity_all(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([])
+ self._get_sync_functional_cutting_tool_entity(objs_all, str_url, token, headers)
+
+ def _get_sync_functional_cutting_tool_entity(self, objs_all, str_url, token, headers):
functional_tool_list = []
if objs_all:
for item in objs_all:
@@ -170,7 +231,7 @@ class FunctionalCuttingToolEntity(models.Model):
if ret.get('code') == 200:
return "功能刀具注册成功"
else:
- raise UserError("没有注册功能刀具信息")
+ logging.info('没有注册功能刀具信息')
@api.model_create_multi
def create(self, vals_list):
@@ -201,6 +262,18 @@ class FunctionalToolWarning(models.Model):
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)])
+ self.get_sync_functional_tool_warning(objs_all, str_url, token, headers)
+
+ def sync_enroll_functional_tool_warning_all(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([])
+ self.get_sync_functional_tool_warning(objs_all, str_url, token, headers)
+
+ def get_sync_functional_tool_warning(self, objs_all, str_url, token, headers):
tool_warning_list = []
if objs_all:
for item in objs_all:
@@ -237,7 +310,7 @@ class FunctionalToolWarning(models.Model):
if ret.get('code') == 200:
return "功能刀具预警注册成功"
else:
- raise UserError("没有注册功能刀具预警信息")
+ logging.info('没有注册功能刀具预警信息')
@api.model_create_multi
def create(self, vals_list):
@@ -262,6 +335,18 @@ class StockMoveLine(models.Model):
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)])
+ self.get_sync_stock_move_line(objs_all, str_url, token, headers)
+
+ def sync_enroll_functional_tool_move_all(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([('functional_tool_name_id', '!=', False)])
+ self.get_sync_stock_move_line(objs_all, str_url, token, headers)
+
+ def get_sync_stock_move_line(self, objs_all, str_url, token, headers):
tool_stock_list = []
if objs_all:
for item in objs_all:
@@ -289,7 +374,7 @@ class StockMoveLine(models.Model):
if ret.get('code') == 200:
return "功能刀具出入库记录注册成功"
else:
- raise UserError("没有注册功能刀具出入库记录信息")
+ logging.info('没有注册功能刀具出入库记录信息')
@api.model_create_multi
def create(self, vals_list):
@@ -314,6 +399,18 @@ class RealTimeDistributionFunctionalTools(models.Model):
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)])
+ self.get_sync_real_time_distribution_functional_tools(objs_all, str_url, token, headers)
+
+ def sync_enroll_functional_tool_real_time_distribution_all(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([])
+ self.get_sync_real_time_distribution_functional_tools(objs_all, str_url, token, headers)
+
+ def get_sync_real_time_distribution_functional_tools(self, objs_all, str_url, token, headers):
tool_distribution_list = []
if objs_all:
for item in objs_all:
@@ -353,7 +450,7 @@ class RealTimeDistributionFunctionalTools(models.Model):
if ret.get('code') == 200:
return "功能刀具出入库记录注册成功"
else:
- raise UserError("没有注册功能刀具出入库记录信息")
+ logging.info('没有注册功能刀具出入库记录信息')
@api.model_create_multi
def create(self, vals_list):
@@ -362,3 +459,9 @@ class RealTimeDistributionFunctionalTools(models.Model):
if record:
record.enroll_functional_tool_real_time_distribution()
return records
+
+ def write(self, vals):
+ res = super().write(vals)
+ if vals.get('sf_functional_cutting_tool_entity_ids') or vals.get('min_stock_num') or vals.get('max_stock_num'):
+ self.enroll_functional_tool_real_time_distribution()
+ return res
diff --git a/sf_tool_management/models/mrp_workorder.py b/sf_tool_management/models/mrp_workorder.py
index df9a341e..8098c5a1 100644
--- a/sf_tool_management/models/mrp_workorder.py
+++ b/sf_tool_management/models/mrp_workorder.py
@@ -36,6 +36,7 @@ class CNCprocessing(models.Model):
obj = super(CNCprocessing, self).create(vals)
# 调用CAM工单程序用刀计划创建方法
self.env['sf.cam.work.order.program.knife.plan'].create_cam_work_plan(obj)
+ logging.info('成功调用CAM工单程序用刀计划创建方法!!!')
return obj
diff --git a/sf_tool_management/models/tool_material_search.py b/sf_tool_management/models/tool_material_search.py
index 75fc02e0..bfb8d64b 100644
--- a/sf_tool_management/models/tool_material_search.py
+++ b/sf_tool_management/models/tool_material_search.py
@@ -20,35 +20,35 @@ class ToolMaterial(models.Model):
specification_id = fields.Many2one('sf.tool.materials.basic.parameters', '规格',
related='product_id.specification_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')
+ number = fields.Integer('总数量', compute='_compute_number', store=True)
+ usable_num = fields.Integer('可用数量', compute='_compute_number', store=True)
+ have_been_used_num = fields.Integer('在用数量', compute='_compute_number', store=True)
+ scrap_num = fields.Integer('报废数量', compute='_compute_number', store=True)
barcode_ids = fields.One2many('stock.lot', 'tool_material_search_id', string='序列号', readonly=True)
- @api.depends('barcode_ids')
+ @api.depends('product_id.stock_quant_ids.quantity')
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 == '刀具组装位置':
- 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
+ for quant in record.product_id.stock_quant_ids:
+ location = quant.location_id.name
+ if location == '刀具房':
+ usable_num += quant.quantity
+ elif location == '刀具组装位置':
+ have_been_used_num += quant.quantity
+ elif location == '进货':
+ pass
+ elif location != 'Vendors':
+ scrap_num += quant.quantity
+ record.usable_num = usable_num
+ record.have_been_used_num = have_been_used_num
+ record.scrap_num = scrap_num
+ record.number = usable_num + have_been_used_num + scrap_num
+ # 更新数据到cloud的动态数据
+ record.enroll_tool_material()
@api.model
def _read_group_cutting_tool_material_id(self, categories, domain, order):
diff --git a/sf_tool_management/security/ir.model.access.csv b/sf_tool_management/security/ir.model.access.csv
index 35217493..3a7b4589 100644
--- a/sf_tool_management/security/ir.model.access.csv
+++ b/sf_tool_management/security/ir.model.access.csv
@@ -1,33 +1,33 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sf_functional_cutting_tool_entity,sf.functional.cutting.tool.entity,model_sf_functional_cutting_tool_entity,sf_base.group_sf_tool_user,1,1,1,0
-access_sf_functional_tool_warning,sf.functional.tool.warning,model_sf_functional_tool_warning,sf_base.group_sf_tool_user,1,1,1,0
-access_sf_real_time_distribution_of_functional_tools,sf.real.time.distribution.of.functional.tools,model_sf_real_time_distribution_of_functional_tools,sf_base.group_sf_tool_user,1,1,1,0
-
-access_sf_cam_work_order_program_knife_plan,sf.cam.work.order.program.knife.plan,model_sf_cam_work_order_program_knife_plan,sf_base.group_sf_tool_user,1,1,1,0
-access_sf_machine_table_tool_changing_apply,sf.machine.table.tool.changing.apply,model_sf_machine_table_tool_changing_apply,sf_base.group_sf_tool_user,1,1,1,0
-
-
-access_sf_tool_change_requirement_information,sf.tool.change.requirement.information,model_sf_tool_change_requirement_information,sf_base.group_sf_tool_user,1,1,1,0
-access_sf_tool_transfer_request_information,sf.tool.transfer.request.information,model_sf_tool_transfer_request_information,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_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_tool_warning,sf.functional.tool.warning,model_sf_functional_tool_warning,sf_base.group_sf_tool_user,1,1,1,0
access_sf_functional_tool_warning_group_plan_dispatch,sf.functional.tool.warning,model_sf_functional_tool_warning,sf_base.group_plan_dispatch,1,0,0,0
+
+access_sf_real_time_distribution_of_functional_tools,sf.real.time.distribution.of.functional.tools,model_sf_real_time_distribution_of_functional_tools,sf_base.group_sf_tool_user,1,1,1,0
access_sf_real_time_distribution_of_functional_tools_group_plan_dispatch,sf.real.time.distribution.of.functional.tools,model_sf_real_time_distribution_of_functional_tools,sf_base.group_plan_dispatch,1,0,0,0
+access_sf_cam_work_order_program_knife_plan,sf.cam.work.order.program.knife.plan,model_sf_cam_work_order_program_knife_plan,sf_base.group_sf_tool_user,1,1,1,0
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
+
+access_sf_machine_table_tool_changing_apply,sf.machine.table.tool.changing.apply,model_sf_machine_table_tool_changing_apply,sf_base.group_sf_tool_user,1,1,1,0
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
-
+access_sf_tool_change_requirement_information,sf.tool.change.requirement.information,model_sf_tool_change_requirement_information,sf_base.group_sf_tool_user,1,1,1,0
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
+
+access_sf_tool_transfer_request_information,sf.tool.transfer.request.information,model_sf_tool_transfer_request_information,sf_base.group_sf_tool_user,1,1,1,0
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
+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_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,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_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,sf.tool.material.search,model_sf_tool_material_search,sf_base.group_sf_tool_user,1,1,1,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
+
+access_sf_fixture_material_search,sf.fixture.material.search,model_sf_fixture_material_search,sf_base.group_sf_order_user,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
\ No newline at end of file
diff --git a/sf_tool_management/views/fixture_material_search_views.xml b/sf_tool_management/views/fixture_material_search_views.xml
index f70eba36..c8f6592f 100644
--- a/sf_tool_management/views/fixture_material_search_views.xml
+++ b/sf_tool_management/views/fixture_material_search_views.xml
@@ -100,6 +100,6 @@
name="夹具物料查询"
id="menu_sf_fixture_material_search"
action="action_sf_fixture_material_search"
- parent="menu_sf_tool_manage"
+ parent="menu_sf_fixture"
/>
\ No newline at end of file
diff --git a/sf_tool_management/views/functional_tool_views.xml b/sf_tool_management/views/functional_tool_views.xml
new file mode 100644
index 00000000..82fbd8bc
--- /dev/null
+++ b/sf_tool_management/views/functional_tool_views.xml
@@ -0,0 +1,514 @@
+
+
+
+
+
+ sf.functional.cutting.tool.entity.list.tree
+ sf.functional.cutting.tool.entity
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sf.functional.cutting.tool.entity.list.form
+ sf.functional.cutting.tool.entity
+
+
+
+
+
+
+ sf.functional.cutting.tool.entity.list.tree
+ sf.functional.cutting.tool.entity
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 功能刀具列表
+ ir.actions.act_window
+ sf.functional.cutting.tool.entity
+ tree,form,search
+
+
+
+
+
+ sf.functional.tool.warning.tree
+ sf.functional.tool.warning
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ sf.functional.tool.warning.search
+ sf.functional.tool.warning
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 功能刀具预警
+ ir.actions.act_window
+ sf.functional.tool.warning
+ tree,search
+
+
+
+
+
+ 功能刀具安全库存
+ sf.real.time.distribution.of.functional.tools
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 功能刀具安全库存
+ sf.real.time.distribution.of.functional.tools
+
+
+
+
+
+
+ 功能刀具安全库存
+ sf.real.time.distribution.of.functional.tools
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 功能刀具安全库存
+ ir.actions.act_window
+ sf.real.time.distribution.of.functional.tools
+ tree,form,search
+
+
+
+
+
+
+ 功能刀具出入库记录
+ stock.move.line
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 功能刀具出入库记录
+ stock.move.line
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 功能刀具出入库记录
+ ir.actions.act_window
+ stock.move.line
+ tree,search
+
+
+ [('functional_tool_name_id', '!=', False)]
+
+
+
+
\ No newline at end of file
diff --git a/sf_tool_management/views/menu_view.xml b/sf_tool_management/views/menu_view.xml
index ea2e0fbd..13a12725 100644
--- a/sf_tool_management/views/menu_view.xml
+++ b/sf_tool_management/views/menu_view.xml
@@ -7,6 +7,13 @@
groups="mrp.group_mrp_routings"
parent="mrp.menu_mrp_root"
sequence="20"/>
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -222,9 +245,10 @@
sf.shelf.location
+
-
+
@@ -238,7 +262,7 @@
ir.actions.act_window
sf.shelf.location
kanban,form
-
+
diff --git a/sf_warehouse/views/view.xml b/sf_warehouse/views/view.xml
index 39d5a8c0..aa3293ce 100644
--- a/sf_warehouse/views/view.xml
+++ b/sf_warehouse/views/view.xml
@@ -67,16 +67,16 @@
-
-
+
+
+
+
+
+
+
+
-
+
@@ -188,23 +188,23 @@
-
- stock.warehouse.form.sf.inherit
- stock.warehouse
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
@@ -220,23 +220,23 @@
-
- stock.route.form.sf.inherit
- stock.route
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
@@ -251,23 +251,23 @@
-
- stock.rule.form.sf.inherit
- stock.rule
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
@@ -282,23 +282,23 @@
-
- stock.picking.type.form.sf.inherit
- stock.picking.type
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
diff --git a/sf_warehouse/wizard/__init__.py b/sf_warehouse/wizard/__init__.py
new file mode 100644
index 00000000..20a7f5c4
--- /dev/null
+++ b/sf_warehouse/wizard/__init__.py
@@ -0,0 +1 @@
+from . import wizard
\ No newline at end of file
diff --git a/sf_warehouse/wizard/wizard.py b/sf_warehouse/wizard/wizard.py
new file mode 100644
index 00000000..db64fe07
--- /dev/null
+++ b/sf_warehouse/wizard/wizard.py
@@ -0,0 +1,64 @@
+from odoo import fields, models, api
+from odoo.exceptions import UserError, ValidationError
+
+
+class ShelfLocationWizard(models.TransientModel):
+ _name = 'sf.shelf.location.wizard'
+ _description = '货位变更'
+
+ name = fields.Char('')
+
+ current_location_id = fields.Many2one('stock.location', string='所属库区', readonly=True)
+
+ current_shelf_id = fields.Many2one('sf.shelf', string='当前货架', readonly=True)
+ current_barcode = fields.Char('当前货位编码', readonly=True)
+ current_name = fields.Char('当前货位名称', readonly=True)
+ current_product_id = fields.Many2one('product.product', string='产品', readonly=True)
+
+ destination_shelf_id = fields.Many2one('sf.shelf', string='目标货架', compute='_compute_destination_name')
+ destination_barcode_id = fields.Many2one('sf.shelf.location', string='目标货位编码', required=True,
+ domain="")
+ destination_name = fields.Char('目标货位名称', compute='_compute_destination_name')
+
+ def return_domain(self):
+ val = [('location_status', '=', '空闲')]
+ if self.current_product_id:
+ val = ['|', ('location_status', '=', '空闲'), ('product_id', '=', self.current_product_id)]
+ if self.destination_shelf_id:
+ val.append(('shelf_id', '=', self.destination_shelf_id))
+ return "%s" % val
+
+ @api.depends('destination_barcode_id')
+ def _compute_destination_name(self):
+ if self.destination_barcode_id:
+ self.destination_name = self.destination_barcode_id.name
+ self.destination_shelf_id = self.destination_barcode_id.shelf_id.id
+ else:
+ self.destination_name = ''
+ self.destination_shelf_id = False
+
+ #
+ # @api.onchange('destination_barcode_id')
+ # def _onchange_destination_shelf_id(self):
+ # if self.destination_barcode_id:
+ # self.destination_shelf_id = self.destination_barcode_id.shelf_id.id
+
+ def confirm_the_change(self):
+ shelf_location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.current_barcode)])
+ # 变更货位
+ if self.destination_barcode_id and shelf_location:
+ if self.destination_barcode_id.product_id and self.destination_barcode_id.product_id == shelf_location.product_id and not self.destination_barcode_id.product_sn_id:
+ self.destination_barcode_id.product_num += shelf_location.product_num
+ else:
+ self.destination_barcode_id.product_sn_id = shelf_location.product_sn_id.id
+ self.destination_barcode_id.product_id = shelf_location.product_id.id
+ self.destination_barcode_id.product_num = shelf_location.product_num
+
+ shelf_location.product_sn_id = False
+ shelf_location.product_id = False
+ shelf_location.product_num = 0
+ else:
+ raise ValidationError('目标货位出错,请联系管理员!')
+
+ # 关闭弹出窗口
+ return {'type': 'ir.actions.act_window_close'}
diff --git a/sf_warehouse/wizard/wizard_view.xml b/sf_warehouse/wizard/wizard_view.xml
new file mode 100644
index 00000000..1bb95e15
--- /dev/null
+++ b/sf_warehouse/wizard/wizard_view.xml
@@ -0,0 +1,49 @@
+
+
+
+ 货位变更
+ sf.shelf.location.wizard
+
+
+
+
+
+
+ 货位变更
+ ir.actions.act_window
+ sf.shelf.location.wizard
+ form
+
+ new
+
+
\ No newline at end of file
|