From 57bfec02eb6ef1571cbb710a8ca18e48044eb320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E7=84=B1?= Date: Mon, 25 Mar 2024 09:07:45 +0800 Subject: [PATCH 01/79] =?UTF-8?q?=E4=BF=AE=E6=94=B9field=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../static/src/js/custom_form_status_indicator.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) 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..10f4b07d 100644 --- a/jikimo_frontend/static/src/js/custom_form_status_indicator.js +++ b/jikimo_frontend/static/src/js/custom_form_status_indicator.js @@ -83,12 +83,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 From ed8c39d005df6d7b408d768ac4797c44cd24fbd8 Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Mon, 25 Mar 2024 16:17:19 +0800 Subject: [PATCH 02/79] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=91=98=E5=B7=A5?= =?UTF-8?q?=E6=A8=A1=E5=9D=97js=E9=97=AE=E9=A2=98=E3=80=81=E8=83=BD?= =?UTF-8?q?=E5=8A=9B=E7=89=B9=E5=BE=81=E5=93=ADjs=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E3=80=81=E8=AE=BE=E5=A4=87=E5=A4=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../static/src/js/custom_form_status_indicator.js | 10 +++------- jikimo_frontend/static/src/js/custom_image_temp.js | 9 ++++++++- sf_maintenance/models/sf_maintenance.py | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) 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..9ff98ca2 100644 --- a/jikimo_frontend/static/src/js/custom_form_status_indicator.js +++ b/jikimo_frontend/static/src/js/custom_form_status_indicator.js @@ -83,13 +83,9 @@ 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); - }, + owl.onMounted(this.setRequired); + return this._super(...arguments); + }, setRequired() { const id = this.props.id const isRequired = filedRequiredList[id] 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/sf_maintenance/models/sf_maintenance.py b/sf_maintenance/models/sf_maintenance.py index 5b0db796..74da7742 100644 --- a/sf_maintenance/models/sf_maintenance.py +++ b/sf_maintenance/models/sf_maintenance.py @@ -148,7 +148,7 @@ class SfMaintenanceEquipment(models.Model): MTcode = fields.Char("机台编码") created_user = fields.Many2one('res.users', string='创建人', default=lambda self: self.env.user) equipment_type = fields.Selection([('机床', '机床'), ('机器人', '机器人'), ('AGV小车', 'AGV小车'), - ('检测设备', '检测设备')], compute='_compute_category_id') + ('检测设备', '检测设备'), ('其他', '其他')], compute='_compute_category_id') @api.depends('category_id') def _compute_category_id(self): From 48cd8399f4dc3f4f463ae7c865be72f7c8b6296f Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Mon, 25 Mar 2024 16:49:49 +0800 Subject: [PATCH 03/79] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E4=B8=AD?= =?UTF-8?q?=E6=8E=A7=E9=9B=B6=E4=BB=B6=E7=89=B9=E9=87=87=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=EF=BC=8C2=E3=80=81=E5=B0=86=E5=88=80=E5=85=B7=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E7=9A=84=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E6=89=80?= =?UTF-8?q?=E6=9C=89rfid=E6=94=B9=E4=B8=BARfid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_quality/models/quality.py | 8 ++++++-- sf_tool_management/models/base.py | 10 +++++----- sf_tool_management/wizard/wizard.py | 6 +++--- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/sf_quality/models/quality.py b/sf_quality/models/quality.py index ee289415..809dbba3 100644 --- a/sf_quality/models/quality.py +++ b/sf_quality/models/quality.py @@ -19,7 +19,10 @@ class QualityCheck(models.Model): # headers = Common.get_headers(self, token, sf_secret_key) headers = {'Authorization': 'Ba F2CF5DCC-1A00-4234-9E95-65603F70CC8A'} crea_url = "https://x24467i973.zicp.fun/AutoDeviceApi/PartSpecProc" - val = ['0037835872'] + origin = self.picking_id.origin + production_id = self.env['mrp.production'].sudo().search([('name', '=', origin)]) + rfid = '' if not production_id.workorder_ids else production_id.workorder_ids[-1].rfid_code or '' + val = [rfid] r = requests.post(crea_url, json=val, headers=headers) ret = r.json() logging.info('_register_quality_check:%s' % ret) @@ -33,4 +36,5 @@ class QualityCheck(models.Model): 'quality_state': 'fail', 'user_id': self.env.user.id, 'control_date': datetime.now()}) - self._register_quality_check() + if self.picking_id and 'WH/MO/' in self.picking_id.origin: + self._register_quality_check() diff --git a/sf_tool_management/models/base.py b/sf_tool_management/models/base.py index 2c4b4364..968f6841 100644 --- a/sf_tool_management/models/base.py +++ b/sf_tool_management/models/base.py @@ -15,7 +15,7 @@ class FunctionalCuttingToolEntity(models.Model): 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) + 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) @@ -222,7 +222,7 @@ class FunctionalToolWarning(models.Model): _description = '功能刀具预警' code = fields.Char('编码', related='functional_tool_name_id.code') - rfid = fields.Char('rfid', related='functional_tool_name_id.rfid') + 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') # 机床信息 @@ -296,7 +296,7 @@ class StockMoveLine(models.Model): 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') + rfid = fields.Char('Rfid') tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组') @api.model @@ -502,7 +502,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, @@ -828,7 +828,7 @@ class FunctionalToolAssembly(models.Model): obj.name = obj.after_assembly_functional_tool_name 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) diff --git a/sf_tool_management/wizard/wizard.py b/sf_tool_management/wizard/wizard.py index c7a039ec..25fcdde9 100644 --- a/sf_tool_management/wizard/wizard.py +++ b/sf_tool_management/wizard/wizard.py @@ -9,7 +9,7 @@ class ToolChangeRequirementInformation(models.TransientModel): _description = '换刀需求信息' 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('名称', related='maintenance_equipment_id.name', store=True, readonly=True) maintenance_equipment_id = fields.Many2one('maintenance.equipment', string='CNC机床', readonly=True) @@ -323,7 +323,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel): # 组装功能刀具参数信息 barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号') - rfid = fields.Char('rfid', required=True) + rfid = fields.Char('Rfid', required=True) tool_code = fields.Char(string='功能刀具编码', readonly=True, compute='_compute_tool_code') after_assembly_functional_tool_name = fields.Char(string='组装后功能刀具名称', compute='_compute_name') after_assembly_functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', @@ -455,7 +455,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel): if obj.rfid: tool_entity = self.env['sf.functional.cutting.tool.entity'].sudo().search([('rfid', '=', obj.rfid)]) if tool_entity: - raise ValidationError('【%s】的rfid已被使用,请重新录入!!!' % obj.rfid) + raise ValidationError('【%s】的Rfid已被使用,请重新录入!!!' % obj.rfid) def functional_tool_assembly(self): """ From d05c0951eb872d27dd2d055f893b8b35f4347a0e Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Tue, 26 Mar 2024 14:10:51 +0800 Subject: [PATCH 04/79] =?UTF-8?q?1.agv=E9=85=8D=E7=BD=AE=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=9C=B0=E7=A0=81=202.bpm=E5=88=86=E9=85=8D?= =?UTF-8?q?=E5=B7=A5=E5=8E=82=E6=97=B6=E7=9A=84=E5=AE=A2=E6=88=B7(?= =?UTF-8?q?=E4=B8=9A=E5=8A=A1=E5=B9=B3=E5=8F=B0)=E7=9A=84=E5=BF=85?= =?UTF-8?q?=E5=A1=AB=E4=BF=A1=E6=81=AF=EF=BC=88=E7=A8=8E=EF=BC=8C=E9=82=AE?= =?UTF-8?q?=E7=AE=B1=EF=BC=8C=E5=8F=B7=E7=A0=81=EF=BC=89=E8=B5=8B=E5=80=BC?= =?UTF-8?q?=203.=E6=8A=A5=E4=BB=B7=E9=A1=B5=E9=9D=A2=E7=9A=84=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E6=94=B9=E4=B8=BA=E4=B8=8D=E5=8F=AF=E6=96=B0=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 13 ++++++++----- sf_mrs_connect/models/res_config_setting.py | 1 + sf_mrs_connect/views/res_config_settings_views.xml | 8 ++++---- sf_sale/models/sale_order.py | 6 +++++- sf_sale/views/sale_order_view.xml | 2 +- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index dfb064cb..c8b2f7d1 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -1,5 +1,6 @@ import logging import base64 +import urllib.parse from datetime import date from datetime import datetime, timedelta import requests @@ -908,15 +909,17 @@ class WorkPieceDelivery(models.Model): # 配送至avg小车 def _delivery_avg(self): - res = {'reqCode': self.production_id.name, 'reqTime': '', 'clientCode': '', 'tokenCode': '', - 'taskTyp': 'F01', 'ctnrTyp': '', 'ctnrCode': '', 'wbCode': '', 'positionCodePath': [], 'podCode': '', + res = {'reqCode': urllib.parse.quote(self.production_id.name), 'reqTime': '', 'clientCode': '', 'tokenCode': '', + 'taskTyp': 'F01', 'ctnrTyp': '', 'ctnrCode': '', 'wbCode': '006848AB006774', 'positionCodePath': [], 'podCode': '', 'podDir': '', 'materialLot': '', 'priority': '', 'taskCode': '', 'agvCode': '', 'materialLot': '', 'data': ''} config = self.env['res.config.settings'].get_values() try: - logging.info('config-AGV请求路径:%s' % config['agv_rcms_url']) - logging.info('config-json:%s' % res) - ret = requests.post((config['agv_rcms_url']), json=res) + logging.info('AGV请求路径:%s' % config['agv_rcs_url']) + logging.info('AGV-json:%s' % res) + + headers = {'Content-Type': 'application/json'} + ret = requests.post((config['agv_rcs_url']), json=res, headers=headers) ret = ret.json() logging.info('config-ret:%s' % ret) if ret['code'] == 0: diff --git a/sf_mrs_connect/models/res_config_setting.py b/sf_mrs_connect/models/res_config_setting.py index 5919e5c7..95718e33 100644 --- a/sf_mrs_connect/models/res_config_setting.py +++ b/sf_mrs_connect/models/res_config_setting.py @@ -16,6 +16,7 @@ class ResConfigSettings(models.TransientModel): 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') + wbcode = fields.Char('地码') model_parser_url = fields.Char('特征识别路径') ftp_host = fields.Char(string='FTP的ip') ftp_port = fields.Char(string='FTP端口') diff --git a/sf_mrs_connect/views/res_config_settings_views.xml b/sf_mrs_connect/views/res_config_settings_views.xml index b879b1f8..5f457b4f 100644 --- a/sf_mrs_connect/views/res_config_settings_views.xml +++ b/sf_mrs_connect/views/res_config_settings_views.xml @@ -81,12 +81,12 @@
-
-
diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index 4848ce7c..a55f9fb3 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -1,5 +1,6 @@ import datetime import base64 +from odoo import Command from odoo import models, fields, api, _ from odoo.exceptions import UserError, ValidationError @@ -88,7 +89,10 @@ class ReSaleOrder(models.Model): if customer: return customer else: - partner = self.env['res.partner'].create({'name': '业务平台'}) + partner_tag = self.env['res.partner.category'].create({'name': '平台客户'}) + partner = self.env['res.partner'].create( + {'name': '业务平台', 'vat': '91430103MA7BRH9K4M', 'phone': '0731-85115515', + 'email': 'jikimo@jikimo.com', 'category_id': [Command.set([partner_tag.id])]}) return partner # 业务平台分配工厂时在创建完产品后再创建销售明细信息 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'])]} From decb6c7792b0d50f0e80ab5d164679deb75b7630 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Tue, 26 Mar 2024 15:16:26 +0800 Subject: [PATCH 05/79] =?UTF-8?q?=E7=A6=81=E7=94=A8=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=88=80=E5=85=B7=E5=AE=89=E5=85=A8=E5=BA=93=E5=AD=98=E7=9A=84?= =?UTF-8?q?=E5=88=80=E5=85=B7=E7=BB=84=E5=AD=97=E6=AE=B5=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E6=96=B0=E8=AE=B0=E5=BD=95=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_tool_management/views/tool_base_views.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sf_tool_management/views/tool_base_views.xml b/sf_tool_management/views/tool_base_views.xml index 20bc3b32..4406a90f 100644 --- a/sf_tool_management/views/tool_base_views.xml +++ b/sf_tool_management/views/tool_base_views.xml @@ -40,8 +40,8 @@
- - + +
@@ -245,8 +245,8 @@ - - + + @@ -322,10 +322,10 @@ sf.real.time.distribution.of.functional.tools - - - - + + + +

@@ -337,7 +337,7 @@ - @@ -462,7 +462,7 @@ - + From 7906ff28367ce42d18935948e38825195c4236a1 Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Tue, 26 Mar 2024 18:09:23 +0800 Subject: [PATCH 06/79] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BF=BB=E8=AF=91?= =?UTF-8?q?=E3=80=81=E6=8E=92=E5=BA=8F=E3=80=81=E6=9D=83=E9=99=90=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_base/security/group_security.xml | 2 +- sf_base/security/ir.model.access.csv | 1 + sf_quality/security/ir.model.access.csv | 2 -- sf_sale/security/ir.model.access.csv | 5 +++++ sf_tool_management/security/ir.model.access.csv | 2 +- sf_warehouse/models/model.py | 4 ++-- sf_warehouse/security/ir.model.access.csv | 8 +------- sf_warehouse/views/change_stock_move_views.xml | 2 +- 8 files changed, 12 insertions(+), 14 deletions(-) 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..2a3cd471 100644 --- a/sf_base/security/ir.model.access.csv +++ b/sf_base/security/ir.model.access.csv @@ -145,6 +145,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 diff --git a/sf_quality/security/ir.model.access.csv b/sf_quality/security/ir.model.access.csv index 4374715d..b147a1df 100644 --- a/sf_quality/security/ir.model.access.csv +++ b/sf_quality/security/ir.model.access.csv @@ -43,8 +43,6 @@ access_quality_alert_team_group_sf_mrp_manager,quality_alert_team_group_sf_mrp_m access_product_template_group_quality,product_template_group_quality,product.model_product_template,sf_base.group_quality,1,0,0,0 access_product_template_group_quality_director,product_template_group_quality_director,product.model_product_template,sf_base.group_quality_director,1,0,0,0 -access_product_template_group_plan_dispatch,product_template_group_plan_dispatch,product.model_product_template,sf_base.group_plan_dispatch,1,0,0,0 -access_product_template_group_plan_director,product_template_group_plan_director,product.model_product_template,sf_base.group_plan_director,1,0,0,0 access_product_template_group_sf_equipment_user,product_template_group_sf_equipment_user,product.model_product_template,sf_base.group_sf_equipment_user,1,0,0,0 access_product_template_group_sf_tool_user,product_template_group_sf_tool_user,product.model_product_template,sf_base.group_sf_tool_user,1,0,0,0 access_product_template_group_sf_order_user,product_template_group_sf_order_user,product.model_product_template,sf_base.group_sf_order_user,1,0,0,0 diff --git a/sf_sale/security/ir.model.access.csv b/sf_sale/security/ir.model.access.csv index 34cea19a..451396e3 100644 --- a/sf_sale/security/ir.model.access.csv +++ b/sf_sale/security/ir.model.access.csv @@ -14,6 +14,8 @@ access_product_product_group_sale_salemanager,product_product_group_sale_saleman access_product_product_group_sale_director,product_product_group_sale_director,product.model_product_product,sf_base.group_sale_director,1,1,1,0 access_product_product_group_purchase,product_product_group_purchase,product.model_product_product,sf_base.group_purchase,1,0,0,0 access_product_product_group_purchase_director,product_product_group_purchase_director,product.model_product_product,sf_base.group_purchase_director,1,1,1,0 +access_product_product_group_plan_dispatch,product_product_group_plan_dispatch,product.model_product_product,sf_base.group_plan_dispatch,1,0,0,0 +access_product_product_group_plan_director,product_product_group_plan_director,product.model_product_product,sf_base.group_plan_director,1,1,1,0 access_product_template_group_sale_salemanager,product_template_group_sale_salemanager,product.model_product_template,sf_base.group_sale_salemanager,1,0,0,0 access_product_template_group_sale_director,product_template_group_sale_director,product.model_product_template,sf_base.group_sale_director,1,1,1,0 access_product_template_group_purchase,product_template_group_purchase,product.model_product_template,sf_base.group_purchase,1,0,0,0 @@ -90,6 +92,9 @@ access_sale_report_group_sale_director,sale_report_group_sale_director,sale.mode access_product_supplierinfo_group_purchase_director,product.supplierinfo group_purchase_director,product.model_product_supplierinfo,sf_base.group_purchase_director,1,1,1,0 access_product_category_group_purchase_director,product.category group_purchase_director,product.model_product_category,sf_base.group_purchase_director,1,1,1,0 +access_product_supplierinfo_group_plan_director,product.supplierinfo user,product.model_product_supplierinfo,sf_base.group_plan_director,1,1,1,0 +access_product_category_group_plan_director,product.category user,product.model_product_category,sf_base.group_plan_director,1,1,1,0 + diff --git a/sf_tool_management/security/ir.model.access.csv b/sf_tool_management/security/ir.model.access.csv index 35217493..bfb92998 100644 --- a/sf_tool_management/security/ir.model.access.csv +++ b/sf_tool_management/security/ir.model.access.csv @@ -18,7 +18,7 @@ access_sf_fixture_material_search,sf.fixture.material.search,model_sf_fixture_ma 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_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_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_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,1,0,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_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 diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py index 43f84d69..2228d2d5 100644 --- a/sf_warehouse/models/model.py +++ b/sf_warehouse/models/model.py @@ -229,7 +229,7 @@ class SfLocation(models.Model): class SfShelf(models.Model): _name = 'sf.shelf' _description = '货架' - _order = 'name' + _order = 'create_date desc' name = fields.Char('货架名称', required=True, size=20) barcode = fields.Char('编码', copy=False, size=15, required=True) @@ -310,7 +310,7 @@ class SfShelf(models.Model): class ShelfLocation(models.Model): _name = 'sf.shelf.location' _description = '货位' - _order = 'name, id' + _order = 'create_date desc' # current_location_id = fields.Many2one('sf.shelf.location', string='当前位置') # # 目的位置 diff --git a/sf_warehouse/security/ir.model.access.csv b/sf_warehouse/security/ir.model.access.csv index 06f69669..db246adc 100644 --- a/sf_warehouse/security/ir.model.access.csv +++ b/sf_warehouse/security/ir.model.access.csv @@ -102,17 +102,11 @@ access_mrp_production_group_sf_stock_user,mrp.production,mrp.model_mrp_productio access_sf_shelf_location_group_plan_dispatch,sf.shelf.location,model_sf_shelf_location,sf_base.group_plan_dispatch,1,0,0,0 access_stock_move,stock.move,stock.model_stock_move,sf_base.group_plan_dispatch,1,1,1,0 -access_stock_picking,stock.picking,stock.model_stock_picking,sf_base.group_plan_dispatch,1,0,0,0 +access_stock_picking_group_plan_dispatch,stock.picking,stock.model_stock_picking,sf_base.group_plan_dispatch,1,0,0,0 access_stock_lot_group_plan_dispatch,stock.lot,stock.model_stock_lot,sf_base.group_plan_dispatch,1,0,0,0 access_stock_lot_group_plan_director,stock.lot,stock.model_stock_lot,sf_base.group_plan_director,1,1,1,0 access_stock_warehouse_orderpoint,stock.warehouse.orderpoint,stock.model_stock_warehouse_orderpoint,sf_base.group_plan_dispatch,1,1,0,0 - -access_product_product,product.product,product.model_product_product,sf_base.group_plan_dispatch,1,0,0,0 -access_product_template,product.template,product.model_product_template,sf_base.group_plan_dispatch,1,0,0,0 -access_product_product,product.product,product.model_product_product,sf_base.group_plan_director,1,1,1,0 -access_product_template,product.template,product.model_product_template,sf_base.group_plan_director,1,1,1,0 - access_stock_inventory_conflict,stock.inventory.conflict,stock.model_stock_inventory_conflict,sf_base.group_plan_dispatch,1,0,0,0 access_stock_inventory_warning,stock.inventory.warning,stock.model_stock_inventory_warning,sf_base.group_plan_dispatch,1,0,0,0 access_stock_inventory_adjustment_name,stock.inventory.adjustment.name,stock.model_stock_inventory_adjustment_name,sf_base.group_plan_dispatch,1,0,0,0 diff --git a/sf_warehouse/views/change_stock_move_views.xml b/sf_warehouse/views/change_stock_move_views.xml index 77021663..cc4213c6 100644 --- a/sf_warehouse/views/change_stock_move_views.xml +++ b/sf_warehouse/views/change_stock_move_views.xml @@ -117,7 +117,7 @@ -

+ + + + + diff --git a/sf_mrs_connect/models/res_config_setting.py b/sf_mrs_connect/models/res_config_setting.py index cbefba19..f34ab06f 100644 --- a/sf_mrs_connect/models/res_config_setting.py +++ b/sf_mrs_connect/models/res_config_setting.py @@ -13,10 +13,11 @@ 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') 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端口') @@ -95,8 +96,9 @@ 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='') + agv_code = config.get_param('agv_code', default='') + task_type_no = config.get_param('task_type_no', 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='') @@ -106,8 +108,9 @@ 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, + agv_code=agv_code, + task_type_no=task_type_no, ftp_host=ftp_host, ftp_port=ftp_port, ftp_user=ftp_user, @@ -121,9 +124,18 @@ 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("agv_code", self.agv_code or "") + ir_config.set_param("task_type_no", self.task_type_no 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 "") ir_config.set_param("ftp_password", self.ftp_password or "") + + +class ResAgvSite(models.Model): + _name = 'res.agv.site' + _description = 'agv站点' + + type = fields.Selection([('00', '位置编号'), ('01', '库区编号'), ('02', '货架编号')], '类型') + content = fields.Char('内容') diff --git a/sf_mrs_connect/security/ir.model.access.csv b/sf_mrs_connect/security/ir.model.access.csv index 0ed43a62..f512ec84 100644 --- a/sf_mrs_connect/security/ir.model.access.csv +++ b/sf_mrs_connect/security/ir.model.access.csv @@ -1,5 +1,6 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_sf_static_resource_datasync,sf_static_resource_datasync,model_sf_static_resource_datasync,base.group_user,1,1,1,1 +access_res_agv_site,access_res_agv_site,model_res_agv_site,base.group_system,1,1,1,1 diff --git a/sf_mrs_connect/views/res_config_settings_views.xml b/sf_mrs_connect/views/res_config_settings_views.xml index 5f457b4f..e297f0eb 100644 --- a/sf_mrs_connect/views/res_config_settings_views.xml +++ b/sf_mrs_connect/views/res_config_settings_views.xml @@ -1,6 +1,26 @@ + + agv站点集合 + res.agv.site + + + + + + + + + + 站点集合 + res.agv.site + tree + + + + res.config.settings.view.form.inherit.sf_sync res.config.settings @@ -84,10 +104,22 @@ diff --git a/sf_base/views/tool_views.xml b/sf_base/views/tool_views.xml index 34b87a41..25d1824f 100644 --- a/sf_base/views/tool_views.xml +++ b/sf_base/views/tool_views.xml @@ -123,7 +123,7 @@ + required="1"/>

@@ -547,7 +547,68 @@ - + ' + + + + sf.tool.inventory.tree + sf.tool.inventory + + + + + + + + + + + + + + + + + + + + + + sf.tool.inventory.search + sf.tool.inventory + + + + + + + + + + + + + + + + + + + + + 功能刀具清单 + ir.actions.act_window + sf.tool.inventory + tree + + + diff --git a/sf_tool_management/models/base.py b/sf_tool_management/models/base.py index 766bb8a9..d90c65bd 100644 --- a/sf_tool_management/models/base.py +++ b/sf_tool_management/models/base.py @@ -309,7 +309,8 @@ class RealTimeDistributionOfFunctionalTools(models.Model): _name = 'sf.real.time.distribution.of.functional.tools' _description = '功能刀具安全库存' - name = fields.Char('功能刀具名称', readonly=True, compute='_compute_name') + 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) @@ -355,13 +356,13 @@ class RealTimeDistributionOfFunctionalTools(models.Model): active = fields.Boolean(string='已归档', default=True) - @api.depends('tool_groups_id', 'diameter', 'knife_tip_r_angle') + @api.depends('functional_name_id') 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) + obj.name = obj.functional_name_id.name else: - obj.sudo().name = None + obj.sudo().name = '' @api.constrains('min_stock_num', 'max_stock_num') def _check_stock_num(self): @@ -452,7 +453,8 @@ class RealTimeDistributionOfFunctionalTools(models.Model): """ # 根据功能刀具名称、刀具组、直径或尖刀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']), + [('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: diff --git a/sf_tool_management/views/tool_base_views.xml b/sf_tool_management/views/tool_base_views.xml index b210ff29..4dd23a4e 100644 --- a/sf_tool_management/views/tool_base_views.xml +++ b/sf_tool_management/views/tool_base_views.xml @@ -299,7 +299,8 @@ sf.real.time.distribution.of.functional.tools - + + @@ -329,9 +330,11 @@

- +

+ diff --git a/sf_tool_management/wizard/wizard.py b/sf_tool_management/wizard/wizard.py index 90b8da63..36bb310d 100644 --- a/sf_tool_management/wizard/wizard.py +++ b/sf_tool_management/wizard/wizard.py @@ -358,10 +358,11 @@ class FunctionalToolAssemblyOrder(models.TransientModel): item.rfid = None # 组装功能刀具参数信息 + after_name_id = fields.Many2one('sf.tool.inventory', string='功能刀具名称', required=True) barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号') rfid = fields.Char('Rfid', readonly=True, store=True, compute='_compute_rfid') tool_code = fields.Char(string='功能刀具编码', readonly=True, compute='_compute_tool_code') - after_assembly_functional_tool_name = fields.Char(string='组装后功能刀具名称', compute='_compute_name') + after_assembly_functional_tool_name = fields.Char(string='组装后功能刀具名称', compute='_compute_name', store=True) after_assembly_functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='组装后功能刀具类型', compute='_compute_after_assembly_functional_tool_type_id') @@ -428,15 +429,13 @@ class FunctionalToolAssemblyOrder(models.TransientModel): num = "%03d" % m return num - @api.depends('after_assembly_functional_tool_diameter', 'after_assembly_knife_tip_r_angle', 'tool_groups_id') + @api.depends('after_name_id') def _compute_name(self): for obj in self: - if obj.tool_groups_id: - obj.after_assembly_functional_tool_name = '%s-D%sR%s' % ( - obj.tool_groups_id.name, obj.after_assembly_functional_tool_diameter, - obj.after_assembly_knife_tip_r_angle) + if obj.after_name_id: + obj.after_assembly_functional_tool_name = obj.after_name_id.name else: - obj.after_assembly_functional_tool_name = None + obj.after_assembly_functional_tool_name = '' @api.onchange('integral_code_id') def _onchange_after_assembly_functional_tool_diameter(self): @@ -530,7 +529,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel): record_1 = self.env['sf.functional.cutting.tool.entity'].create(desc_2) # 创建安全库存信息 self.env['sf.real.time.distribution.of.functional.tools'].create_or_edit_safety_stock({ - 'name': self.after_assembly_functional_tool_name, + 'functional_name_id': self.after_name_id.id, 'sf_cutting_tool_type_id': self.after_assembly_functional_tool_type_id.id, 'tool_groups_id': self.tool_groups_id.id, 'diameter': self.after_assembly_functional_tool_diameter, diff --git a/sf_tool_management/wizard/wizard_view.xml b/sf_tool_management/wizard/wizard_view.xml index f055ffba..a1b35664 100644 --- a/sf_tool_management/wizard/wizard_view.xml +++ b/sf_tool_management/wizard/wizard_view.xml @@ -342,7 +342,8 @@ - + + From 0a4c86f6013a34591db07bbb8539d242d3698118 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Tue, 9 Apr 2024 13:38:13 +0800 Subject: [PATCH 33/79] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7?= =?UTF-8?q?=E6=B8=85=E5=8D=95=E6=B7=BB=E5=8A=A0=E5=88=80=E5=85=B7=E7=BB=84?= =?UTF-8?q?=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_base/models/tool_base_new.py | 2 ++ sf_base/views/tool_views.xml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sf_base/models/tool_base_new.py b/sf_base/models/tool_base_new.py index e3b737f0..d442639b 100644 --- a/sf_base/models/tool_base_new.py +++ b/sf_base/models/tool_base_new.py @@ -327,4 +327,6 @@ class ToolInventory(models.Model): blade_number = fields.Integer('刃数(个)') extension = fields.Float('伸出长度(mm)') + tool_groups_id = fields.Many2one('sf.tool.groups', string='刀具组') + active = fields.Boolean('已归档', default=True) diff --git a/sf_base/views/tool_views.xml b/sf_base/views/tool_views.xml index 25d1824f..13f3da8d 100644 --- a/sf_base/views/tool_views.xml +++ b/sf_base/views/tool_views.xml @@ -557,6 +557,7 @@ + @@ -580,6 +581,7 @@ + From 961b4f8e2df39afe8a9b795689eb2a99a0db3c87 Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Tue, 9 Apr 2024 15:21:47 +0800 Subject: [PATCH 34/79] =?UTF-8?q?=E5=BA=93=E5=AD=98=E9=9C=80=E6=B1=82?= =?UTF-8?q?=E4=BF=AE=E6=94=B91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_warehouse/models/model.py | 57 +++++++++++++------ .../views/change_stock_move_views.xml | 16 ++++-- sf_warehouse/views/shelf_location.xml | 1 + 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py index 347fd658..63a02e0d 100644 --- a/sf_warehouse/models/model.py +++ b/sf_warehouse/models/model.py @@ -310,7 +310,7 @@ class SfShelf(models.Model): class ShelfLocation(models.Model): _name = 'sf.shelf.location' _description = '货位' - _order = 'create_date desc' + _order = 'id asc, create_date asc' # current_location_id = fields.Many2one('sf.shelf.location', string='当前位置') # # 目的位置 @@ -363,8 +363,10 @@ class ShelfLocation(models.Model): ('禁用', '禁用') ], string='货位状态', default='空闲', readonly=True) # product_id = fields.Many2one('product.template', string='产品') - product_id = fields.Many2one('product.product', string='产品', readonly=True) + product_id = fields.Many2one('product.product', string='产品', compute='_compute_product_id', store=True) product_sn_id = fields.Many2one('stock.lot', string='产品序列号') + # 产品数量 + product_num = fields.Integer('数量') # 修改货位状态为禁用 def action_location_status_disable(self): @@ -381,12 +383,20 @@ class ShelfLocation(models.Model): """ for record in self: if record.product_sn_id: - record.sudo().product_id = record.product_sn_id.product_id - record.sudo().location_status = '占用' + try: + record.sudo().product_id = record.product_sn_id.product_id + record.sudo().location_status = '占用' + record.sudo().product_num = 1 + except Exception as e: + print('eeeeeee占用', e) else: - record.product_id = False - # record.location_status = '空闲' + try: + record.sudo().product_id = False + record.sudo().location_status = '空闲' + record.sudo().product_num = 0 + except Exception as e: + print('eeeeeee空闲', e) # 调取获取货位信息接口 def get_sf_shelf_location_info(self): @@ -423,6 +433,8 @@ class Sf_stock_move_line(models.Model): location_dest_id_value = fields.Integer(compute='_compute_location_dest_id_value', store=True) # lot_qr_code = fields.Binary(string='二维码', compute='_compute_lot_qr_code', store=True) lot_qr_code = fields.Binary(string='二维码', compute='_compute_lot_qr_code', store=True) + current_product_id = fields.Integer(compute='_compute_location_dest_id_value', store=True) + there_is_no_sn = fields.Boolean('是否有序列号', default=False) def action_revert_inventory(self): # 检查用户是否有执行操作的权限 @@ -692,6 +704,7 @@ class Sf_stock_move_line(models.Model): def _compute_location_dest_id_value(self): for record in self: record.location_dest_id_value = record.location_dest_id.id if record.location_dest_id else False + record.current_product_id = record.product_id.id if record.product_id else False destination_location_id = fields.Many2one( 'sf.shelf.location', string='目标货位') @@ -699,23 +712,31 @@ class Sf_stock_move_line(models.Model): @api.onchange('destination_location_id') def _compute_destination_location_id(self): for record in self: - shelf_location_obj = self.env['sf.shelf.location'].search( - [('product_sn_id', '=', record.lot_id.id)]) - if shelf_location_obj: - shelf_location_obj.product_sn_id = False - # obj = self.env['sf.shelf.location'].search([('location_id', '=', - # self.destination_location_id.id)]) - obj = self.env['sf.shelf.location'].search([('name', '=', - self.destination_location_id.name)]) - if obj: - obj.product_sn_id = record.lot_id.id + if record.lot_id: + shelf_location_obj = self.env['sf.shelf.location'].search( + [('product_sn_id', '=', record.lot_id.id)]) + if shelf_location_obj: + shelf_location_obj.product_sn_id = False + # obj = self.env['sf.shelf.location'].search([('location_id', '=', + # self.destination_location_id.id)]) + obj = self.env['sf.shelf.location'].search([('name', '=', + self.destination_location_id.name)]) + if obj: + obj.product_sn_id = record.lot_id.id + else: + pass else: - pass + obj = self.env['sf.shelf.location'].search([('name', '=', + self.destination_location_id.name)]) + if obj: + obj.product_sn_id = record.lot_id.id else: obj = self.env['sf.shelf.location'].search([('name', '=', self.destination_location_id.name)]) if obj: - obj.product_sn_id = record.lot_id.id + obj.product_id = record.product_id.id + obj.location_status = '占用' + obj.product_num = record.reserved_uom_qty class SfStockPicking(models.Model): diff --git a/sf_warehouse/views/change_stock_move_views.xml b/sf_warehouse/views/change_stock_move_views.xml index cc4213c6..c9db5059 100644 --- a/sf_warehouse/views/change_stock_move_views.xml +++ b/sf_warehouse/views/change_stock_move_views.xml @@ -10,10 +10,18 @@ - + + + + + + + + + + diff --git a/sf_warehouse/views/shelf_location.xml b/sf_warehouse/views/shelf_location.xml index 49fdf42e..9cd4446a 100644 --- a/sf_warehouse/views/shelf_location.xml +++ b/sf_warehouse/views/shelf_location.xml @@ -149,6 +149,7 @@ + From 85649daef666fa783d154201ab76114784c6616c Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Tue, 9 Apr 2024 16:53:15 +0800 Subject: [PATCH 35/79] =?UTF-8?q?1=E3=80=81=E5=8A=9F=E8=83=BD=E5=88=80?= =?UTF-8?q?=E5=85=B7=E6=B8=85=E5=8D=95=E6=A8=A1=E5=9E=8B=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E7=B1=BB=E5=9E=8B=E3=80=81?= =?UTF-8?q?=E5=8A=A0=E5=B7=A5=E6=9D=90=E6=96=99=E3=80=81=E5=AF=BF=E5=91=BD?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=EF=BC=9B2=E3=80=81=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E4=BE=9B=E5=BA=94=E5=95=86=E7=9A=84=E5=9C=B0=E5=9D=80=E5=92=8C?= =?UTF-8?q?email=E5=BF=85=E5=A1=AB=EF=BC=9B3=E3=80=81=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E7=BB=84=E8=A3=85=E5=8D=95?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=EF=BC=8C=E6=96=B0=E5=A2=9E=E4=BA=94=E7=A7=8D?= =?UTF-8?q?=E7=89=A9=E6=96=99=E7=9A=84=E8=B4=A7=E4=BD=8D=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9=E7=BB=A7=E6=89=BF=E5=85=B3=E7=B3=BB?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=A0=B9=E6=8D=AE=E8=B4=A7=E4=BD=8D?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=88=80=E5=85=B7=E7=89=A9=E6=96=99=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E5=8A=9F=E8=83=BD=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_base/models/tool_base_new.py | 3 + sf_base/views/tool_views.xml | 15 ++-- sf_mrs_connect/models/sync_common.py | 2 - sf_sale/views/res_partner_view.xml | 10 +-- sf_tool_management/wizard/wizard.py | 90 +++++++++++++++-------- sf_tool_management/wizard/wizard_view.xml | 40 ++++------ 6 files changed, 94 insertions(+), 66 deletions(-) diff --git a/sf_base/models/tool_base_new.py b/sf_base/models/tool_base_new.py index d442639b..f2010b4a 100644 --- a/sf_base/models/tool_base_new.py +++ b/sf_base/models/tool_base_new.py @@ -316,6 +316,7 @@ class ToolInventory(models.Model): 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)') @@ -326,6 +327,8 @@ class ToolInventory(models.Model): 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='刀具组') diff --git a/sf_base/views/tool_views.xml b/sf_base/views/tool_views.xml index 13f3da8d..e52a6222 100644 --- a/sf_base/views/tool_views.xml +++ b/sf_base/views/tool_views.xml @@ -556,20 +556,23 @@ - + - - + + + + - + + @@ -580,8 +583,10 @@ - + + + diff --git a/sf_mrs_connect/models/sync_common.py b/sf_mrs_connect/models/sync_common.py index 3ee916e7..81cd05de 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() 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_tool_management/wizard/wizard.py b/sf_tool_management/wizard/wizard.py index 36bb310d..d736ad53 100644 --- a/sf_tool_management/wizard/wizard.py +++ b/sf_tool_management/wizard/wizard.py @@ -222,72 +222,104 @@ class FunctionalToolAssemblyOrder(models.TransientModel): image = fields.Binary('图片') # 功能刀具组装信息 - # 整体式刀具型号 + # ===============整体式刀具型号================= + integral_freight_barcode = fields.Char('整体式刀具货位') integral_code_id = fields.Many2one('stock.lot', string='整体式刀具序列号', domain=[('product_id.cutting_tool_material_id.name', '=', '整体式刀具'), ('tool_material_status', '=', '可用')]) + 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') + related='integral_product_id.brand_id') - # 刀片型号 + @api.depends('integral_freight_barcode') + def _compute_integral_product_id(self): + pass + + # ===============刀片型号==================== + blade_freight_barcode = fields.Char('刀片货位') blade_code_id = fields.Many2one('stock.lot', '刀片序列号', domain=[('product_id.cutting_tool_material_id.name', '=', '刀片'), ('tool_material_status', '=', '可用')]) + 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_code_id.product_id.cutting_tool_model_id') - blade_name = fields.Char('刀片名称', related='blade_code_id.product_id.name') + related='blade_product_id.cutting_tool_model_id') 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') + 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): + pass + + # ====================刀杆型号================== + bar_freight_barcode = fields.Char('刀杆货位') bar_code_id = fields.Many2one('stock.lot', '刀杆序列号', domain=[('product_id.cutting_tool_material_id.name', '=', '刀杆'), ('tool_material_status', '=', '可用')]) + 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_code_id.product_id.cutting_tool_model_id') - bar_name = fields.Char('刀杆名称', related='bar_code_id.product_id.name') + related='bar_product_id.cutting_tool_model_id') 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') + 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): + pass + + # ===============刀盘型号=================== + pad_freight_barcode = fields.Char('刀盘货位') pad_code_id = fields.Many2one('stock.lot', '刀盘序列号', domain=[('product_id.cutting_tool_material_id.name', '=', '刀盘'), ('tool_material_status', '=', '可用')]) + 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_code_id.product_id.cutting_tool_model_id') - pad_name = fields.Char('刀盘名称', related='pad_code_id.product_id.name') + related='pad_product_id.cutting_tool_model_id') 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') + 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): + pass + + # ================刀柄型号=============== handle_code_id = fields.Many2one('stock.lot', '刀柄序列号', required=True, domain=[('product_id.cutting_tool_material_id.name', '=', '刀柄'), ('tool_material_status', '=', '可用')]) + handle_product_id = fields.Many2one('product.product', string='刀柄名称', related='handle_code_id.product_id') 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', '夹头序列号', required=True, + # =================夹头型号============== + chuck_freight_barcode = fields.Char('夹头货位', required=True) + chuck_code_id = fields.Many2one('stock.lot', '夹头序列号', domain=[('product_id.cutting_tool_material_id.name', '=', '夹头'), ('tool_material_status', '=', '可用')]) + 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_code_id.product_id.cutting_tool_model_id') - chuck_name = fields.Char('夹头名称', related='chuck_code_id.product_id.name') + related='chuck_product_id.cutting_tool_model_id') 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='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): + pass + + # ======================================== def on_barcode_scanned(self, barcode): """ @@ -437,7 +469,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel): else: obj.after_assembly_functional_tool_name = '' - @api.onchange('integral_code_id') + @api.onchange('integral_freight_barcode') def _onchange_after_assembly_functional_tool_diameter(self): for obj in self: if obj.integral_code_id: diff --git a/sf_tool_management/wizard/wizard_view.xml b/sf_tool_management/wizard/wizard_view.xml index a1b35664..912f7dcf 100644 --- a/sf_tool_management/wizard/wizard_view.xml +++ b/sf_tool_management/wizard/wizard_view.xml @@ -201,20 +201,18 @@ + attrs="{'invisible': ['|','|',('blade_freight_barcode', '!=', False),('bar_freight_barcode', '!=', False),('pad_freight_barcode', '!=', False)]}">
- + - + @@ -223,20 +221,18 @@
- +
- + - + @@ -246,20 +242,18 @@ + attrs="{'invisible': ['|',('integral_freight_barcode', '!=', False),('pad_freight_barcode', '!=', False)]}">
- + - + @@ -269,20 +263,18 @@ + attrs="{'invisible': ['|',('bar_freight_barcode', '!=', False),('bar_freight_barcode', '!=', False)]}">
- + - + @@ -304,7 +296,7 @@ - + @@ -319,14 +311,12 @@

- + - + From abdb6361767811ec6710d9f21a8f91e0555d6cc6 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Tue, 9 Apr 2024 17:10:53 +0800 Subject: [PATCH 36/79] =?UTF-8?q?1.=E8=A1=A5=E5=85=85agv=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=202.=E4=BF=AE=E5=A4=8D=E5=88=80=E5=85=B7?= =?UTF-8?q?=E7=89=A9=E6=96=99=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 16 +- sf_mrs_connect/models/res_config_setting.py | 3 + sf_mrs_connect/models/sync_common.py | 393 +++++++++----------- 3 files changed, 201 insertions(+), 211 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 81580db7..89510ae0 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -974,16 +974,24 @@ class WorkPieceDelivery(models.Model): # 配送至avg小车 def _delivery_avg(self): - res = {'reqCode': urllib.parse.quote(self.production_id.name), 'reqTime': '', 'clientCode': '', 'tokenCode': '', - 'taskTyp': 'F01', 'ctnrTyp': '', 'ctnrCode': '', 'wbCode': '006848AB006774', 'positionCodePath': [], + config = self.env['res.config.settings'].get_values() + agv_site = self.env['res.agv.site'].search([]) + positionCode_Arr = [] + if agv_site: + for item in agv_site: + positionCode_Arr.append({ + 'positionCode': item.content, + 'code': item.type + }) + res = {'reqCode': self.production_id.name, 'reqTime': '', 'clientCode': '', 'tokenCode': '', + 'taskTyp': config['task_type_no'], 'ctnrTyp': '', 'ctnrCode': '', 'wbCode': config['wbcode'], + 'positionCodePath': positionCode_Arr, 'podCode': '', 'podDir': '', 'materialLot': '', 'priority': '', 'taskCode': '', 'agvCode': '', 'materialLot': '', 'data': ''} - config = self.env['res.config.settings'].get_values() try: logging.info('AGV请求路径:%s' % config['agv_rcs_url']) logging.info('AGV-json:%s' % res) - headers = {'Content-Type': 'application/json'} ret = requests.post((config['agv_rcs_url']), json=res, headers=headers) ret = ret.json() diff --git a/sf_mrs_connect/models/res_config_setting.py b/sf_mrs_connect/models/res_config_setting.py index f34ab06f..7aa46639 100644 --- a/sf_mrs_connect/models/res_config_setting.py +++ b/sf_mrs_connect/models/res_config_setting.py @@ -97,6 +97,7 @@ class ResConfigSettings(models.TransientModel): sf_secret_key = config.get_param('sf_secret_key', default='') sf_url = config.get_param('sf_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='') task_type_no = config.get_param('task_type_no', default='') ftp_host = config.get_param('ftp_host', default='') @@ -109,6 +110,7 @@ class ResConfigSettings(models.TransientModel): sf_secret_key=sf_secret_key, sf_url=sf_url, agv_rcs_url=agv_rcs_url, + wbcode=wbcode, agv_code=agv_code, task_type_no=task_type_no, ftp_host=ftp_host, @@ -125,6 +127,7 @@ class ResConfigSettings(models.TransientModel): 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_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("task_type_no", self.task_type_no or "") ir_config.set_param("ftp_host", self.ftp_host or "") diff --git a/sf_mrs_connect/models/sync_common.py b/sf_mrs_connect/models/sync_common.py index 3ee916e7..0a44f130 100644 --- a/sf_mrs_connect/models/sync_common.py +++ b/sf_mrs_connect/models/sync_common.py @@ -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("每齿走刀量认证未通过") @@ -2771,29 +2763,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( @@ -2835,35 +2824,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( @@ -2894,24 +2881,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( @@ -2955,38 +2940,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( @@ -3023,30 +3006,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( @@ -3085,30 +3066,28 @@ class CuttingToolBasicParameters(models.Model): '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'], - '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'], - }) + 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("刀具物料基本参数认证未通过") From f19a1a282a0bca6bc893fa6e117e7beae3450dac Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Tue, 9 Apr 2024 17:27:37 +0800 Subject: [PATCH 37/79] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E6=89=AB?= =?UTF-8?q?=E6=8F=8F=E5=BD=95=E5=85=A5=E5=88=80=E5=85=B7=E7=89=A9=E6=96=99?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_tool_management/wizard/wizard.py | 111 ++++++++++++---------------- 1 file changed, 47 insertions(+), 64 deletions(-) diff --git a/sf_tool_management/wizard/wizard.py b/sf_tool_management/wizard/wizard.py index d736ad53..303c87d5 100644 --- a/sf_tool_management/wizard/wizard.py +++ b/sf_tool_management/wizard/wizard.py @@ -238,7 +238,9 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('integral_freight_barcode') def _compute_integral_product_id(self): - pass + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.integral_freight_barcode)]) + if location: + self.integral_product_id = location.product_id.id # ===============刀片型号==================== blade_freight_barcode = fields.Char('刀片货位') @@ -255,7 +257,9 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('blade_freight_barcode') def _compute_blade_product_id(self): - pass + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.blade_freight_barcode)]) + if location: + self.blade_product_id = location.product_id.id # ====================刀杆型号================== bar_freight_barcode = fields.Char('刀杆货位') @@ -272,7 +276,9 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('bar_freight_barcode') def _compute_bar_product_id(self): - pass + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.bar_freight_barcode)]) + if location: + self.bar_product_id = location.product_id.id # ===============刀盘型号=================== pad_freight_barcode = fields.Char('刀盘货位') @@ -289,7 +295,9 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('pad_freight_barcode') def _compute_pad_product_id(self): - pass + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.pad_freight_barcode)]) + if location: + self.pad_product_id = location.product_id.id # ================刀柄型号=============== handle_code_id = fields.Many2one('stock.lot', '刀柄序列号', required=True, @@ -317,69 +325,44 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('chuck_freight_barcode') def _compute_chuck_product_id(self): - pass + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.chuck_freight_barcode)]) + if location: + self.chuck_product_id = location.product_id.id # ======================================== def on_barcode_scanned(self, barcode): """ - 智能工厂组装单处扫码绑定刀具物料') + 智能工厂组装单处扫码绑定刀具物料 """ for record in self: - if 'DJWL' in barcode: - lot_ids = record.env['stock.lot'].sudo().search([('name', '=', barcode)]) - if not lot_ids: - raise ValidationError('扫描的条形码数据不存在,请重新扫描!') - for lot_id in lot_ids: - if lot_id.quant_ids[-1].location_id.name == '刀具组装位置': - raise ValidationError('该刀具物料已使用,请重新扫描!!!') - elif lot_id.quant_ids[-1].location_id.name not in '刀具房': - raise ValidationError('该刀具物料未入库,请重新扫描!!!') - tool_material_name = lot_id.product_id.cutting_tool_material_id.name - if tool_material_name == '整体式刀具': - record.integral_code_id = lot_id.id - elif tool_material_name == '刀片': - record.blade_code_id = lot_id.id - elif tool_material_name == '刀杆': - record.bar_code_id = lot_id.id - elif tool_material_name == '刀盘': - record.pad_code_id = lot_id.id - elif tool_material_name == '刀柄': - record.handle_code_id = lot_id.id - record.chuck_code_id = record.get_chuck_code_id(lot_id).id or False - elif tool_material_name == '夹头': - record.chuck_code_id = lot_id.id - else: - raise ValidationError('扫描的刀具物料不存在,请重新扫描!') - else: - lot_ids = self.env['stock.lot'].sudo().search([('rfid', '=', barcode)]) - if not lot_ids: - raise ValidationError('扫描的刀具物料不存在,请重新扫描!') + lot_ids = self.env['stock.lot'].sudo().search([('rfid', '=', barcode)]) + if lot_ids: for lot_id in lot_ids: if lot_id.quant_ids[-1].location_id.name in '刀具房': record.handle_code_id = lot_id.id - record.chuck_code_id = record.get_chuck_code_id(lot_id).id or False elif lot_id.quant_ids[-1].location_id.name == '刀具组装位置': raise ValidationError('该刀柄已使用,请重新扫描!!!') else: raise ValidationError('该刀柄未入库,请重新扫描!!!') - - def get_chuck_code_id(self, lot_id): - # 适用夹头型号 - cutting_tool_chuck_id = lot_id.product_id.cutting_tool_chuck_id - # 适用夹头尺寸 - fit_chuck_size = lot_id.product_id.cutting_tool_fit_chuck_size - # 适用夹头产品 - chuck_product_id = self.env['product.product'].sudo().search( - [('cutting_tool_model_id', '=', cutting_tool_chuck_id.id), - ('cutting_tool_er_size_model', '=', fit_chuck_size)]) - # 适用夹头产品序列号 - chuck_product_lot_ids = self.env['stock.lot'].sudo().search( - [('product_id', '=', chuck_product_id.id), ('tool_material_status', '=', '可用')]) - for chuck_product_lot_id in chuck_product_lot_ids: - if chuck_product_lot_id.quant_ids[-1].location_id.name in '刀具房': - return chuck_product_lot_id - return False + else: + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', barcode)]) + if location: + material_name = location.product_id.cutting_tool_material_id.name + if material_name == '整体式刀具': + record.integral_freight_barcode = barcode + elif material_name == '刀片': + record.blade_freight_barcode = barcode + elif material_name == '刀杆': + record.bar_freight_barcode = barcode + elif material_name == '刀盘': + record.pad_freight_barcode = barcode + elif material_name == '夹头': + record.chuck_freight_barcode = barcode + else: + raise ValidationError('扫描的刀具物料不存在,请重新扫描!') + else: + raise ValidationError('扫描的刀具物料不存在,请重新扫描!') @api.depends('handle_code_id') def _compute_rfid(self): @@ -605,12 +588,12 @@ class FunctionalToolAssemblyOrder(models.TransientModel): 'name': self.after_assembly_functional_tool_name, 'rfid': self.rfid, 'tool_groups_id': self.tool_groups_id.id, - 'integral_code_id': self.integral_code_id.id, - 'blade_code_id': self.blade_code_id.id, - 'bar_code_id': self.bar_code_id.id, - 'pad_code_id': self.pad_code_id.id, + 'integral_product_id': self.integral_product_id.id, + 'blade_product_id': self.blade_product_id.id, + 'bar_product_id': self.bar_product_id.id, + 'pad_product_id': self.pad_product_id.id, 'handle_code_id': self.handle_code_id.id, - 'chuck_code_id': self.chuck_code_id.id, + 'chuck_product_id': self.chuck_product_id.id, 'after_assembly_functional_tool_name': self.after_assembly_functional_tool_name, 'after_assembly_functional_tool_type_id': self.after_assembly_functional_tool_type_id.id, @@ -645,12 +628,12 @@ class FunctionalToolAssemblyOrder(models.TransientModel): 'tool_groups_id': self.tool_groups_id.id, 'functional_tool_name_id': functional_tool_assembly_id.id, 'sf_cutting_tool_type_id': self.after_assembly_functional_tool_type_id.id, - 'cutting_tool_integral_model_id': self.integral_code_id.product_id.id, - 'cutting_tool_blade_model_id': self.blade_code_id.product_id.id, - 'cutting_tool_cutterbar_model_id': self.bar_code_id.product_id.id, - 'cutting_tool_cutterpad_model_id': self.pad_code_id.product_id.id, - 'cutting_tool_cutterhandle_model_id': self.handle_code_id.product_id.id, - 'cutting_tool_cutterhead_model_id': self.chuck_code_id.product_id.id, + 'cutting_tool_integral_model_id': self.integral_product_id.id, + 'cutting_tool_blade_model_id': self.blade_product_id.id, + 'cutting_tool_cutterbar_model_id': self.bar_product_id.id, + 'cutting_tool_cutterpad_model_id': self.pad_product_id.id, + 'cutting_tool_cutterhandle_model_id': self.handle_product_id.id, + 'cutting_tool_cutterhead_model_id': self.chuck_product_id.id, 'functional_tool_diameter': self.after_assembly_functional_tool_diameter, 'knife_tip_r_angle': self.after_assembly_knife_tip_r_angle, From 310a2de34f5e8a8fb2abfca022c0aa27be6b2c01 Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Tue, 9 Apr 2024 20:14:44 +0800 Subject: [PATCH 38/79] =?UTF-8?q?=E5=BC=80=E5=AE=8C=E5=BA=93=E5=AD=98?= =?UTF-8?q?=E5=A4=84=E6=96=B0=E5=A2=9E=E9=9C=80=E6=B1=82=E5=9F=BA=E6=9C=AC?= =?UTF-8?q?=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_warehouse/models/model.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py index 63a02e0d..1e1d8328 100644 --- a/sf_warehouse/models/model.py +++ b/sf_warehouse/models/model.py @@ -132,7 +132,7 @@ class SfLocation(models.Model): for record in self: if record.product_sn_id: record.product_id = record.product_sn_id.product_id - record.location_status = '占用' + # record.location_status = '占用' else: record.product_id = False # record.location_status = '空闲' @@ -361,13 +361,21 @@ class ShelfLocation(models.Model): ('空闲', '空闲'), ('占用', '占用'), ('禁用', '禁用') - ], string='货位状态', default='空闲', readonly=True) + ], string='货位状态', default='空闲', compute='_compute_product_num', store=True) # product_id = fields.Many2one('product.template', string='产品') product_id = fields.Many2one('product.product', string='产品', compute='_compute_product_id', store=True) product_sn_id = fields.Many2one('stock.lot', string='产品序列号') # 产品数量 product_num = fields.Integer('数量') + @api.depends('product_num') + def _compute_product_num(self): + for record in self: + if record.product_num > 0: + record.location_status = '占用' + elif record.product_num == 0: + record.location_status = '空闲' + # 修改货位状态为禁用 def action_location_status_disable(self): self.location_status = '禁用' @@ -385,7 +393,7 @@ class ShelfLocation(models.Model): if record.product_sn_id: try: record.sudo().product_id = record.product_sn_id.product_id - record.sudo().location_status = '占用' + # record.sudo().location_status = '占用' record.sudo().product_num = 1 except Exception as e: print('eeeeeee占用', e) @@ -393,7 +401,7 @@ class ShelfLocation(models.Model): else: try: record.sudo().product_id = False - record.sudo().location_status = '空闲' + # record.sudo().location_status = '空闲' record.sudo().product_num = 0 except Exception as e: print('eeeeeee空闲', e) @@ -735,8 +743,8 @@ class Sf_stock_move_line(models.Model): self.destination_location_id.name)]) if obj: obj.product_id = record.product_id.id - obj.location_status = '占用' - obj.product_num = record.reserved_uom_qty + # obj.location_status = '占用' + obj.product_num += record.reserved_uom_qty class SfStockPicking(models.Model): @@ -761,8 +769,11 @@ class SfStockPicking(models.Model): for line in self.move_line_ids: if line: if line.current_location_id: - line.current_location_id.product_sn_id = False - line.current_location_id.location_status = '空闲' + if line.current_location_id.product_sn_id: + line.current_location_id.product_sn_id = False + # line.current_location_id.location_status = '空闲' + line.current_location_id.product_num = 0 + return res # def print_all_barcode(self): From 7f6444cc890309824ef3318f0cd51433e3c2ecc1 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Wed, 10 Apr 2024 17:32:35 +0800 Subject: [PATCH 39/79] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=88=80=E5=85=B7=E7=BB=84=E8=A3=85=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=EF=BC=8C=E9=87=8D=E6=9E=84=E5=88=80=E5=85=B7=E7=89=A9=E6=96=99?= =?UTF-8?q?=E7=9A=84=E7=BB=84=E6=88=90=E7=BB=93=E6=9E=84=EF=BC=9B2?= =?UTF-8?q?=E3=80=81=E4=BC=98=E5=8C=96=E5=88=80=E5=85=B7=E7=89=A9=E6=96=99?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E6=A8=A1=E5=9E=8B=EF=BC=8C=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E5=88=80=E5=85=B7=E7=89=A9=E6=B5=81=E5=BA=93=E5=AD=98=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1=E6=96=B9=E6=B3=95=EF=BC=9B3=E3=80=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E7=BB=84=E8=A3=85?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=EF=BC=8C=E9=87=8D=E6=9E=84=E5=88=80=E5=85=B7?= =?UTF-8?q?=E7=89=A9=E6=96=99=E5=87=BA=E5=BA=93=E6=96=B9=E6=B3=95=EF=BC=9B?= =?UTF-8?q?4=E3=80=81=E9=87=8D=E6=9E=84=E6=89=AB=E7=A0=81=E5=BD=95?= =?UTF-8?q?=E5=85=A5=E5=88=80=E5=85=B7=E7=89=A9=E6=96=99=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=9B5=E3=80=81=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E5=88=97=E8=A1=A8=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_tool_management/__manifest__.py | 1 + sf_tool_management/models/__init__.py | 1 + sf_tool_management/models/base.py | 624 ++++-------------- sf_tool_management/models/functional_tool.py | 488 ++++++++++++++ .../models/tool_material_search.py | 55 +- .../views/functional_tool_views.xml | 511 ++++++++++++++ sf_tool_management/views/tool_base_views.xml | 592 ++--------------- .../views/tool_material_search.xml | 2 +- sf_tool_management/wizard/wizard.py | 146 ++-- sf_tool_management/wizard/wizard_view.xml | 11 +- 10 files changed, 1302 insertions(+), 1129 deletions(-) create mode 100644 sf_tool_management/models/functional_tool.py create mode 100644 sf_tool_management/views/functional_tool_views.xml diff --git a/sf_tool_management/__manifest__.py b/sf_tool_management/__manifest__.py index a7750f69..f2389f48 100644 --- a/sf_tool_management/__manifest__.py +++ b/sf_tool_management/__manifest__.py @@ -16,6 +16,7 @@ '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', 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 d90c65bd..0b444a98 100644 --- a/sf_tool_management/models/base.py +++ b/sf_tool_management/models/base.py @@ -1,477 +1,8 @@ # -*- coding: utf-8 -*- -import re -import json -import requests 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', 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.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 class MachineTableToolChangingApply(models.Model): @@ -819,12 +350,12 @@ 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) tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', readonly=True) - name = fields.Char(string='名称', readonly=True, compute='_compute_name', store=True) + name = fields.Char(string='名称', readonly=True, compute='_compute_name') assembly_order_code = fields.Char(string='组装单编码', readonly=True) functional_tool_name_id = fields.Many2one('product.product', string='功能刀具', readonly=True) @@ -864,56 +395,137 @@ 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) + related='integral_product_id.brand_id') + + @api.depends('integral_freight_barcode') + def _compute_integral_product_id(self): + for item in self: + 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_code_id.product_id.cutting_tool_model_id') - blade_name = fields.Char('刀片名称', related='blade_code_id.product_id.name') + related='blade_product_id.cutting_tool_model_id') 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) + 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: + 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_code_id.product_id.cutting_tool_model_id') - bar_name = fields.Char('刀杆名称', related='bar_code_id.product_id.name') + related='bar_product_id.cutting_tool_model_id') 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) + 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: + 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_code_id.product_id.cutting_tool_model_id') - pad_name = fields.Char('刀盘名称', related='pad_code_id.product_id.name') + related='pad_product_id.cutting_tool_model_id') 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) + 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: + 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_barcode = fields.Char('刀柄货位') + handle_code_id = fields.Many2one('stock.lot', '刀柄序列号', compute='_compute_handle_product_id', store=True) + 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_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') + @api.depends('handle_freight_barcode') + def _compute_handle_product_id(self): + for item in self: + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.handle_freight_barcode)]) + if location: + item.handle_code_id = location.product_sn_id.id + item.handle_product_id = location.product_id.id + else: + item.handle_code_id = False + item.handle_product_id = 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: + 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..334511a6 --- /dev/null +++ b/sf_tool_management/models/functional_tool.py @@ -0,0 +1,488 @@ +# -*- 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) + + @api.depends('functional_tool_name_id') + def _compute_name(self): + for item in self: + if item.functional_tool_name_id: + name = item.functional_tool_name_id.after_assembly_functional_tool_name + inventory = self.env['sf.tool.inventory'].sudo().search([('name', '=', name)]) + item.name = name + if inventory: + item.tool_name_id = inventory.id + else: + item.tool_name_id = False + else: + item.name = '' + item.tool_name_id = False + + 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('名称', compute='_compute_name', stroe=True) + tool_name_id = fields.Many2one('sf.tool.inventory', '功能刀具名称', compute='_compute_name', store=True) + 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.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/tool_material_search.py b/sf_tool_management/models/tool_material_search.py index 75fc02e0..1338d758 100644 --- a/sf_tool_management/models/tool_material_search.py +++ b/sf_tool_management/models/tool_material_search.py @@ -27,28 +27,49 @@ class ToolMaterial(models.Model): barcode_ids = fields.One2many('stock.lot', 'tool_material_search_id', string='序列号', readonly=True) - @api.depends('barcode_ids') + @api.depends('product_id') 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 + + # @api.depends('barcode_ids') + # def _compute_number(self): + # for record in self: + # usable_num = 0 + # have_been_used_num = 0 + # scrap_num = 0 + # if record.barcode_ids: + # record.number = len(record.barcode_ids) + # for barcode_id in record.barcode_ids: + # if barcode_id.quant_ids: + # if barcode_id.quant_ids[-1].location_id.name == '刀具组装位置': + # have_been_used_num = have_been_used_num + 1 + # else: + # usable_num = usable_num + 1 + # record.usable_num = usable_num + # record.have_been_used_num = have_been_used_num + # record.scrap_num = scrap_num + # else: + # record.number = 0 + # record.usable_num = 0 + # record.have_been_used_num = 0 + # record.scrap_num = 0 @api.model def _read_group_cutting_tool_material_id(self, categories, domain, order): 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..1e30dc41 --- /dev/null +++ b/sf_tool_management/views/functional_tool_views.xml @@ -0,0 +1,511 @@ + + + + + + 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/tool_base_views.xml b/sf_tool_management/views/tool_base_views.xml index 4dd23a4e..68b6c9a4 100644 --- a/sf_tool_management/views/tool_base_views.xml +++ b/sf_tool_management/views/tool_base_views.xml @@ -1,513 +1,6 @@ - - - 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)] - - - 机床换刀申请 @@ -998,7 +491,7 @@ 功能刀具组装 sf.functional.tool.assembly -
+
@@ -23,12 +24,21 @@ - - - - - - + + +